merge with the media-0.2.1 branch (contains a completely redesigned medium rendering layer, fixes the Blender plugin and contains many other bugfixes)
commit
8573a9b28c
|
@ -18,27 +18,33 @@
|
|||
|
||||
import os
|
||||
|
||||
bl_addon_info = {
|
||||
bl_info = {
|
||||
"name": "Mitsuba",
|
||||
"author": "Wenzel Jakob",
|
||||
"version": (0, 1),
|
||||
"blender": (2, 5, 5),
|
||||
"api": 31667,
|
||||
"version": (0, 2, 1),
|
||||
"blender": (2, 5, 6),
|
||||
"api": 35669,
|
||||
"category": "Render",
|
||||
"location": "Render > Engine > Mitsuba",
|
||||
"description": "Basic Mitsuba integration for Blender",
|
||||
"warning": "",
|
||||
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
|
||||
"Scripts/Render/Mitsuba",
|
||||
"tracker_url": "https://www.mitsuba-renderer.org/bugtracker/projects/mitsuba",
|
||||
"category": "Render"}
|
||||
"tracker_url": "https://www.mitsuba-renderer.org/bugtracker/projects/mitsuba"}
|
||||
|
||||
def plugin_path():
|
||||
return os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
from .core import RENDERENGINE_mitsuba
|
||||
if 'core' in locals():
|
||||
import imp
|
||||
imp.reload(core)
|
||||
else:
|
||||
import bpy
|
||||
|
||||
from extensions_framework import Addon
|
||||
MitsubaAddon = Addon(bl_info)
|
||||
register, unregister = MitsubaAddon.init_functions()
|
||||
|
||||
def register():
|
||||
RENDERENGINE_mitsuba.install()
|
||||
|
||||
def unregister():
|
||||
RENDERENGINE_mitsuba.uninstall()
|
||||
# Importing the core package causes extensions_framework managed
|
||||
# RNA class registration via @MitsubaAddon.addon_register_class
|
||||
from . import core
|
||||
|
|
|
@ -17,98 +17,149 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# System libs
|
||||
import os, time, threading, subprocess, sys, copy
|
||||
import os, time, threading, sys, copy, subprocess
|
||||
|
||||
# Blender libs
|
||||
import bpy
|
||||
import bpy, bl_ui, time
|
||||
|
||||
# Framework libs
|
||||
from extensions_framework.engine import engine_base
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
# Mitsuba-related classes
|
||||
from mitsuba import plugin_path
|
||||
from mitsuba.properties.engine import mitsuba_engine
|
||||
from mitsuba.properties.sampler import mitsuba_sampler
|
||||
from mitsuba.properties.integrator import mitsuba_integrator
|
||||
from mitsuba.properties.lamp import mitsuba_lamp
|
||||
from mitsuba.properties.texture import mitsuba_texture, \
|
||||
mitsuba_tex_ldrtexture, mitsuba_tex_checkerboard, \
|
||||
mitsuba_tex_gridtexture, mitsuba_tex_mapping
|
||||
from mitsuba.properties.material import mitsuba_material, \
|
||||
mitsuba_mat_lambertian, mitsuba_mat_phong, mitsuba_mat_ward, \
|
||||
mitsuba_mat_microfacet, mitsuba_mat_roughglass, \
|
||||
mitsuba_mat_roughmetal, mitsuba_mat_dielectric, \
|
||||
mitsuba_mat_mirror, mitsuba_mat_difftrans, \
|
||||
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 import translate_id
|
||||
from mitsuba.export.film import resolution
|
||||
from mitsuba.export import get_instance_materials
|
||||
from mitsuba.ui import render_panels, lamps
|
||||
from mitsuba.ui.textures import TEXTURE_PT_context_texture_mts
|
||||
from mitsuba.ui.textures import main, ldrtexture, checkerboard, \
|
||||
gridtexture, mapping
|
||||
from mitsuba.ui.materials import MATERIAL_PT_context_material_mts
|
||||
from mitsuba.ui.materials import main, lambertian, phong, ward, \
|
||||
microfacet, roughglass, roughmetal, dielectric, \
|
||||
mirror, difftrans, composite, emission
|
||||
from .. import MitsubaAddon, plugin_path
|
||||
|
||||
from ..outputs import MtsLog, MtsFilmDisplay
|
||||
from ..export import (get_instance_materials,
|
||||
resolution, MtsLaunch, MtsExporter)
|
||||
|
||||
from ..properties import (
|
||||
engine, sampler, integrator, lamp, texture,
|
||||
material, mesh, camera, world
|
||||
);
|
||||
|
||||
from ..ui import (
|
||||
render_panels, lamps, materials, mesh,
|
||||
camera, world
|
||||
)
|
||||
|
||||
from ..ui.textures import (
|
||||
main, ldrtexture, checkerboard, gridtexture, mapping
|
||||
)
|
||||
|
||||
from ..ui.materials import (
|
||||
main, lambertian, phong, ward, microfacet, roughglass,
|
||||
roughmetal, dielectric, mirror, difftrans, composite,
|
||||
emission
|
||||
)
|
||||
|
||||
from .. import operators
|
||||
|
||||
def compatible(mod):
|
||||
mod = __import__(mod)
|
||||
mod = getattr(bl_ui, mod)
|
||||
for subclass in mod.__dict__.values():
|
||||
try:
|
||||
subclass.COMPAT_ENGINES.add('mitsuba')
|
||||
subclass.COMPAT_ENGINES.add(MitsubaAddon.BL_IDNAME)
|
||||
except:
|
||||
pass
|
||||
del mod
|
||||
|
||||
import properties_data_lamp
|
||||
properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('mitsuba')
|
||||
del properties_data_lamp
|
||||
|
||||
import properties_render
|
||||
properties_render.RENDER_PT_render.COMPAT_ENGINES.add('mitsuba')
|
||||
properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('mitsuba')
|
||||
properties_render.RENDER_PT_output.COMPAT_ENGINES.add('mitsuba')
|
||||
del properties_render
|
||||
bl_ui.properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add(MitsubaAddon.BL_IDNAME)
|
||||
bl_ui.properties_render.RENDER_PT_render.COMPAT_ENGINES.add(MitsubaAddon.BL_IDNAME)
|
||||
bl_ui.properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add(MitsubaAddon.BL_IDNAME)
|
||||
bl_ui.properties_render.RENDER_PT_output.COMPAT_ENGINES.add(MitsubaAddon.BL_IDNAME)
|
||||
|
||||
compatible("properties_data_mesh")
|
||||
compatible("properties_data_camera")
|
||||
compatible("properties_particle")
|
||||
|
||||
class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||
bl_idname = 'mitsuba'
|
||||
@MitsubaAddon.addon_register_class
|
||||
class RENDERENGINE_mitsuba(bpy.types.RenderEngine):
|
||||
bl_idname = MitsubaAddon.BL_IDNAME
|
||||
bl_label = 'Mitsuba'
|
||||
bl_use_preview = True
|
||||
|
||||
property_groups = [
|
||||
('Scene', mitsuba_engine),
|
||||
('Scene', mitsuba_integrator),
|
||||
('Scene', mitsuba_sampler),
|
||||
('Lamp', mitsuba_lamp),
|
||||
('Texture', mitsuba_texture),
|
||||
('mitsuba_texture', mitsuba_tex_ldrtexture),
|
||||
('mitsuba_texture', mitsuba_tex_checkerboard),
|
||||
('mitsuba_texture', mitsuba_tex_gridtexture),
|
||||
('mitsuba_texture', mitsuba_tex_mapping),
|
||||
('Material', mitsuba_material),
|
||||
('Material', mitsuba_emission),
|
||||
('mitsuba_material', mitsuba_mat_lambertian),
|
||||
('mitsuba_material', mitsuba_mat_phong),
|
||||
('mitsuba_material', mitsuba_mat_ward),
|
||||
('mitsuba_material', mitsuba_mat_microfacet),
|
||||
('mitsuba_material', mitsuba_mat_roughglass),
|
||||
('mitsuba_material', mitsuba_mat_roughmetal),
|
||||
('mitsuba_material', mitsuba_mat_dielectric),
|
||||
('mitsuba_material', mitsuba_mat_difftrans),
|
||||
('mitsuba_material', mitsuba_mat_mirror),
|
||||
('mitsuba_material', mitsuba_mat_composite)
|
||||
]
|
||||
|
||||
render_lock = threading.Lock()
|
||||
|
||||
def render(self, scene):
|
||||
if self is None or scene is None:
|
||||
MtsLog('ERROR: Scene is missing!')
|
||||
return
|
||||
if scene.mitsuba_engine.binary_path == '':
|
||||
MtsLog('ERROR: The binary path is unspecified!')
|
||||
return
|
||||
|
||||
with self.render_lock: # just render one thing at a time
|
||||
if scene.name == 'preview':
|
||||
self.render_preview(scene)
|
||||
return
|
||||
|
||||
config_updates = {}
|
||||
binary_path = os.path.abspath(efutil.filesystem_path(scene.mitsuba_engine.binary_path))
|
||||
if os.path.isdir(binary_path) and os.path.exists(binary_path):
|
||||
config_updates['binary_path'] = binary_path
|
||||
|
||||
try:
|
||||
for k, v in config_updates.items():
|
||||
efutil.write_config_value('mitsuba', 'defaults', k, v)
|
||||
except Exception as err:
|
||||
MtsLog('WARNING: Saving Mitsuba configuration failed, please set your user scripts dir: %s' % err)
|
||||
|
||||
scene_path = efutil.filesystem_path(scene.render.filepath)
|
||||
if os.path.isdir(scene_path):
|
||||
output_dir = scene_path
|
||||
else:
|
||||
output_dir = os.path.dirname(scene_path)
|
||||
|
||||
if scene.render.use_color_management == False:
|
||||
MtsLog('WARNING: Color Management is switched off, render results may look too dark.')
|
||||
|
||||
MtsLog('MtsBlend: Current directory = "%s"' % output_dir)
|
||||
output_basename = efutil.scene_filename() + '.%s.%05i' % (scene.name, scene.frame_current)
|
||||
|
||||
result = MtsExporter(
|
||||
directory = output_dir,
|
||||
filename = output_basename,
|
||||
).export(scene)
|
||||
|
||||
if not result:
|
||||
MtsLog('Error while exporting -- check the console for details.')
|
||||
return
|
||||
|
||||
if scene.mitsuba_engine.export_mode == 'render':
|
||||
|
||||
MtsLog("MtsBlend: Launching renderer ..")
|
||||
if scene.mitsuba_engine.render_mode == 'gui':
|
||||
MtsLaunch(scene.mitsuba_engine.binary_path, output_dir,
|
||||
['mtsgui', efutil.export_path])
|
||||
elif scene.mitsuba_engine.render_mode == 'cli':
|
||||
output_file = efutil.export_path[:-4] + ".png"
|
||||
mitsuba_process = MtsLaunch(scene.mitsuba_engine.binary_path, output_dir,
|
||||
['mitsuba', '-r', str(scene.mitsuba_engine.refresh_interval),
|
||||
'-o', output_file, efutil.export_path]
|
||||
)
|
||||
framebuffer_thread = MtsFilmDisplay()
|
||||
framebuffer_thread.set_kick_period(scene.mitsuba_engine.refresh_interval)
|
||||
framebuffer_thread.begin(self, output_file, resolution(scene))
|
||||
render_update_timer = None
|
||||
while mitsuba_process.poll() == None and not self.test_break():
|
||||
render_update_timer = threading.Timer(1, self.process_wait_timer)
|
||||
render_update_timer.start()
|
||||
if render_update_timer.isAlive(): render_update_timer.join()
|
||||
|
||||
# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
|
||||
if mitsuba_process.poll() == None:
|
||||
# Use SIGTERM because that's the only one supported on Windows
|
||||
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
||||
|
||||
# Stop updating the render result and load the final image
|
||||
framebuffer_thread.stop()
|
||||
framebuffer_thread.join()
|
||||
|
||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||
else:
|
||||
framebuffer_thread.kick(render_end=True)
|
||||
framebuffer_thread.shutdown()
|
||||
|
||||
def process_wait_timer(self):
|
||||
# Nothing to do here
|
||||
pass
|
||||
|
@ -116,8 +167,9 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
def render_preview(self, scene):
|
||||
# Iterate through the preview scene, finding objects with materials attached
|
||||
objects_materials = {}
|
||||
(width, height) = resolution(scene)
|
||||
|
||||
if resolution(scene) == (96, 96):
|
||||
if (width, height) == (96, 96):
|
||||
return
|
||||
|
||||
for object in [ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render]:
|
||||
|
@ -137,157 +189,60 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
return
|
||||
|
||||
tempdir = efutil.temp_directory()
|
||||
matfile = os.path.join(tempdir, "matpreview_materials.xml")
|
||||
matfile = "matpreview_materials.xml"
|
||||
output_file = os.path.join(tempdir, "matpreview.png")
|
||||
scene_file = os.path.join(os.path.join(plugin_path(),
|
||||
"matpreview"), "matpreview.xml")
|
||||
pm = likely_materials[0]
|
||||
adj = MtsAdjustments(matfile, tempdir,
|
||||
exporter = MtsExporter(tempdir, matfile,
|
||||
bpy.data.materials, bpy.data.textures)
|
||||
adj.writeHeader()
|
||||
adj.exportMaterial(pm)
|
||||
adj.exportPreviewMesh(pm)
|
||||
adj.writeFooter()
|
||||
mts_path = scene.mitsuba_engine.binary_path
|
||||
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||||
env = copy.copy(os.environ)
|
||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||||
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||||
mts_bidir_libpath = os.path.join(mts_path, "src/libbidir")
|
||||
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath + ":" + mts_bidir_libpath
|
||||
(width, height) = resolution(scene)
|
||||
exporter.adj_filename = os.path.join(tempdir, matfile)
|
||||
if not exporter.writeHeader():
|
||||
MtsLog('Error while exporting -- check the console for details.')
|
||||
return;
|
||||
exporter.exportMaterial(pm)
|
||||
exporter.exportPreviewMesh(scene, pm)
|
||||
exporter.writeFooter()
|
||||
refresh_interval = 1
|
||||
preview_spp = int(efutil.find_config_value('mitsuba', 'defaults', 'preview_spp', '16'))
|
||||
preview_depth = int(efutil.find_config_value('mitsuba', 'defaults', 'preview_depth', '2'))
|
||||
mitsuba_process = subprocess.Popen(
|
||||
[mitsuba_binary, '-q',
|
||||
|
||||
mitsuba_process = MtsLaunch(scene.mitsuba_engine.binary_path, tempdir,
|
||||
['mitsuba', '-q',
|
||||
'-r%i' % refresh_interval,
|
||||
'-o', output_file, '-Dmatfile=%s' % matfile,
|
||||
'-b16',
|
||||
'-o', output_file, '-Dmatfile=%s' % os.path.join(tempdir, matfile),
|
||||
'-Dwidth=%i' % width,
|
||||
'-Dheight=%i' % height,
|
||||
'-Dspp=%i' % preview_spp,
|
||||
'-Ddepth=%i' % preview_depth,
|
||||
'-o', output_file, scene_file],
|
||||
env = env,
|
||||
cwd = mts_path
|
||||
)
|
||||
framebuffer_thread = MtsFilmDisplay({
|
||||
'resolution': resolution(scene),
|
||||
'RE': self,
|
||||
'output_file': output_file
|
||||
})
|
||||
'-o', output_file, scene_file])
|
||||
|
||||
framebuffer_thread = MtsFilmDisplay()
|
||||
framebuffer_thread.set_kick_period(refresh_interval)
|
||||
framebuffer_thread.start()
|
||||
framebuffer_thread.begin(self, output_file, resolution(scene), preview=True)
|
||||
render_update_timer = None
|
||||
while mitsuba_process.poll() == None and not self.test_break():
|
||||
render_update_timer = threading.Timer(1, self.process_wait_timer)
|
||||
render_update_timer.start()
|
||||
if render_update_timer.isAlive(): render_update_timer.join()
|
||||
|
||||
cancelled = False
|
||||
# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
|
||||
if mitsuba_process.poll() == None:
|
||||
MtsLog("MtsBlend: Terminating process..")
|
||||
# Use SIGTERM because that's the only one supported on Windows
|
||||
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
||||
cancelled = True
|
||||
|
||||
# Stop updating the render result and load the final image
|
||||
framebuffer_thread.stop()
|
||||
framebuffer_thread.join()
|
||||
|
||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||
else:
|
||||
framebuffer_thread.kick(render_end=True)
|
||||
|
||||
|
||||
def render(self, scene):
|
||||
if scene is None:
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text='Scene to render is not valid')
|
||||
return
|
||||
if scene.mitsuba_engine.binary_path == '':
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text='The Mitsuba binary path is unspecified!')
|
||||
return
|
||||
|
||||
with self.render_lock: # just render one thing at a time
|
||||
if scene.name == 'preview':
|
||||
self.render_preview(scene)
|
||||
return
|
||||
|
||||
scene_path = efutil.filesystem_path(scene.render.filepath)
|
||||
if os.path.isdir(scene_path):
|
||||
output_dir = scene_path
|
||||
if not cancelled:
|
||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||
else:
|
||||
output_dir = os.path.dirname(scene_path)
|
||||
if output_dir[-1] != '/':
|
||||
output_dir += '/'
|
||||
efutil.export_path = output_dir
|
||||
os.chdir(output_dir)
|
||||
framebuffer_thread.kick(render_end=True)
|
||||
framebuffer_thread.shutdown()
|
||||
|
||||
if scene.render.use_color_management == False:
|
||||
MtsLog('WARNING: Colour Management is switched off, render results may look too dark.')
|
||||
|
||||
MtsLog('MtsBlend: Current directory = "%s"' % output_dir)
|
||||
output_basename = efutil.scene_filename() + '.%s.%05i' % (scene.name, scene.frame_current)
|
||||
|
||||
export_result = bpy.ops.export.mitsuba(
|
||||
directory = output_dir,
|
||||
filename = output_basename,
|
||||
scene = scene.name
|
||||
)
|
||||
if 'CANCELLED' in export_result:
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text='Error while exporting -- check the console for details.')
|
||||
return
|
||||
|
||||
if scene.mitsuba_engine.export_mode == 'render':
|
||||
mts_path = scene.mitsuba_engine.binary_path
|
||||
mtsgui_binary = os.path.join(mts_path, "mtsgui")
|
||||
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||||
env = copy.copy(os.environ)
|
||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||||
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||||
mts_bidir_libpath = os.path.join(mts_path, "src/libbidir")
|
||||
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath + ":" + mts_bidir_libpath
|
||||
|
||||
MtsLog("MtsBlend: Launching renderer ..")
|
||||
if scene.mitsuba_engine.render_mode == 'gui':
|
||||
subprocess.Popen(
|
||||
[mtsgui_binary, efutil.export_path],
|
||||
env = env,
|
||||
cwd = mts_path
|
||||
)
|
||||
elif scene.mitsuba_engine.render_mode == 'cli':
|
||||
output_file = efutil.export_path[:-4] + ".png"
|
||||
mitsuba_process = subprocess.Popen(
|
||||
[mitsuba_binary, '-r', '%d' % scene.mitsuba_engine.refresh_interval,
|
||||
'-o', output_file, efutil.export_path],
|
||||
env = env,
|
||||
cwd = mts_path
|
||||
)
|
||||
framebuffer_thread = MtsFilmDisplay({
|
||||
'resolution': resolution(scene),
|
||||
'RE': self,
|
||||
'output_file': output_file
|
||||
})
|
||||
framebuffer_thread.set_kick_period(scene.mitsuba_engine.refresh_interval)
|
||||
framebuffer_thread.start()
|
||||
render_update_timer = None
|
||||
while mitsuba_process.poll() == None and not self.test_break():
|
||||
render_update_timer = threading.Timer(1, self.process_wait_timer)
|
||||
render_update_timer.start()
|
||||
if render_update_timer.isAlive(): render_update_timer.join()
|
||||
|
||||
# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
|
||||
if mitsuba_process.poll() == None:
|
||||
# Use SIGTERM because that's the only one supported on Windows
|
||||
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
||||
|
||||
# Stop updating the render result and load the final image
|
||||
framebuffer_thread.stop()
|
||||
framebuffer_thread.join()
|
||||
|
||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text='Rendering failed -- check the console.')
|
||||
else:
|
||||
framebuffer_thread.kick(render_end=True)
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import os
|
||||
import bpy, os, copy, subprocess, math, mathutils
|
||||
from extensions_framework import util as efutil
|
||||
from ..outputs import MtsLog
|
||||
|
||||
# From collada_internal.cpp
|
||||
|
||||
|
@ -110,27 +112,23 @@ class ParamSetItem(list):
|
|||
self.append(self.type_name)
|
||||
self.append(self.value)
|
||||
|
||||
def to_string(self):
|
||||
def export(self, exporter):
|
||||
if self.type == "color":
|
||||
return '\t\t<rgb name="%s" value="%s %s %s"/>\n' % (self.name,
|
||||
self.value[0], self.value[1], self.value[2])
|
||||
exporter.parameter('rgb', self.name,
|
||||
{ 'value' : "%s %s %s" % (self.value[0], self.value[1], self.value[2])})
|
||||
elif self.type == "point" or self.type == "vector":
|
||||
return '\t\t<%s name="%s" value="%s %s %s"/>\n' % (self.type,
|
||||
self.name, self.value[0], self.value[1], self.value[2])
|
||||
exporter.parameter(self.type, self.name,
|
||||
{ 'value' : "%s %s %s" % (self.value[0], self.value[1], self.value[2])})
|
||||
elif self.type == "integer" or self.type == "float" \
|
||||
or self.type == "string":
|
||||
return '\t\t<%s name="%s" value="%s"/>\n' % (self.type, self.name, self.value)
|
||||
else:
|
||||
return ""
|
||||
exporter.parameter(self.type, self.name, { 'value' : "%s" % self.value })
|
||||
|
||||
def to_string_ref(self):
|
||||
if self.type == "reference_texture" or self.type == "reference_material":
|
||||
if self.name == "":
|
||||
return '\t\t<ref id="%s"/>\n' % translate_id(self.value)
|
||||
def export_ref(self, exporter):
|
||||
if self.type == "reference_texture" or self.type == "reference_material" or self.type == 'reference_medium':
|
||||
if self.name != "":
|
||||
exporter.element('ref', {'id' : translate_id(self.value), 'name' : self.name})
|
||||
else:
|
||||
return '\t\t<ref name="%s" id="%s"/>\n' % (self.name, translate_id(self.value))
|
||||
else:
|
||||
return ""
|
||||
exporter.element('ref', {'id' : translate_id(self.value)})
|
||||
|
||||
class ParamSet(list):
|
||||
names = []
|
||||
|
@ -184,12 +182,12 @@ class ParamSet(list):
|
|||
self.add('color', name, [c for c in value])
|
||||
return self
|
||||
|
||||
def to_string(self):
|
||||
return ''.join(item.to_string() for item in self)
|
||||
|
||||
def to_string_ref(self):
|
||||
return ''.join(item.to_string_ref() for item in self)
|
||||
|
||||
def export(self, exporter):
|
||||
for item in self:
|
||||
item.export(exporter)
|
||||
for item in self:
|
||||
item.export_ref(exporter)
|
||||
|
||||
def get_instance_materials(ob):
|
||||
obmats = []
|
||||
# Grab materials attached to object instances ...
|
||||
|
@ -201,3 +199,413 @@ def get_instance_materials(ob):
|
|||
for m in ob.data.materials:
|
||||
obmats.append(m)
|
||||
return obmats
|
||||
|
||||
def resolution(scene):
|
||||
'''
|
||||
scene bpy.types.scene
|
||||
Calculate the output render resolution
|
||||
Returns tuple(2) (floats)
|
||||
'''
|
||||
xr = scene.render.resolution_x * scene.render.resolution_percentage / 100.0
|
||||
yr = scene.render.resolution_y * scene.render.resolution_percentage / 100.0
|
||||
|
||||
return xr, yr
|
||||
|
||||
def MtsLaunch(mts_path, path, commandline):
|
||||
env = copy.copy(os.environ)
|
||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||||
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||||
mts_bidir_libpath = os.path.join(mts_path, "src/libbidir")
|
||||
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath + ":" + mts_bidir_libpath
|
||||
commandline[0] = os.path.join(mts_path, commandline[0])
|
||||
return subprocess.Popen(commandline, env = env, cwd = path)
|
||||
|
||||
class MtsExporter:
|
||||
'''
|
||||
Exports the scene using COLLADA and write additional information
|
||||
to an "adjustments" file. Thim mechanism is used to capture
|
||||
any information that gets lost in translation when using the
|
||||
Blender COLLADA exporter.
|
||||
'''
|
||||
|
||||
def __init__(self, directory, filename, materials = None, textures = None):
|
||||
mts_basename = os.path.join(directory, filename)
|
||||
(path, ext) = os.path.splitext(mts_basename)
|
||||
if ext == '.xml':
|
||||
mts_basename = path
|
||||
self.dae_filename = mts_basename + ".dae"
|
||||
self.xml_filename = mts_basename + ".xml"
|
||||
self.adj_filename = mts_basename + "_adjustments.xml"
|
||||
self.meshes_dir = os.path.join(directory, "meshes")
|
||||
self.exported_materials = []
|
||||
self.exported_textures = []
|
||||
self.exported_media = []
|
||||
self.materials = materials if materials != None else bpy.data.materials
|
||||
self.textures = textures if textures != None else bpy.data.textures
|
||||
self.indent = 0
|
||||
self.stack = []
|
||||
if directory[-1] != '/':
|
||||
directory += '/'
|
||||
self.output_directory = directory
|
||||
efutil.export_path = self.xml_filename
|
||||
|
||||
def writeHeader(self):
|
||||
try:
|
||||
self.out = open(self.adj_filename, 'w')
|
||||
except IOError:
|
||||
MtsLog('Error: unable to write to file \"%s\"!' % self.adj_filename)
|
||||
return False
|
||||
self.out.write('<?xml version="1.0" encoding="utf-8"?>\n');
|
||||
self.openElement('scene')
|
||||
return True
|
||||
|
||||
def writeFooter(self):
|
||||
self.closeElement()
|
||||
self.out.close()
|
||||
|
||||
def openElement(self, name, attributes = {}):
|
||||
self.out.write('\t' * self.indent + '<%s' % name)
|
||||
for (k, v) in attributes.items():
|
||||
self.out.write(' %s=\"%s\"' % (k, v))
|
||||
self.out.write('>\n')
|
||||
self.indent = self.indent+1
|
||||
self.stack.append(name)
|
||||
|
||||
def closeElement(self):
|
||||
self.indent = self.indent-1
|
||||
name = self.stack.pop()
|
||||
self.out.write('\t' * self.indent + '</%s>\n' % name)
|
||||
|
||||
def element(self, name, attributes = {}):
|
||||
self.out.write('\t' * self.indent + '<%s' % name)
|
||||
for (k, v) in attributes.items():
|
||||
self.out.write(' %s=\"%s\"' % (k, v))
|
||||
self.out.write('/>\n')
|
||||
|
||||
def parameter(self, paramType, paramName, attributes = {}):
|
||||
self.out.write('\t' * self.indent + '<%s name="%s"' % (paramType, paramName))
|
||||
for (k, v) in attributes.items():
|
||||
self.out.write(' %s=\"%s\"' % (k, v))
|
||||
self.out.write('/>\n')
|
||||
|
||||
def exportWorldTrafo(self, trafo):
|
||||
self.openElement('transform', {'name' : 'toWorld'})
|
||||
value = ""
|
||||
for j in range(0,4):
|
||||
for i in range(0,4):
|
||||
value += "%f " % trafo[i][j]
|
||||
self.element('matrix', {'value' : value})
|
||||
self.closeElement()
|
||||
|
||||
def exportLamp(self, scene, lamp, idx):
|
||||
ltype = lamp.data.type
|
||||
name = translate_id(lamp.data.name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
if lamp.data.mitsuba_lamp.inside_medium:
|
||||
self.exportMedium(scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
|
||||
if ltype == 'POINT':
|
||||
self.openElement('luminaire', { 'type' : 'point', 'id' : '%s-light' % name })
|
||||
self.exportWorldTrafo(lamp.matrix_world)
|
||||
self.parameter('rgb', 'intensity', {'value' :
|
||||
"%f %f %f" % (lamp.data.color.r*mult, lamp.data.color.g*mult,
|
||||
lamp.data.color.b*mult)})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
|
||||
if lamp.data.mitsuba_lamp.inside_medium:
|
||||
self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
|
||||
self.closeElement()
|
||||
elif ltype == 'AREA':
|
||||
self.element('remove', { 'id' : '%s-light' % name})
|
||||
self.openElement('shape', { 'type' : 'obj'} )
|
||||
(size_x, size_y) = (lamp.data.size, lamp.data.size)
|
||||
if lamp.data.shape == 'RECTANGLE':
|
||||
size_y = lamp.data.size_y
|
||||
mult = mult / (2 * size_x * size_y)
|
||||
filename = "area_luminaire_%d.obj" % idx
|
||||
try:
|
||||
os.mkdir(self.meshes_dir)
|
||||
except OSError:
|
||||
pass
|
||||
self.parameter('string', 'filename', { 'value' : 'meshes/%s' % filename})
|
||||
self.exportWorldTrafo(lamp.matrix_world)
|
||||
|
||||
self.openElement('luminaire', { 'id' : '%s-arealight' % name, 'type' : 'area'})
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
|
||||
self.closeElement()
|
||||
self.openElement('bsdf', { 'type' : 'lambertian'})
|
||||
self.parameter('spectrum', 'reflectance', {'value' : '0'})
|
||||
self.closeElement()
|
||||
self.closeElement()
|
||||
path = os.path.join(self.meshes_dir, filename)
|
||||
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))
|
||||
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))
|
||||
objFile.write('f 4 3 2 1\n')
|
||||
objFile.close()
|
||||
elif ltype == 'SUN':
|
||||
self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'directional'})
|
||||
scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
|
||||
self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
|
||||
self.closeElement()
|
||||
elif ltype == 'SPOT':
|
||||
self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'spot'})
|
||||
self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
|
||||
self.parameter('float', 'cutoffAngle', {'value' : '%f' % (lamp.data.spot_size * 180 / (math.pi * 2))})
|
||||
self.parameter('float', 'beamWidth', {'value' : '%f' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2))})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
|
||||
if lamp.data.mitsuba_lamp.inside_medium:
|
||||
self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
|
||||
self.closeElement()
|
||||
elif ltype == 'HEMI':
|
||||
if lamp.data.mitsuba_lamp.envmap_type == 'constant':
|
||||
self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'constant'})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
|
||||
self.closeElement()
|
||||
elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
|
||||
self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'envmap'})
|
||||
self.parameter('string', 'filename', {'value' : efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file)})
|
||||
self.exportWorldTrafo(lamp.matrix_world)
|
||||
self.parameter('float', 'intensityScale', {'value' : '%f' % lamp.data.mitsuba_lamp.intensity})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
|
||||
self.closeElement()
|
||||
|
||||
def exportIntegrator(self, integrator):
|
||||
self.openElement('integrator', { 'id' : 'integrator', 'type' : integrator.type})
|
||||
self.parameter('integer', 'maxDepth', { 'value' : str(integrator.maxdepth)})
|
||||
self.closeElement()
|
||||
|
||||
def exportSampler(self, sampler):
|
||||
self.openElement('sampler', { 'id' : 'sampler', 'type' : sampler.type})
|
||||
self.parameter('integer', 'sampleCount', { 'value' : '%i' % sampler.sampleCount})
|
||||
self.closeElement()
|
||||
|
||||
def findTexture(self, name):
|
||||
if name in self.textures:
|
||||
return self.textures[name]
|
||||
else:
|
||||
raise Exception('Failed to find texture "%s"' % name)
|
||||
|
||||
|
||||
def findMaterial(self, name):
|
||||
if name in self.materials:
|
||||
return self.materials[name]
|
||||
else:
|
||||
raise Exception('Failed to find material "%s" in "%s"' % (name,
|
||||
str(self.materials)))
|
||||
|
||||
def exportTexture(self, tex):
|
||||
if tex.name in self.exported_textures:
|
||||
return
|
||||
self.exported_textures += [tex.name]
|
||||
params = tex.mitsuba_texture.get_params()
|
||||
|
||||
for p in params:
|
||||
if p.type == 'reference_texture':
|
||||
self.exportTexture(self.findTexture(p.value))
|
||||
|
||||
self.openElement('texture', {'id' : '%s' % translate_id(tex.name), 'type' : tex.mitsuba_texture.type})
|
||||
params.export(self)
|
||||
self.closeElement()
|
||||
|
||||
def exportMaterial(self, mat):
|
||||
if not hasattr(mat, 'name') or mat.name in self.exported_materials:
|
||||
return
|
||||
self.exported_materials += [mat.name]
|
||||
mmat = mat.mitsuba_material
|
||||
if mmat.type == 'none':
|
||||
self.element('null', {'id' : '%s-material' % translate_id(mat.name)})
|
||||
return
|
||||
params = mmat.get_params()
|
||||
twosided = False
|
||||
|
||||
if mmat.twosided and mmat.type in ['lambertian', 'phong', 'ward',
|
||||
'mirror', 'roughmetal', 'microfacet', 'composite']:
|
||||
twosided = True
|
||||
|
||||
for p in params:
|
||||
if p.type == 'reference_material':
|
||||
self.exportMaterial(self.findMaterial(p.value))
|
||||
elif p.type == 'reference_texture':
|
||||
self.exportTexture(self.findTexture(p.value))
|
||||
|
||||
if twosided:
|
||||
self.openElement('bsdf', {'id' : '%s-material' % translate_id(mat.name), 'type' : 'twosided'})
|
||||
self.openElement('bsdf', {'type' : mmat.type})
|
||||
else:
|
||||
self.openElement('bsdf', {'id' : '%s-material' % translate_id(mat.name), 'type' : mmat.type})
|
||||
|
||||
params.export(self)
|
||||
self.closeElement()
|
||||
|
||||
if twosided:
|
||||
self.closeElement()
|
||||
|
||||
def exportEmission(self, obj):
|
||||
lamp = obj.data.materials[0].mitsuba_emission
|
||||
if obj.data.users > 1:
|
||||
MtsLog("Error: luminaires cannot be instantiated!")
|
||||
return
|
||||
mult = lamp.intensity
|
||||
name = translate_id(obj.data.name) + "-mesh_0"
|
||||
self.openElement('append', { 'id' : name})
|
||||
self.openElement('luminaire', { 'id' : '%s-emission' % name, 'type' : 'area'})
|
||||
self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.samplingWeight})
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.color.r*mult, lamp.color.g*mult, lamp.color.b*mult)})
|
||||
self.closeElement()
|
||||
self.closeElement()
|
||||
|
||||
def exportNormalMode(self, obj):
|
||||
mesh = obj.data.mitsuba_mesh
|
||||
name = translate_id(obj.data.name) + "-mesh_0"
|
||||
if mesh.normals == 'facenormals':
|
||||
self.openElement('append', { 'id' : name})
|
||||
self.parameter('boolean', 'faceNormals', {'value' : 'true'})
|
||||
self.closeElement()
|
||||
|
||||
def exportMediumReference(self, scene, obj, role, mediumName):
|
||||
if mediumName == "":
|
||||
return
|
||||
if obj.data.users > 1:
|
||||
MtsLog("Error: medium transitions cannot be instantiated (at least for now)!")
|
||||
return
|
||||
self.exportMedium(scene.mitsuba_media.media[mediumName])
|
||||
shapeName = translate_id(obj.data.name) + "-mesh_0"
|
||||
self.openElement('append', { 'id' : shapeName})
|
||||
if role == '':
|
||||
self.element('ref', { 'id' : mediumName})
|
||||
else:
|
||||
self.element('ref', { 'name' : role, 'id' : mediumName})
|
||||
self.closeElement()
|
||||
|
||||
def exportPreviewMesh(self, scene, material):
|
||||
mmat = material.mitsuba_material
|
||||
lamp = material.mitsuba_emission
|
||||
if mmat.is_medium_transition:
|
||||
mainScene = bpy.data.scenes[0]
|
||||
if mmat.interior_medium != '':
|
||||
self.exportMedium(mainScene.mitsuba_media.media[mmat.interior_medium])
|
||||
if mmat.exterior_medium != '':
|
||||
self.exportMedium(mainScene.mitsuba_media.media[mmat.exterior_medium])
|
||||
self.openElement('shape', {'id' : 'Exterior-mesh_0', 'type' : 'serialized'})
|
||||
self.parameter('string', 'filename', {'value' : 'matpreview.serialized'})
|
||||
self.parameter('integer', 'shapeIndex', {'value' : '1'})
|
||||
self.openElement('transform', {'name' : 'toWorld'})
|
||||
self.element('matrix', {'value' : '0.614046 0.614047 0 -1.78814e-07 -0.614047 0.614046 0 2.08616e-07 0 0 0.868393 1.02569 0 0 0 1'})
|
||||
self.element('translate', { 'z' : '0.01'})
|
||||
self.closeElement()
|
||||
if mmat.type != 'none':
|
||||
self.element('ref', {'name' : 'bsdf', 'id' : '%s-material' % translate_id(material.name)})
|
||||
if lamp and lamp.use_emission:
|
||||
mult = lamp.intensity
|
||||
self.openElement('luminaire', {'type' : 'area'})
|
||||
self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
|
||||
% (lamp.color.r*mult, lamp.color.g*mult, lamp.color.b*mult)})
|
||||
self.closeElement()
|
||||
if mmat.is_medium_transition:
|
||||
if mmat.interior_medium != '':
|
||||
self.element('ref', { 'name' : 'interior', 'id' : mmat.interior_medium})
|
||||
if mmat.exterior_medium != '':
|
||||
self.element('ref', { 'name' : 'exterior', 'id' : mmat.exterior_medium})
|
||||
self.closeElement()
|
||||
|
||||
def exportCameraSettings(self, scene, camera):
|
||||
mcam = camera.data.mitsuba_camera
|
||||
if scene.mitsuba_integrator.motionblur:
|
||||
frameTime = 1.0/scene.render.fps
|
||||
shuttertime = scene.mitsuba_integrator.shuttertime
|
||||
shutterOpen = (scene.frame_current - shuttertime/2) * frameTime
|
||||
shutterClose = (scene.frame_current + shuttertime/2) * frameTime
|
||||
self.openElement('prepend', {'id' : '%s-camera' % translate_id(camera.name)})
|
||||
self.parameter('float', 'shutterOpen', {'value' : str(shutterOpen)})
|
||||
self.parameter('float', 'shutterClose', {'value' : str(shutterClose)})
|
||||
self.closeElement()
|
||||
if mcam.exterior_medium != '':
|
||||
self.exportMedium(scene.mitsuba_media.media[mcam.exterior_medium])
|
||||
self.openElement('prepend', {'id' : '%s-camera' % translate_id(camera.name)})
|
||||
self.element('ref', { 'name' : 'exterior', 'id' : mcam.exterior_medium})
|
||||
self.closeElement()
|
||||
|
||||
def exportMedium(self, medium):
|
||||
if medium.name in self.exported_media:
|
||||
return
|
||||
self.exported_media += [medium.name]
|
||||
self.openElement('medium', {'id' : medium.name, 'type' : medium.type})
|
||||
if medium.g == 0:
|
||||
self.element('phase', {'type' : 'isotropic'})
|
||||
else:
|
||||
self.openElement('phase', {'type' : 'hg'})
|
||||
self.parameter('float', 'g', {'value' : str(medium.g)})
|
||||
self.closeElement()
|
||||
if medium.type == 'homogeneous':
|
||||
self.parameter('float', 'densityMultiplier', {'value' :
|
||||
str(medium.densityMultiplier)})
|
||||
self.parameter('rgb', 'sigmaA', {'value' : '%f %f %f' % (
|
||||
(1-medium.albedo.r) * medium.sigmaT[0],
|
||||
(1-medium.albedo.g) * medium.sigmaT[1],
|
||||
(1-medium.albedo.b) * medium.sigmaT[2])})
|
||||
self.parameter('rgb', 'sigmaS', {'value' : '%f %f %f' % (
|
||||
medium.albedo.r * medium.sigmaT[0],
|
||||
medium.albedo.g * medium.sigmaT[1],
|
||||
medium.albedo.b * medium.sigmaT[2])})
|
||||
|
||||
self.closeElement()
|
||||
|
||||
def export(self, scene):
|
||||
if scene.mitsuba_engine.binary_path == '':
|
||||
MtsLog("Error: the Mitsuba binary path was not specified!")
|
||||
return False
|
||||
|
||||
idx = 0
|
||||
# Force scene update; NB, scene.update() doesn't work
|
||||
scene.frame_set(scene.frame_current)
|
||||
|
||||
MtsLog('MtsBlend: Writing adjustments file to "%s"' % self.adj_filename)
|
||||
if not self.writeHeader():
|
||||
return False
|
||||
|
||||
self.exportIntegrator(scene.mitsuba_integrator)
|
||||
self.exportSampler(scene.mitsuba_sampler)
|
||||
for obj in scene.objects:
|
||||
if obj.type == 'LAMP':
|
||||
self.exportLamp(scene, obj, idx)
|
||||
elif obj.type == 'MESH':
|
||||
self.exportNormalMode(obj)
|
||||
for mat in obj.data.materials:
|
||||
self.exportMaterial(mat)
|
||||
if len(obj.data.materials) > 0 and obj.data.materials[0] != None:
|
||||
if obj.data.materials[0].mitsuba_emission.use_emission:
|
||||
self.exportEmission(obj)
|
||||
mmat = obj.data.materials[0].mitsuba_material
|
||||
if mmat.is_medium_transition:
|
||||
self.exportMediumReference(scene, obj, 'interior', mmat.interior_medium)
|
||||
self.exportMediumReference(scene, obj, 'exterior', mmat.exterior_medium)
|
||||
elif obj.type == 'CAMERA':
|
||||
self.exportCameraSettings(scene, obj)
|
||||
idx = idx+1
|
||||
self.writeFooter()
|
||||
(width, height) = resolution(scene)
|
||||
|
||||
MtsLog('MtsBlend: Writing COLLADA file to "%s"' % self.dae_filename)
|
||||
scene.collada_export(self.dae_filename)
|
||||
|
||||
MtsLog("MtsBlend: Launching mtsimport")
|
||||
command = ['mtsimport', '-r', '%dx%d' % (width, height),
|
||||
'-n', '-l', 'pngfilm', self.dae_filename, self.xml_filename, self.adj_filename]
|
||||
if scene.mitsuba_integrator.motionblur:
|
||||
command += ['-z']
|
||||
process = MtsLaunch(scene.mitsuba_engine.binary_path,
|
||||
self.output_directory, command);
|
||||
if process.wait() != 0:
|
||||
return False
|
||||
return True
|
||||
|
|
|
@ -1,249 +0,0 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import os, math, mathutils
|
||||
|
||||
import bpy
|
||||
|
||||
from extensions_framework import util as efutil
|
||||
from mitsuba.export import translate_id
|
||||
|
||||
class MtsAdjustments:
|
||||
'''
|
||||
Writes scene information to an "adjustments" file. This
|
||||
mechanism is used to capture information which gets lost
|
||||
in translation when using the COLLADA exporter.
|
||||
'''
|
||||
|
||||
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.materials
|
||||
self.textures = textures if textures != None else bpy.data.textures
|
||||
|
||||
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):
|
||||
self.out.write("%f " % trafo[i][j])
|
||||
self.out.write('"/>\n\t\t</transform>\n')
|
||||
|
||||
def exportLamp(self, lamp, idx):
|
||||
ltype = lamp.data.mitsuba_lamp.type
|
||||
name = translate_id(lamp.data.name)
|
||||
if ltype == 'POINT':
|
||||
self.out.write('\t<luminaire id="%s-light" type="point">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
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))
|
||||
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':
|
||||
self.out.write('\t<remove id="%s-light"/>\n' % name)
|
||||
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
|
||||
mts_meshes_dir = os.path.join(self.target_dir, 'meshes')
|
||||
filename = "area_luminaire_%d.obj" % idx
|
||||
|
||||
self.out.write('\t\t<string name="filename" value="meshes/%s"/>\n' % filename)
|
||||
self.exportWorldtrafo(lamp.matrix_world)
|
||||
self.out.write('\n\t\t<luminaire id="%s-arealight" type="area">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity / (2 * size_x * size_y)
|
||||
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))
|
||||
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')
|
||||
|
||||
try:
|
||||
os.mkdir(mts_meshes_dir)
|
||||
except OSError:
|
||||
pass
|
||||
path = os.path.join(mts_meshes_dir, filename)
|
||||
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))
|
||||
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))
|
||||
objFile.write('f 4 3 2 1\n')
|
||||
objFile.close()
|
||||
elif ltype == 'SUN':
|
||||
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.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))
|
||||
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':
|
||||
self.out.write('\t<luminaire id="%s-light" type="spot">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
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))
|
||||
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':
|
||||
self.out.write('\t<luminaire id="%s-light" type="constant">\n' % name)
|
||||
mult = lamp.data.mitsuba_lamp.intensity
|
||||
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))
|
||||
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':
|
||||
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 exportIntegrator(self, integrator):
|
||||
self.out.write('\t<integrator id="integrator" type="%s">\n' % integrator.type)
|
||||
self.out.write('\t</integrator>\n')
|
||||
|
||||
def exportSampler(self, sampler):
|
||||
self.out.write('\t<sampler id="sampler" type="%s">\n' % sampler.type)
|
||||
self.out.write('\t\t<integer name="sampleCount" value="%i"/>\n' % sampler.sampleCount)
|
||||
self.out.write('\t</sampler>\n')
|
||||
|
||||
def findTexture(self, name):
|
||||
if name in self.textures:
|
||||
return self.textures[name]
|
||||
else:
|
||||
raise Exception('Failed to find texture "%s"' % name)
|
||||
|
||||
|
||||
def findMaterial(self, name):
|
||||
if name in self.materials:
|
||||
return self.materials[name]
|
||||
else:
|
||||
raise Exception('Failed to find material "%s" in "%s"' % (name,
|
||||
str(self.materials)))
|
||||
|
||||
def exportTexture(self, mat):
|
||||
if mat.name in self.exported_textures:
|
||||
return
|
||||
self.exported_textures += [mat.name]
|
||||
params = mat.mitsuba_texture.get_params()
|
||||
|
||||
for p in params:
|
||||
if p.type == 'reference_texture':
|
||||
self.exportTexture(self.findTexture(p.value))
|
||||
|
||||
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 exportMaterial(self, mat):
|
||||
if not hasattr(mat, 'name') or not mat.name in self.exported_materials:
|
||||
return
|
||||
self.exported_materials += [mat.name]
|
||||
params = mat.mitsuba_material.get_params()
|
||||
|
||||
for p in params:
|
||||
if p.type == 'reference_material':
|
||||
self.exportMaterial(self.findMaterial(p.value))
|
||||
elif p.type == 'reference_texture':
|
||||
self.exportTexture(self.findTexture(p.value))
|
||||
|
||||
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 exportEmission(self, obj):
|
||||
lamp = obj.data.materials[0].mitsuba_emission
|
||||
name = translate_id(obj.data.name)
|
||||
self.out.write('\t<append id="%s-mesh_0">\n' % name)
|
||||
self.out.write('\t\t<luminaire id="%s-emission" type="area">\n' % name)
|
||||
mult = lamp.intensity
|
||||
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))
|
||||
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</append>\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 exportPreviewMesh(self, material):
|
||||
self.out.write('\t\t<shape id="Exterior-mesh_0" type="serialized">\n')
|
||||
self.out.write('\t\t\t<string name="filename" value="matpreview.serialized"/>\n')
|
||||
self.out.write('\t\t\t<integer name="shapeIndex" value="1"/>\n')
|
||||
self.out.write('\t\t\t<transform name="toWorld">\n')
|
||||
self.out.write('\t\t\t\t<matrix value="0.614046 0.614047 0 -1.78814e-07 -0.614047 0.614046 0 2.08616e-07 0 0 0.868393 1.02569 0 0 0 1"/>\n')
|
||||
self.out.write('\t\t\t</transform>\n')
|
||||
self.out.write('\t\t\t<ref id="%s" name="bsdf"/>\n' % translate_id(material.name))
|
||||
lamp = material.mitsuba_emission
|
||||
if lamp and lamp.use_emission:
|
||||
mult = lamp.intensity
|
||||
self.out.write('\t\t\t<luminaire type="area">\n')
|
||||
self.out.write('\t\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||
% (lamp.color.r*mult, lamp.color.g*mult, lamp.color.b*mult))
|
||||
self.out.write('\t\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.samplingWeight)
|
||||
self.out.write('\t\t\t</luminaire>\n')
|
||||
self.out.write('\t\t</shape>\n')
|
||||
self.out.write('\n')
|
||||
|
||||
def exportCameraSettings(self, scene, camera):
|
||||
if scene.mitsuba_integrator.motionblur:
|
||||
frameTime = 1.0/scene.render.fps
|
||||
shuttertime = scene.mitsuba_integrator.shuttertime
|
||||
shutterOpen = (scene.frame_current - shuttertime/2) * frameTime
|
||||
shutterClose = (scene.frame_current + shuttertime/2) * frameTime
|
||||
self.out.write('\t<prepend id="%s-camera">\n' % translate_id(camera.name))
|
||||
self.out.write('\t\t<float name="shutterOpen" value="%f"/>\n' % shutterOpen)
|
||||
self.out.write('\t\t<float name="shutterClose" value="%f"/>\n' % shutterClose)
|
||||
self.out.write('\t</prepend>\n')
|
||||
|
||||
def export(self, scene):
|
||||
idx = 0
|
||||
self.writeHeader()
|
||||
self.exportIntegrator(scene.mitsuba_integrator)
|
||||
self.exportSampler(scene.mitsuba_sampler)
|
||||
for obj in scene.objects:
|
||||
if obj.type == 'LAMP':
|
||||
self.exportLamp(obj, idx)
|
||||
elif obj.type == 'MESH':
|
||||
for mat in obj.data.materials:
|
||||
self.exportMaterial(mat)
|
||||
if len(obj.data.materials) > 0 and obj.data.materials[0] != None and obj.data.materials[0].mitsuba_emission.use_emission:
|
||||
self.exportEmission(obj)
|
||||
elif obj.type == 'CAMERA':
|
||||
self.exportCameraSettings(scene, obj)
|
||||
idx = idx+1
|
||||
self.writeFooter()
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
def resolution(scene):
|
||||
'''
|
||||
scene bpy.types.scene
|
||||
Calculate the output render resolution
|
||||
Returns tuple(2) (floats)
|
||||
'''
|
||||
xr = scene.render.resolution_x * scene.render.resolution_percentage / 100.0
|
||||
yr = scene.render.resolution_y * scene.render.resolution_percentage / 100.0
|
||||
|
||||
return xr, yr
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
-->
|
||||
<scene>
|
||||
<integrator id="integrator" type="path">
|
||||
<integrator id="integrator" type="volpath">
|
||||
<integer name="maxDepth" value="$depth"/>
|
||||
</integrator>
|
||||
|
||||
|
|
|
@ -17,54 +17,49 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# System Libs
|
||||
import os, sys, copy, subprocess, traceback, string
|
||||
import os, sys, subprocess, traceback, string, math
|
||||
|
||||
# Blender Libs
|
||||
import bpy
|
||||
from presets import AddPresetBase
|
||||
import bpy, bl_operators
|
||||
|
||||
# Extensions_Framework Libs
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
from mitsuba.outputs import MtsLog
|
||||
from mitsuba.export.adjustments import MtsAdjustments
|
||||
from .. import MitsubaAddon
|
||||
from ..outputs import MtsLog
|
||||
from ..export import MtsExporter
|
||||
|
||||
def try_preset_path_create(preset_subdir):
|
||||
target_path = os.path.join(bpy.utils.preset_paths('')[0], preset_subdir)
|
||||
if not os.path.exists(target_path):
|
||||
os.makedirs(target_path)
|
||||
|
||||
class MITSUBA_MT_base(object):
|
||||
class MITSUBA_MT_base(bpy.types.Menu):
|
||||
preset_operator = "script.execute_preset"
|
||||
def draw(self, context):
|
||||
try_preset_path_create(self.preset_subdir)
|
||||
return bpy.types.Menu.draw_preset(self, context)
|
||||
return self.draw_preset(context)
|
||||
|
||||
class MITSUBA_OT_preset_base(AddPresetBase):
|
||||
def execute(self, context):
|
||||
try_preset_path_create(self.preset_subdir)
|
||||
return super().execute(context)
|
||||
|
||||
class MITSUBA_MT_presets_engine(MITSUBA_MT_base, bpy.types.Menu):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_MT_presets_engine(MITSUBA_MT_base):
|
||||
bl_label = "Mitsuba Engine Presets"
|
||||
preset_subdir = "mitsuba/engine"
|
||||
|
||||
class MITSUBA_OT_preset_engine_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_preset_engine_add(bl_operators.presets.AddPresetBase, bpy.types.Operator):
|
||||
'''Save the current settings as a preset'''
|
||||
bl_idname = 'mitsuba.preset_engine_add'
|
||||
bl_label = 'Add Mitsuba Engine settings preset'
|
||||
preset_menu = 'MITSUBA_MT_presets_engine'
|
||||
preset_values = [
|
||||
'bpy.context.scene.mitsuba_engine.%s'%v['attr'] for v in bpy.types.mitsuba_engine.get_exportable_properties()
|
||||
]
|
||||
preset_subdir = 'mitsuba/engine'
|
||||
|
||||
def execute(self, context):
|
||||
self.preset_values = [
|
||||
'bpy.context.scene.mitsuba_engine.%s'%v['attr'] for v in bpy.types.mitsuba_engine.get_exportable_properties()
|
||||
]
|
||||
return super().execute(context)
|
||||
|
||||
|
||||
class MITSUBA_MT_presets_texture(MITSUBA_MT_base, bpy.types.Menu):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_MT_presets_texture(MITSUBA_MT_base):
|
||||
bl_label = "Mitsuba Texture Presets"
|
||||
preset_subdir = "mitsuba/texture"
|
||||
|
||||
class MITSUBA_OT_preset_texture_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_preset_texture_add(bl_operators.presets.AddPresetBase, bpy.types.Operator):
|
||||
'''Save the current settings as a preset'''
|
||||
bl_idname = 'mitsuba.preset_texture_add'
|
||||
bl_label = 'Add Mitsuba Texture settings preset'
|
||||
|
@ -89,12 +84,13 @@ class MITSUBA_OT_preset_texture_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
|||
self.preset_values = pv
|
||||
return super().execute(context)
|
||||
|
||||
|
||||
class MITSUBA_MT_presets_material(MITSUBA_MT_base, bpy.types.Menu):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_MT_presets_material(MITSUBA_MT_base):
|
||||
bl_label = "Mitsuba Material Presets"
|
||||
preset_subdir = "mitsuba/material"
|
||||
|
||||
class MITSUBA_OT_preset_material_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_preset_material_add(bl_operators.presets.AddPresetBase, bpy.types.Operator):
|
||||
'''Save the current settings as a preset'''
|
||||
bl_idname = 'mitsuba.preset_material_add'
|
||||
bl_label = 'Add Mitsuba Material settings preset'
|
||||
|
@ -121,6 +117,7 @@ class MITSUBA_OT_preset_material_add(MITSUBA_OT_preset_base, bpy.types.Operator)
|
|||
self.preset_values = pv
|
||||
return super().execute(context)
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class EXPORT_OT_mitsuba(bpy.types.Operator):
|
||||
bl_idname = 'export.mitsuba'
|
||||
bl_label = 'Export Mitsuba Scene (.xml)'
|
||||
|
@ -130,7 +127,7 @@ class EXPORT_OT_mitsuba(bpy.types.Operator):
|
|||
scene = bpy.props.StringProperty(options={'HIDDEN'}, default='')
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.add_fileselect(self)
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def execute(self, context):
|
||||
|
@ -140,66 +137,12 @@ class EXPORT_OT_mitsuba(bpy.types.Operator):
|
|||
else:
|
||||
scene = bpy.data.scenes[self.properties.scene]
|
||||
|
||||
if scene is None:
|
||||
self.report({'ERROR'}, 'Scene is not valid for export to %s' % self.properties.filename)
|
||||
return {'CANCELLED'}
|
||||
|
||||
# Force scene update; NB, scene.update() doesn't work
|
||||
scene.frame_set(scene.frame_current)
|
||||
result = MtsExporter(
|
||||
directory = self.properties.directory,
|
||||
filename = self.properties.filename).export(scene)
|
||||
|
||||
mts_basename = os.path.join(
|
||||
self.properties.directory,
|
||||
self.properties.filename)
|
||||
(path, ext) = os.path.splitext(mts_basename)
|
||||
if ext == '.xml':
|
||||
mts_basename = path
|
||||
mts_dae_file = mts_basename + ".dae"
|
||||
mts_xml_file = mts_basename + ".xml"
|
||||
mts_adj_file = mts_basename + "_adjustments.xml"
|
||||
mts_meshes_dir = os.path.join(self.properties.directory, "meshes")
|
||||
|
||||
efutil.export_path = mts_xml_file
|
||||
try:
|
||||
os.mkdir(mts_meshes_dir)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
scene.collada_export(mts_dae_file)
|
||||
|
||||
MtsLog('MtsBlend: Writing adjustments file to "%s"' % mts_adj_file)
|
||||
adj = MtsAdjustments(mts_adj_file, self.properties.directory)
|
||||
adj.export(scene)
|
||||
|
||||
if scene.mitsuba_engine.binary_path == '':
|
||||
self.report({'ERROR'}, 'Mitsuba binary path must be specified!')
|
||||
return {'CANCELLED'}
|
||||
|
||||
mts_path = scene.mitsuba_engine.binary_path
|
||||
mtsimport_binary = os.path.join(mts_path, "mtsimport")
|
||||
env = copy.copy(os.environ)
|
||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||||
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||||
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath
|
||||
render = scene.render
|
||||
width = int(render.resolution_x * render.resolution_percentage * 0.01)
|
||||
height = int(render.resolution_y * render.resolution_percentage * 0.01)
|
||||
|
||||
MtsLog("MtsBlend: Launching mtsimport")
|
||||
try:
|
||||
command = [mtsimport_binary, '-r', '%dx%d' % (width, height),
|
||||
'-n', '-l', 'pngfilm', mts_dae_file, mts_xml_file, mts_adj_file]
|
||||
if scene.mitsuba_integrator.motionblur:
|
||||
command += ['-z']
|
||||
process = subprocess.Popen(command,
|
||||
env = env,
|
||||
cwd = mts_path
|
||||
)
|
||||
if process.wait() != 0:
|
||||
self.report({'ERROR'}, "mtsimport returned with a nonzero status!")
|
||||
return {'CANCELLED'}
|
||||
except OSError:
|
||||
self.report({'ERROR'}, "Could not execute '%s'" % mtsimport_binary)
|
||||
if not result:
|
||||
self.report({'ERROR'}, "Unsucessful export!");
|
||||
return {'CANCELLED'}
|
||||
|
||||
return {'FINISHED'}
|
||||
|
@ -207,14 +150,15 @@ class EXPORT_OT_mitsuba(bpy.types.Operator):
|
|||
typ, value, tb = sys.exc_info()
|
||||
elist = traceback.format_exception(typ, value, tb)
|
||||
MtsLog("Caught exception: %s" % ''.join(elist))
|
||||
self.report({'ERROR'}, "Unsucessful export!");
|
||||
return {'CANCELLED'}
|
||||
|
||||
def menu_func(self, context):
|
||||
default_path = os.path.splitext(os.path.basename(bpy.data.filepath))[0] + ".xml"
|
||||
self.layout.operator("export.mitsuba", text="Export Mitsuba scene...").filename = default_path
|
||||
|
||||
bpy.types.INFO_MT_file_export.append(menu_func)
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_material_slot_move(bpy.types.Operator):
|
||||
''' Rearrange the material slots '''
|
||||
bl_idname = 'mitsuba.material_slot_move'
|
||||
|
@ -245,6 +189,7 @@ class MITSUBA_OT_material_slot_move(bpy.types.Operator):
|
|||
obj.active_material_index = new_index
|
||||
return {'FINISHED'}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_material_add(bpy.types.Operator):
|
||||
''' Append a new material '''
|
||||
bl_idname = 'mitsuba.material_add'
|
||||
|
@ -262,3 +207,107 @@ class MITSUBA_OT_material_add(bpy.types.Operator):
|
|||
obj.data.materials.append(mat)
|
||||
obj.active_material_index = len(obj.data.materials)-1
|
||||
return {'FINISHED'}
|
||||
|
||||
def material_converter(report, scene, blender_mat):
|
||||
try:
|
||||
mitsuba_mat = blender_mat.mitsuba_material
|
||||
|
||||
mitsuba_mat.type = 'microfacet'
|
||||
mitsuba_mat.mitsuba_mat_microfacet.diffuseReflectance_color = [blender_mat.diffuse_intensity*i for i in blender_mat.diffuse_color]
|
||||
mitsuba_mat.mitsuba_mat_microfacet.specularAmount = 1.0
|
||||
mitsuba_mat.mitsuba_mat_microfacet.diffuseAmount = 1.0
|
||||
|
||||
logHardness = math.log(blender_mat.specular_hardness)
|
||||
specular_scale = 2.0 * max(0.0128415*logHardness**2 - 0.171266*logHardness + 0.575631, 0.0)
|
||||
mitsuba_mat.mitsuba_mat_microfacet.specularReflectance_color = [specular_scale * blender_mat.specular_intensity*i for i in blender_mat.specular_color]
|
||||
mitsuba_mat.mitsuba_mat_microfacet.alphaB = min(max(0.757198 - 0.120395*logHardness, 0.0), 1.0)
|
||||
|
||||
report({'INFO'}, 'Converted blender material "%s"' % blender_mat.name)
|
||||
return {'FINISHED'}
|
||||
except Exception as err:
|
||||
report({'ERROR'}, 'Cannot convert material: %s' % err)
|
||||
return {'CANCELLED'}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_convert_all_materials(bpy.types.Operator):
|
||||
bl_idname = 'mitsuba.convert_all_materials'
|
||||
bl_label = 'Convert all Blender materials'
|
||||
|
||||
def report_log(self, level, msg):
|
||||
MtsLog('Material conversion %s: %s' % (level, msg))
|
||||
|
||||
def execute(self, context):
|
||||
for blender_mat in bpy.data.materials:
|
||||
# Don't convert materials from linked-in files
|
||||
if blender_mat.library == None:
|
||||
material_converter(self.report_log, context.scene, blender_mat)
|
||||
return {'FINISHED'}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_convert_material(bpy.types.Operator):
|
||||
bl_idname = 'mitsuba.convert_material'
|
||||
bl_label = 'Convert selected Blender material'
|
||||
|
||||
material_name = bpy.props.StringProperty(default='')
|
||||
|
||||
def execute(self, context):
|
||||
if self.properties.material_name == '':
|
||||
blender_mat = context.material
|
||||
else:
|
||||
blender_mat = bpy.data.materials[self.properties.material_name]
|
||||
|
||||
material_converter(self.report, context.scene, blender_mat)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_MT_presets_medium(MITSUBA_MT_base):
|
||||
bl_label = "Mitsuba Medium Presets"
|
||||
preset_subdir = "mitsuba/medium"
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_preset_medium_add(bl_operators.presets.AddPresetBase, bpy.types.Operator):
|
||||
'''Save the current settings as a preset'''
|
||||
bl_idname = 'mitsuba.preset_medium_add'
|
||||
bl_label = 'Add Mitsuba Medium settings preset'
|
||||
preset_menu = 'MITSUBA_MT_presets_medium'
|
||||
preset_values = []
|
||||
preset_subdir = 'mitsuba/medium'
|
||||
|
||||
def execute(self, context):
|
||||
ks = 'bpy.context.scene.mitsuba_media.media[bpy.context.scene.mitsuba_media.media_index].%s'
|
||||
pv = [
|
||||
ks%v['attr'] for v in bpy.types.mitsuba_medium_data.get_exportable_properties()
|
||||
]
|
||||
|
||||
self.preset_values = pv
|
||||
return super().execute(context)
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_medium_add(bpy.types.Operator):
|
||||
'''Add a new medium definition to the scene'''
|
||||
|
||||
bl_idname = "mitsuba.medium_add"
|
||||
bl_label = "Add Mitsuba Medium"
|
||||
|
||||
new_medium_name = bpy.props.StringProperty(default='New Medium')
|
||||
|
||||
def invoke(self, context, event):
|
||||
v = context.scene.mitsuba_media.media
|
||||
v.add()
|
||||
new_vol = v[len(v)-1]
|
||||
new_vol.name = self.properties.new_medium_name
|
||||
return {'FINISHED'}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MITSUBA_OT_medium_remove(bpy.types.Operator):
|
||||
'''Remove the selected medium definition'''
|
||||
|
||||
bl_idname = "mitsuba.medium_remove"
|
||||
bl_label = "Remove Mitsuba Medium"
|
||||
|
||||
def invoke(self, context, event):
|
||||
w = context.scene.mitsuba_media
|
||||
w.media.remove( w.media_index )
|
||||
w.media_index = len(w.media)-1
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -18,20 +18,37 @@ class MtsFilmDisplay(TimerThread):
|
|||
|
||||
STARTUP_DELAY = 1
|
||||
|
||||
def begin(self, renderer, output_file, resolution, preview = False):
|
||||
(self.xres, self.yres) = (int(resolution[0]), int(resolution[1]))
|
||||
self.renderer = renderer
|
||||
self.output_file = output_file
|
||||
self.resolution = resolution
|
||||
self.preview = preview
|
||||
if not self.preview:
|
||||
self.result = self.renderer.begin_result(0, 0, self.xres, self.yres)
|
||||
self.start()
|
||||
|
||||
def shutdown(self):
|
||||
if not self.preview:
|
||||
self.renderer.end_result(self.result)
|
||||
|
||||
def kick(self, render_end=False):
|
||||
xres, yres = self.LocalStorage['resolution']
|
||||
|
||||
if render_end:
|
||||
MtsLog('Final render result %ix%i' % (xres,yres))
|
||||
else:
|
||||
MtsLog('Updating render result %ix%i' % (xres,yres))
|
||||
|
||||
result = self.LocalStorage['RE'].begin_result(0, 0, int(xres), int(yres))
|
||||
if os.path.exists(self.LocalStorage['output_file']):
|
||||
lay = result.layers[0]
|
||||
lay.load_from_file(self.LocalStorage['output_file'])
|
||||
else:
|
||||
err_msg = 'ERROR: Could not load render result from %s' % self.LocalStorage['output_file']
|
||||
MtsLog(err_msg)
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text=err_msg)
|
||||
self.LocalStorage['RE'].end_result(result)
|
||||
if not bpy.app.background or render_end:
|
||||
if os.path.exists(self.output_file):
|
||||
if render_end:
|
||||
MtsLog('Final render result %ix%i' % self.resolution)
|
||||
else:
|
||||
MtsLog('Updating render result %ix%i' % self.resolution)
|
||||
try:
|
||||
if self.preview:
|
||||
self.result = self.renderer.begin_result(0, 0, self.xres, self.yres)
|
||||
self.result.layers[0].load_from_file(self.output_file)
|
||||
self.renderer.end_result(self.result)
|
||||
else:
|
||||
self.result.layers[0].load_from_file(self.output_file)
|
||||
self.renderer.update_result(self.result)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
err_msg = 'ERROR: Could not load render result from %s' % self.output_file
|
||||
MtsLog(err_msg)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
def MediumParameter(attr, name):
|
||||
return [
|
||||
{
|
||||
'attr': '%s_medium' % attr,
|
||||
'type': 'string',
|
||||
'name': '%s_medium' % attr,
|
||||
'description': '%s; blank means vacuum' % name,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'prop_search',
|
||||
'attr': attr,
|
||||
'src': lambda s,c: s.scene.mitsuba_media,
|
||||
'src_attr': 'media',
|
||||
'trg': lambda s,c: c.mitsuba_camera,
|
||||
'trg_attr': '%s_medium' % attr,
|
||||
'name': name
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_camera(declarative_property_group):
|
||||
ef_attach_to = ['Camera']
|
||||
|
||||
controls = [
|
||||
'exterior'
|
||||
]
|
||||
|
||||
visibility = { }
|
||||
|
||||
properties = MediumParameter('exterior', 'Exterior medium')
|
|
@ -16,15 +16,14 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_engine(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Engine settings.
|
||||
This class will be instantiated within a Blender scene
|
||||
object.
|
||||
'''
|
||||
ef_attach_to = ['Scene']
|
||||
|
||||
controls = [
|
||||
'export_mode',
|
||||
|
@ -68,7 +67,7 @@ class mitsuba_engine(declarative_property_group):
|
|||
'subtype': 'DIR_PATH',
|
||||
'attr': 'binary_path',
|
||||
'name': 'Executable path',
|
||||
'description': 'Path to the "mitsuba" executable',
|
||||
'description': 'Path to the Mitsuba install',
|
||||
'default': efutil.find_config_value('mitsuba', 'defaults', 'binary_path', '')
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_integrator(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Integrator settings.
|
||||
|
@ -26,8 +28,11 @@ class mitsuba_integrator(declarative_property_group):
|
|||
object.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Scene']
|
||||
|
||||
controls = [
|
||||
'type',
|
||||
'maxdepth',
|
||||
['motionblur',
|
||||
'shuttertime']
|
||||
]
|
||||
|
@ -42,10 +47,12 @@ class mitsuba_integrator(declarative_property_group):
|
|||
'attr': 'type',
|
||||
'name': 'Type',
|
||||
'description': 'Specifies the type of integrator to use',
|
||||
'default': 'ldintegrator',
|
||||
'default': 'direct',
|
||||
'items': [
|
||||
('direct', 'Direct Illumination', 'direct'),
|
||||
('volpath', 'Volumetric path tracer', 'volpath'),
|
||||
('path', 'Path tracer', 'path'),
|
||||
('direct', 'Direct Illumination', 'direct'),
|
||||
('ptracer', 'Adjoint Particle Tracer', 'ptracer')
|
||||
],
|
||||
'save_in_preset': True
|
||||
},
|
||||
|
@ -66,6 +73,16 @@ class mitsuba_integrator(declarative_property_group):
|
|||
'min': 0,
|
||||
'max': 100,
|
||||
'default': 1
|
||||
},
|
||||
{
|
||||
'type': 'int',
|
||||
'attr': 'maxdepth',
|
||||
'name': 'Max. path depth',
|
||||
'description': 'Maximum path depth to be rendered. 2 corresponds to direct illumination, 3 is 1-bounce indirect illumination, etc.',
|
||||
'save_in_preset': True,
|
||||
'min': 2,
|
||||
'max': 100,
|
||||
'default': 4
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -16,36 +16,30 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from ..properties.world import MediumParameter
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_lamp(declarative_property_group):
|
||||
ef_attach_to = ['Lamp']
|
||||
|
||||
controls = [
|
||||
'samplingWeight',
|
||||
'envmap_type',
|
||||
'envmap_file'
|
||||
'envmap_file',
|
||||
'inside_medium',
|
||||
'medium'
|
||||
]
|
||||
|
||||
visibility = {
|
||||
'envmap_type': { 'type': 'ENV' },
|
||||
'envmap_file': { 'type': 'ENV', 'envmap_type' : 'envmap' }
|
||||
'envmap_file': { 'type': 'ENV', 'envmap_type' : 'envmap' },
|
||||
'medium' : { 'inside_medium': True }
|
||||
}
|
||||
|
||||
properties = [
|
||||
{
|
||||
'type': 'enum',
|
||||
'attr': 'type',
|
||||
'name': 'Light source type',
|
||||
'description': 'Specifies the behavior of the light source',
|
||||
'default': 'POINT',
|
||||
'items': [
|
||||
('POINT', 'Point', 'Omnidirectional spot light source'),
|
||||
('SUN', 'Dir', 'Constant direction parallel light source'),
|
||||
('SPOT', 'Spot', 'Directional cone light source'),
|
||||
('ENV', 'Env', 'Environment map light source'),
|
||||
('AREA', 'Area', 'Diffuse area light source')
|
||||
],
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'float',
|
||||
'attr': 'samplingWeight',
|
||||
|
@ -90,6 +84,14 @@ class mitsuba_lamp(declarative_property_group):
|
|||
'description': 'EXR image to use for lighting (in latitude-longitude format)',
|
||||
'default': '',
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'bool',
|
||||
'attr': 'inside_medium',
|
||||
'name': 'Located inside a medium',
|
||||
'description': 'Check if the lamp lies within a participating medium',
|
||||
'default': False,
|
||||
'save_in_preset': True
|
||||
}
|
||||
]
|
||||
] + MediumParameter('lamp', 'Lamp')
|
||||
|
||||
|
|
|
@ -1,13 +1,33 @@
|
|||
import math
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy, math
|
||||
from copy import deepcopy
|
||||
|
||||
import bpy
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
from extensions_framework.validate import Logic_Operator
|
||||
from mitsuba.properties.texture import TextureParameter
|
||||
from mitsuba.export import ParamSet
|
||||
from extensions_framework.validate import Logic_Operator, Logic_OR as O
|
||||
from ..properties.texture import TextureParameter
|
||||
from ..export import ParamSet
|
||||
|
||||
from ..properties.world import MediumParameter
|
||||
|
||||
param_reflectance = TextureParameter('reflectance', 'Reflectance', \
|
||||
'Diffuse reflectance value', default=(0.5, 0.5, 0.5))
|
||||
|
@ -22,46 +42,116 @@ def dict_merge(*args):
|
|||
vis.update(deepcopy(vis_dict))
|
||||
return vis
|
||||
|
||||
mat_names = {
|
||||
'lambertian' : 'Lambertian',
|
||||
'phong' : 'Phong',
|
||||
'ward' : 'Anisotropic Ward',
|
||||
'mirror' : 'Ideal mirror',
|
||||
'dielectric' : 'Ideal dielectric',
|
||||
'roughmetal' : 'Rough metal',
|
||||
'roughglass' : 'Rough glass',
|
||||
'microfacet' : 'Microfacet',
|
||||
'composite' : 'Composite material',
|
||||
'difftrans' : 'Diffuse transmitter',
|
||||
'none' : 'Passthrough material'
|
||||
}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MATERIAL_OT_set_mitsuba_type(bpy.types.Operator):
|
||||
bl_idname = 'material.set_mitsuba_type'
|
||||
bl_label = 'Set material type'
|
||||
|
||||
mat_name = bpy.props.StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.material and \
|
||||
context.material.mitsuba_material
|
||||
|
||||
def execute(self, context):
|
||||
context.material.mitsuba_material.set_type(self.properties.mat_name)
|
||||
return {'FINISHED'}
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MATERIAL_MT_mitsuba_type(bpy.types.Menu):
|
||||
bl_label = 'Material Type'
|
||||
|
||||
def draw(self, context):
|
||||
sl = self.layout
|
||||
from operator import itemgetter
|
||||
result = sorted(mat_names.items(), key=itemgetter(1))
|
||||
for item in result:
|
||||
op = sl.operator('MATERIAL_OT_set_mitsuba_type', text = item[1])
|
||||
op.mat_name = item[0]
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_material(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Material settings.
|
||||
This class will be instantiated within a Blender Material
|
||||
object.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Material']
|
||||
|
||||
controls = [
|
||||
'type',
|
||||
]
|
||||
'twosided',
|
||||
'is_medium_transition',
|
||||
'interior',
|
||||
'exterior'
|
||||
]
|
||||
|
||||
visibility = {
|
||||
'twosided' : { 'type' : O(['lambertian', 'phong', 'ward',
|
||||
'mirror', 'roughmetal', 'microfacet', 'composite'])},
|
||||
'exterior' : { 'is_medium_transition' : True },
|
||||
'interior' : { 'is_medium_transition' : True }
|
||||
}
|
||||
|
||||
properties = [
|
||||
# Material Type Select
|
||||
{
|
||||
'type': 'enum',
|
||||
'attr': 'type_label',
|
||||
'name': 'Mitsuba material type',
|
||||
'type': 'string',
|
||||
'default': 'Lambertian',
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'string',
|
||||
'attr': 'type',
|
||||
'name': 'Type',
|
||||
'description': 'Mitsuba material type',
|
||||
'default': 'matte',
|
||||
'items': [
|
||||
('lambertian', 'Lambertian', 'Lambertian (i.e. ideally diffuse) material'),
|
||||
('phong', 'Phong', 'Modified Phong BRDF'),
|
||||
('ward', 'Anisotropic Ward', 'Anisotropic Ward BRDF'),
|
||||
('dielectric', 'Ideal dielectric', 'Ideal dielectric material (e.g. glass)'),
|
||||
('mirror', 'Ideal mirror', 'Ideal mirror material'),
|
||||
('roughglass', 'Rough glass', 'Rough dielectric material (e.g. sand-blasted glass)'),
|
||||
('roughmetal', 'Rough metal', 'Rough conductor (e.g. sand-blasted metal)'),
|
||||
('difftrans', 'Diffuse transmitter', 'Material with an ideally diffuse transmittance'),
|
||||
('microfacet', 'Microfacet', 'Microfacet material (like the rough glass material, but without transmittance)'),
|
||||
('composite', 'Composite material', 'Allows creating mixtures of different materials')
|
||||
],
|
||||
'default': 'lambertian',
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'bool',
|
||||
'attr': 'twosided',
|
||||
'name': 'Use two-sided shading',
|
||||
'description': 'Use two-sided shading for this material? This only makes sense for non-transparent/translucent materials.',
|
||||
'default': False,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'bool',
|
||||
'attr': 'is_medium_transition',
|
||||
'name': 'Mark as medium transition',
|
||||
'description': 'Activate this property if the material specifies a transition from one participating medium to another.',
|
||||
'default': False,
|
||||
'save_in_preset': True
|
||||
}
|
||||
]
|
||||
] + MediumParameter('interior', 'Interior') \
|
||||
+ MediumParameter('exterior', 'Exterior')
|
||||
|
||||
def set_type(self, mat_type):
|
||||
self.type = mat_type
|
||||
self.type_label = mat_names[mat_type]
|
||||
|
||||
def get_params(self):
|
||||
sub_type = getattr(self, 'mitsuba_mat_%s' % self.type)
|
||||
return sub_type.get_params()
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_emission(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Material emission settings.
|
||||
|
@ -69,6 +159,8 @@ class mitsuba_emission(declarative_property_group):
|
|||
object.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Material']
|
||||
|
||||
controls = [
|
||||
'color',
|
||||
'intensity',
|
||||
|
@ -136,7 +228,9 @@ class mitsuba_emission(declarative_property_group):
|
|||
params.add_float('samplingWeight', self.samplingWeight)
|
||||
return params
|
||||
|
||||
class mitsuba_mat_lambertian(declarative_property_group):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_lambertian(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = param_reflectance.controls
|
||||
|
||||
properties = param_reflectance.properties
|
||||
|
@ -148,7 +242,9 @@ class mitsuba_mat_lambertian(declarative_property_group):
|
|||
params.update(param_reflectance.get_params(self))
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_phong(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'diffuseAmount',
|
||||
'specularAmount',
|
||||
|
@ -204,7 +300,9 @@ class mitsuba_mat_phong(declarative_property_group):
|
|||
params.add_float('exponent', self.exponent)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_ward(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'diffuseAmount',
|
||||
'specularAmount',
|
||||
|
@ -271,7 +369,9 @@ class mitsuba_mat_ward(declarative_property_group):
|
|||
params.add_float('alphaY', self.alphaY)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_microfacet(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'diffuseAmount',
|
||||
'specularAmount',
|
||||
|
@ -350,7 +450,9 @@ class mitsuba_mat_microfacet(declarative_property_group):
|
|||
params.add_float('intIOR', self.intIOR)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_roughglass(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'specularReflectance',
|
||||
'specularTransmittance',
|
||||
|
@ -422,7 +524,9 @@ class mitsuba_mat_roughglass(declarative_property_group):
|
|||
params.add_float('intIOR', self.intIOR)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_roughmetal(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'alphaB',
|
||||
'ior', 'k'
|
||||
|
@ -446,7 +550,7 @@ class mitsuba_mat_roughmetal(declarative_property_group):
|
|||
'name' : 'IOR',
|
||||
'description' : 'Per-channel index of refraction of the conductor',
|
||||
'default' : (0.370, 0.370, 0.370),
|
||||
'min': 1.0,
|
||||
'min': 0.1,
|
||||
'max': 10.0,
|
||||
'expand' : False,
|
||||
'save_in_preset': True
|
||||
|
@ -473,7 +577,9 @@ class mitsuba_mat_roughmetal(declarative_property_group):
|
|||
params.add_color('k', self.k)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_dielectric(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'specularReflectance',
|
||||
'specularTransmittance',
|
||||
|
@ -533,7 +639,9 @@ class mitsuba_mat_dielectric(declarative_property_group):
|
|||
params.add_float('intIOR', self.intIOR)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_mirror(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'specularReflectance'
|
||||
]
|
||||
|
@ -557,7 +665,9 @@ class mitsuba_mat_mirror(declarative_property_group):
|
|||
params.add_color('specularReflectance', self.specularReflectance)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_difftrans(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'transmittance'
|
||||
]
|
||||
|
@ -631,7 +741,9 @@ def mitsuba_mat_composite_visibility():
|
|||
result["mat%i_weight" % i] = {'nElements' : Logic_Operator({'gte' : i})}
|
||||
return result
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mat_composite(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_material']
|
||||
controls = [
|
||||
'nElements'
|
||||
] + sum(map(lambda x: x.get_controls(), param_mat), [])
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_mesh(declarative_property_group):
|
||||
ef_attach_to = ['Mesh', 'SurfaceCurve', 'TextCurve', 'Curve']
|
||||
|
||||
controls = [
|
||||
'normals'
|
||||
]
|
||||
|
||||
visibility = {
|
||||
}
|
||||
|
||||
properties = [
|
||||
{
|
||||
'type': 'enum',
|
||||
'attr': 'normals',
|
||||
'name': 'Normal mode',
|
||||
'description': 'Specifies how Mitsuba obtains normal information',
|
||||
'items' : [
|
||||
('dihedralangle','Smooth vertex normals (using angle constraint)', 'dihedralangle'),
|
||||
('vertexnormals','Smooth vertex normals (using connectivity)', 'vertexnormals'),
|
||||
('facenormals','Flat face normals', 'facenormals'),
|
||||
('default','Use normals from Blender', 'default')
|
||||
],
|
||||
'default': 'default'
|
||||
}
|
||||
]
|
||||
|
|
@ -16,9 +16,12 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_sampler(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Sampler settings.
|
||||
|
@ -26,6 +29,8 @@ class mitsuba_sampler(declarative_property_group):
|
|||
object.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Scene']
|
||||
|
||||
controls = [
|
||||
'type',
|
||||
'sampleCount'
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
from extensions_framework import util as efutil
|
||||
from extensions_framework.validate import Logic_OR as O
|
||||
|
@ -123,7 +125,7 @@ class TextureParameter(TextureParameterBase):
|
|||
vis.update(self.get_extra_visibility())
|
||||
return vis
|
||||
|
||||
# colour for each material type. If the property name is
|
||||
# color for each material type. If the property name is
|
||||
# not set, then the color won't be changed.
|
||||
master_color_map = {
|
||||
'lambertian': 'reflectance',
|
||||
|
@ -137,18 +139,6 @@ class TextureParameter(TextureParameterBase):
|
|||
'roughmetal': 'specularReflectance'
|
||||
}
|
||||
|
||||
def set_master_colour(self, s, c):
|
||||
'''
|
||||
This neat little hack will set the blender material colour to the value
|
||||
given in the material panel via the property's 'draw' lambda function.
|
||||
'''
|
||||
|
||||
if c.type in self.master_color_map.keys() and self.attr == self.master_color_map[c.type]:
|
||||
submat = getattr(c, 'mitsuba_mat_%s'%c.type)
|
||||
submat_col = getattr(submat, self.attr+'_color')
|
||||
if s.material.diffuse_color != submat_col:
|
||||
s.material.diffuse_color = submat_col
|
||||
|
||||
def get_properties(self):
|
||||
return [
|
||||
{
|
||||
|
@ -181,7 +171,6 @@ class TextureParameter(TextureParameterBase):
|
|||
'max': self.max,
|
||||
'soft_max': self.max,
|
||||
'subtype': 'COLOR',
|
||||
'draw': lambda s,c: self.set_master_colour(s, c),
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
|
@ -214,12 +203,15 @@ class TextureParameter(TextureParameterBase):
|
|||
)
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_texture(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Texture settings.
|
||||
This class will be instantiated within a Blender Texture
|
||||
object.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Texture']
|
||||
|
||||
controls = [
|
||||
'type'
|
||||
|
@ -249,7 +241,10 @@ class mitsuba_texture(declarative_property_group):
|
|||
else:
|
||||
return ParamSet()
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_tex_mapping(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_texture']
|
||||
|
||||
controls = [
|
||||
['uscale', 'vscale'],
|
||||
['uoffset', 'voffset']
|
||||
|
@ -310,7 +305,10 @@ class mitsuba_tex_mapping(declarative_property_group):
|
|||
mapping_params.add_float('voffset', self.voffset)
|
||||
return mapping_params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_tex_ldrtexture(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_texture']
|
||||
|
||||
controls = [
|
||||
'filename',
|
||||
'wrapMode',
|
||||
|
@ -391,7 +389,7 @@ class mitsuba_tex_ldrtexture(declarative_property_group):
|
|||
def get_params(self):
|
||||
params = ParamSet()
|
||||
|
||||
params.add_string('filename', efutil.path_relative_to_export(self.filename) ) \
|
||||
params.add_string('filename', efutil.path_relative_to_export(self.filename)) \
|
||||
.add_string('filterType', self.filterType) \
|
||||
.add_float('maxAnisotropy', self.maxAnisotropy) \
|
||||
.add_string('wrapMode', self.wrapMode) \
|
||||
|
@ -399,7 +397,10 @@ class mitsuba_tex_ldrtexture(declarative_property_group):
|
|||
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_tex_checkerboard(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_texture']
|
||||
|
||||
controls = [
|
||||
'darkColor',
|
||||
'brightColor'
|
||||
|
@ -438,7 +439,10 @@ class mitsuba_tex_checkerboard(declarative_property_group):
|
|||
|
||||
return params
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_tex_gridtexture(declarative_property_group):
|
||||
ef_attach_to = ['mitsuba_texture']
|
||||
|
||||
controls = [
|
||||
'darkColor',
|
||||
'brightColor',
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework import declarative_property_group
|
||||
|
||||
def MediumParameter(attr, name):
|
||||
return [
|
||||
{
|
||||
'attr': '%s_medium' % attr,
|
||||
'type': 'string',
|
||||
'name': '%s_medium' % attr,
|
||||
'description': '%s medium; blank means vacuum' % attr,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'prop_search',
|
||||
'attr': attr,
|
||||
'src': lambda s,c: s.scene.mitsuba_media,
|
||||
'src_attr': 'media',
|
||||
'trg': lambda s,c: c.mitsuba_material,
|
||||
'trg_attr': '%s_medium' % attr,
|
||||
'name': name
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_medium_data(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba medium data. The
|
||||
mitsuba_media object will store 1 or more of
|
||||
these in its CollectionProperty 'media'.
|
||||
'''
|
||||
|
||||
ef_attach_to = [] # not attached
|
||||
|
||||
controls = [
|
||||
'type', 'g', 'densityMultiplier', 'sigmaT', 'albedo'
|
||||
]
|
||||
|
||||
properties = [
|
||||
{
|
||||
'type': 'enum',
|
||||
'attr': 'type',
|
||||
'name': 'Type',
|
||||
'items': [
|
||||
('homogeneous', 'Homogeneous', 'homogeneous'),
|
||||
('heterogeneous', 'Heterogeneous', 'heterogeneous'),
|
||||
],
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'float',
|
||||
'attr': 'g',
|
||||
'name': 'Asymmetry',
|
||||
'description': 'Scattering asymmetry RGB. -1 means back-scattering, 0 is isotropic, 1 is forwards scattering.',
|
||||
'default': 0.0,
|
||||
'min': -1.0,
|
||||
'soft_min': -1.0,
|
||||
'max': 1.0,
|
||||
'soft_max': 1.0,
|
||||
'precision': 4,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'float',
|
||||
'attr': 'densityMultiplier',
|
||||
'name': 'Density',
|
||||
'description': 'In conjunction with the scattering and absorption coefficients, this number determines the optical density of the medium',
|
||||
'default': 1.0,
|
||||
'min': 0,
|
||||
'max': 10000,
|
||||
'precision': 4,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'float_vector',
|
||||
'attr': 'sigmaT',
|
||||
'name' : 'Extinction',
|
||||
'description' : 'Extinction due to scattering and absorption. Please ' +
|
||||
'keep these value roughly equal across color channels (or expect noise).',
|
||||
'default' : (1.0, 1.0, 1.0),
|
||||
'min': 0.0,
|
||||
'max': 1.0,
|
||||
'expand' : False,
|
||||
'save_in_preset': True
|
||||
},
|
||||
{
|
||||
'type': 'float_vector',
|
||||
'attr': 'albedo',
|
||||
'subtype': 'COLOR',
|
||||
'name' : 'Single-scattering albedo',
|
||||
'description' : 'Specifies the albedo of a single scattering interaction',
|
||||
'default' : (0.8, 0.8, 0.8),
|
||||
'min': 0.0,
|
||||
'max': 1.0,
|
||||
'expand' : False,
|
||||
'save_in_preset': True
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class mitsuba_media(declarative_property_group):
|
||||
'''
|
||||
Storage class for Mitsuba Material media.
|
||||
'''
|
||||
|
||||
ef_attach_to = ['Scene']
|
||||
|
||||
controls = [
|
||||
'media_select',
|
||||
['op_vol_add', 'op_vol_rem']
|
||||
]
|
||||
|
||||
visibility = {}
|
||||
|
||||
properties = [
|
||||
{
|
||||
'type': 'collection',
|
||||
'ptype': mitsuba_medium_data,
|
||||
'name': 'media',
|
||||
'attr': 'media',
|
||||
'items': [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
'type': 'int',
|
||||
'name': 'media_index',
|
||||
'attr': 'media_index',
|
||||
},
|
||||
{
|
||||
'type': 'template_list',
|
||||
'name': 'media_select',
|
||||
'attr': 'media_select',
|
||||
'trg': lambda sc,c: c.mitsuba_media,
|
||||
'trg_attr': 'media_index',
|
||||
'src': lambda sc,c: c.mitsuba_media,
|
||||
'src_attr': 'media',
|
||||
},
|
||||
{
|
||||
'type': 'operator',
|
||||
'attr': 'op_vol_add',
|
||||
'operator': 'mitsuba.medium_add',
|
||||
'text': 'Add',
|
||||
'icon': 'ZOOMIN',
|
||||
},
|
||||
{
|
||||
'type': 'operator',
|
||||
'attr': 'op_vol_rem',
|
||||
'operator': 'mitsuba.medium_remove',
|
||||
'text': 'Remove',
|
||||
'icon': 'ZOOMOUT',
|
||||
},
|
||||
]
|
|
@ -0,0 +1,41 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy, bl_ui
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
|
||||
class world_panel(bl_ui.properties_data_camera.CameraButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class cameraes(world_panel):
|
||||
'''
|
||||
Camera Settings
|
||||
'''
|
||||
|
||||
bl_label = 'Mitsuba Camera Options'
|
||||
|
||||
display_property_groups = [
|
||||
( ('camera',), 'mitsuba_camera' )
|
||||
]
|
||||
|
||||
def draw(self, context):
|
||||
super().draw(context)
|
|
@ -16,17 +16,19 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from properties_data_lamp import DataButtonsPanel
|
||||
import bpy, bl_ui
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
|
||||
narrowui = 180
|
||||
|
||||
class lamps(DataButtonsPanel, property_group_renderer, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class lamps(bl_ui.properties_data_lamp.DataButtonsPanel, property_group_renderer, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Lamps'
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
display_property_groups = [
|
||||
( ('lamp',), 'mitsuba_lamp' )
|
||||
]
|
||||
|
@ -39,14 +41,9 @@ class lamps(DataButtonsPanel, property_group_renderer, bpy.types.Panel):
|
|||
wide_ui = context.region.width > narrowui
|
||||
|
||||
if wide_ui:
|
||||
layout.prop(lamp.mitsuba_lamp, "type", expand=True)
|
||||
layout.prop(lamp, "type", expand=True)
|
||||
else:
|
||||
layout.prop(lamp.mitsuba_lamp, "type", text="")
|
||||
|
||||
if lamp.mitsuba_lamp.type == 'ENV':
|
||||
lamp.type = 'HEMI'
|
||||
else:
|
||||
lamp.type = lamp.mitsuba_lamp.type
|
||||
layout.prop(lamp, "type", text="")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
|
@ -94,5 +91,12 @@ class lamps(DataButtonsPanel, property_group_renderer, bpy.types.Panel):
|
|||
elif wide_ui:
|
||||
col = split.column()
|
||||
|
||||
layout.prop(lamp.mitsuba_lamp, "inside_medium")
|
||||
if lamp.mitsuba_lamp.inside_medium:
|
||||
layout.prop_search(
|
||||
lamp.mitsuba_lamp, 'lamp_medium',
|
||||
context.scene.mitsuba_media, 'media',
|
||||
text = 'Medium'
|
||||
)
|
||||
if lamp.type == 'HEMI':
|
||||
layout.label('Note: these cover the whole sphere')
|
||||
layout.label('Note: covers the whole sphere')
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from properties_material import MaterialButtonsPanel
|
||||
import bpy, bl_ui
|
||||
|
||||
from ... import MitsubaAddon
|
||||
from ...outputs import MtsLog
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
from mitsuba.outputs import MtsLog
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
material_cache = {}
|
||||
|
@ -36,8 +37,8 @@ def copy(value):
|
|||
else:
|
||||
raise Exception("Copy: don't know how to handle '%s'" % str(vlaue))
|
||||
|
||||
class mitsuba_material_base(MaterialButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
class mitsuba_material_base(bl_ui.properties_material.MaterialButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
MTS_PROPS = ['type']
|
||||
|
||||
def validate(self, context):
|
||||
|
@ -60,7 +61,7 @@ class mitsuba_material_base(MaterialButtonsPanel, property_group_renderer):
|
|||
if repaint:
|
||||
# Cause a repaint
|
||||
MtsLog("Forcing a repaint")
|
||||
context.material.preview_render_type = context.material.preview_render_type
|
||||
#context.material.preview_render_type = context.material.preview_render_type
|
||||
|
||||
def draw(self, context):
|
||||
if not hasattr(context, 'material'):
|
||||
|
@ -71,8 +72,8 @@ class mitsuba_material_base(MaterialButtonsPanel, property_group_renderer):
|
|||
def get_contents(self, mat):
|
||||
return mat.mitsuba_material
|
||||
|
||||
class mitsuba_material_sub(MaterialButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
class mitsuba_material_sub(bl_ui.properties_material.MaterialButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
MTS_COMPAT = set()
|
||||
MTS_PROPS = []
|
||||
|
||||
|
@ -113,12 +114,13 @@ class mitsuba_material_sub(MaterialButtonsPanel, property_group_renderer):
|
|||
if repaint:
|
||||
# Cause a repaint
|
||||
MtsLog("Forcing a repaint")
|
||||
context.material.preview_render_type = context.material.preview_render_type
|
||||
#context.material.preview_render_type = context.material.preview_render_type
|
||||
return super().draw(context)
|
||||
|
||||
class MATERIAL_PT_preview_mts(MaterialButtonsPanel, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MATERIAL_PT_preview_mts(bl_ui.properties_material.MaterialButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Preview"
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
def draw(self, context):
|
||||
if not hasattr(context, 'material'):
|
||||
|
@ -137,15 +139,15 @@ class MATERIAL_PT_preview_mts(MaterialButtonsPanel, bpy.types.Panel):
|
|||
cached_spp = engine.preview_spp
|
||||
if actualChange:
|
||||
MtsLog("Forcing a repaint")
|
||||
context.material.preview_render_type = context.material.preview_render_type
|
||||
#context.material.preview_render_type = context.material.preview_render_type
|
||||
efutil.write_config_value('mitsuba', 'defaults', 'preview_spp', str(cached_spp))
|
||||
efutil.write_config_value('mitsuba', 'defaults', 'preview_depth', str(cached_depth))
|
||||
|
||||
|
||||
class MATERIAL_PT_context_material_mts(MaterialButtonsPanel, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class MATERIAL_PT_context_material_mts(bl_ui.properties_material.MaterialButtonsPanel, bpy.types.Panel):
|
||||
bl_label = ""
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
from properties_material import active_node_mat
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_composite(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Composite Material'
|
||||
|
||||
|
@ -33,7 +33,7 @@ class ui_material_composite(mitsuba_material_sub, bpy.types.Panel):
|
|||
def draw(self, context):
|
||||
super().draw(context)
|
||||
|
||||
mat = active_node_mat(context.material).mitsuba_material.mitsuba_mat_composite
|
||||
mat = bl_ui.properties_material.active_node_mat(context.material).mitsuba_material.mitsuba_mat_composite
|
||||
weight = 0
|
||||
missing = False
|
||||
selfRef = False
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_dielectric(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Dielectric Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_difftrans(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Diffuse Transmitter Material'
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_base
|
||||
from properties_material import active_node_mat
|
||||
import bpy, bl_ui
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class emission(mitsuba_material_base, bpy.types.Panel):
|
||||
'''
|
||||
Material Emission Settings
|
||||
|
@ -39,6 +39,6 @@ class emission(mitsuba_material_base, bpy.types.Panel):
|
|||
|
||||
def draw_header(self, context):
|
||||
if hasattr(context, "material"):
|
||||
mat = active_node_mat(context.material)
|
||||
mat = bl_ui.properties_material.active_node_mat(context.material)
|
||||
self.layout.prop(mat.mitsuba_emission, "use_emission", text="")
|
||||
self.validate(context)
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_lambertian(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Lambertian Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_base
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class main(mitsuba_material_base, bpy.types.Panel):
|
||||
'''
|
||||
Material Editor UI Panel
|
||||
|
@ -36,5 +37,12 @@ class main(mitsuba_material_base, bpy.types.Panel):
|
|||
row.menu("MITSUBA_MT_presets_material", text=bpy.types.MITSUBA_MT_presets_material.bl_label)
|
||||
row.operator("mitsuba.preset_material_add", text="", icon="ZOOMIN")
|
||||
row.operator("mitsuba.preset_material_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("mitsuba.convert_all_materials", icon='WORLD_DATA')
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("mitsuba.convert_material", icon='MATERIAL_DATA')
|
||||
row = self.layout.row(align=True)
|
||||
|
||||
row.menu('MATERIAL_MT_mitsuba_type', text=context.material.mitsuba_material.type_label)
|
||||
super().draw(context)
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_microfacet(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Microfacet Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_mirror(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Mirror Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_phong(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Phong Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_roughglass(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Rough Glass Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_roughmetal(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Rough Metal Material'
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.materials import mitsuba_material_sub
|
||||
|
||||
from mitsuba.ui.materials import mitsuba_material_sub
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_material_ward(mitsuba_material_sub, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Ward Material'
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy, bl_ui
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
|
||||
class world_panel(bl_ui.properties_data_mesh.MeshButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class meshes(world_panel):
|
||||
'''
|
||||
Mesh Settings
|
||||
'''
|
||||
|
||||
bl_label = 'Mitsuba Mesh Options'
|
||||
|
||||
display_property_groups = [
|
||||
( ('mesh',), 'mitsuba_mesh' )
|
||||
]
|
||||
|
||||
def draw(self, context):
|
||||
super().draw(context)
|
|
@ -16,22 +16,22 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import os, bpy
|
||||
from properties_render import RenderButtonsPanel
|
||||
import os, bpy, bl_ui
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
from extensions_framework import util as efutil
|
||||
|
||||
cached_binary_path = None
|
||||
|
||||
class render_described_context(RenderButtonsPanel, property_group_renderer):
|
||||
class render_panel(bl_ui.properties_render.RenderButtonsPanel, property_group_renderer):
|
||||
'''
|
||||
Base class for render engine settings panels
|
||||
'''
|
||||
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
class setup_preset(render_described_context, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class setup_preset(render_panel, bpy.types.Panel):
|
||||
'''
|
||||
Engine settings presets UI Panel
|
||||
'''
|
||||
|
@ -46,7 +46,8 @@ class setup_preset(render_described_context, bpy.types.Panel):
|
|||
|
||||
super().draw(context)
|
||||
|
||||
class engine(render_described_context, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class engine(render_panel, bpy.types.Panel):
|
||||
'''
|
||||
Engine settings UI Panel
|
||||
'''
|
||||
|
@ -56,22 +57,9 @@ class engine(render_described_context, bpy.types.Panel):
|
|||
display_property_groups = [
|
||||
( ('scene',), 'mitsuba_engine' )
|
||||
]
|
||||
|
||||
def draw(self, context):
|
||||
global cached_binary_path
|
||||
binary_path = context.scene.mitsuba_engine.binary_path
|
||||
if binary_path != "" and cached_binary_path != binary_path:
|
||||
binary_path = os.path.abspath(efutil.filesystem_path(binary_path))
|
||||
if os.path.isfile(binary_path):
|
||||
(binary_path, tail) = os.path.split(binary_path)
|
||||
actualChange = cached_binary_path != None
|
||||
cached_binary_path = binary_path
|
||||
context.scene.mitsuba_engine.binary_path = binary_path
|
||||
print('Updating binary_path to "%s"\n' % binary_path)
|
||||
efutil.write_config_value('mitsuba', 'defaults', 'binary_path', binary_path)
|
||||
super().draw(context)
|
||||
|
||||
class integrator(render_described_context, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class integrator(render_panel, bpy.types.Panel):
|
||||
'''
|
||||
Integrator settings UI Panel
|
||||
'''
|
||||
|
@ -82,8 +70,8 @@ class integrator(render_described_context, bpy.types.Panel):
|
|||
( ('scene',), 'mitsuba_integrator' )
|
||||
]
|
||||
|
||||
|
||||
class sampler(render_described_context, bpy.types.Panel):
|
||||
@MitsubaAddon.addon_register_class
|
||||
class sampler(render_panel, bpy.types.Panel):
|
||||
'''
|
||||
Sampler settings UI Panel
|
||||
'''
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
|
||||
from properties_texture import TextureButtonsPanel
|
||||
from properties_texture import context_tex_datablock
|
||||
import bpy, bl_ui
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
|
||||
class TEXTURE_PT_context_texture_mts(TextureButtonsPanel, bpy.types.Panel):
|
||||
from ... import MitsubaAddon
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class TEXTURE_PT_context_texture_mts(bl_ui.properties_texture.TextureButtonsPanel, bpy.types.Panel):
|
||||
bl_label = ""
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -42,7 +42,7 @@ class TEXTURE_PT_context_texture_mts(TextureButtonsPanel, bpy.types.Panel):
|
|||
node = context.texture_node
|
||||
space = context.space_data
|
||||
tex = context.texture
|
||||
idblock = context_tex_datablock(context)
|
||||
idblock = bl_ui.properties_texture.context_tex_datablock(context)
|
||||
tex_collection = space.pin_id is None and type(idblock) != bpy.types.Brush and not node
|
||||
|
||||
if tex_collection:
|
||||
|
@ -70,12 +70,12 @@ class TEXTURE_PT_context_texture_mts(TextureButtonsPanel, bpy.types.Panel):
|
|||
|
||||
col = split.column()
|
||||
|
||||
class mitsuba_texture_base(TextureButtonsPanel, property_group_renderer):
|
||||
class mitsuba_texture_base(bl_ui.properties_texture.TextureButtonsPanel, property_group_renderer):
|
||||
'''
|
||||
This is the base class for all Mitsuba texture sub-panels.
|
||||
'''
|
||||
|
||||
COMPAT_ENGINES = {'mitsuba'}
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
MTS_COMPAT = set()
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.textures import mitsuba_texture_base
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.textures import mitsuba_texture_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_texture_checkerboard(mitsuba_texture_base, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Checkerboard Texture'
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.textures import mitsuba_texture_base
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.textures import mitsuba_texture_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_texture_gridtexture(mitsuba_texture_base, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Grid Texture'
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.textures import mitsuba_texture_base
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.textures import mitsuba_texture_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_texture_ldrtexture(mitsuba_texture_base, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba Bitmap Texture'
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.textures import mitsuba_texture_base
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.textures import mitsuba_texture_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_texture_main(mitsuba_texture_base, bpy.types.Panel):
|
||||
'''
|
||||
Texture Editor UI Panel
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
import bpy
|
||||
|
||||
from mitsuba.ui.textures import mitsuba_texture_base
|
||||
from ... import MitsubaAddon
|
||||
from ...ui.textures import mitsuba_texture_base
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class ui_texture_mapping(mitsuba_texture_base, bpy.types.Panel):
|
||||
bl_label = 'Mitsuba UV Mapping'
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy, bl_ui
|
||||
|
||||
from .. import MitsubaAddon
|
||||
|
||||
from extensions_framework.ui import property_group_renderer
|
||||
|
||||
class world_panel(bl_ui.properties_world.WorldButtonsPanel, property_group_renderer):
|
||||
COMPAT_ENGINES = { MitsubaAddon.BL_IDNAME }
|
||||
|
||||
@MitsubaAddon.addon_register_class
|
||||
class media(world_panel):
|
||||
'''
|
||||
Participating Media Settings
|
||||
'''
|
||||
|
||||
bl_label = 'Mitsuba Media'
|
||||
|
||||
display_property_groups = [
|
||||
( ('scene',), 'mitsuba_media' )
|
||||
]
|
||||
|
||||
def draw(self, context):
|
||||
super().draw(context)
|
||||
|
||||
if context.world:
|
||||
row = self.layout.row(align=True)
|
||||
row.menu("MITSUBA_MT_presets_medium", text=bpy.types.MITSUBA_MT_presets_medium.bl_label)
|
||||
row.operator("mitsuba.preset_medium_add", text="", icon="ZOOMIN")
|
||||
row.operator("mitsuba.preset_medium_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
|
||||
if len(context.scene.mitsuba_media.media) > 0:
|
||||
current_vol_ind = context.scene.mitsuba_media.media_index
|
||||
current_vol = context.scene.mitsuba_media.media[current_vol_ind]
|
||||
# 'name' is not a member of current_vol.properties,
|
||||
# so we draw it explicitly
|
||||
self.layout.prop(
|
||||
current_vol, 'name'
|
||||
)
|
||||
# Here we draw the currently selected mitsuba_media_data property group
|
||||
for control in current_vol.controls:
|
||||
self.draw_column(
|
||||
control,
|
||||
self.layout,
|
||||
current_vol,
|
||||
context,
|
||||
property_group = current_vol
|
||||
)
|
||||
else:
|
||||
self.layout.label('No active World available!')
|
|
@ -590,7 +590,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = include/mitsuba/core doc/doxyfiles
|
||||
INPUT = include/mitsuba/core include/mitsuba/render doc/doxyfiles
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
|
|
@ -11,6 +11,7 @@ Mitsuba makes heavy use of the following amazing libraries and tools:
|
|||
\item Qt 4 by Nokia
|
||||
\item OpenEXR by Industrial Light \& Magic
|
||||
\item Xerces-C+\!+ by the Apache Foundation
|
||||
\item Eigen by Beno\^it Jacob and Ga\"el Guennebaud
|
||||
\item The Boost C+\!+ class library
|
||||
\item GLEW by Milan Ikits, Marcelo E. Magallon and Lev Povalahev
|
||||
\item Mersenne Twister by Makoto Matsumoto and Takuji Nishimura
|
||||
|
|
|
@ -182,6 +182,7 @@ choices are available:
|
|||
\item Scaling operations. The coefficients may also be negative to obtain a flip, e.g.
|
||||
\begin{xml}
|
||||
<scale x="2" y="1" z="-1"/>
|
||||
<scale value="5"/> <!-- (uniform scale) -->
|
||||
\end{xml}
|
||||
\item Explicit 4$\times$4 matrices, e.g
|
||||
\begin{xml}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
\documentclass[footexclude,12pt,DIV11]{scrartcl}
|
||||
\documentclass[footexclude,11pt,DIV11]{scrartcl}
|
||||
|
||||
% Wenzel's standard prelude
|
||||
% ----- 8< ----- 8< ------
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -384,7 +384,7 @@ public:
|
|||
#ifdef MTS_SSE
|
||||
/**
|
||||
* \brief Intersect against a packet of four rays.
|
||||
* \return \a false if none of the rays intersect.
|
||||
* \return \c false if none of the rays intersect.
|
||||
*/
|
||||
FINLINE bool rayIntersectPacket(const RayPacket4 &ray, RayInterval4 &interval) const;
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -20,6 +20,7 @@
|
|||
#define __BRENT_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -27,24 +28,22 @@ MTS_NAMESPACE_BEGIN
|
|||
* \brief Brent's method nonlinear zero finder
|
||||
*
|
||||
* The implementation is transcribed from the Apache Commons
|
||||
* Java implementation. The function \a Func is required to be
|
||||
* Java implementation. The supplied function is required to be
|
||||
* continuous, but not necessarily smooth.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
template <typename T, typename Func> class BrentSolver {
|
||||
class BrentSolver {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
/// Return value of \ref BrentSolver::solve()
|
||||
struct Result {
|
||||
bool success;
|
||||
int iterations;
|
||||
value_type x;
|
||||
value_type y;
|
||||
Float x;
|
||||
Float y;
|
||||
|
||||
/// Create a new result instance
|
||||
inline Result(bool success, int iterations, value_type x, value_type y)
|
||||
inline Result(bool success, int iterations, Float x, Float y)
|
||||
: success(success), iterations(iterations), x(x), y(y) { }
|
||||
|
||||
/// Return a string representation of the result
|
||||
|
@ -75,10 +74,10 @@ public:
|
|||
* Absolute accuracy requirement of the position -- the
|
||||
* iterations will stop when |minX-maxX|/minX < relAccuracyPos.
|
||||
*/
|
||||
inline BrentSolver(int maxIterations = 100,
|
||||
value_type absAccuracy = 1e-6f,
|
||||
value_type absAccuracyPos = 1e-6f,
|
||||
value_type relAccuracyPos = 1e-6f)
|
||||
inline BrentSolver(size_t maxIterations = 100,
|
||||
Float absAccuracy = 1e-6f,
|
||||
Float absAccuracyPos = 1e-6f,
|
||||
Float relAccuracyPos = 1e-6f)
|
||||
: m_maxIterations(maxIterations),
|
||||
m_absAccuracy(absAccuracy),
|
||||
m_absAccuracyPos(absAccuracyPos),
|
||||
|
@ -94,27 +93,8 @@ public:
|
|||
* \param max the upper bound for the interval.
|
||||
* \return the value where the function is zero
|
||||
*/
|
||||
Result solve(Func &f, value_type min, value_type max) const {
|
||||
// return the first endpoint if it is good enough
|
||||
value_type yMin = f(min);
|
||||
if (std::abs(yMin) <= m_absAccuracy)
|
||||
return Result(true, 0, min, yMin);
|
||||
|
||||
// return the second endpoint if it is good enough
|
||||
value_type yMax = f(max);
|
||||
if (std::abs(yMax) <= m_absAccuracy)
|
||||
return Result(true, 0, max, yMax);
|
||||
|
||||
value_type sign = yMin * yMax;
|
||||
if (sign > 0) {
|
||||
SLog(EWarn, "BrentSolver: Function values at the endpoints do not have different signs -- "
|
||||
"endpoints: [%f, %f], values: [%f, %f]", min, max, yMin, yMax);
|
||||
return Result(false, 0, 0, 0);
|
||||
} else {
|
||||
// solve using only the first endpoint as initial guess
|
||||
return solve(f, min, yMin, max, yMax, min, yMin);
|
||||
}
|
||||
}
|
||||
Result solve(const boost::function<Float (Float)> &func,
|
||||
Float min, Float max) const;
|
||||
|
||||
/**
|
||||
* \brief Find a zero in the given interval with an initial guess
|
||||
|
@ -130,41 +110,8 @@ public:
|
|||
* if no initial point is known)
|
||||
* \return the value where the function is zero
|
||||
*/
|
||||
Result solve(Func &f, value_type min, value_type max, value_type initial) const {
|
||||
if (initial < min || initial > max) {
|
||||
SLog(EWarn, "BrentSolver: Invalid interval: lower=%f, initial=%f, upper=%f",
|
||||
min, max, initial);
|
||||
return Result(false, 0, 0, 0);
|
||||
}
|
||||
|
||||
// return the initial guess if it is good enough
|
||||
value_type yInitial = f(initial);
|
||||
if (std::abs(yInitial) <= m_absAccuracy)
|
||||
return Result(true, 0, initial, yInitial);
|
||||
|
||||
// return the first endpoint if it is good enough
|
||||
value_type yMin = f(min);
|
||||
if (std::abs(yMin) <= m_absAccuracy)
|
||||
return Result(true, 0, min, yMin);
|
||||
|
||||
// reduce interval if min and initial bracket the root
|
||||
if (yInitial * yMin < 0)
|
||||
return solve(f, min, yMin, initial, yInitial, min, yMin);
|
||||
|
||||
// return the second endpoint if it is good enough
|
||||
value_type yMax = f(max);
|
||||
if (std::abs(yMax) <= m_absAccuracy)
|
||||
return Result(true, 0, max, yMax);
|
||||
|
||||
// reduce interval if initial and max bracket the root
|
||||
if (yInitial * yMax < 0)
|
||||
return solve(f, initial, yInitial, max, yMax, initial, yInitial);
|
||||
|
||||
SLog(EWarn, "BrentSolver: Function values at the endpoints do not have different signs -- "
|
||||
"endpoints: [%f, %f], values: [%f, %f]", min, max, yMin, yMax);
|
||||
|
||||
return Result(false, 0, 0, 0);
|
||||
}
|
||||
Result solve(const boost::function<Float (Float)> &func,
|
||||
Float min, Float max, Float initial) const;
|
||||
|
||||
/**
|
||||
* Find a zero starting search according to the three provided points.
|
||||
|
@ -179,105 +126,15 @@ public:
|
|||
* \param y2 function value at the bracket point.
|
||||
* \return the value where the function is zero
|
||||
*/
|
||||
Result solve(Func &f,
|
||||
value_type x0, value_type y0,
|
||||
value_type x1, value_type y1,
|
||||
value_type x2, value_type y2) const {
|
||||
value_type delta = x1 - x0;
|
||||
value_type oldDelta = delta;
|
||||
|
||||
int i = 0;
|
||||
while (i < m_maxIterations) {
|
||||
if (std::abs(y2) < std::abs(y1)) {
|
||||
// use the bracket point if is better than last approximation
|
||||
x0 = x1;
|
||||
x1 = x2;
|
||||
x2 = x0;
|
||||
y0 = y1;
|
||||
y1 = y2;
|
||||
y2 = y0;
|
||||
}
|
||||
if (std::abs(y1) <= m_absAccuracy) {
|
||||
// Avoid division by very small values. Assume
|
||||
// the iteration has converged (the problem may
|
||||
// still be ill conditioned)
|
||||
return Result(true, i, x1, y1);
|
||||
}
|
||||
value_type dx = x2 - x1;
|
||||
value_type tolerance =
|
||||
std::max(m_relAccuracyPos * std::abs(x1), m_absAccuracyPos);
|
||||
|
||||
if (std::abs(dx) <= tolerance)
|
||||
return Result(true, i, x1, y1);
|
||||
if ((std::abs(oldDelta) < tolerance) ||
|
||||
(std::abs(y0) <= std::abs(y1))) {
|
||||
// Force bisection.
|
||||
delta = (value_type) 0.5f * dx;
|
||||
oldDelta = delta;
|
||||
} else {
|
||||
value_type r3 = y1 / y0;
|
||||
value_type p;
|
||||
value_type p1;
|
||||
// the equality test (x0 == x2) is intentional,
|
||||
// it is part of the original Brent's method,
|
||||
// it should NOT be replaced by proximity test
|
||||
if (x0 == x2) {
|
||||
// Linear interpolation.
|
||||
p = dx * r3;
|
||||
p1 = 1 - r3;
|
||||
} else {
|
||||
// Inverse quadratic interpolation.
|
||||
value_type r1 = y0 / y2;
|
||||
value_type r2 = y1 / y2;
|
||||
p = r3 * (dx * r1 * (r1 - r2) - (x1 - x0) * (r2 - 1));
|
||||
p1 = (r1 - 1) * (r2 - 1) * (r3 - 1);
|
||||
}
|
||||
if (p > 0) {
|
||||
p1 = -p1;
|
||||
} else {
|
||||
p = -p;
|
||||
}
|
||||
if (2 * p >= (value_type) 1.5f * dx * p1 - std::abs(tolerance * p1) ||
|
||||
p >= std::abs((value_type) 0.5f * oldDelta * p1)) {
|
||||
// Inverse quadratic interpolation gives a value
|
||||
// in the wrong direction, or progress is slow.
|
||||
// Fall back to bisection.
|
||||
delta = (value_type) 0.5f * dx;
|
||||
oldDelta = delta;
|
||||
} else {
|
||||
oldDelta = delta;
|
||||
delta = p / p1;
|
||||
}
|
||||
}
|
||||
// Save old X1, Y1
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
// Compute new X1, Y1
|
||||
if (std::abs(delta) > tolerance) {
|
||||
x1 = x1 + delta;
|
||||
} else if (dx > 0) {
|
||||
x1 = x1 + (value_type) 0.5f * tolerance;
|
||||
} else if (dx <= 0) {
|
||||
x1 = x1 - (value_type) 0.5f * tolerance;
|
||||
}
|
||||
y1 = f(x1);
|
||||
if ((y1 > 0) == (y2 > 0)) {
|
||||
x2 = x0;
|
||||
y2 = y0;
|
||||
delta = x1 - x0;
|
||||
oldDelta = delta;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
SLog(EWarn, "BrentSolver: Maximum number of iterations (%i) exceeded!",
|
||||
m_maxIterations);
|
||||
return Result(false, i, x1, y1);
|
||||
}
|
||||
private:
|
||||
int m_maxIterations;
|
||||
value_type m_absAccuracy;
|
||||
value_type m_absAccuracyPos;
|
||||
value_type m_relAccuracyPos;
|
||||
Result solve(const boost::function<Float (Float)> &func,
|
||||
Float x0, Float y0,
|
||||
Float x1, Float y1,
|
||||
Float x2, Float y2) const;
|
||||
protected:
|
||||
size_t m_maxIterations;
|
||||
Float m_absAccuracy;
|
||||
Float m_absAccuracyPos;
|
||||
Float m_relAccuracyPos;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -80,7 +80,7 @@ struct BSphere {
|
|||
|
||||
/**
|
||||
* \brief Calculate the intersection points with the given ray
|
||||
* \return \a true if the ray intersects the bounding sphere
|
||||
* \return \c true if the ray intersects the bounding sphere
|
||||
*/
|
||||
inline bool rayIntersect(const Ray &ray, Float &nearHit, Float &farHit) const {
|
||||
Vector originToCenter = center - ray.o;
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CHI_SQUARE_TEST_H)
|
||||
#define __CHI_SQUARE_TEST_H
|
||||
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/core/quad.h>
|
||||
#include <mitsuba/core/timer.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/math/distributions/chi_squared.hpp>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Chi-square goodness-of-fit test on the sphere
|
||||
*
|
||||
* This class performs a chi-square goodness-of-fit test of the null hypothesis
|
||||
* that a specified sampling procedure produces samples that are distributed
|
||||
* according to a supplied density function. This is very useful to verify BRDF
|
||||
* and phase function sampling codes for their correctness.
|
||||
*
|
||||
* This implementation works by generating a large batch of samples, which are
|
||||
* then accumulated into rectangular bins in spherical coordinates. To obtain
|
||||
* reference bin counts, the provided density function is numerically
|
||||
* integrated over the area of each bin. Comparing the actual and reference
|
||||
* bin counts yields the desired test statistic.
|
||||
*
|
||||
* Given a probability distribution with the following interface
|
||||
*
|
||||
* <code>
|
||||
* class MyDistribution {
|
||||
* // Sample a (optionally weighted) direction. A non-unity weight
|
||||
* // in the return value is needed when the sampling distribution
|
||||
* // doesn't exactly match the implementation in pdf()
|
||||
* std::pair<Vector, Float> generateSample() const;
|
||||
*
|
||||
* /// Compute the probability density for the specified direction
|
||||
* Float pdf(const Vector &direction) const;
|
||||
* };
|
||||
* </code>
|
||||
*
|
||||
* the code in this class might be used as follows
|
||||
*
|
||||
* <code>
|
||||
* MyDistribution myDistrInstance;
|
||||
* ChiSquareTest chiSqr;
|
||||
*
|
||||
* // Initialize the tables used by the chi-square test
|
||||
* chiSqr.fill(
|
||||
* boost::bind(&MyDistribution::generateSample, myDistrInstance),
|
||||
* boost::bind(&MyDistribution::pdf, myDistrInstance, _1)
|
||||
* );
|
||||
*
|
||||
* // Optional: dump the tables to a MATLAB file for external analysis
|
||||
* chiSqr.dumpTables("debug.m");
|
||||
*
|
||||
* // (the folowing assumes that the distribution has 1 parameter, e.g. exponent value)
|
||||
* if (!chiSqr.runTest(1))
|
||||
* Log(EError, "Uh oh -- test failed, the implementation is probably incorrect!");
|
||||
* </code>
|
||||
*/
|
||||
class ChiSquareTest {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a new Chi-square test instance with the given
|
||||
* resolution and sample count
|
||||
*
|
||||
* \param thetaBins
|
||||
* Number of bins wrt. latitude. The default is 10
|
||||
*
|
||||
* \param phiBins
|
||||
* Number of bins wrt. azimuth. The default is to use
|
||||
* twice the number of \c thetaBins
|
||||
*
|
||||
* \param sampleCount
|
||||
* Number of samples to be used when computing the bin
|
||||
* values. The default is \c thetaBins*phiBins*5000
|
||||
*/
|
||||
ChiSquareTest(int thetaBins = 10, int phiBins = 0, size_t sampleCount = 0)
|
||||
: m_thetaBins(thetaBins), m_phiBins(phiBins), m_sampleCount(sampleCount) {
|
||||
if (m_phiBins == 0)
|
||||
m_phiBins = 2*m_thetaBins;
|
||||
if (m_sampleCount == 0)
|
||||
m_sampleCount = m_thetaBins * m_phiBins * 1000;
|
||||
m_table = new Float[m_thetaBins*m_phiBins];
|
||||
m_refTable = new Float[m_thetaBins*m_phiBins];
|
||||
}
|
||||
|
||||
/// Release all memory
|
||||
~ChiSquareTest() {
|
||||
delete[] m_table;
|
||||
delete[] m_refTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill the actual and reference bin counts
|
||||
*
|
||||
* Please see the class documentation for a description
|
||||
* on how to invoke this function
|
||||
*/
|
||||
void fill(
|
||||
const boost::function<std::pair<Vector, Float>()> &sampleFn,
|
||||
const boost::function<Float (const Vector &)> &pdfFn) {
|
||||
memset(m_table, 0, m_thetaBins*m_phiBins*sizeof(Float));
|
||||
|
||||
SLog(EInfo, "Accumulating " SIZE_T_FMT " samples into a %ix%i"
|
||||
" contingency table", m_sampleCount, m_thetaBins, m_phiBins);
|
||||
Point2 factor(m_thetaBins / M_PI, m_phiBins / (2*M_PI));
|
||||
|
||||
ref<Timer> timer = new Timer();
|
||||
for (size_t i=0; i<m_sampleCount; ++i) {
|
||||
std::pair<Vector, Float> sample = sampleFn();
|
||||
Point2 sphCoords = toSphericalCoordinates(sample.first);
|
||||
|
||||
int thetaBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.x * factor.x)), m_thetaBins-1);
|
||||
int phiBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.y * factor.y)), m_phiBins-1);
|
||||
|
||||
m_table[thetaBin * m_phiBins + phiBin] += sample.second;
|
||||
}
|
||||
SLog(EInfo, "Done, took %i ms.", timer->getMilliseconds());
|
||||
factor = Point2(M_PI / m_thetaBins, (2*M_PI) / m_phiBins);
|
||||
|
||||
SLog(EInfo, "Integrating reference contingency table");
|
||||
timer->reset();
|
||||
Float min[2], max[2];
|
||||
size_t idx = 0;
|
||||
|
||||
NDIntegrator integrator(1, 2, 100000, 0, 1e-6f);
|
||||
Float maxError = 0, integral = 0;
|
||||
for (int i=0; i<m_thetaBins; ++i) {
|
||||
min[0] = i * factor.x;
|
||||
max[0] = (i+1) * factor.x;
|
||||
for (int j=0; j<m_phiBins; ++j) {
|
||||
min[1] = j * factor.y;
|
||||
max[1] = (j+1) * factor.y;
|
||||
Float result, error;
|
||||
size_t evals;
|
||||
|
||||
integrator.integrateVectorized(
|
||||
boost::bind(&ChiSquareTest::integrand, pdfFn, _1, _2, _3),
|
||||
min, max, &result, &error, evals
|
||||
);
|
||||
|
||||
integral += result;
|
||||
m_refTable[idx++] = result * m_sampleCount;
|
||||
maxError = std::max(maxError, error);
|
||||
}
|
||||
}
|
||||
SLog(EInfo, "Done, took %i ms (max error = %f, integral=%f).",
|
||||
timer->getMilliseconds(), maxError, integral);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dump the bin counts to a file using MATLAB format
|
||||
*/
|
||||
void dumpTables(const fs::path &filename) {
|
||||
fs::ofstream out(filename);
|
||||
out << "tbl_counts = [ ";
|
||||
for (int i=0; i<m_thetaBins; ++i) {
|
||||
for (int j=0; j<m_phiBins; ++j) {
|
||||
out << m_table[i*m_phiBins+j];
|
||||
if (j+1 < m_phiBins)
|
||||
out << ", ";
|
||||
}
|
||||
if (i+1 < m_thetaBins)
|
||||
out << "; ";
|
||||
}
|
||||
out << " ];" << endl
|
||||
<< "tbl_ref = [ ";
|
||||
for (int i=0; i<m_thetaBins; ++i) {
|
||||
for (int j=0; j<m_phiBins; ++j) {
|
||||
out << m_refTable[i*m_phiBins+j];
|
||||
if (j+1 < m_phiBins)
|
||||
out << ", ";
|
||||
}
|
||||
if (i+1 < m_thetaBins)
|
||||
out << "; ";
|
||||
}
|
||||
out << " ];" << endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform the actual chi-square test
|
||||
*
|
||||
* \param distParams
|
||||
* Number of parameters of the distribution in question.
|
||||
* Anything such as lobe width, indices of refraction, etc.
|
||||
* should be counted.
|
||||
*
|
||||
* \param pvalThresh
|
||||
* The implementation will reject the null hypothesis
|
||||
* when the computed p-value lies below this parameter
|
||||
* (default: 0.01f)
|
||||
*
|
||||
* \return \c false if the null hypothesis was rejected
|
||||
* and \c true otherwise.
|
||||
*/
|
||||
bool runTest(int distParams, Float pvalThresh = 0.01f) {
|
||||
/* Compute the chi-square statistic */
|
||||
Float chsq = 0.0f;
|
||||
Float pooledCounts = 0, pooledRef = 0;
|
||||
int pooledCells = 0;
|
||||
int df = 0;
|
||||
|
||||
for (int i=0; i<m_thetaBins*m_phiBins; ++i) {
|
||||
if (m_refTable[i] < 5) {
|
||||
pooledCounts += m_table[i];
|
||||
pooledRef += m_refTable[i];
|
||||
++pooledCells;
|
||||
} else {
|
||||
Float diff = m_table[i]-m_refTable[i];
|
||||
chsq += (diff*diff) / m_refTable[i];
|
||||
++df;
|
||||
}
|
||||
}
|
||||
|
||||
if (pooledCells > 0) {
|
||||
SLog(EInfo, "Pooled %i cells with an expected "
|
||||
"number of < 5 entries!", pooledCells);
|
||||
if (pooledRef < 5) {
|
||||
SLog(EWarn, "Even after pooling, the expected "
|
||||
"number of entries is < 5 (%f), expect badness!",
|
||||
pooledRef);
|
||||
}
|
||||
Float diff = pooledCounts - pooledRef;
|
||||
chsq += (diff*diff) / pooledRef;
|
||||
++df;
|
||||
}
|
||||
|
||||
df -= distParams + 1;
|
||||
SLog(EInfo, "Chi-square statistic = %e (df=%i)", chsq, df);
|
||||
boost::math::chi_squared chSqDist(df);
|
||||
/* Probability of obtaining a test statistic at least
|
||||
as extreme as the one observed under the assumption
|
||||
that the distributions match */
|
||||
Float pval = 1 - boost::math::cdf(chSqDist, chsq);
|
||||
SLog(EInfo, "P-value = %e", pval);
|
||||
|
||||
if (pval < pvalThresh) {
|
||||
SLog(EWarn, "Rejecting the null hypothesis");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
protected:
|
||||
static void integrand(
|
||||
const boost::function<Float (const Vector &)> &pdfFn,
|
||||
size_t nPts, const Float *in, Float *out) {
|
||||
#pragma omp parallel for
|
||||
for (size_t i=0; i<nPts; ++i)
|
||||
out[i] = pdfFn(sphericalDirection(in[2*i], in[2*i+1])) * std::sin(in[2*i]);
|
||||
}
|
||||
private:
|
||||
int m_thetaBins, m_phiBins;
|
||||
size_t m_sampleCount;
|
||||
Float *m_table;
|
||||
Float *m_refTable;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __CHI_SQUARE_TEST_H */
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
* to automatically do this for you.
|
||||
*
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param abstract \c true if the class contains pure virtual methods
|
||||
* \param superClassName Name of the parent class
|
||||
* \param instPtr Pointer to an instantiation function
|
||||
* \param unSerPtr Pointer to an unserialization function
|
||||
|
@ -124,6 +124,8 @@ private:
|
|||
|
||||
/*! @{ */
|
||||
|
||||
#define MTS_CLASS(x) x::m_theClass
|
||||
|
||||
/**
|
||||
* \brief This macro must be used in the declaration of
|
||||
* all classes derived from \ref Object.
|
||||
|
@ -136,7 +138,7 @@ public: \
|
|||
/**
|
||||
* \brief Creates basic RTTI support for a class
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param abstract \c true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS(name, abstract, super) \
|
||||
|
@ -149,7 +151,7 @@ public: \
|
|||
* \brief Creates basic RTTI support for a class. Assumes that
|
||||
* the class can be instantiated by name.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param abstract \c true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_I(name, abstract, super) \
|
||||
|
@ -165,7 +167,7 @@ public: \
|
|||
* \brief Creates basic RTTI support for a class. Assumes that
|
||||
* the class can be unserialized from a binary data stream.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param abstract \c true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_S(name, abstract, super) \
|
||||
|
@ -182,7 +184,7 @@ public: \
|
|||
* the class can be unserialized from a binary data stream as well
|
||||
* as instantiated by name.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param abstract \c true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_IS(name, abstract, super) \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -24,14 +24,25 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Stream-style interface to the default stdin/stdout console streams
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE ConsoleStream : public Stream {
|
||||
public:
|
||||
// =============================================================
|
||||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/// Create a new console stream
|
||||
ConsoleStream();
|
||||
|
||||
/* Stream implementation */
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Implementation of the Stream interface
|
||||
// =============================================================
|
||||
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
|
@ -42,6 +53,9 @@ public:
|
|||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -36,7 +36,7 @@ MTS_NAMESPACE_BEGIN
|
|||
*/
|
||||
class MTS_EXPORT_CORE FileStream : public Stream {
|
||||
public:
|
||||
/// File opening modes
|
||||
/// Supported file opening modes
|
||||
enum EFileMode {
|
||||
EReadOnly = 0, ///< rb
|
||||
EReadWrite, ///< rb+
|
||||
|
@ -46,12 +46,23 @@ public:
|
|||
EAppendReadWrite ///< ab+
|
||||
};
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/// Create a file stream class with no file open
|
||||
FileStream();
|
||||
|
||||
/// Create a file stream class and open a file with a given EFileMode
|
||||
explicit FileStream(const fs::path &path, EFileMode mode = EReadOnly);
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name File-specific features
|
||||
// =============================================================
|
||||
|
||||
/// Return the file path
|
||||
inline const fs::path &getPath() const { return m_path; }
|
||||
|
||||
|
@ -67,7 +78,13 @@ public:
|
|||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
|
||||
/* Stream implementation */
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Stream interface
|
||||
// =============================================================
|
||||
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
|
@ -78,6 +95,9 @@ public:
|
|||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/** \brief Virtual destructor
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -62,7 +62,7 @@ class MTS_EXPORT_CORE WaitFlag : public Object {
|
|||
public:
|
||||
/**
|
||||
* \brief Create a new wait flag
|
||||
* @param flag
|
||||
* \param flag
|
||||
* Initial state of the flag. If set to true, \ref wait()
|
||||
* will immediately return.
|
||||
*/
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
* \brief Temporarily wait for the flag to be set to true
|
||||
*
|
||||
* Similar to \ref wait(), but also uses a time value given
|
||||
* in milliseconds. A return value of \a false signals
|
||||
* in milliseconds. A return value of \c false signals
|
||||
* that a timeout has occurred.
|
||||
*
|
||||
* \param ms Maximum waiting time in milliseconds
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
* \brief Temporarily wait for a signal and release the lock in the meanwhile.
|
||||
*
|
||||
* Similar to wait(), but also uses a time value given
|
||||
* in milliseconds. A return value of \a false signals
|
||||
* in milliseconds. A return value of \c false signals
|
||||
* that a timeout has occurred. The lock is held after
|
||||
* returning in either case.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -279,7 +279,7 @@ public:
|
|||
* together in a packed format)
|
||||
* \param piv Storage for the permutation created by the pivoting
|
||||
* \param pivsign Sign of the permutation
|
||||
* \return \a true if the matrix was nonsingular.
|
||||
* \return \c true if the matrix was nonsingular.
|
||||
*
|
||||
* Based on the implementation in JAMA.
|
||||
*/
|
||||
|
@ -291,7 +291,7 @@ public:
|
|||
*
|
||||
* \param L Target matrix (a lower triangular matrix such
|
||||
* that A=L*L')
|
||||
* \return \a false If the matrix is not symmetric positive
|
||||
* \return \c false If the matrix is not symmetric positive
|
||||
* definite.
|
||||
* Based on the implementation in JAMA.
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -32,12 +32,30 @@ MTS_NAMESPACE_BEGIN
|
|||
*/
|
||||
class MTS_EXPORT_CORE MemoryStream : public Stream {
|
||||
public:
|
||||
// =============================================================
|
||||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/// Create a new memory stream
|
||||
MemoryStream(size_t initialSize = 512);
|
||||
|
||||
/// Create a memory stream, which operates on a pre-allocated buffer
|
||||
/**
|
||||
* \brief Create a memory stream, which operates on a
|
||||
* pre-allocated buffer.
|
||||
*
|
||||
* A memory stream created in this way will never resize the
|
||||
* underlying buffer. An exception is thrown e.g. when attempting
|
||||
* to extend its size
|
||||
*/
|
||||
MemoryStream(void *ptr, size_t size);
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Memory stream-specific features
|
||||
// =============================================================
|
||||
|
||||
/// Return the underlying data
|
||||
inline uint8_t *getData() { return m_data; }
|
||||
|
||||
|
@ -53,7 +71,13 @@ public:
|
|||
/// Set size and position to zero without changing the underlying buffer
|
||||
void reset();
|
||||
|
||||
/* Stream implementation */
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Implementation of the Stream interface
|
||||
// =============================================================
|
||||
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
|
@ -64,6 +88,9 @@ public:
|
|||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -76,7 +76,11 @@ protected:
|
|||
public:
|
||||
static Class *m_theClass; ///< Pointer to the object's class descriptor
|
||||
private:
|
||||
#ifndef WIN32
|
||||
volatile mutable int m_refCount;
|
||||
#else
|
||||
volatile mutable LONG m_refCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline int Object::getRefCount() const {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -55,12 +55,12 @@ public:
|
|||
}
|
||||
|
||||
/// Access a PDF entry
|
||||
inline Float &operator[](unsigned int entry) {
|
||||
inline Float &operator[](size_t entry) {
|
||||
return m_pdf[entry];
|
||||
}
|
||||
|
||||
/// Access a PDF entry
|
||||
inline const Float &operator[](unsigned int entry) const {
|
||||
inline const Float &operator[](size_t entry) const {
|
||||
return m_pdf[entry];
|
||||
}
|
||||
|
||||
|
@ -82,10 +82,10 @@ public:
|
|||
inline Float build() {
|
||||
SAssert(m_pdf.size() > 0);
|
||||
m_cdf[0] = 0.0f;
|
||||
for (unsigned int i=1; i<m_cdf.size(); ++i)
|
||||
for (size_t i=1; i<m_cdf.size(); ++i)
|
||||
m_cdf[i] = m_cdf[i-1] + m_pdf[i-1];
|
||||
m_originalSum = m_cdf[m_cdf.size()-1];
|
||||
for (unsigned int i=0; i<m_pdf.size(); ++i) {
|
||||
for (size_t i=0; i<m_pdf.size(); ++i) {
|
||||
m_cdf[i] /= m_originalSum;
|
||||
m_pdf[i] /= m_originalSum;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -132,6 +132,7 @@ extern std::string __ubi_bundlepath();
|
|||
extern void __ubi_chdir_to_bundlepath();
|
||||
#define MTS_AUTORELEASE_BEGIN() __ubi_autorelease_begin();
|
||||
#define MTS_AUTORELEASE_END() __ubi_autorelease_end();
|
||||
#define MTS_AMBIGUOUS_SIZE_T 1
|
||||
#else
|
||||
#define MTS_AUTORELEASE_BEGIN()
|
||||
#define MTS_AUTORELEASE_END()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -72,10 +72,14 @@ public:
|
|||
|
||||
/// Set an integer value
|
||||
void setLong(const std::string &name, int64_t value, bool warnDuplicates = true);
|
||||
/// Get an intteger value
|
||||
/// Get an integer value
|
||||
int64_t getLong(const std::string &name) const;
|
||||
/// Get an integer value (with default);
|
||||
int64_t getLong(const std::string &name, int64_t defVal) const;
|
||||
/// Get a size value
|
||||
size_t getSize(const std::string &name) const;
|
||||
/// Get an size value (with default);
|
||||
size_t getSize(const std::string &name, size_t defVal) const;
|
||||
|
||||
/// Set a single precision floating point value
|
||||
void setFloat(const std::string &name, Float value, bool warnDuplicates = true);
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
/*
|
||||
Copyright (C) 2008 Klaus Spanderen
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
This file is based on code in QuantLib, a free-software/open-source library
|
||||
for financial quantitative analysts and developers - http://quantlib.org/
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
QuantLib is free software: you can redistribute it and/or modify it
|
||||
under the terms of the QuantLib license. You should have received a
|
||||
copy of the license along with this program; if not, please email
|
||||
<quantlib-dev@lists.sf.net>. The license is also available online at
|
||||
<http://quantlib.org/license.shtml>.
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the license for more details.
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(__QUADRATURE_H)
|
||||
#define __QUADRATURE_H
|
||||
|
||||
|
@ -24,9 +26,10 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Computes the integral of a one-dimensional function.
|
||||
* \brief Computes the integral of a one-dimensional function
|
||||
* using adaptive Gauss-Lobatto quadrature.
|
||||
*
|
||||
* Given a target accuracy \f$ \epsilon \f$, the integral of
|
||||
* Given a target error \f$ \epsilon \f$, the integral of
|
||||
* a function \f$ f \f$ between \f$ a \f$ and \f$ b \f$ is
|
||||
* calculated by means of the Gauss-Lobatto formula.
|
||||
*
|
||||
|
@ -39,10 +42,17 @@ MTS_NAMESPACE_BEGIN
|
|||
*
|
||||
* The original MATLAB version can be downloaded here
|
||||
* http://www.inf.ethz.ch/personal/gander/adaptlob.m
|
||||
*
|
||||
* This particular implementation is based on code in QuantLib,
|
||||
* a free-software/open-source library for financial quantitative
|
||||
* analysts and developers - http://quantlib.org/
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE GaussLobattoIntegrator {
|
||||
public:
|
||||
typedef boost::function<Float (Float)> Integrand;
|
||||
|
||||
/**
|
||||
* Initialize a Gauss-Lobatto integration scheme
|
||||
*
|
||||
|
@ -50,22 +60,25 @@ public:
|
|||
* integrator will throw an exception when this limit is
|
||||
* exceeded.
|
||||
*
|
||||
* \param absAccuracy Absolute accuracy requirement (0 to disable)
|
||||
* \param relAccuracy Relative accuracy requirement (0 to disable)
|
||||
* \param absError Absolute error requirement (0 to disable)
|
||||
* \param relError Relative error requirement (0 to disable)
|
||||
*
|
||||
* \param useConvergenceEstimate Estimate the convergence behavior
|
||||
* of the GL-quadrature by comparing the 4, 7 and 13-point
|
||||
* variants and increase the absolute tolerance accordingly.
|
||||
*/
|
||||
GaussLobattoIntegrator(size_t maxEvals,
|
||||
Float absAccuracy = 0,
|
||||
Float relAccuracy = 0,
|
||||
Float absError = 0,
|
||||
Float relError = 0,
|
||||
bool useConvergenceEstimate = true);
|
||||
|
||||
Float integrate(const boost::function<Float (Float)>& f,
|
||||
Float a, Float b);
|
||||
|
||||
inline size_t getEvaluations() const { return m_evals; }
|
||||
/**
|
||||
* \brief Integrate the function \c f from \c a to \c b.
|
||||
*
|
||||
* Also returns the total number of evaluations
|
||||
*/
|
||||
Float integrate(const Integrand &f, Float a, Float b,
|
||||
size_t &evals) const;
|
||||
protected:
|
||||
/**
|
||||
* \brief Perform one step of the 4-point Gauss-Lobatto rule, then
|
||||
|
@ -80,18 +93,17 @@ protected:
|
|||
* \param is Absolute tolerance in epsilons
|
||||
*/
|
||||
Float adaptiveGaussLobattoStep(const boost::function<Float (Float)>& f,
|
||||
Float a, Float b, Float fa, Float fb,
|
||||
Float is);
|
||||
Float a, Float b, Float fa, Float fb, Float is, size_t &evals) const;
|
||||
|
||||
/**
|
||||
* Compute the absolute error tolerance using a 13-point
|
||||
* Gauss-Lobatto rule.
|
||||
*/
|
||||
Float calculateAbsTolerance(const boost::function<Float (Float)>& f,
|
||||
Float a, Float b);
|
||||
|
||||
Float m_absAccuracy, m_relAccuracy;
|
||||
size_t m_evals, m_maxEvals;
|
||||
Float a, Float b, size_t &evals) const;
|
||||
protected:
|
||||
Float m_absError, m_relError;
|
||||
size_t m_maxEvals;
|
||||
const bool m_useConvergenceEstimate;
|
||||
static const Float m_alpha;
|
||||
static const Float m_beta;
|
||||
|
@ -100,6 +112,104 @@ protected:
|
|||
static const Float m_x3;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Adaptively computes the integral of a multidimensional function using
|
||||
* either a Gauss-Kronod (1D) or a Genz-Malik (>1D) cubature rule.
|
||||
*
|
||||
* This class is a C++ wrapper around the \c cubature code by Steven G. Johnson
|
||||
* (http://ab-initio.mit.edu/wiki/index.php/Cubature)
|
||||
*
|
||||
* The original implementation is based on algorithms proposed in
|
||||
*
|
||||
* A. C. Genz and A. A. Malik, "An adaptive algorithm for numeric integration
|
||||
* over an N-dimensional rectangular region," J. Comput. Appl. Math. 6 (4),
|
||||
* 295–302 (1980).
|
||||
*
|
||||
* and
|
||||
*
|
||||
* J. Berntsen, T. O. Espelid, and A. Genz, "An adaptive algorithm for the
|
||||
* approximate calculation of multiple integrals," ACM Trans. Math. Soft. 17
|
||||
* (4), 437–451 (1991).
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE NDIntegrator {
|
||||
public:
|
||||
typedef boost::function<void (const Float *, Float *)> Integrand;
|
||||
typedef boost::function<void (size_t, const Float *, Float *)> VectorizedIntegrand;
|
||||
|
||||
enum EResult {
|
||||
ESuccess = 0,
|
||||
EFailure = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the Cubature integration scheme
|
||||
*
|
||||
* \param fDim Number of integrands (i.e. dimensions of the image space)
|
||||
* \param nDim Number of integration dimensions (i.e. dimensions of the
|
||||
* function domain)
|
||||
* \param maxEvals Maximum number of function evaluationn (0 means no
|
||||
* limit). The error bounds will likely be exceeded when the
|
||||
* integration is forced to stop prematurely. Note: the actual
|
||||
* number of evaluations may somewhat exceed this value.
|
||||
* \param absError Absolute error requirement (0 to disable)
|
||||
* \param relError Relative error requirement (0 to disable)
|
||||
*/
|
||||
NDIntegrator(size_t fDim, size_t dim,
|
||||
size_t maxEvals, Float absError = 0, Float relError = 0);
|
||||
|
||||
/**
|
||||
* \brief Integrate the function \c f over the rectangular domain
|
||||
* bounded by \c min and \c max.
|
||||
*
|
||||
* The supplied function should have the interface
|
||||
*
|
||||
* <code>
|
||||
* void integrand(const Float *in, Float *out);
|
||||
* </code>
|
||||
*
|
||||
* The input array \c in consists of one set of input parameters
|
||||
* having \c dim entries. The function is expected to store the
|
||||
* results of the evaluation into the \c out array using \c fDim entries.
|
||||
*/
|
||||
EResult integrate(const Integrand &f, const Float *min, const Float *max,
|
||||
Float *result, Float *error, size_t &evals) const;
|
||||
|
||||
/**
|
||||
* \brief Integrate the function \c f over the rectangular domain
|
||||
* bounded by \c min and \c max.
|
||||
*
|
||||
* This function implements a vectorized version of the above
|
||||
* integration function, which is more efficient by evaluating
|
||||
* the integrant in `batches'. The supplied function should
|
||||
* have the interface
|
||||
*
|
||||
* <code>
|
||||
* void integrand(int numPoints, const Float *in, Float *out);
|
||||
* </code>
|
||||
*
|
||||
* Note that \c in in is not a single point, but an array of \c numPoints points
|
||||
* (length \c numPoints x \c dim), and upon return the values of all \c fDim
|
||||
* integrands at all \c numPoints points should be stored in \c out
|
||||
* (length \c fDim x \c numPoints). In particular, out[i*dim + j] is the j-th
|
||||
* coordinate of the i-th point, and the k-th function evaluation (k<fDim)
|
||||
* for the i-th point is returned in out[k*npt + i].
|
||||
* The size of \c numPoints will vary with the dimensionality of the problem;
|
||||
* higher-dimensional problems will have (exponentially) larger numbers,
|
||||
* allowing for the possibility of more parallelism. Currently, \c numPoints
|
||||
* starts at 15 in 1d, 17 in 2d, and 33 in 3d, but as the integrator
|
||||
* calls your integrand more and more times the value will grow. e.g. if you end
|
||||
* up requiring several thousand points in total, \c numPoints may grow to
|
||||
* several hundred.
|
||||
*/
|
||||
EResult integrateVectorized(const VectorizedIntegrand &f, const Float *min,
|
||||
const Float *max, Float *result, Float *error, size_t &evals) const;
|
||||
protected:
|
||||
size_t m_fdim, m_dim, m_maxEvals;
|
||||
Float m_absError, m_relError;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __QUADRATURE_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -120,10 +120,10 @@ public:
|
|||
void seed(uint64_t *values, uint64_t length);
|
||||
|
||||
/// Return an integer on the [0, 2^63-1]-interval
|
||||
uint64_t nextLong();
|
||||
uint64_t nextULong();
|
||||
|
||||
/// Return an integer on the [0, n)-interval
|
||||
unsigned int nextInteger(unsigned int n);
|
||||
uint32_t nextUInt(uint32_t n);
|
||||
|
||||
/// Return a floating point value on the [0, 1) interval
|
||||
Float nextFloat();
|
||||
|
@ -136,7 +136,7 @@ public:
|
|||
*/
|
||||
template <typename Iterator> void shuffle(Iterator it1, Iterator it2) {
|
||||
for (Iterator it = it2 - 1; it > it1; --it)
|
||||
std::iter_swap(it, it1 + nextInteger((int) (it-it1)));
|
||||
std::iter_swap(it, it1 + nextUInt((uint32_t) (it-it1)));
|
||||
}
|
||||
|
||||
/// Serialize a random generator to a binary data stream
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -182,6 +182,21 @@ struct RayDifferential : public Ray {
|
|||
#endif
|
||||
hasDifferentials = false;
|
||||
}
|
||||
|
||||
/// Return a string representation of this ray
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "RayDifferential[" << endl
|
||||
<< " orig = " << o.toString() << "," << endl
|
||||
<< " dest = " << d.toString() << "," << endl
|
||||
<< " mint = " << mint << "," << endl
|
||||
<< " maxt = " << maxt << "," << endl
|
||||
<< " time = " << time << "," << endl
|
||||
<< " rx = " << indent(rx.toString()) << "," << endl
|
||||
<< " ry = " << indent(ry.toString()) << endl
|
||||
<< "]" << endl;
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(MTS_SSE)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -268,7 +268,7 @@ public:
|
|||
* \brief Is this process strictly local?
|
||||
*
|
||||
* If a process is marked as local, it shouldn't be distributed
|
||||
* to remote processing nodes? The default implementation
|
||||
* to remote processing nodes. The default implementation
|
||||
* returns false.
|
||||
*/
|
||||
virtual bool isLocal() const;
|
||||
|
@ -327,8 +327,8 @@ public:
|
|||
* \brief Schedule a parallelizable process for execution.
|
||||
*
|
||||
* If the scheduler is currently running and idle, its execution
|
||||
* will begin immediately. Returns \a false if the process
|
||||
* is already scheduled and has not yet terminated and \a true
|
||||
* will begin immediately. Returns \c false if the process
|
||||
* is already scheduled and has not yet terminated and \c true
|
||||
* in any other case.
|
||||
*/
|
||||
bool schedule(ParallelProcess *process);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -216,15 +216,15 @@ public:
|
|||
/**
|
||||
* \brief Create a new stream backend
|
||||
*
|
||||
* @param name
|
||||
* \param name
|
||||
* Name of the created thread
|
||||
* @param scheduler
|
||||
* \param scheduler
|
||||
* Scheduler instance used to process work units
|
||||
* @param nodeName
|
||||
* \param nodeName
|
||||
* Exposed name of this node
|
||||
* @param stream
|
||||
* \param stream
|
||||
* Stream used for communications
|
||||
* @param detach
|
||||
* \param detach
|
||||
* Should the associated thread be joinable or detach instead?
|
||||
*/
|
||||
StreamBackend(const std::string &name, Scheduler *scheduler,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
m_points.reserve(m_size.x*m_size.y);
|
||||
m_size = size; m_pos = PointType(0);
|
||||
generate(
|
||||
log2i(std::max(m_size.x, m_size.y)),
|
||||
log2i((uint32_t) std::max(m_size.x, m_size.y)),
|
||||
ENorth, EEast, ESouth, EWest);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -27,7 +27,7 @@ MTS_NAMESPACE_BEGIN
|
|||
/** \brief Stream implementation based on an encrypted SSH tunnel
|
||||
*
|
||||
* This class remotely starts a program and exposes its stdin/stdout
|
||||
* streams through an instance of <tt>\ref Stream</tt>. To make all
|
||||
* streams through an instance of \ref Stream. To make all
|
||||
* of this work, passwordless authentication must be enabled (for
|
||||
* example by using public key authentication in addition to a
|
||||
* running ssh-agent, which stores the decrypted private key).
|
||||
|
@ -42,6 +42,10 @@ MTS_NAMESPACE_BEGIN
|
|||
*/
|
||||
class MTS_EXPORT_CORE SSHStream : public Stream {
|
||||
public:
|
||||
// =============================================================
|
||||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/**
|
||||
* Create a new SSH stream. The timeout parameter specifies specifies
|
||||
* the maximum amount of time that can be spent before failing to
|
||||
|
@ -60,16 +64,12 @@ public:
|
|||
int port = 22, int timeout = 10
|
||||
);
|
||||
|
||||
/* Stream implementation */
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
size_t getPos() const;
|
||||
size_t getSize() const;
|
||||
void truncate(size_t size);
|
||||
void flush();
|
||||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name SSH stream-specific features
|
||||
// =============================================================
|
||||
|
||||
/// Return the destination machine's host name
|
||||
inline const std::string &getHostName() const { return m_hostName; }
|
||||
|
@ -83,6 +83,27 @@ public:
|
|||
/// Return the number of sent bytes
|
||||
inline size_t getSentBytes() const { return m_sent; }
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Implementation of the Stream interface
|
||||
// =============================================================
|
||||
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
size_t getPos() const;
|
||||
size_t getSize() const;
|
||||
void truncate(size_t size);
|
||||
void flush();
|
||||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -30,13 +30,19 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Portable %Stream implementation, which encapsulates a socket
|
||||
* for IPv4/IPv6 network communications. Set to use network byte order
|
||||
* by default.
|
||||
* for IPv4/IPv6 network communications.
|
||||
*
|
||||
* By default, this type of stream is configured to use network byte
|
||||
* order (= big endian).
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE SocketStream : public Stream {
|
||||
public:
|
||||
// =============================================================
|
||||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/// Create a stream from an existing socket
|
||||
#if defined(WIN32)
|
||||
SocketStream(SOCKET socket);
|
||||
|
@ -47,16 +53,12 @@ public:
|
|||
/// Connect to the given host/port
|
||||
SocketStream(const std::string &host, int port);
|
||||
|
||||
/* Stream implementation */
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
size_t getPos() const;
|
||||
size_t getSize() const;
|
||||
void truncate(size_t size);
|
||||
void flush();
|
||||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Socket stream-specific features
|
||||
// =============================================================
|
||||
|
||||
/// Return the peer's name
|
||||
inline const std::string &getPeer() const { return m_peer; }
|
||||
|
@ -70,9 +72,29 @@ public:
|
|||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
|
||||
/// Handle a socket error
|
||||
/// Handle the last socket-specific error (looks up the appropriate OS description)
|
||||
static void handleError(const std::string &cmd, ELogLevel level = EError);
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
//! @{ \name Implementation of the Stream interface
|
||||
// =============================================================
|
||||
|
||||
void read(void *ptr, size_t size);
|
||||
void write(const void *ptr, size_t size);
|
||||
void setPos(size_t pos);
|
||||
size_t getPos() const;
|
||||
size_t getSize() const;
|
||||
void truncate(size_t size);
|
||||
void flush();
|
||||
bool canWrite() const;
|
||||
bool canRead() const;
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/** \brief Virtual destructor
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -27,21 +27,23 @@ MTS_NAMESPACE_BEGIN
|
|||
// Statistics collection
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/// Size of the console-based progress message
|
||||
/// Size (in characters) of the console-based progress message
|
||||
#define PROGRESS_MSG_SIZE 56
|
||||
|
||||
/**
|
||||
* Specifies the number of internal counters associated with each
|
||||
* statistics counter. Needed for SMP/ccNUMA systems where different
|
||||
* processors might be contending for a cache line containing a counter.
|
||||
* The solution used here tries to ensure that every processor has
|
||||
* its own local counter.
|
||||
* \ref StatsCounter instance.
|
||||
*
|
||||
* This is needed for SMP/ccNUMA systems where different processors might
|
||||
* be contending for a cache line containing a counter. The solution used
|
||||
* here tries to ensure that every processor has its own local counter.
|
||||
*/
|
||||
|
||||
#define NUM_COUNTERS 128 // Must be a power of 2
|
||||
|
||||
/// Bitmask for \ref NUM_COUNTERS
|
||||
#define NUM_COUNTERS_MASK (NUM_COUNTERS-1)
|
||||
|
||||
/// Determines the multiples (e.g. 1000, 1024) and units
|
||||
/// Determines the multiples (e.g. 1000, 1024) and units of a \ref StatsCounter
|
||||
enum EStatsType {
|
||||
ENumberValue = 0, ///< Simple unitless number, e.g. # of rays
|
||||
EByteCount, ///< Number of read/written/transferred bytes
|
||||
|
@ -52,8 +54,7 @@ enum EStatsType {
|
|||
/**
|
||||
* \brief Counter data structure, which is suitable for ccNUMA/SMP machines
|
||||
*
|
||||
* This counter takes up at least one cache line
|
||||
* to reduce false sharing.
|
||||
* This counter takes up at least one cache line to reduce false sharing.
|
||||
*/
|
||||
struct CacheLineCounter {
|
||||
#if (defined(WIN32) && !defined(WIN64)) || (defined(__POWERPC__) && !defined(_LP64))
|
||||
|
@ -185,6 +186,13 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
/// Reset the stored counter values
|
||||
inline void reset() {
|
||||
for (int i=0; i<NUM_COUNTERS; ++i) {
|
||||
m_value[i].value = m_base[i].value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sorting by name (for the statistics)
|
||||
bool operator<(const StatsCounter &v) const;
|
||||
private:
|
||||
|
@ -196,6 +204,11 @@ private:
|
|||
};
|
||||
|
||||
/** \brief General-purpose progress reporter
|
||||
*
|
||||
* This class is used to track the progress of various operations that might
|
||||
* take longer than, say, a second. It provides interactive feedback on both
|
||||
* the console binaries and within Mitsuba's Qt-based GUI.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE ProgressReporter {
|
||||
|
@ -241,8 +254,9 @@ private:
|
|||
const void *m_ptr;
|
||||
};
|
||||
|
||||
/** \brief Collects various rendering statistics. Only
|
||||
* one instance is created during a program run
|
||||
/** \brief Collects various rendering statistics and presents them
|
||||
* in a human-readable form.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
class MTS_EXPORT_CORE Statistics : public Object {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -88,76 +88,8 @@ namespace std {
|
|||
};
|
||||
using std::select2nd;
|
||||
using std::compose1;
|
||||
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
MTS_NAMESPACE_BEGIN
|
||||
extern MTS_EXPORT_CORE void * __restrict allocAligned(size_t size);
|
||||
extern MTS_EXPORT_CORE void freeAligned(void *ptr);
|
||||
|
||||
/**
|
||||
* \brief Aligned memory allocator for use with SSE2-based code
|
||||
* \headerfile mitsuba/core/stl.h mitsuba/mitsuba.h
|
||||
*
|
||||
* Basic implementaiton, which forwards all calls to \ref allocAligned.
|
||||
*/
|
||||
template <typename T> class aligned_allocator {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
/// \cond
|
||||
template <class U> struct rebind {
|
||||
typedef aligned_allocator<U> other;
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
pointer address (reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
const_pointer address (const_reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
aligned_allocator() throw() { }
|
||||
|
||||
aligned_allocator(const aligned_allocator&) throw() { }
|
||||
|
||||
template <class U> aligned_allocator (const aligned_allocator<U>&) throw() { }
|
||||
|
||||
~aligned_allocator() throw() { }
|
||||
|
||||
size_type max_size () const throw() {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
||||
T* __restrict allocate (size_type num, const_pointer *hint = 0) {
|
||||
return (T *) mitsuba::allocAligned(num*sizeof(T));
|
||||
}
|
||||
|
||||
void construct (pointer p, const T& value) {
|
||||
*p=value;
|
||||
}
|
||||
|
||||
void destroy (pointer p) {
|
||||
p->~T();
|
||||
};
|
||||
|
||||
void deallocate (pointer p, size_type num) {
|
||||
freeAligned(p);
|
||||
}
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#if defined(WIN32)
|
||||
inline bool mts_isnan(float f) {
|
||||
int classification = ::_fpclass(f);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -67,7 +67,9 @@ public:
|
|||
/// Return a string representation
|
||||
virtual std::string toString() const;
|
||||
|
||||
/// @{ \name Abstract methods to be implemented by subclasses
|
||||
// ======================================================================
|
||||
/// @{ \name Abstract methods that need to be implemented by subclasses
|
||||
// ======================================================================
|
||||
|
||||
/// Read a specified amount of data from the stream
|
||||
virtual void read(void *ptr, size_t size) = 0;
|
||||
|
@ -97,8 +99,11 @@ public:
|
|||
virtual bool canRead() const = 0;
|
||||
|
||||
/// @}
|
||||
// ======================================================================
|
||||
|
||||
/// @{ \name Convenience functions
|
||||
// ======================================================================
|
||||
/// @{ \name Convenience functions with automatic endianness conversion
|
||||
// ======================================================================
|
||||
|
||||
/// Skip the given number of bytes
|
||||
void skip(size_t amount);
|
||||
|
@ -139,9 +144,12 @@ public:
|
|||
/// Write an array of signed ints (64 bit) to the stream
|
||||
void writeLongArray(const int64_t *values, size_t size);
|
||||
|
||||
/// Write an unsigned int (32 bit) to the stream
|
||||
/// Write an unsigned int (64 bit) to the stream
|
||||
void writeULong(uint64_t value);
|
||||
|
||||
|
||||
/// Write a size value to the stream
|
||||
void writeSize(size_t value) { writeULong((uint64_t) value); }
|
||||
|
||||
/// Write an array of unsigned ints (64 bit) to the stream
|
||||
void writeULongArray(const uint64_t *values, size_t size);
|
||||
|
||||
|
@ -225,6 +233,9 @@ public:
|
|||
|
||||
/// Read an unsigned int (64 bit) from the stream
|
||||
uint64_t readULong();
|
||||
|
||||
/// Read a size value from the stream
|
||||
size_t readSize() { return (size_t) readULong(); }
|
||||
|
||||
/// Read an array of unsigned ints (64 bit) from the stream
|
||||
void readULongArray(uint64_t *dst, size_t size);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
* This does not always work -- for instance, Linux
|
||||
* requires root privileges for this operation.
|
||||
*
|
||||
* \return \a true upon success.
|
||||
* \return \c true upon success.
|
||||
*/
|
||||
bool setPriority(EThreadPriority priority);
|
||||
|
||||
|
@ -66,7 +66,7 @@ public:
|
|||
*
|
||||
* When an thread marked critical crashes from an uncaught
|
||||
* exception, the whole process is brought down.
|
||||
* The default is \a false.
|
||||
* The default is \c false.
|
||||
*/
|
||||
inline void setCritical(bool critical) { m_critical = critical; }
|
||||
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
static void staticShutdown();
|
||||
|
||||
/// Initialize Mitsuba's threading system for simultaneous use of OpenMP
|
||||
static void initializeOpenMP();
|
||||
static void initializeOpenMP(size_t threadCount);
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue