|
import os |
|
import sys |
|
import fcntl |
|
import stat |
|
import json |
|
import math |
|
import subprocess |
|
import fnmatch |
|
import re |
|
import tempfile |
|
import shutil |
|
|
|
OUTDIR = os.getcwd() |
|
CAMFILE = OUTDIR + "/json/cameras/shotCam.json" |
|
LIGHTFILE = OUTDIR + "/json/lights/lights.json" |
|
|
|
|
|
|
|
TMPDIR = '/tmp' |
|
IDENTITY = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] |
|
|
|
|
|
|
|
DIS2PBRT = { |
|
"metallic": "float metallic", |
|
"roughness": "float roughness", |
|
"anisotropic": "float anisotropic", |
|
"specularTint": "float speculartint", |
|
"sheen": "float sheen", |
|
"sheenTint": "float sheentint", |
|
"clearcoat" : "float clearcoat", |
|
"clearcoatGloss": "float clearcoatgloss", |
|
"specTrans" : "float spectrans", |
|
"ior" : "float eta" |
|
} |
|
|
|
|
|
def mon2lin(color): |
|
return [math.pow(color[0], 2.2), math.pow(color[1], 2.2), math.pow(color[2], 2.2)] |
|
|
|
|
|
def readJsonFile(jsonFile): |
|
""" |
|
Wrapper script to import json file as dict. |
|
:param jsonFile: file as string |
|
:return: dict |
|
""" |
|
with open(os.path.abspath(jsonFile), "r") as jf: |
|
jsonDict = json.load(jf) |
|
return jsonDict if jsonDict else {} |
|
|
|
|
|
def writeEmbreeEcsFile(): |
|
ecsFilePath = os.path.abspath("embree/island.ecs") |
|
ecsFile = os.open(ecsFilePath, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(ecsFile, fcntl.LOCK_EX) |
|
try: |
|
f = os.fdopen(ecsFile,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (ecsFilePath, strerror) |
|
return False |
|
|
|
f.writelines('-i island_flattened.xml --instancing flattened --verbose 1\n') |
|
|
|
os.fsync(ecsFile) |
|
fcntl.flock(ecsFile, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(ecsFilePath, stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IWGRP|stat.S_IROTH|stat.S_IWOTH) |
|
print "Writing main ECS file: ", ecsFilePath |
|
|
|
return True |
|
|
|
def writeMainPbrtFile(outPbrtFile="embree/island.xml"): |
|
""" |
|
Create the main XML file with has all the camera, lights and geometry includes and WorldBegin/End |
|
:param outPbrtFile: file to create |
|
:return: success |
|
""" |
|
pbrtFile = os.path.abspath(outPbrtFile) |
|
pbrtFileObj = os.open(pbrtFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtFile, strerror) |
|
return False |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines('<scene>\n') |
|
|
|
|
|
with open(CAMFILE, "r") as cf: |
|
cameraDict = json.load(cf) |
|
|
|
f.writelines(' <PerspectiveCamera name="default"\n') |
|
f.writelines(' from="%f %f %f"\n' % (cameraDict["eye"][0], cameraDict["eye"][1], cameraDict["eye"][2])) |
|
f.writelines(' to="%f %f %f"\n' % (cameraDict["look"][0], cameraDict["look"][1], cameraDict["look"][2])) |
|
f.writelines(' up="%f %f %f"\n' % (cameraDict["up"][0], cameraDict["up"][1], cameraDict["up"][2])) |
|
f.writelines(' fov="%f"\n' % cameraDict["fov"]) |
|
f.writelines(' />\n') |
|
f.writelines('\n') |
|
|
|
f.writelines(' <DirectionalLight>\n') |
|
f.writelines(' <AffineSpace>\n') |
|
f.writelines(' 1 0 -1 0\n') |
|
f.writelines(' 0 0 -1 0\n') |
|
f.writelines(' 0 1 0 0\n') |
|
f.writelines(' </AffineSpace>\n') |
|
f.writelines(' <E>10 10 10</E>\n') |
|
f.writelines(' </DirectionalLight>\n') |
|
f.writelines('\n') |
|
|
|
f.writelines(' <AmbientLight>\n') |
|
f.writelines(' <AffineSpace>\n') |
|
f.writelines(' 1 0 0 0\n') |
|
f.writelines(' 0 1 0 0\n') |
|
f.writelines(' 0 0 1 0\n') |
|
f.writelines(' </AffineSpace>\n') |
|
f.writelines(' <L>0.5 0.5 0.5</L>\n') |
|
f.writelines(' </AmbientLight>\n') |
|
f.writelines('\n') |
|
|
|
|
|
|
|
|
|
|
|
|
|
f.writelines(insertElements()) |
|
f.writelines('</scene>\n\n') |
|
|
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtFile, stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IWGRP|stat.S_IROTH|stat.S_IWOTH) |
|
print "Writing main XML file: ", pbrtFile |
|
return True |
|
|
|
|
|
def createDefaultHeader(): |
|
header = 'Scale -1 1 1\n' |
|
header += 'Film "image" "string filename" ["island.png"]\n' |
|
header += ' "integer xresolution" [1024] "integer yresolution" [429]\n' |
|
header += ' "float maxsampleluminance" 10\n\n' |
|
return header |
|
|
|
|
|
def createCamera(f,jsonCamFile): |
|
""" |
|
:param: camFile: Json file with raw camera data from maya. |
|
:return: |
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createLights(jsonLightsFile): |
|
lightText = "" |
|
|
|
with open(os.path.abspath(jsonLightsFile), "r") as lf: |
|
lightsDict = json.load(lf) |
|
|
|
for lightName, lightDict in lightsDict.iteritems(): |
|
|
|
lc = mon2lin(lightDict["color"]) |
|
le = math.pow(2, lightDict["exposure"]) |
|
rot = lightDict["rotation"] |
|
loc = lightDict["location"] |
|
tm = lightDict["translationMatrix"] |
|
|
|
if lightDict["type"] == "dome": |
|
|
|
mapname = os.path.basename(lightDict["envmapCamera"]) |
|
lightText += "# skydome: %s\n" % lightName |
|
lightText += "AttributeBegin\n" |
|
|
|
|
|
|
|
lightText += " Scale -1 1 1\n" |
|
lightText += " Rotate 90 -1 0 0\n" |
|
lightText += " Rotate 65 0 0 1\n" |
|
lightText += """ LightSource "infinite" "string mapname" "%s"\n""" % os.path.join("..","textures",mapname) |
|
lightText += "AttributeEnd\n\n" |
|
|
|
elif lightDict["type"] == "distant": |
|
lightText += "# distant light: %s\n" % lightName |
|
lightText += "AttributeBegin\n" |
|
lightText += " Translate %f %f %f\n" % (loc[0], loc[1], loc[2]) |
|
lightText += " Rotate %f %f %f 1\n" % (rot[0], rot[1], rot[2]) |
|
lightText += """ LightSource "distant" "point from" [ 0.0 0.0 0.0]\n""" |
|
lightText += """ "point to" [ 0.0 0.0 -1.0 ]\n""" |
|
lightText += """ "rgb L" [ %f %f %f ]\n""" % (lc[0], lc[1], lc[2]) |
|
lightText += "AttributeEnd\n\n" |
|
|
|
elif lightDict["type"] == "quad": |
|
hw = float(lightDict["width"]) / 2 |
|
hh = float(lightDict["height"]) / 2 |
|
lightText += "# quad light w/ simple triangle mesh: %s\n" % lightName |
|
lightText += "AttributeBegin\n" |
|
lightText += """ AreaLightSource "diffuse" "rgb L" [%f %f %f]\n""" % (lc[0]*le, lc[1]*le, lc[2]*le) |
|
lightText += " Transform [%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f]\n" % tuple(tm) |
|
lightText += """ Shape "trianglemesh" "integer indices" [0 2 1 0 3 2] "float alpha" 0\n""" |
|
lightText += """ "point P"[%f %f 0 %f %f 0 %f %f 0 %f %f 0]\n""" % (hw, hh, -hw, hh, -hw, -hh, hw, -hh) |
|
lightText += "AttributeEnd\n\n" |
|
|
|
else: |
|
print "Light type not supported:", lightName, lightDict["type"] |
|
|
|
return lightText |
|
|
|
|
|
def createDefaultTail(): |
|
return "\nWorldEnd\n" |
|
|
|
|
|
def createGeometryHeader(gp, jsonFile, materialsName): |
|
gp.write("<!--Created from %s-->\n" % jsonFile) |
|
gp.write("AttributeBegin\n") |
|
gp.write(" Include \"%s\"\n\n" % materialsName) |
|
|
|
|
|
def createGeometryTail(gp): |
|
gp.write("AttributeEnd\n") |
|
|
|
|
|
def insertElements(): |
|
elementText = '' |
|
for element in os.listdir(os.path.abspath("obj")): |
|
elementText += ' <xml src="%s"/>\n'% (element + ".xml") |
|
return elementText |
|
|
|
|
|
def geomToPbrt(objFile, pbrtFile, matFile, root_folder): |
|
""" |
|
That's an obj file and converts it to pbrt using 'obj2pbrt'. In addition, to support a binding hack, it comments |
|
out the MakeNamedMaterial lines left by 'obj2pbrt'. We are just using the bindings, since OBJ format does not |
|
support our materials. |
|
[NEW] Added hardcoded materials where a mesh-specific texture is required. |
|
:param objFile: |
|
:param pbrtFile: |
|
:param bakeTextures: |
|
:return: |
|
""" |
|
|
|
fpObjFile = os.path.abspath(objFile) |
|
fpPbrtFile = os.path.abspath(pbrtFile) |
|
|
|
dwd = os.getcwd() |
|
os.chdir(os.path.dirname(fpObjFile)) |
|
print "Creating pbrt geometry from", objFile |
|
|
|
xmlFile = "xml/"+objFile[4:-4]+".xml" |
|
|
|
f = open(pbrtFile,'w') |
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines('<scene>\n'); |
|
if matFile != "": f.writelines(' <xml src="'+root_folder+'%s"/>\n' % matFile); |
|
f.writelines(' <xml src="'+root_folder+'%s"/>\n' % xmlFile); |
|
f.writelines('</scene>\n'); |
|
f.close() |
|
|
|
os.chdir(dwd) |
|
|
|
|
|
|
|
|
|
def writeMaterial(f, matName, valueDict): |
|
|
|
f.writelines('<assign type="material" id="%s">\n'%matName) |
|
f.writelines(' <material>\n') |
|
f.writelines(' <code>"OBJ"</code>\n') |
|
f.writelines(' <parameters>\n') |
|
|
|
if 'baseColor' in valueDict: |
|
color = mon2lin(valueDict['baseColor']) |
|
f.writelines(' <float3 name="Kd">%1.2f %1.2f %1.2f</float3>\n'% (color[0], color[1],color[2])) |
|
else: |
|
print "WARNING WARNING WARNING: Can not find 'baseColor' in", element, matName |
|
f.writelines(' <float3 name="Kd">1 0 0</float3>\n') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
f.writelines(' </parameters>\n') |
|
f.writelines(' </material>\n\n') |
|
f.writelines('</assign>\n\n') |
|
|
|
def matToPbrt(element, matFile, pbrtFile): |
|
""" |
|
Take a json file and convert it into a pbrt "Named" material file which will be used for reference. |
|
:param element: Element name -- Used for error codes and top-of-file comments. |
|
:param matFile: Json material file to be parsed. |
|
:param pbrtFile: Pbrt material file to be output. |
|
:return: None |
|
""" |
|
with open(matFile, "r") as jf: |
|
matDict = json.load(jf) |
|
|
|
if not matDict: |
|
print "ERROR: Unable to parse matfile: ", matFile |
|
return |
|
print "Converting ", matFile |
|
|
|
pbrtFileObj = os.open(pbrtFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtFile, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines("<!--Materials for %s-->\n"%element) |
|
f.writelines("<!--Converted from %s-->\n\n"%matFile) |
|
|
|
f.writelines('<scene>\n\n') |
|
|
|
f.writelines('<assign type="material" id="default">\n') |
|
f.writelines(' <material>\n') |
|
f.writelines(' <code>"OBJ"</code>\n') |
|
f.writelines(' <parameters>\n') |
|
f.writelines(' <float3 name="Kd">1 0 0</float3>\n') |
|
f.writelines(' </parameters>\n') |
|
f.writelines(' </material>\n\n') |
|
f.writelines('</assign>\n\n') |
|
|
|
for matName, valueDict in matDict.iteritems(): |
|
|
|
if matName == "hidden": |
|
f.writelines('<assign type="material" id="%s">\n'%matName) |
|
f.writelines(' <material>\n') |
|
f.writelines(' <code>"OBJ"</code>\n') |
|
f.writelines(' <parameters>\n') |
|
f.writelines(' <float3 name="Kd">1 0 0</float3>\n') |
|
f.writelines(' </parameters>\n') |
|
f.writelines(' </material>\n') |
|
f.writelines('</assign>\n\n') |
|
continue |
|
|
|
writeMaterial(f,matName,valueDict) |
|
|
|
f.writelines('</scene>\n\n') |
|
|
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtFile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing XML file: ", pbrtFile |
|
|
|
|
|
def jsonPrimitiveToPbrt(primType, element, primitiveName, iDict): |
|
if primType == "curve": |
|
return jsonPrimitiveCurveToPbrt(element, primitiveName, iDict) |
|
elif primType == "element": |
|
return jsonPrimitiveElementToPbrt(element, primitiveName, iDict) |
|
else: |
|
return jsonPrimitiveArchiveToPbrt(element, primitiveName, primitiveJsonFile=iDict["jsonFile"]) |
|
|
|
|
|
def jsonPrimitiveArchiveToPbrt(element, primitiveName, primitiveJsonFile): |
|
""" |
|
Create the pbrt reference file for a particular primitive instance. This will be a raw list |
|
of all the instances that make up this particular primitive with the transformations. |
|
:param element: The name of the element (used the build paths) |
|
:param primitiveName: The name of the primitive description we're converting. |
|
:param primitiveJsonFile: Json file containing the archives and all instances of them. |
|
:return: The 'short' path name, which is the partial path without the pbrt directory in front |
|
""" |
|
fileName = os.path.basename(primitiveJsonFile)[:-4] + "xml" if primitiveJsonFile else primitiveName + ".xml" |
|
pbrtPrimitiveFile = os.path.join("embree", element, primitiveName, fileName) |
|
root = "../../" |
|
shortFileName = os.path.join(element, primitiveName, fileName) |
|
iDict = readJsonFile(primitiveJsonFile) |
|
|
|
pbrtFileObj = os.open(pbrtPrimitiveFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtPrimitiveFile, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines("<!--Converted from %s-->\n\n" % primitiveJsonFile) |
|
f.writelines('<scene>\n\n') |
|
|
|
for archive, primitiveDict in iDict.iteritems(): |
|
|
|
archiveName = os.path.basename(archive)[:-4] |
|
for instanceName, transform in primitiveDict.iteritems(): |
|
writeInstance(f, root, archiveName, instanceName, transform, concat=True) |
|
|
|
f.writelines('</scene>\n\n') |
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtPrimitiveFile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing primitive archive XML file: ", pbrtPrimitiveFile |
|
return shortFileName |
|
|
|
|
|
def jsonPrimitiveCurveToPbrt(element, primitiveName, cDict): |
|
""" |
|
Convert json primitive curve to pbrt curve |
|
:param element: used to find json files |
|
:param primitiveName: used to find json files |
|
:param cDict: dictionary of all curves |
|
:return: |
|
""" |
|
primitiveJsonFile = cDict["jsonFile"] |
|
matFile = os.path.join("json", element, "materials.json") |
|
fileName = os.path.basename(primitiveJsonFile)[:-4] + "xml" if primitiveJsonFile else primitiveName + ".xml" |
|
pbrtPrimitiveFile = os.path.join("embree", element, primitiveName, fileName) |
|
shortFileName = os.path.join(element, primitiveName, fileName) |
|
curveList = readJsonFile(primitiveJsonFile) |
|
|
|
pbrtFileObj = os.open(pbrtPrimitiveFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtPrimitiveFile, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines("<!--Converted from %s-->\n\n" % primitiveJsonFile) |
|
f.writelines('<scene>\n\n') |
|
|
|
f.writelines(' <Curves type="round" basis="bspline">\n\n') |
|
|
|
|
|
mat = findMaterial(primitiveName, readJsonFile(matFile)) |
|
if mat: |
|
f.writelines(' <material id="%s"/>\n'%mat) |
|
else: |
|
f.writelines(' <material id="default"/>\n') |
|
print "WARNING: curve has no material" |
|
f.writelines('\n') |
|
|
|
i=0 |
|
f.writelines(' <indices>\n') |
|
for curve in curveList: |
|
i=writeCurveIndices(f, i, curve, cDict) |
|
f.writelines('\n') |
|
f.writelines(' </indices>\n') |
|
f.writelines('\n') |
|
|
|
f.writelines(' <positions>\n') |
|
for curve in curveList: |
|
writeCurveVertices(f, curve, cDict) |
|
f.writelines('\n') |
|
f.writelines(' </positions>\n') |
|
|
|
f.writelines(' </Curves>\n\n') |
|
|
|
f.writelines('</scene>\n\n') |
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtPrimitiveFile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing primitive curve XML file: ", pbrtPrimitiveFile |
|
return shortFileName |
|
|
|
|
|
def jsonPrimitiveElementToPbrt(element, primitiveName, eDict): |
|
""" |
|
The primitive being instanced around is a copy of another element, which could include its own primitive data. |
|
:param element: The name of the element (used the build paths) |
|
:param primitiveName: The name of the primitive description we're converting. |
|
:param eDict: Dictionary includes reference element, possible variant and the source json file with the transforms |
|
by variant. "base" variant is assumed to the the top level element definition. |
|
:return: The 'short' path name, which is the partial path without the pbrt directory in front |
|
""" |
|
primitiveJsonFile = eDict["jsonFile"] |
|
fileName = os.path.basename(primitiveJsonFile)[:-4] + "xml" if primitiveJsonFile else primitiveName + ".xml" |
|
pbrtPrimitiveFile = os.path.join("embree", element, primitiveName, fileName) |
|
root = "../../" |
|
shortFileName = os.path.join(element, primitiveName, fileName) |
|
iDict = readJsonFile(primitiveJsonFile) |
|
|
|
|
|
sourceJsonFile = os.path.abspath(os.path.join("json", eDict["element"], eDict["element"] + ".json")) |
|
sourceDict = readJsonFile(sourceJsonFile) |
|
|
|
pbrtFileObj = os.open(pbrtPrimitiveFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtPrimitiveFile, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines("<!--Converted from %s-->\n\n" % primitiveJsonFile) |
|
f.writelines('<scene>\n\n') |
|
|
|
for variant, primitiveDict in iDict.iteritems(): |
|
inclFileList = [] |
|
if variant == "base": |
|
instanceRef = os.path.basename(sourceDict["geomObjFile"])[:-4] |
|
if "instancedPrimitiveJsonFiles" in sourceDict: |
|
for primitiveName, ipDict in sourceDict["instancedPrimitiveJsonFiles"].iteritems(): |
|
fileName = os.path.basename(ipDict["jsonFile"])[:-4] + "xml" |
|
inclFileList.append(os.path.join(eDict["element"], primitiveName, fileName)) |
|
|
|
elif variant in sourceDict["variants"]: |
|
instanceRef = os.path.basename(sourceDict["variants"][variant]["geomObjFile"])[:-4] |
|
if "instancedPrimitiveJsonFiles" in sourceDict["variants"][variant]: |
|
for primitiveName, ipDict in sourceDict["variants"][variant]["instancedPrimitiveJsonFiles"].iteritems(): |
|
fileName = os.path.basename(ipDict["jsonFile"])[:-4] + "xml" |
|
inclFileList.append(os.path.join(eDict["element"], primitiveName, fileName)) |
|
|
|
else: |
|
print "Error: Problems finding variant %s for element %s\n" %(variant, eDict["element"]) |
|
sys.exit() |
|
|
|
for instanceName, transform in primitiveDict.iteritems(): |
|
writeInstance(f, root, instanceRef, instanceName, transform, inclFileList=inclFileList, concat=True) |
|
|
|
f.writelines('</scene>\n\n') |
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtPrimitiveFile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing primitive archive embree file: ", pbrtPrimitiveFile |
|
return shortFileName |
|
|
|
|
|
def writeObject(f, objectName, pbrtGeometryFile, matFile=None): |
|
""" |
|
Create named object definition around single geometry file. |
|
:param f: |
|
:param objectName: What to call the object |
|
:param pbrtGeometryFile: The file being referenced |
|
:param matFile: Some variants need a separate matFile, include override for that here. |
|
:return: |
|
""" |
|
f.writelines(' <assign type="scene" id="%s">\n' % objectName) |
|
f.writelines(' <xml src="../%s"/>\n' % pbrtGeometryFile) |
|
f.writelines(' </assign>\n') |
|
|
|
def writeInstance(f, root, objectName, instanceName, xfm, inclFileList=[], concat=False): |
|
""" |
|
Create instances of previously named object |
|
:param f: |
|
:param objectName: Name of object |
|
:param instanceName: Name of instance (for reference back to json file) |
|
:param transform: Transform |
|
:param inclFileList: For primitive files that need to be referenced after object |
|
:param concat: Use ConcatTransform to properly inherit final instance position of copies of elements. |
|
:return: |
|
""" |
|
f.writelines('<!-- %s -->\n' % instanceName) |
|
f.writelines('<Transform>\n') |
|
if concat: |
|
f.writelines(' <AffineSpace>%f %f %f %f %f %f %f %f %f %f %f %f</AffineSpace>\n' % (xfm[0],xfm[4],xfm[8],xfm[12],xfm[1],xfm[5],xfm[9],xfm[13],xfm[2],xfm[6],xfm[10],xfm[14]) ) |
|
else: |
|
f.writelines(' <AffineSpace>%f %f %f %f %f %f %f %f %f %f %f %f</AffineSpace>\n' % (xfm[0],xfm[4],xfm[8],xfm[12],xfm[1],xfm[5],xfm[9],xfm[13],xfm[2],xfm[6],xfm[10],xfm[14]) ) |
|
f.writelines(' <ref id="%s"/>\n' % objectName) |
|
for inclFile in inclFileList: |
|
f.writelines(' <xml src="' + root + '%s"/>\n' % inclFile) |
|
f.writelines('</Transform>\n\n') |
|
|
|
|
|
def writeCurveIndices(f, i, curve, cDict): |
|
for j in range(0, len(curve)-1): |
|
f.writelines(' %i\n'%i) |
|
i = i+1 |
|
i = i+3 |
|
return i |
|
|
|
def writeCurveVertices(f, curve, cDict): |
|
""" |
|
Updated to work with new pbrt bspline format. |
|
:param f: |
|
:return: |
|
""" |
|
w0 = cDict["widthRoot"] |
|
w1 = cDict["widthTip"] |
|
|
|
|
|
|
|
i=0 |
|
f.writelines(' %f %f %f %f\n' % (curve[0][0], curve[0][1], curve[0][2], w0)) |
|
for p in curve: |
|
x=i/float(len(curve)-1) |
|
w=(1-x)*w0 + x*w1 |
|
f.writelines(' %f %f %f %f\n' % (p[0], p[1], p[2], w)) |
|
i=i+1 |
|
f.writelines(' %f %f %f %f\n' % (curve[-1][0], curve[-1][1], curve[-1][2], w1)) |
|
|
|
def writeObjectFile(element, pbrtOutGeometry, instCopies = None, primDict = None): |
|
""" |
|
Keep all the object references in a single file to keep the main element file readable. Because we can't embed |
|
instances in pbrt, we need to include all references here, both the main element and all primitives or variants |
|
it might be referring too. |
|
:param element: main element |
|
:param pbrtOutGeometry: main element geometry file |
|
:param instCopies: if an instanced copy has its own geometry, we need to reference that as well. |
|
:param primDict: And all primitives used by the geometry. |
|
:return: |
|
""" |
|
|
|
if not pbrtOutGeometry and not primDict and not instCopies: |
|
return "" |
|
|
|
shortName = os.path.join(element, "objects.xml") |
|
pbrtOutObjects = os.path.abspath(os.path.join("embree", shortName)) |
|
|
|
pbrtFileObj = os.open(pbrtOutObjects, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtOutObjects, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines('<scene>\n\n') |
|
|
|
|
|
if primDict: |
|
for primName, primInstanceDict in primDict.iteritems(): |
|
f.writelines("\n<!-- archives used by %s -->\n" % primName) |
|
|
|
if "archives" in primInstanceDict: |
|
for archive in primInstanceDict["archives"]: |
|
|
|
archiveName = os.path.basename(archive)[:-4] |
|
|
|
pbrtArchiveFile = os.path.join(element, primName, archiveName + "_geometry.xml") |
|
|
|
matFile = os.path.join(primInstanceDict["element"], "materials.xml")\ |
|
if primInstanceDict["type"] == "element" else "" |
|
writeObject(f, archiveName, pbrtArchiveFile, matFile=matFile) |
|
|
|
|
|
if pbrtOutGeometry: |
|
f.writelines("\n<!-- main object for the element: %s -->\n" % element) |
|
writeObject(f, element, pbrtOutGeometry) |
|
|
|
|
|
if instCopies: |
|
f.writelines("\n<!-- instanced copies of the element with their own geometry -->\n") |
|
for instanceName, icDict in instCopies.iteritems(): |
|
if "geomObjFile" in icDict and icDict["geomObjFile"]: |
|
|
|
pbrtOutFile =icDict["geomObjFile"][4:-4] + "_geometry.xml" |
|
writeObject(f, icDict["name"], pbrtOutFile) |
|
|
|
f.writelines('</scene>\n\n') |
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtOutObjects, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing XML file: ", pbrtOutObjects |
|
return shortName |
|
|
|
|
|
def writeMainElement(pbrtOutElement, pbrtOutMaterials, pbrtOutGeometry, primitiveFiles, sourceJsonFile=""): |
|
|
|
jDict = readJsonFile(sourceJsonFile) |
|
element = jDict["name"] |
|
transform = jDict["transformMatrix"] |
|
|
|
pbrtFileObj = os.open(pbrtOutElement, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_EX) |
|
|
|
try: |
|
f = os.fdopen(pbrtFileObj,'w') |
|
except IOError as (errno, strerror): |
|
print "Couldn't open %s for write: %s" % (pbrtOutElement, strerror) |
|
return |
|
|
|
f.writelines('<?xml version="1.0"?>\n\n') |
|
f.writelines('<scene>\n\n') |
|
|
|
if sourceJsonFile: |
|
f.writelines("<!-- Converted from %s -->\n\n" % sourceJsonFile) |
|
|
|
|
|
|
|
|
|
f.writelines("<xml src=\"../%s\"/>\n" % pbrtOutMaterials) |
|
|
|
|
|
|
|
|
|
|
|
primitiveDict = jDict["instancedPrimitiveJsonFiles"] if "instancedPrimitiveJsonFiles" in jDict else {} |
|
instancedCopiesDict = jDict["instancedCopies"] if "instancedCopies" in jDict else {} |
|
|
|
objectsFile = writeObjectFile(element, pbrtOutGeometry, instCopies=instancedCopiesDict, primDict=primitiveDict) |
|
if objectsFile: |
|
f.writelines("<xml src=\"../%s\"/>\n" % objectsFile) |
|
|
|
|
|
|
|
f.writelines("\n<!-- Main element -->\n\n") |
|
|
|
primList = [] |
|
primFileList = [] |
|
if primitiveDict: |
|
for primName, primInstanceDict in primitiveDict.iteritems(): |
|
primList.append(primName) |
|
primFileList.append(os.path.join(element, primName, element + "_" + primName + ".xml")) |
|
|
|
|
|
writeInstance(f, "../", element, element, transform, primFileList) |
|
|
|
if instancedCopiesDict: |
|
f.writelines("\n<!-- Instanced copies of main element -->\n\n") |
|
|
|
|
|
|
|
for instance, icDict in instancedCopiesDict.iteritems(): |
|
primOverrides = icDict["instancedPrimitiveJsonFiles"].keys() if "instancedPrimitiveJsonFiles" in icDict else [] |
|
includedPrimFileList = [] |
|
for prim in primList: |
|
|
|
if prim in primOverrides: |
|
primName = instance + '_' + prim + ".xml" |
|
else: |
|
primName = element + '_' + prim + ".xml" |
|
includedPrimFileList.append(os.path.join(element, prim, primName)) |
|
if "geomObjFile" in icDict and icDict["geomObjFile"]: |
|
|
|
writeInstance(f, "../", instance, instance, icDict["transformMatrix"], includedPrimFileList) |
|
else: |
|
writeInstance(f, "../", element, instance, icDict["transformMatrix"], includedPrimFileList) |
|
|
|
|
|
|
|
f.writelines('</scene>\n\n') |
|
os.fsync(pbrtFileObj) |
|
fcntl.flock(pbrtFileObj, fcntl.LOCK_UN) |
|
f.close() |
|
os.chmod(pbrtOutElement, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) |
|
print "Writing XML file: ", pbrtOutElement |
|
return pbrtOutElement |
|
|
|
|
|
def findMaterial(mesh, matDict, hierDict="", quiet=False): |
|
""" |
|
Given a patch, a materials dictionary and an optional hierarchy dictionary, this finds the correct |
|
material for that patch. |
|
:param mesh: The name of the mesh |
|
:param matDict: A dictionary of materials, created from the json materials file. |
|
:param hierDict: A dictionary of hierarchy expansions, created from the json .hier file. |
|
:param quiet: Suppress the no bindings error message |
|
:return: Matching material as string |
|
""" |
|
longNameMesh = hierDict[mesh] + '|' + mesh if mesh in hierDict else mesh |
|
|
|
found = [] |
|
for k, v in matDict.iteritems(): |
|
|
|
bindings = v['assignment'] |
|
for binding in bindings: |
|
if fnmatch.fnmatchcase(longNameMesh, "*" + binding + "*"): |
|
found.append(k) |
|
if found: |
|
|
|
if len(found) == 1: |
|
return found[0] |
|
else: |
|
|
|
|
|
for f in found: |
|
if mesh in matDict[f]['assignment']: |
|
return f |
|
|
|
|
|
for f in found: |
|
print "f" |
|
sys.exit() |
|
|
|
return found[-1] |
|
else: |
|
if not quiet: |
|
print "ERROR: Unable to find binding for mesh: ", mesh |
|
return "" |
|
|
|
|
|
def insertTextureOverrides(pbrtGeomFile, matFile): |
|
""" |
|
Find a mesh that's using a material with a texture and insert the texture override that includes the specific |
|
mesh name. i.e. textures/isGardeniaA/Color/archiveflowerbud0001_geo.ptx |
|
:param pbrtGeomFile: The pbrt geometry file created with obj2pbrt |
|
:param matFile: The json material file |
|
:param hierFile: The file containing the full hierarchy of the meshes (stripped out to create the obj files) |
|
:return: None |
|
""" |
|
COMMENT = "# Inserted materials directly above Shape for custom texture per mesh. v2.\n" |
|
handle, tempPbrtFile = tempfile.mkstemp(prefix='IS', suffix='.xml', dir=TMPDIR) |
|
tof = open(tempPbrtFile,"w") |
|
print "Inserting pbrt materials into: ", tempPbrtFile |
|
|
|
|
|
mDict = readJsonFile(matFile) |
|
textureMats = [key for key in mDict if "colorMap" in mDict[key] and mDict[key]["colorMap"]] |
|
matDict = {mat: mDict[mat] for mat in textureMats} |
|
|
|
|
|
with open(os.path.abspath(pbrtGeomFile), "r") as pgf: |
|
tof.write(COMMENT) |
|
meshName = "" |
|
colorName = "" |
|
dispName = "" |
|
colorMap = "" |
|
dispMap = "" |
|
material = "" |
|
for line in pgf.xreadlines(): |
|
if line.startswith(COMMENT[:20]): |
|
|
|
continue |
|
|
|
if line.startswith("# Name"): |
|
m = re.search('# Name "(.+?)"$', line) |
|
if not m: |
|
tof.write(line) |
|
continue |
|
meshName = m.group(1) |
|
tof.write(line) |
|
continue |
|
|
|
if line.startswith("NamedMaterial"): |
|
m = re.search('^NamedMaterial "(.+?)"$', line) |
|
if not m: |
|
tof.write(line) |
|
continue |
|
material = m.group(1) |
|
if material not in matDict: |
|
material = "" |
|
tof.write(line) |
|
continue |
|
colorMap = matDict[material]["colorMap"] if "colorMap" in matDict[material] else "" |
|
dispMap = matDict[material]["displacementMap"]if "displacementMap" in matDict[material] else "" |
|
if colorMap: |
|
colorName = material + "_Color" |
|
texPath = os.path.join("..", os.path.dirname(colorMap),meshName + ".ptx") |
|
tof.write('Texture "%s" "color" "ptex"\n' % colorName) |
|
tof.write(' "string filename" ["%s"]\n\n'%texPath) |
|
if dispMap: |
|
dispName = material + "_Disp" |
|
texPath = os.path.join("..", os.path.dirname(dispMap),meshName + ".ptx") |
|
tof.write('Texture "%s" "float" "ptex"\n' % dispName) |
|
tof.write(' "string filename" ["%s"]\n\n'%texPath) |
|
|
|
tof.write(line) |
|
continue |
|
|
|
if line.startswith("Shape") and meshName and material: |
|
tof.write(line) |
|
m = re.search('^Shape "trianglemesh"$', line) |
|
if not m: continue |
|
if colorMap: |
|
tof.write(' "texture color" "%s"\n' % colorName) |
|
colorMap = "" |
|
if dispMap: |
|
tof.write(' "texture bumpmap" "%s"\n' % dispName) |
|
dispMap = "" |
|
continue |
|
|
|
|
|
tof.write(line) |
|
|
|
tof.close() |
|
|
|
|
|
print "Replacing ", pbrtGeomFile |
|
shutil.copy2(tempPbrtFile, os.path.abspath(pbrtGeomFile)) |
|
|