merge with the media-0.2.1 branch (contains a completely redesigned medium rendering layer, fixes the Blender plugin and contains many other bugfixes)

metadata
Wenzel Jakob 2011-04-14 18:02:35 +02:00
commit 8573a9b28c
452 changed files with 11350 additions and 6379 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
-->
<scene>
<integrator id="integrator" type="path">
<integrator id="integrator" type="volpath">
<integer name="maxDepth" value="$depth"/>
</integrator>

View File

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

View File

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

View File

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

View File

@ -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', '')
},
{

View File

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

View File

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

View File

@ -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), [])

View File

@ -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'
}
]

View File

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

View File

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

View File

@ -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',
},
]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
\documentclass[footexclude,12pt,DIV11]{scrartcl}
\documentclass[footexclude,11pt,DIV11]{scrartcl}
% Wenzel's standard prelude
% ----- 8< ----- 8< ------

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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),
* 295302 (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), 437451 (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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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