MtsBlend: general improvements

metadata
Wenzel Jakob 2010-11-17 00:39:09 +01:00
parent df1a3fc3ba
commit 7a7c615b5f
4 changed files with 145 additions and 80 deletions

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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