MtsBlend: general improvements
parent
df1a3fc3ba
commit
7a7c615b5f
|
@ -40,7 +40,9 @@ from mitsuba.properties.material import mitsuba_material, \
|
|||
mitsuba_mat_composite, mitsuba_emission
|
||||
from mitsuba.operators import MITSUBA_OT_preset_engine_add, EXPORT_OT_mitsuba
|
||||
from mitsuba.outputs import MtsLog, MtsFilmDisplay
|
||||
from mitsuba.export.adjustments import MtsAdjustments
|
||||
from mitsuba.export.film import resolution
|
||||
from mitsuba.export import get_instance_materials
|
||||
from mitsuba.ui import render_panels
|
||||
from mitsuba.ui import lamps
|
||||
from mitsuba.ui.textures import TEXTURE_PT_context_texture_mts
|
||||
|
@ -70,12 +72,17 @@ properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('mitsuba')
|
|||
properties_render.RENDER_PT_output.COMPAT_ENGINES.add('mitsuba')
|
||||
del properties_render
|
||||
|
||||
import properties_material
|
||||
properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add('mitsuba')
|
||||
del properties_material
|
||||
|
||||
compatible("properties_data_mesh")
|
||||
compatible("properties_data_camera")
|
||||
|
||||
class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||
bl_idname = 'mitsuba'
|
||||
bl_label = 'Mitsuba'
|
||||
bl_use_preview = True
|
||||
|
||||
property_groups = [
|
||||
('Scene', mitsuba_engine),
|
||||
|
@ -104,6 +111,37 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
def process_wait_timer(self):
|
||||
# Nothing to do here
|
||||
pass
|
||||
|
||||
def render_preview(self, scene):
|
||||
# Iterate through the preview scene, finding objects with materials attached
|
||||
objects_materials = {}
|
||||
|
||||
for object in [ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render]:
|
||||
for mat in get_instance_materials(object):
|
||||
if mat is not None:
|
||||
if not object.name in objects_materials.keys(): objects_materials[object] = []
|
||||
objects_materials[object].append(mat)
|
||||
|
||||
# find objects that are likely to be the preview objects
|
||||
preview_objects = [o for o in objects_materials.keys() if o.name.startswith('preview')]
|
||||
if len(preview_objects) < 1:
|
||||
return
|
||||
|
||||
# find the materials attached to the likely preview object
|
||||
likely_materials = objects_materials[preview_objects[0]]
|
||||
if len(likely_materials) < 1:
|
||||
return
|
||||
print(materials)
|
||||
|
||||
tempdir = efutil.temp_directory()
|
||||
matpreview_file = os.path.join(tempdir, "matpreview_materials.xml")
|
||||
pm = likely_materials[0]
|
||||
adj = MtsAdjustments(matpreview_file, tempdir,
|
||||
bpy.data.materials, bpy.data.textures)
|
||||
adj.writeHeader()
|
||||
adj.exportMaterial(pm)
|
||||
adj.writeFooter()
|
||||
|
||||
|
||||
def render(self, scene):
|
||||
if scene is None:
|
||||
|
@ -118,6 +156,11 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
self.output_dir = os.path.dirname(scene_path)
|
||||
if self.output_dir[-1] != '/':
|
||||
self.output_dir += '/'
|
||||
|
||||
if scene.name == 'preview':
|
||||
self.render_preview(scene)
|
||||
return
|
||||
|
||||
efutil.export_path = self.output_dir
|
||||
os.chdir(self.output_dir)
|
||||
|
||||
|
|
|
@ -189,3 +189,15 @@ class ParamSet(list):
|
|||
|
||||
def to_string_ref(self):
|
||||
return ''.join(item.to_string_ref() for item in self)
|
||||
|
||||
def get_instance_materials(ob):
|
||||
obmats = []
|
||||
# Grab materials attached to object instances ...
|
||||
if hasattr(ob, 'material_slots'):
|
||||
for ms in ob.material_slots:
|
||||
obmats.append(ms.material)
|
||||
# ... and to the object's mesh data
|
||||
if hasattr(ob.data, 'materials'):
|
||||
for m in ob.data.materials:
|
||||
obmats.append(m)
|
||||
return obmats
|
||||
|
|
|
@ -30,48 +30,51 @@ class MtsAdjustments:
|
|||
in translation when using the COLLADA exporter.
|
||||
'''
|
||||
|
||||
def __init__(self, target_file, target_dir):
|
||||
def __init__(self, target_file, target_dir, materials = None, textures = None):
|
||||
self.target_file = target_file
|
||||
self.target_dir = target_dir
|
||||
self.exported_materials = []
|
||||
self.exported_textures = []
|
||||
self.materials = materials if materials != None else bpy.data.textures
|
||||
self.textures = textures if textures != None else bpy.data.textures
|
||||
|
||||
def export_worldtrafo(self, adjfile, trafo):
|
||||
adjfile.write('\t\t<transform name="toWorld">\n')
|
||||
adjfile.write('\t\t\t<matrix value="')
|
||||
def exportWorldtrafo(self, trafo):
|
||||
self.out.write('\t\t<transform name="toWorld">\n')
|
||||
self.out.write('\t\t\t<matrix value="')
|
||||
for j in range(0,4):
|
||||
for i in range(0,4):
|
||||
adjfile.write("%f " % trafo[i][j])
|
||||
adjfile.write('"/>\n\t\t</transform>\n')
|
||||
self.out.write("%f " % trafo[i][j])
|
||||
self.out.write('"/>\n\t\t</transform>\n')
|
||||
|
||||
def export_lamp(self, adjfile, lamp, idx):
|
||||
def exportLamp(self, lamp, idx):
|
||||
ltype = lamp.data.mitsuba_lamp.type
|
||||
name = translate_id(lamp.data.name)
|
||||
if ltype == 'POINT':
|
||||
adjfile.write('\t<luminaire id="%s-light" type="point">\n' % lamp.data.name)
|
||||
self.out.write('\t<luminaire id="%s-light" type="point">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.exportWorldtrafo(lamp.matrix_world)
|
||||
self.out.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
adjfile.write('\t</luminaire>\n')
|
||||
self.out.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
self.out.write('\t</luminaire>\n')
|
||||
elif ltype == 'AREA':
|
||||
adjfile.write('\t<shape type="obj">\n')
|
||||
self.out.write('\t<shape type="obj">\n')
|
||||
size_x = lamp.data.size
|
||||
size_y = lamp.data.size
|
||||
if lamp.data.shape == 'RECTANGLE':
|
||||
size_y = lamp.data.size_y
|
||||
path = os.path.join(os.path.join(self.target_dir, 'meshes'), "_area_luminaire_%d.obj" % idx)
|
||||
|
||||
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % path)
|
||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||
self.out.write('\t\t<string name="filename" value="%s"/>\n' % path)
|
||||
self.exportWorldtrafo(lamp.matrix_world)
|
||||
|
||||
adjfile.write('\n\t\t<luminaire id="%s-light" type="area">\n' % lamp.data.name)
|
||||
self.out.write('\n\t\t<luminaire id="%s-light" type="area">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity / (2 * size_x * size_y)
|
||||
adjfile.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.out.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||
adjfile.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
adjfile.write('\t\t</luminaire>\n')
|
||||
adjfile.write('\t</shape>\n')
|
||||
self.out.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
self.out.write('\t\t</luminaire>\n')
|
||||
self.out.write('\t</shape>\n')
|
||||
objFile = open(path, 'w')
|
||||
objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2))
|
||||
objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2))
|
||||
|
@ -80,52 +83,53 @@ class MtsAdjustments:
|
|||
objFile.write('f 4 3 2 1\n')
|
||||
objFile.close()
|
||||
elif ltype == 'SUN':
|
||||
adjfile.write('\t<luminaire id="%s-light" type="directional">\n' % lamp.data.name)
|
||||
self.out.write('\t<luminaire id="%s-light" type="directional">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
|
||||
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.exportWorldtrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
self.out.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
adjfile.write('\t</luminaire>\n')
|
||||
self.out.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
self.out.write('\t</luminaire>\n')
|
||||
elif ltype == 'SPOT':
|
||||
adjfile.write('\t<luminaire id="%s-light" type="spot">\n' % lamp.data.name)
|
||||
self.out.write('\t<luminaire id="%s-light" type="spot">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.exportWorldtrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
self.out.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||
adjfile.write('\t\t<float name="cutoffAngle" value="%f"/>\n' % (lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||
adjfile.write('\t\t<float name="beamWidth" value="%f"/>\n' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
adjfile.write('\t</luminaire>\n')
|
||||
self.out.write('\t\t<float name="cutoffAngle" value="%f"/>\n' % (lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||
self.out.write('\t\t<float name="beamWidth" value="%f"/>\n' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||
self.out.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
self.out.write('\t</luminaire>\n')
|
||||
elif ltype == 'ENV':
|
||||
if lamp.data.mitsuba_lamp.envmap_type == 'constant':
|
||||
adjfile.write('\t<luminaire id="%s-light" type="constant">\n' % lamp.data.name)
|
||||
self.out.write('\t<luminaire id="%s-light" type="constant">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.out.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
adjfile.write('\t</luminaire>\n')
|
||||
self.out.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.samplingWeight)
|
||||
self.out.write('\t</luminaire>\n')
|
||||
elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
|
||||
adjfile.write('\t<luminaire id="%s-light" type="envmap">\n' % lamp.data.name)
|
||||
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file))
|
||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||
adjfile.write('\t\t<float name="intensityScale" value="%f"/>\n' % lamp.data.mitsuba_lamp.intensity)
|
||||
adjfile.write('\t</luminaire>\n')
|
||||
self.out.write('\t<luminaire id="%s-light" type="envmap">\n' % name)
|
||||
self.out.write('\t\t<string name="filename" value="%s"/>\n' % efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file))
|
||||
self.exportWorldtrafo(lamp.matrix_world)
|
||||
self.out.write('\t\t<float name="intensityScale" value="%f"/>\n' % lamp.data.mitsuba_lamp.intensity)
|
||||
self.out.write('\t</luminaire>\n')
|
||||
|
||||
def find_texture(self, name):
|
||||
if name in bpy.data.textures:
|
||||
return bpy.data.textures[name]
|
||||
def findTexture(self, name):
|
||||
if name in self.textures:
|
||||
return self.textures[name]
|
||||
else:
|
||||
raise Exception('Failed to find texture "%s"' % name)
|
||||
|
||||
def find_material(self, name):
|
||||
if name in bpy.data.materials:
|
||||
return bpy.data.materials[name]
|
||||
|
||||
def findMaterial(self, name):
|
||||
if name in self.materials:
|
||||
return self.materials[name]
|
||||
else:
|
||||
raise Exception('Failed to find material "%s"' % name)
|
||||
|
||||
def export_texture(self, adjfile, mat):
|
||||
def export_texture(self, mat):
|
||||
if mat.name in self.exported_textures:
|
||||
return
|
||||
self.exported_textures += [mat.name]
|
||||
|
@ -133,14 +137,14 @@ class MtsAdjustments:
|
|||
|
||||
for p in params:
|
||||
if p.type == 'reference_texture':
|
||||
self.export_texture(adjfile, self.find_texture(p.value))
|
||||
self.export_texture(self.findTexture(p.value))
|
||||
|
||||
adjfile.write('\t<texture id="%s" type="%s">\n' % (translate_id(mat.name), mat.mitsuba_texture.type))
|
||||
adjfile.write(params.to_string())
|
||||
adjfile.write(params.to_string_ref())
|
||||
adjfile.write('\t</texture>\n')
|
||||
self.out.write('\t<texture id="%s" type="%s">\n' % (translate_id(mat.name), mat.mitsuba_texture.type))
|
||||
self.out.write(params.to_string())
|
||||
self.out.write(params.to_string_ref())
|
||||
self.out.write('\t</texture>\n')
|
||||
|
||||
def export_material(self, adjfile, mat):
|
||||
def exportMaterial(self, mat):
|
||||
if mat.name in self.exported_materials:
|
||||
return
|
||||
self.exported_materials += [mat.name]
|
||||
|
@ -148,44 +152,49 @@ class MtsAdjustments:
|
|||
|
||||
for p in params:
|
||||
if p.type == 'reference_material':
|
||||
self.export_material(adjfile, self.find_material(p.value))
|
||||
self.exportMaterial(self.findMaterial(p.value))
|
||||
elif p.type == 'reference_texture':
|
||||
self.export_texture(adjfile, self.find_texture(p.value))
|
||||
self.export_texture(self.findTexture(p.value))
|
||||
|
||||
adjfile.write('\t<bsdf id="%s" type="%s">\n' % (translate_id(mat.name), mat.mitsuba_material.type))
|
||||
adjfile.write(params.to_string())
|
||||
adjfile.write(params.to_string_ref())
|
||||
adjfile.write('\t</bsdf>\n')
|
||||
self.out.write('\t<bsdf id="%s" type="%s">\n' % (translate_id(mat.name), mat.mitsuba_material.type))
|
||||
self.out.write(params.to_string())
|
||||
self.out.write(params.to_string_ref())
|
||||
self.out.write('\t</bsdf>\n')
|
||||
|
||||
def export_emission(self, adjfile, obj):
|
||||
def exportEmission(self, obj):
|
||||
lamp = obj.data.materials[0].mitsuba_emission
|
||||
name = translate_id(obj.data.name)
|
||||
adjfile.write('\t<shape id="%s-mesh_0" type="serialized">\n' % name)
|
||||
adjfile.write('\t\t<string name="filename" value="meshes/%s-mesh_0.serialized"/>\n' % name)
|
||||
self.export_worldtrafo(adjfile, obj.matrix_world)
|
||||
adjfile.write('\t\t<luminaire type="area">\n')
|
||||
self.out.write('\t<shape id="%s-mesh_0" type="serialized">\n' % name)
|
||||
self.out.write('\t\t<string name="filename" value="meshes/%s-mesh_0.serialized"/>\n' % name)
|
||||
self.exportWorldtrafo(obj.matrix_world)
|
||||
self.out.write('\t\t<luminaire type="area">\n')
|
||||
mult = lamp.intensity
|
||||
adjfile.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
self.out.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.color.r*mult, lamp.color.g*mult, lamp.color.b*mult))
|
||||
adjfile.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.samplingWeight)
|
||||
adjfile.write('\t\t</luminaire>\n')
|
||||
adjfile.write('\t</shape>\n')
|
||||
self.out.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.samplingWeight)
|
||||
self.out.write('\t\t</luminaire>\n')
|
||||
self.out.write('\t</shape>\n')
|
||||
|
||||
def writeHeader(self):
|
||||
self.out = open(self.target_file, 'w')
|
||||
self.out.write('<scene>\n');
|
||||
|
||||
def writeFooter(self):
|
||||
self.out.write('</scene>\n');
|
||||
self.out.close()
|
||||
|
||||
def export(self, scene):
|
||||
adjfile = open(self.target_file, 'w')
|
||||
adjfile.write('<adjustments>\n');
|
||||
idx = 0
|
||||
self.writeHeader()
|
||||
for obj in scene.objects:
|
||||
if obj.type == 'LAMP':
|
||||
self.export_lamp(adjfile, obj, idx)
|
||||
self.exportLamp(obj, idx)
|
||||
elif obj.type == 'MESH':
|
||||
for mat in obj.data.materials:
|
||||
self.export_material(adjfile, mat)
|
||||
self.exportMaterial(mat)
|
||||
if len(obj.data.materials) > 0 and obj.data.materials[0].mitsuba_emission.use_emission:
|
||||
self.export_emission(adjfile, obj)
|
||||
self.exportEmission(obj)
|
||||
idx = idx+1
|
||||
adjfile.write('</adjustments>\n');
|
||||
adjfile.close()
|
||||
|
||||
self.writeFooter()
|
||||
|
||||
|
||||
|
|
|
@ -147,8 +147,6 @@ class EXPORT_OT_mitsuba(bpy.types.Operator):
|
|||
# Force scene update; NB, scene.update() doesn't work
|
||||
scene.frame_set(scene.frame_current)
|
||||
|
||||
(self.properties.filename, _) = os.path.splitext(self.properties.filename)
|
||||
|
||||
mts_basename = os.path.join(
|
||||
self.properties.directory,
|
||||
self.properties.filename)
|
||||
|
@ -251,7 +249,10 @@ class MITSUBA_OT_material_add(bpy.types.Operator):
|
|||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
index = obj.active_material_index
|
||||
curName = obj.material_slots[index].name
|
||||
if len(obj.material_slots) == 0:
|
||||
curName = 'Material'
|
||||
else:
|
||||
curName = obj.material_slots[index].name
|
||||
mat = bpy.data.materials.new(name=curName)
|
||||
obj.data.materials.append(mat)
|
||||
obj.active_material_index = len(obj.data.materials)-1
|
||||
|
|
Loading…
Reference in New Issue