diff --git a/SConstruct b/SConstruct index 8caceb1f..8d3ee649 100644 --- a/SConstruct +++ b/SConstruct @@ -34,6 +34,8 @@ build('src/librender/SConscript') build('src/libhw/SConscript') # Bidirectional support library build('src/libbidir/SConscript') +# Python binding library +build('src/libpython/SConscript') # ===== Build the applications ===== env = env.Clone() @@ -45,11 +47,12 @@ mainEnv = build('src/mitsuba/SConscript') converter_objects = build('src/converter/SConscript', ['mainEnv']) # Build the Qt-based GUI binaries -build('src/qtgui/SConscript', ['mainEnv', 'converter_objects'], duplicate=True) +build('src/mtsgui/SConscript', ['mainEnv', 'converter_objects'], duplicate=True) + +env['SHLIBPREFIX']='' # ===== Build the plugins ===== -env['SHLIBPREFIX']='' Export('env') # Utilities diff --git a/build/SConscript.configure b/build/SConscript.configure index e8d5b5e5..788bcd9f 100644 --- a/build/SConscript.configure +++ b/build/SConscript.configure @@ -1,4 +1,4 @@ -import multiprocessing +import re, multiprocessing Import('sys', 'os', 'SCons', 'resources') @@ -14,15 +14,20 @@ print("Using configuation file \"%s\"" % configFile) AddOption("--parallelize", dest="parallelize", action='store_true', help='Parallelize to the available number of cores?') parallelize = GetOption('parallelize') +EnsureSConsVersion(2, 0, 0) + if parallelize == True: SetOption('num_jobs', multiprocessing.cpu_count()) if not os.path.exists(configFile): - print 'A configuration file must be selected! Have a look at http://www.mitsuba-renderer.org/docs.html' + print '\nA configuration file must be selected! Have a look at http://www.mitsuba-renderer.org/docs.html' Exit(1) -if (sys.platform == 'win32' or sys.platform == 'darwin') and not os.path.exists(GetBuildPath('#dependencies')): - print 'The dependencies are missing -- see http://www.mitsuba-renderer.org/devblog/archives/11-Build-system-changes.html' +if not os.path.exists(GetBuildPath('#dependencies')): + print '\nThe build dependency files are missing -- please check them out' + print 'from Mercurial by running the following command *inside* the ' + print 'Mitsuba directory:\n' + print '$ hg clone https://www.mitsuba-renderer.org/hg/dependencies\n' Exit(1) # Parse configuration options @@ -32,14 +37,17 @@ vars.Add('DISTDIR', 'Target directory for the final build') vars.Add('CXX', 'C++ compiler') vars.Add('CC', 'C compiler') vars.Add('CXXFLAGS', 'C++ flags') -vars.Add('CCFLAGS', 'C compiler flags') -vars.Add('SHCXXFLAGS', 'C++ flags (for shared libraries)') +vars.Add('SHCXXFLAGS', 'Extra C++ flags (for shared libraries)') +vars.Add('CCFLAGS', 'Extra C++ flags (for C files)') vars.Add('LINK', 'Linker') vars.Add('LINKFLAGS', 'Linker flags') vars.Add('SHLINKFLAGS', 'Linker flags (dynamic libraries)') vars.Add('BASEINCLUDE', 'Base include path') vars.Add('BASELIB', 'Base libraries') vars.Add('BASELIBDIR', 'Base library search path') +vars.Add('PYTHONINCLUDE', 'Python include path') +vars.Add('PYTHONLIB', 'Python libraries') +vars.Add('PYTHONLIBDIR', 'Python library path') vars.Add('XERCESINCLUDE', 'Xerces-C include path') vars.Add('XERCESLIB', 'Xerces-C libraries') vars.Add('XERCESLIBDIR', 'Xerces-C library path') @@ -81,6 +89,8 @@ except Exception: hasQt = False hasCollada=True +hasPython = True + env.Append(CPPPATH=env['BASEINCLUDE']) env.Append(CPPFLAGS=[]) env.Append(LIBPATH=[]) @@ -137,6 +147,8 @@ if env.has_key('COLLADAINCLUDE'): env.Prepend(CPPPATH=env['COLLADAINCLUDE']) if env.has_key('COLLADALIBDIR'): env.Prepend(LIBPATH=env['COLLADALIBDIR']) +if env.has_key('PYTHONINCLUDE'): + env.Prepend(CPPPATH=env['PYTHONINCLUDE']) if not conf.CheckCXX(): print 'Could not compile a simple C++ fragment, verify that ' + \ @@ -159,6 +171,9 @@ if not conf.CheckCXXHeader('xercesc/dom/DOMLSParser.hpp'): if not conf.CheckCXXHeader('dae.h'): hasCollada = False print 'COLLADA DOM is missing: not building the COLLADA importer' +if not conf.CheckCXXHeader('pyconfig.h'): + hasPython = False + print 'Python is missing: not building the python support library' if not conf.CheckCXXHeader('boost/math/distributions/students_t.hpp'): print 'Boost is missing (install libboost-dev)!' Exit(1) @@ -214,6 +229,29 @@ else: print MTS_VERSION Export('MTS_VERSION') +versionFilename = GetBuildPath('#dependencies/version') +versionMismatch = False + +if not os.path.exists(versionFilename): + versionMismatch = True + depVersion = "" +else: + with open(versionFilename) as f: + depVersion = f.readline().strip() + if MTS_VERSION != depVersion: + versionMismatch = True + +if versionMismatch: + print '\nThe dependency directory and your Mitsuba codebase have different version' + print 'numbers! Your copy of Mitsuba has version %s, whereas the dependencies ' % MTS_VERSION + print 'have version %s. Please bring them into sync, either by running\n' % depVersion + print '$ hg update -r v%s\n' % depVersion + print 'in the Mitsuba directory, or by running\n' + print '$ cd dependencies' + print '$ hg pull' + print '$ hg update -r v%s\n' % MTS_VERSION + Exit(1) + env = conf.Finish() dist = GetOption('dist') != None @@ -222,10 +260,68 @@ Export('dist') def osxlibinst_build_function(self, target, source, pkgname = None, use_own = None): inst = self.Install(target, source) prefix, name = os.path.split(source) - self.AddPostAction(inst, 'install_name_tool -id @executable_path/../Frameworks/' + name + ' $TARGET') + self.AddPostAction(inst, 'install_name_tool -id @loader_path/../Frameworks/' + name + ' $TARGET') return inst +def osxlibinst_as_build_function(self, target, source, pkgname = None, use_own = None): + inst = self.InstallAs(target, source) + prefix, name = os.path.split(source) + self.AddPostAction(inst, 'install_name_tool -id @loader_path/../Frameworks/' + name + ' $TARGET') + return inst + +def remove_flag(env, flag): + try: + env['CXXFLAGS'].remove(flag) + return True + except: + return False + +def match_pattern(x, patterns): + match = False + for pattern in patterns: + if re.search(pattern, x): + match = True + break + return match + +def remove_flags(env, patterns): + env['CCFLAGS'][:] = [ x for x in env['CCFLAGS'] if not match_pattern(x, patterns) ] + env['CXXFLAGS'][:] = [ x for x in env['CXXFLAGS'] if not match_pattern(x, patterns) ] + env['LINKFLAGS'][:] = [ x for x in env['LINKFLAGS'] if not match_pattern(x, patterns) ] + +def append_flag(env, value): + env['CXXFLAGS'].append(value) + +env.__class__.RemoveFlag = remove_flag +env.__class__.RemoveFlags = remove_flags +env.__class__.AppendFlag = append_flag env.__class__.OSXLibInst = osxlibinst_build_function +env.__class__.OSXLibInstAs = osxlibinst_as_build_function + +def configure_for_objective_cpp(env): + # The OSX Objective C++ compiler does not permit the following flags + env.RemoveFlags(['-fstrict-aliasing', '-ftree-vectorize', + '-std=c\+\+0x']) + # Remove Intel compiler-specific optimization flags + env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div', + '-fp-model', 'fast=.*', '-wd.*', '-openmp']) + env['CCFLAGS'] += ['-fno-strict-aliasing'] + # Enforce GCC usage (Intel compiler doesn't handle Objective C/C++) + env['CXX'] = 'g++' + env['CC'] = 'gcc' + +def relax_compiler_settings(env): + # Relax the compiler settings when compiling heavy templated code + # (e.g. Boost::Spirit parsers, etc., which don't necessarily have + # to be that fast) + env.RemoveFlags(['-g', '/Z7', '-ipo', '/GL']) + if env.RemoveFlag('-O3'): + env.AppendFlag('-Os') + if env.RemoveFlag('/O2'): + env.AppendFlag('/O1') + +env.__class__.ConfigureForObjectiveCPP = configure_for_objective_cpp +env.__class__.RelaxCompilerSettings = relax_compiler_settings if hasCollada: env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]] ) @@ -237,6 +333,6 @@ if sys.platform == 'win32': env['LINKCOM'] = [env['LINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1'] env['SHLINKCOM'] = [env['SHLINKCOM'], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2'] -env.Export('hasQt', 'hasCollada', 'resources') +env.Export('hasQt', 'hasCollada', 'hasPython', 'resources') Return('env') diff --git a/build/SConscript.install b/build/SConscript.install index 0a080883..01df8c9e 100644 --- a/build/SConscript.install +++ b/build/SConscript.install @@ -1,10 +1,21 @@ import fnmatch Import('env', 'os', 'sys', 'plugins', 'dist', - 'MTS_VERSION', 'hasQt', 'hasCollada') + 'MTS_VERSION', 'hasQt', 'hasCollada', 'hasPython') installTargets = [] +def fixOSXPluginPath(plugin): + return env.AddPostAction(plugin, + 'install_name_tool -change @loader_path/../Frameworks/libmitsuba-core.dylib @loader_path/../Contents/Frameworks/libmitsuba-core.dylib ${TARGET}; ' + + 'install_name_tool -change @loader_path/../Frameworks/libmitsuba-render.dylib @loader_path/../Contents/Frameworks/libmitsuba-render.dylib ${TARGET}; ' + + 'install_name_tool -change @loader_path/../Frameworks/libmitsuba-hw.dylib @loader_path/../Contents/Frameworks/libmitsuba-hw.dylib ${TARGET}; ' + + 'install_name_tool -change @loader_path/../Frameworks/libmitsuba-bidir.dylib @loader_path/../Contents/Frameworks/libmitsuba-bidir.dylib ${TARGET}; ' + + 'install_name_tool -change @loader_path/../Frameworks/libboost_system.dylib @loader_path/../Contents/Frameworks/libboost_system.dylib ${TARGET}; ' + + 'install_name_tool -change @loader_path/../Frameworks/libboost_filesystem.dylib @loader_path/../Contents/Frameworks/libboost_filesystem.dylib ${TARGET};' + + 'install_name_tool -change @loader_path/../Frameworks/libboost_python.dylib @loader_path/../Contents/Frameworks/libboost_python.dylib ${TARGET}' + ) + def install(target, paths, prefix = None): global installTargets if prefix == None: @@ -15,6 +26,17 @@ def install(target, paths, prefix = None): else: installTargets += env.Install(target, prefix + '/' + path) +def installAs(target, path, prefix = None): + global installTargets + if prefix == None: + prefix = env['BUILDDIR'] + if os.path.splitext(path)[1] == '.dylib': + result = env.OSXLibInstAs(target, prefix + '/' + path) + else: + result = env.InstallAs(target, prefix + '/' + path) + installTargets += result + return result + if not 'DISTDIR' in env: print 'The \"DISTDIR\" variable is missing. Please update your configuration file!' Exit(1) @@ -33,7 +55,9 @@ if sys.platform == 'linux2': installTargets += env.Install(os.path.join(distDir, 'plugins'), plugin) install(distDir, ['libcore/libmitsuba-core.so', 'libhw/libmitsuba-hw.so', 'librender/libmitsuba-render.so', 'libbidir/libmitsuba-bidir.so']) - install(distDir, ['mitsuba/mitsuba', 'mitsuba/mtssrv', 'mitsuba/mtsutil', 'qtgui/mtsgui']) + if hasPython: + install(os.path.join(distDir, 'python'), ['libpython/mitsuba.so']) + install(distDir, ['mitsuba/mitsuba', 'mitsuba/mtssrv', 'mitsuba/mtsutil', 'mtsgui/mtsgui']) if hasCollada: install(distDir, ['converter/mtsimport']) if sys.platform == 'win32': @@ -58,11 +82,14 @@ if sys.platform == 'win32': install(distDir, ['mitsuba/mitsuba.exe', 'mitsuba/mtssrv.exe', 'mitsuba/mtsutil.exe']) install(distDir, ['libcore/libmitsuba-core.dll', 'libhw/libmitsuba-hw.dll', 'librender/libmitsuba-render.dll', 'libbidir/libmitsuba-bidir.dll']) + if hasPython: + installAs(os.path.join(distDir, 'python/mitsuba.pyd'), 'libpython/mitsuba.dll') install(distDir, ['Iex.dll', 'Half.dll','IlmThread.dll', 'Imath.dll','IlmImf.dll','zlib1.dll', 'libpng13.dll', 'jpeg62.dll', 'pthreadVCE2.dll', 'xerces-c_3_0.dll', 'glew32mx.dll'], prefix=dllprefix) - install(distDir, ['libcollada14dom23.dll', 'boost_system-%s-mt-1_44.dll' % compilerType, - 'boost_filesystem-%s-mt-1_44.dll' % compilerType], dllprefix + '/' + compilerType + '/') + install(distDir, ['libcollada14dom23.dll', 'boost_python-%s-mt-1_44.dll' % compilerType, + 'boost_system-%s-mt-1_44.dll' % compilerType, 'boost_filesystem-%s-mt-1_44.dll' % compilerType], + dllprefix + '/' + compilerType + '/') if 'WIN64' in env['CXXFLAGS']: installTargets += env.Install(distDir, '#dependencies/windows/bin/vcredist_2010_sp1_x64.exe') else: @@ -73,12 +100,13 @@ if sys.platform == 'win32': install(distDir, ['libmmd.dll', 'libiomp5md.dll'], prefix = env['REDIST_PATH']) if hasQt: - install(distDir, ['qtgui/mtsgui.exe']) + install(distDir, ['mtsgui/mtsgui.exe']) install(distDir, ['QtCore4.dll', 'QtGui4.dll', 'QtXml4.dll', 'QtNetwork4.dll', 'QtOpenGL4.dll', 'QtXmlPatterns4.dll'], prefix = env['QT4_BINPATH']) elif sys.platform == 'darwin': for i in plugins: - installTargets += env.Install(os.path.join(distDir, 'plugins'), i) + plugin = env.Install(os.path.join(distDir, 'plugins'), i) + installTargets += fixOSXPluginPath(plugin) install(os.path.join(distDir, 'Contents/MacOS'), ['mitsuba/mitsuba', 'mitsuba/mtssrv', 'mitsuba/mtsutil']) if hasCollada: install(os.path.join(distDir, 'Contents/MacOS'), ['converter/mtsimport']) @@ -91,31 +119,36 @@ elif sys.platform == 'darwin': install(frameworkDir, ['libcore/libmitsuba-core.dylib', 'libhw/libmitsuba-hw.dylib', 'librender/libmitsuba-render.dylib', 'libbidir/libmitsuba-bidir.dylib']) + if hasPython: + plugin = installAs(os.path.join(distDir, 'python/mitsuba.so'), 'libpython/mitsuba.dylib') + installTargets += fixOSXPluginPath(plugin) install(frameworkDir, [ 'GLEW.framework/Resources/libs/libGLEW.dylib', 'OpenEXR.framework/Resources/lib/libHalf.6.dylib', 'OpenEXR.framework/Resources/lib/libIex.6.dylib', 'OpenEXR.framework/Resources/lib/libImath.6.dylib', 'OpenEXR.framework/Resources/lib/libIlmThread.6.dylib', 'OpenEXR.framework/Resources/lib/libIlmImf.6.dylib', 'Xerces-C.framework/Resources/lib/libxerces-c-3.0.dylib', 'libpng.framework/Resources/lib/libpng.dylib', - 'libjpeg.framework/Resources/lib/libjpeg.dylib', 'libboost.framework/Resources/lib/libboost_system.dylib', + 'libjpeg.framework/Resources/lib/libjpeg.dylib', 'libboost.framework/Resources/lib/libboost_python.dylib', + 'libboost.framework/Resources/lib/libboost_system.dylib', 'libboost.framework/Resources/lib/libboost_filesystem.dylib'], '#dependencies/darwin') if hasCollada: install(frameworkDir, [ 'Collada14Dom.framework/Resources/lib/libCollada14Dom.dylib'], '#dependencies/darwin') if hasQt: - install(os.path.join(distDir, 'Contents/MacOS'), ['qtgui/mtsgui']) + install(os.path.join(distDir, 'Contents/MacOS'), ['mtsgui/mtsgui']) + install(os.path.join(distDir, 'Contents/MacOS'), ['mtsgui/symlinks_install']) installTargets += env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtCore.framework/Versions/4/QtCore') opengl = env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL') xml = env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtXml.framework/Versions/4/QtXml') xmlpatterns = env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtXmlPatterns.framework/Versions/4/QtXmlPatterns') network = env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtNetwork.framework/Versions/4/QtNetwork') gui = env.OSXLibInst(frameworkDir, '/Library/Frameworks/QtGui.framework/Versions/4/QtGui') - installTargets += env.AddPostAction(xml, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - installTargets += env.AddPostAction(xmlpatterns, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - installTargets += env.AddPostAction(xmlpatterns, 'install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork $TARGET') - installTargets += env.AddPostAction(network, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - installTargets += env.AddPostAction(gui, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - installTargets += env.AddPostAction(opengl, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - installTargets += env.AddPostAction(opengl, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui $TARGET') + installTargets += env.AddPostAction(xml, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + installTargets += env.AddPostAction(xmlpatterns, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + installTargets += env.AddPostAction(xmlpatterns, 'install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @loader_path/../Frameworks/QtNetwork $TARGET') + installTargets += env.AddPostAction(network, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + installTargets += env.AddPostAction(gui, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + installTargets += env.AddPostAction(opengl, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + installTargets += env.AddPostAction(opengl, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @loader_path/../Frameworks/QtGui $TARGET') installTargets += env.Install(os.path.join(distDir, 'Contents/Resources'), '/Library/Frameworks//QtGui.framework/Versions/4/Resources/qt_menu.nib') installTargets += env.Install(os.path.join(distDir, 'Contents/Resources/PreviewSettings.nib'), '#data/darwin/PreviewSettings.nib/designable.nib') installTargets += env.Install(os.path.join(distDir, 'Contents/Resources/PreviewSettings.nib'), '#data/darwin/PreviewSettings.nib/keyedobjects.nib') diff --git a/build/config-darwin-universal.py b/build/config-darwin-universal.py index 8b4a1038..94740780 100644 --- a/build/config-darwin-universal.py +++ b/build/config-darwin-universal.py @@ -1,9 +1,9 @@ BUILDDIR = '#build/release' DISTDIR = '#Mitsuba.app' -CXX = 'g++' -CC = 'gcc' -CXXFLAGS = ['-arch', 'i386', '-arch', 'x86_64', '-mmacosx-version-min=10.5', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] -LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'i386', '-arch', 'x86_64', '-mmacosx-version-min=10.5', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk'] +CXX = 'g++' +CC = 'gcc' +CXXFLAGS = ['-arch', 'i386', '-arch', 'x86_64', '-mmacosx-version-min=10.6', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] +LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'i386', '-arch', 'x86_64', '-mmacosx-version-min=10.6', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk', '-Wl,-headerpad,128'] BASEINCLUDE = ['#include'] BASELIB = ['m', 'pthread', 'gomp'] OEXRINCLUDE = ['#dependencies/darwin/OpenEXR.framework/Headers/OpenEXR'] @@ -25,6 +25,8 @@ GLFLAGS = ['-DGLEW_MX'] BOOSTINCLUDE = ['#dependencies'] BOOSTLIB = ['boost_filesystem', 'boost_system'] BOOSTLIBDIR = ['#dependencies/darwin/libboost.framework/Resources/lib'] +PYTHONINCLUDE = ['/System/Library/Frameworks/Python.framework/Versions/2.6/Headers'] +PYTHONLIB = ['boost_python', 'boost_system', 'Python'] COLLADAINCLUDE = ['#dependencies/windows/include/colladadom', '#dependencies/windows/include/colladadom/1.4'] COLLADALIB = ['libCollada14Dom'] COLLADALIBDIR = ['#dependencies/darwin/Collada14Dom.framework/Resources/lib'] diff --git a/build/config-darwin-x86.py b/build/config-darwin-x86.py index f9eca9d6..3110a1c4 100644 --- a/build/config-darwin-x86.py +++ b/build/config-darwin-x86.py @@ -1,9 +1,9 @@ BUILDDIR = '#build/release' DISTDIR = '#Mitsuba.app' -CXX = 'g++' -CC = 'gcc' -CXXFLAGS = ['-arch', 'i386', '-mmacosx-version-min=10.5', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] -LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'i386', '-mmacosx-version-min=10.5', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk'] +CXX = 'g++' +CC = 'gcc' +CXXFLAGS = ['-arch', 'i386', '-mmacosx-version-min=10.6', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] +LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'i386', '-mmacosx-version-min=10.6', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk', '-Wl,-headerpad,128'] BASEINCLUDE = ['#include'] BASELIB = ['m', 'pthread', 'gomp'] OEXRINCLUDE = ['#dependencies/darwin/OpenEXR.framework/Headers/OpenEXR'] @@ -25,6 +25,8 @@ GLFLAGS = ['-DGLEW_MX'] BOOSTINCLUDE = ['#dependencies'] BOOSTLIB = ['boost_filesystem', 'boost_system'] BOOSTLIBDIR = ['#dependencies/darwin/libboost.framework/Resources/lib'] +PYTHONINCLUDE = ['/System/Library/Frameworks/Python.framework/Versions/2.6/Headers'] +PYTHONLIB = ['boost_python', 'boost_system', 'Python'] COLLADAINCLUDE = ['#dependencies/windows/include/colladadom', '#dependencies/windows/include/colladadom/1.4'] COLLADALIB = ['libCollada14Dom'] COLLADALIBDIR = ['#dependencies/darwin/Collada14Dom.framework/Resources/lib'] diff --git a/build/config-darwin-x86_64.py b/build/config-darwin-x86_64.py index 344e84ab..3bd77dc3 100644 --- a/build/config-darwin-x86_64.py +++ b/build/config-darwin-x86_64.py @@ -1,9 +1,9 @@ BUILDDIR = '#build/release' DISTDIR = '#Mitsuba.app' -CXX = 'g++' -CC = 'gcc' -CXXFLAGS = ['-arch', 'x86_64', '-mmacosx-version-min=10.5', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] -LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'x86_64', '-mmacosx-version-min=10.5', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk'] +CXX = 'g++' +CC = 'gcc' +CXXFLAGS = ['-arch', 'x86_64', '-mmacosx-version-min=10.6', '-march=nocona', '-msse2', '-mfpmath=sse', '-ftree-vectorize', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk', '-O3', '-Wall', '-g', '-pipe', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fstrict-aliasing', '-fsched-interblock', '-freorder-blocks'] +LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'x86_64', '-mmacosx-version-min=10.6', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk', '-Wl,-headerpad,128'] BASEINCLUDE = ['#include'] BASELIB = ['m', 'pthread', 'gomp'] OEXRINCLUDE = ['#dependencies/darwin/OpenEXR.framework/Headers/OpenEXR'] @@ -25,6 +25,8 @@ GLFLAGS = ['-DGLEW_MX'] BOOSTINCLUDE = ['#dependencies'] BOOSTLIB = ['boost_filesystem', 'boost_system'] BOOSTLIBDIR = ['#dependencies/darwin/libboost.framework/Resources/lib'] +PYTHONINCLUDE = ['/System/Library/Frameworks/Python.framework/Versions/2.6/Headers'] +PYTHONLIB = ['boost_python', 'boost_system', 'Python'] COLLADAINCLUDE = ['#dependencies/windows/include/colladadom', '#dependencies/windows/include/colladadom/1.4'] COLLADALIB = ['libCollada14Dom'] COLLADALIBDIR = ['#dependencies/darwin/Collada14Dom.framework/Resources/lib'] diff --git a/build/config-icl12-darwin-x86.py b/build/config-icl12-darwin-x86.py new file mode 100644 index 00000000..936037f3 --- /dev/null +++ b/build/config-icl12-darwin-x86.py @@ -0,0 +1,33 @@ +BUILDDIR = '#build/release' +DISTDIR = '#Mitsuba.app' +CXX = 'icpc' +CC = 'icc' +CCFLAGS = ['-arch', 'i386', '-mmacosx-version-min=10.6', '-mfpmath=sse', '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk', '-O3', '-ipo', '-no-prec-div', '-xSSSE3', '-fp-model', 'fast=2', '-openmp', '-wd279', '-Wall', '-g', '-pipe'] +CXXFLAGS = ['$CCFLAGS', '-std=c++0x', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT'] +LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'i386', '-mmacosx-version-min=10.6', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk', '-openmp', '-Wl,-headerpad,128'] +BASEINCLUDE = ['#include'] +BASELIB = ['m', 'pthread', 'gomp'] +OEXRINCLUDE = ['#dependencies/darwin/OpenEXR.framework/Headers/OpenEXR'] +OEXRLIBDIR = ['#dependencies/darwin/OpenEXR.framework/Resources/lib'] +OEXRLIB = ['Half', 'IlmImf', 'Imath', 'z'] +PNGINCLUDE = ['#dependencies/darwin/libpng.framework/Headers'] +PNGLIBDIR = ['#dependencies/darwin/libpng.framework/Resources/lib'] +PNGLIB = ['png'] +JPEGINCLUDE = ['#dependencies/darwin/libjpeg.framework/Headers'] +JPEGLIBDIR = ['#dependencies/darwin/libjpeg.framework/Resources/lib'] +JPEGLIB = ['jpeg'] +XERCESINCLUDE = ['#dependencies/darwin/Xerces-C.framework/Headers'] +XERCESLIBDIR = ['#dependencies/darwin/Xerces-C.framework/Resources/lib'] +XERCESLIB = ['xerces-c'] +GLINCLUDE = ['#dependencies/darwin/GLEW.framework/Headers'] +GLLIBDIR = ['#dependencies/darwin/GLEW.framework/Resources/libs'] +GLLIB = ['GLEW', 'objc'] +GLFLAGS = ['-DGLEW_MX'] +BOOSTINCLUDE = ['#dependencies'] +BOOSTLIB = ['boost_filesystem', 'boost_system'] +BOOSTLIBDIR = ['#dependencies/darwin/libboost.framework/Resources/lib'] +PYTHONINCLUDE = ['/System/Library/Frameworks/Python.framework/Versions/2.6/Headers'] +PYTHONLIB = ['boost_python', 'boost_system', 'Python'] +COLLADAINCLUDE = ['#dependencies/windows/include/colladadom', '#dependencies/windows/include/colladadom/1.4'] +COLLADALIB = ['libCollada14Dom'] +COLLADALIBDIR = ['#dependencies/darwin/Collada14Dom.framework/Resources/lib'] diff --git a/build/config-icl12-darwin-x86_64.py b/build/config-icl12-darwin-x86_64.py new file mode 100644 index 00000000..2c9a6eff --- /dev/null +++ b/build/config-icl12-darwin-x86_64.py @@ -0,0 +1,33 @@ +BUILDDIR = '#build/release' +DISTDIR = '#Mitsuba.app' +CXX = 'icpc' +CC = 'icc' +CCFLAGS = ['-arch', 'x86_64', '-mmacosx-version-min=10.6', '-mfpmath=sse', '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk', '-O3', '-ipo', '-xSSSE3', '-fp-model', 'fast=2', '-openmp', '-wd279', '-Wall', '-g', '-pipe'] +CXXFLAGS = ['$CCFLAGS', '-std=c++0x', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT'] +LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'x86_64', '-mmacosx-version-min=10.6', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk', '-openmp', '-Wl,-headerpad,128'] +BASEINCLUDE = ['#include'] +BASELIB = ['m', 'pthread', 'gomp'] +OEXRINCLUDE = ['#dependencies/darwin/OpenEXR.framework/Headers/OpenEXR'] +OEXRLIBDIR = ['#dependencies/darwin/OpenEXR.framework/Resources/lib'] +OEXRLIB = ['Half', 'IlmImf', 'Imath', 'z'] +PNGINCLUDE = ['#dependencies/darwin/libpng.framework/Headers'] +PNGLIBDIR = ['#dependencies/darwin/libpng.framework/Resources/lib'] +PNGLIB = ['png'] +JPEGINCLUDE = ['#dependencies/darwin/libjpeg.framework/Headers'] +JPEGLIBDIR = ['#dependencies/darwin/libjpeg.framework/Resources/lib'] +JPEGLIB = ['jpeg'] +XERCESINCLUDE = ['#dependencies/darwin/Xerces-C.framework/Headers'] +XERCESLIBDIR = ['#dependencies/darwin/Xerces-C.framework/Resources/lib'] +XERCESLIB = ['xerces-c'] +GLINCLUDE = ['#dependencies/darwin/GLEW.framework/Headers'] +GLLIBDIR = ['#dependencies/darwin/GLEW.framework/Resources/libs'] +GLLIB = ['GLEW', 'objc'] +GLFLAGS = ['-DGLEW_MX'] +BOOSTINCLUDE = ['#dependencies'] +BOOSTLIB = ['boost_filesystem', 'boost_system'] +BOOSTLIBDIR = ['#dependencies/darwin/libboost.framework/Resources/lib'] +PYTHONINCLUDE = ['/System/Library/Frameworks/Python.framework/Versions/2.6/Headers'] +PYTHONLIB = ['boost_python', 'boost_system', 'Python'] +COLLADAINCLUDE = ['#dependencies/windows/include/colladadom', '#dependencies/windows/include/colladadom/1.4'] +COLLADALIB = ['libCollada14Dom'] +COLLADALIBDIR = ['#dependencies/darwin/Collada14Dom.framework/Resources/lib'] diff --git a/build/config-icl12-msv2010-win32.py b/build/config-icl12-msv2010-win32.py index e1dff224..c44d80bc 100644 --- a/build/config-icl12-msv2010-win32.py +++ b/build/config-icl12-msv2010-win32.py @@ -1,3 +1,5 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'icl' @@ -24,6 +26,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib32', '#dependencies/windows/lib32/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-icl12-msv2010-win64.py b/build/config-icl12-msv2010-win64.py index 2552d791..58bada2a 100644 --- a/build/config-icl12-msv2010-win64.py +++ b/build/config-icl12-msv2010-win64.py @@ -1,3 +1,5 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'icl' @@ -24,6 +26,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib64', '#dependencies/windows/lib64/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-linux-debug.py b/build/config-linux-debug.py index 393ce32b..01220590 100644 --- a/build/config-linux-debug.py +++ b/build/config-linux-debug.py @@ -1,10 +1,12 @@ +import os + BUILDDIR = '#build/debug' DISTDIR = '#dist' -CXX = 'g++' -CC = 'gcc' +CXX = 'g++' +CC = 'gcc' CXXFLAGS = ['-O0', '-Wall', '-g', '-pipe', '-march=nocona', '-msse2', '-ftree-vectorize', '-mfpmath=sse', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp'] LINKFLAGS = [] -SHLINKFLAGS = ['-rdynamic', '-shared', '-fPIC'] +SHLINKFLAGS = ['-rdynamic', '-shared', '-fPIC', '-lstdc++'] BASEINCLUDE = ['#include'] BASELIB = ['dl', 'm', 'pthread', 'gomp'] OEXRINCLUDE = ['/usr/include/OpenEXR'] @@ -15,6 +17,14 @@ XERCESINCLUDE = [] XERCESLIB = ['xerces-c'] GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11'] GLFLAGS = ['-DGLEW_MX'] -BOOSTLIB = ['libboost_system', 'libboost_filesystem'] +BOOSTLIB = ['boost_system', 'boost_filesystem'] COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4'] -COLLADALIB = ['libcollada14dom'] +COLLADALIB = ['collada14dom'] +PYTHONINCLUDE = [] +PYTHONLIB = ['boost_python'] + +for entry in os.popen("python-config --cflags --libs").read().split(): + if entry[:2] == '-I': + PYTHONINCLUDE += [entry[2:]] + if entry[:2] == '-l': + PYTHONLIB += [entry[2:]] diff --git a/build/config-linux.py b/build/config-linux.py index 00baa7e8..3b6f3d75 100644 --- a/build/config-linux.py +++ b/build/config-linux.py @@ -1,10 +1,12 @@ +import os + BUILDDIR = '#build/release' DISTDIR = '#dist' -CXX = 'g++' -CC = 'gcc' +CXX = 'g++' +CC = 'gcc' CXXFLAGS = ['-O3', '-Wall', '-g', '-pipe', '-march=nocona', '-msse2', '-ftree-vectorize', '-mfpmath=sse', '-funsafe-math-optimizations', '-fno-rounding-math', '-fno-signaling-nans', '-fomit-frame-pointer', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp'] LINKFLAGS = [] -SHLINKFLAGS = ['-rdynamic', '-shared', '-fPIC'] +SHLINKFLAGS = ['-rdynamic', '-shared', '-fPIC', '-lstdc++'] BASEINCLUDE = ['#include'] BASELIB = ['dl', 'm', 'pthread', 'gomp'] OEXRINCLUDE = ['/usr/include/OpenEXR'] @@ -15,6 +17,14 @@ XERCESINCLUDE = [] XERCESLIB = ['xerces-c'] GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11'] GLFLAGS = ['-DGLEW_MX'] -BOOSTLIB = ['libboost_system', 'libboost_filesystem'] +BOOSTLIB = ['boost_system', 'boost_filesystem'] COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4'] -COLLADALIB = ['libcollada14dom'] +COLLADALIB = ['collada14dom'] +PYTHONINCLUDE = [] +PYTHONLIB = ['boost_python'] + +for entry in os.popen("python-config --cflags --libs").read().split(): + if entry[:2] == '-I': + PYTHONINCLUDE += [entry[2:]] + if entry[:2] == '-l': + PYTHONLIB += [entry[2:]] diff --git a/build/config-msvc2008-win32-debug.py b/build/config-msvc2008-win32-debug.py index 7d888cc2..f355d0be 100644 --- a/build/config-msvc2008-win32-debug.py +++ b/build/config-msvc2008-win32-debug.py @@ -1,8 +1,10 @@ +import sys, os + BUILDDIR = '#build/debug' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS CXXFLAGS = ['/nologo', '/Od', '/Z7', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib32', '#dependencies/windows/lib32/vc90'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2008-win32.py b/build/config-msvc2008-win32.py index 050a2e74..67281dea 100644 --- a/build/config-msvc2008-win32.py +++ b/build/config-msvc2008-win32.py @@ -1,11 +1,13 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS -CXXFLAGS = ['/nologo', '/Ox', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] +CXXFLAGS = ['/nologo', '/O2', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] SHCXXFLAGS = CXXFLAGS TARGET_ARCH = 'x86' MSVC_VERSION = '9.0' @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib32', '#dependencies/windows/lib32/vc90'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2008-win64-debug.py b/build/config-msvc2008-win64-debug.py index e7a91188..e6c2f3a2 100644 --- a/build/config-msvc2008-win64-debug.py +++ b/build/config-msvc2008-win64-debug.py @@ -1,8 +1,10 @@ +import sys, os + BUILDDIR = '#build/debug' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS CXXFLAGS = ['/nologo', '/Od', '/Z7', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib64', '#dependencies/windows/lib64/vc90'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2008-win64.py b/build/config-msvc2008-win64.py index 3aa9c583..9e8bf2cb 100644 --- a/build/config-msvc2008-win64.py +++ b/build/config-msvc2008-win64.py @@ -1,11 +1,13 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS -CXXFLAGS = ['/nologo', '/Ox', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] +CXXFLAGS = ['/nologo', '/O2', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] SHCXXFLAGS = CXXFLAGS TARGET_ARCH = 'x86_64' MSVC_VERSION = '9.0' @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib64', '#dependencies/windows/lib64/vc90'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2010-win32-debug.py b/build/config-msvc2010-win32-debug.py index 3d7be9f5..a4d3ccc2 100644 --- a/build/config-msvc2010-win32-debug.py +++ b/build/config-msvc2010-win32-debug.py @@ -1,8 +1,10 @@ +import sys, os + BUILDDIR = '#build/debug' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS CXXFLAGS = ['/nologo', '/Od', '/Z7', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib32', '#dependencies/windows/lib32/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2010-win32.py b/build/config-msvc2010-win32.py index 420ef257..2fe9acd9 100644 --- a/build/config-msvc2010-win32.py +++ b/build/config-msvc2010-win32.py @@ -1,11 +1,13 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS -CXXFLAGS = ['/nologo', '/Ox', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] +CXXFLAGS = ['/nologo', '/O2', '/fp:fast', '/arch:SSE2' ,'/D', 'WIN32', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] SHCXXFLAGS = CXXFLAGS TARGET_ARCH = 'x86' MSVC_VERSION = '10.0' @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib32', '#dependencies/windows/lib32/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2010-win64-debug.py b/build/config-msvc2010-win64-debug.py index fc1f5d0f..65882194 100644 --- a/build/config-msvc2010-win64-debug.py +++ b/build/config-msvc2010-win64-debug.py @@ -1,8 +1,10 @@ +import sys, os + BUILDDIR = '#build/debug' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS CXXFLAGS = ['/nologo', '/Od', '/Z7', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib64', '#dependencies/windows/lib64/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/config-msvc2010-win64.py b/build/config-msvc2010-win64.py index a4d43be9..2d3bee4d 100644 --- a/build/config-msvc2010-win64.py +++ b/build/config-msvc2010-win64.py @@ -1,11 +1,13 @@ +import sys, os + BUILDDIR = '#build/release' DISTDIR = '#dist' CXX = 'cl' CC = 'cl' -# /Ox=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission +# /O2=optimize for speed, global optimizations, intrinsic functions, favor fast code, frame pointer omission # /EHsc=C++ exceptions, /fp:fast=Enable reasonable FP optimizations, /GS-=No buffer security checks, /GL=whole program optimizations # To include debug information add '/Z7' to CXXFLAGS and '/DEBUG' to LINKFLAGS -CXXFLAGS = ['/nologo', '/Ox', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] +CXXFLAGS = ['/nologo', '/O2', '/fp:fast', '/D', 'WIN32', '/D', 'WIN64', '/W3', '/EHsc', '/GS-', '/GL', '/MD', '/D', 'MTS_DEBUG', '/D', 'SINGLE_PRECISION', '/D', 'SPECTRUM_SAMPLES=3', '/D', 'MTS_SSE', '/D', 'MTS_HAS_COHERENT_RT', '/D', '_CONSOLE', '/D', 'NDEBUG', '/openmp'] SHCXXFLAGS = CXXFLAGS TARGET_ARCH = 'x86_64' MSVC_VERSION = '10.0' @@ -25,6 +27,9 @@ JPEGLIB = ['jpeg62'] GLLIB = ['opengl32', 'glu32', 'glew32mx', 'gdi32', 'user32'] GLFLAGS = ['/D', 'GLEW_MX'] BASELIBDIR = ['#dependencies/windows/lib64', '#dependencies/windows/lib64/vc100'] +PYTHONINCLUDE = [os.path.join(os.path.split(sys.executable)[0], 'include')] +PYTHONLIBDIR = [os.path.join(os.path.split(sys.executable)[0], 'libs')] +PYTHONLIB = ['boost_python-vc100-mt-1_44'] SHLIBPREFIX = 'lib' SHLIBSUFFIX = '.dll' PROGSUFFIX = '.exe' diff --git a/build/mitsuba-msvc2008.vcproj b/build/mitsuba-msvc2008.vcproj index 2a837d4e..89b235b4 100644 --- a/build/mitsuba-msvc2008.vcproj +++ b/build/mitsuba-msvc2008.vcproj @@ -367,57 +367,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/build/mitsuba-msvc2010.vcxproj b/build/mitsuba-msvc2010.vcxproj index 29c225ed..f0a3ecf4 100644 --- a/build/mitsuba-msvc2010.vcxproj +++ b/build/mitsuba-msvc2010.vcxproj @@ -135,53 +135,53 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -769,53 +769,53 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/build/mitsuba-msvc2010.vcxproj.filters b/build/mitsuba-msvc2010.vcxproj.filters index 0d8fc053..bfe91231 100644 --- a/build/mitsuba-msvc2010.vcxproj.filters +++ b/build/mitsuba-msvc2010.vcxproj.filters @@ -59,10 +59,10 @@ {629f51ab-8f77-4abd-9c1c-38e13b2db010} - + {7922cc88-966d-4a2a-ad99-0f932bf0eda3} - + {12abdb4a-638a-4680-b01d-af8075fc74ee} @@ -559,77 +559,77 @@ Source Files\phase - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui Source Files\rfilters @@ -804,77 +804,77 @@ Source Files\phase - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui - - Source Files\qtgui + + Source Files\mtsgui Source Files\shapes diff --git a/data/darwin/Mitsuba.dmgCanvas/Disk Image b/data/darwin/Mitsuba.dmgCanvas/Disk Image deleted file mode 100644 index 261705ac..00000000 Binary files a/data/darwin/Mitsuba.dmgCanvas/Disk Image and /dev/null differ diff --git a/data/darwin/Mitsuba.dmgCanvas/QuickLook/Preview.jpg b/data/darwin/Mitsuba.dmgCanvas/QuickLook/Preview.jpg deleted file mode 100644 index 9dbf81bd..00000000 Binary files a/data/darwin/Mitsuba.dmgCanvas/QuickLook/Preview.jpg and /dev/null differ diff --git a/data/linux/arch/collada-dom/PKGBUILD b/data/linux/arch/collada-dom/PKGBUILD new file mode 100644 index 00000000..9ab6bd93 --- /dev/null +++ b/data/linux/arch/collada-dom/PKGBUILD @@ -0,0 +1,32 @@ +# Contributer: N30N +# Contributer: Wenzel Jakob + +pkgname="collada-dom" +pkgver=2.3.1 +pkgrel=1 +pkgdesc="An API that provides a C++ object representation of a COLLADA XML instance document." +url="http://collada-dom.sourceforge.net/" +license=("MIT") +arch=("i686" "x86_64") +depends=("libxml2" "boost" "pcre") #"libminizip" +# makedepends=() +source=("http://downloads.sourceforge.net/${pkgname}/collada_dom-${pkgver}-src.tgz") +md5sums=("a74d19c1187806a713cec90c2f0f692c") + +build() { + cd ${pkgname}-${pkgver}/dom + make project=dom +} + +package() { + cd ${pkgname}-${pkgver}/dom + + install -d ${pkgdir}/usr/lib ${pkgdir}/usr/include + make prefix=${pkgdir}/usr project=dom install + mv ${pkgdir}/usr/include/colladadom ${pkgdir}/usr/include/collada-dom + + install -m755 build/linux-1.4/libminizip.so* ${pkgdir}/usr/lib + install -D -m644 license.txt "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" +} + +# vim: set noet ff=unix: diff --git a/data/linux/arch/mitsuba/PKGBUILD b/data/linux/arch/mitsuba/PKGBUILD new file mode 100644 index 00000000..24ebfaeb --- /dev/null +++ b/data/linux/arch/mitsuba/PKGBUILD @@ -0,0 +1,64 @@ +# Contributer: N30N +# Contributer: Alex Combas +# Contributer: Wenzel Jakob +pkgname="mitsuba-hg" +pkgver=1 +pkgrel=1 +pkgdesc="Mitsuba physically based renderer" +url="http://mitsuba-renderer.org/" +license=("GPL3") +arch=("i686" "x86_64") +depends=("xerces-c" "glew" "openexr" "boost" "libpng" "libjpeg" "qt" "collada-dom") +makedepends=("mercurial" "scons") +provides=("mitsuba") + +_hgroot="https://mitsuba-renderer.org/hg" +_hgrepo="mitsuba" + +build() { + cd ${_hgrepo} + cp build/config-linux.py config.py + if [ -e dependencies ]; then + cd dependencies + hg pull -u + cd .. + else + hg clone https://www.mitsuba-renderer.org/hg/dependencies + fi + + scons --jobs=$[${MAKEFLAGS/-j/} - 1] +} + +package() { + install -d \ + ${pkgdir}/usr/bin \ + ${pkgdir}/usr/lib \ + ${pkgdir}/usr/share/mitsuba/plugins \ + ${pkgdir}/usr/share/mitsuba/data/schema \ + ${pkgdir}/usr/share/mitsuba/data/ior \ + ${pkgdir}/usr/share/applications \ + ${pkgdir}/usr/share/pixmaps \ + ${pkgdir}/usr/include/mitsuba/{core,hw,render,bidir} \ + ${pkgdir}/usr/lib/python2.7/lib-dynload + + cd ${_hgrepo} + install -m755 dist/mitsuba dist/mtsgui dist/mtsimport dist/mtssrv dist/mtsutil ${pkgdir}/usr/bin + install -m755 dist/libmitsuba-core.so \ + dist/libmitsuba-hw.so \ + dist/libmitsuba-render.so \ + dist/libmitsuba-bidir.so \ + ${pkgdir}/usr/lib + install -m755 dist/plugins/* ${pkgdir}/usr/share/mitsuba/plugins + install -m644 dist/data/schema/* ${pkgdir}/usr/share/mitsuba/data/schema + install -m644 dist/data/ior/* ${pkgdir}/usr/share/mitsuba/data/ior + install -m644 dist/python/mitsuba.so ${pkgdir}/usr/lib/python2.7/lib-dynload + install -m644 data/linux/mitsuba.desktop ${pkgdir}/usr/share/applications + install -m644 src/mtsgui/resources/mitsuba48.png ${pkgdir}/usr/share/pixmaps + install -m644 include/mitsuba/*.h ${pkgdir}/usr/include/mitsuba + install -m644 include/mitsuba/core/* ${pkgdir}/usr/include/mitsuba/core + install -m644 include/mitsuba/render/* ${pkgdir}/usr/include/mitsuba/render + install -m644 include/mitsuba/hw/* ${pkgdir}/usr/include/mitsuba/hw + install -m644 include/mitsuba/bidir/* ${pkgdir}/usr/include/mitsuba/bidir +} + +# vim: set noet ff=unix: diff --git a/data/linux/debian/changelog b/data/linux/debian/changelog index e24ab1b1..fe3c3873 100644 --- a/data/linux/debian/changelog +++ b/data/linux/debian/changelog @@ -1,6 +1,27 @@ mitsuba (0.3.0-1) unstable; urgency=low - * Initial python bindings + * Added basic Python bindings that can be used to instantiate plugins + and control rendering processes. + * Spectral rendering: most of the code pertaining to spectral + rendering has seen a significant overhaul. It is now faster and + in certain cases more accurate. + * Flexible material classes: this release introduces a robust and + very general suite of eight physically-based smooth and rough + (microfacet-based) material classes. + * Material modifiers: two new material modifiers (bump & coating) + can be applied to BSDFs to create new materials. + * Material verification: the sampling methods of all material + models in Mitsuba are now automatically verified with the help + of statistical hypothesis tests (using Chi^2-tests). + * Generated documentation: there is now a javadoc-like system, + which extracts documentation directly from the plugin source code + and stitches it into a LaTeX reference document. + * lookAt: Mitsuba inherited a bug from PBRT, where the + tag changed the handedness of the coordinate system. This is now + fixed--also, the syntax of this tag has changed to make it easier to read. + * Scene portability: A new conversion tool ensures that old and incompatible + scenes can be translated into the scene description format of the + most recent version. -- Wenzel Jakob Mon, 14 Aug 2011 00:00:00 -0400 diff --git a/data/linux/debian/mitsuba.install b/data/linux/debian/mitsuba.install.template similarity index 69% rename from data/linux/debian/mitsuba.install rename to data/linux/debian/mitsuba.install.template index 7a6768cf..dd8c6591 100644 --- a/data/linux/debian/mitsuba.install +++ b/data/linux/debian/mitsuba.install.template @@ -6,8 +6,9 @@ dist/mtsimport /usr/bin dist/libmitsuba-hw.so /usr/lib dist/libmitsuba-render.so /usr/lib dist/libmitsuba-core.so /usr/lib -dist/python/mitsuba.so /usr/lib/pyshared/python2.7 +dist/libmitsuba-bidir.so /usr/lib +dist/python/mitsuba.so /usr/lib/pymodules/pythonPYTHONVERSION dist/plugins/* /usr/share/mitsuba/plugins dist/data/* /usr/share/mitsuba/data -src/qtgui/resources/mitsuba48.png /usr/share/pixmaps +src/mtsgui/resources/mitsuba48.png /usr/share/pixmaps data/linux/mitsuba.desktop /usr/share/applications diff --git a/data/linux/debian/rules b/data/linux/debian/rules index 27693951..6e1b719e 100755 --- a/data/linux/debian/rules +++ b/data/linux/debian/rules @@ -9,6 +9,8 @@ # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 +PYTHONVERSION = `python-config --includes | sed -e 's/^.*python\([0-9\.]*\).*/\1/'` + clean: dh_testdir dh_testroot @@ -28,6 +30,7 @@ binary-arch: scons -j 2 dh_installdirs dh_auto_install + cat debian/mitsuba.install.template | sed -e s/PYTHONVERSION/$(PYTHONVERSION)/ > debian/mitsuba.install dh_install dh_installmenu dh_compress diff --git a/data/linux/fedora/mitsuba.spec b/data/linux/fedora/mitsuba.spec new file mode 100644 index 00000000..eff5a86e --- /dev/null +++ b/data/linux/fedora/mitsuba.spec @@ -0,0 +1,66 @@ +Name: mitsuba +Version: 0.3.0 +Release: 1%{?dist} +Summary: Mitsuba renderer +Group: Applications/Graphics +License: GPL-3 +URL: http://www.mitsuba-renderer.org +Source: %{name}-%{version}.tar.gz +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +BuildRequires: gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel +Requires: boost qt4 OpenEXR-libs xerces-c python libGLEWmx collada-dom +%description +Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased as well as biased techniques and contains heavy optimizations targeted towards current CPU architectures. + +The program currently runs on Linux, MacOS X and Microsoft Windows and makes use of SSE2 optimizations on x86 and x86_64 platforms. So far, its main use has been as a testbed for algorithm development in computer graphics, but there are many other interesting applications. + +Mitsuba comes with a command-line interface as well as a graphical frontend to interactively explore scenes. While navigating, a rough preview is shown that becomes increasingly accurate as soon as all movements are stopped. Once a viewpoint has been chosen, a wide range of rendering techniques can be used to generate images, and their parameters can be tuned from within the program. +%package devel +Summary: Mitsuba development files +Requires: boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel +%description devel +This package contains the development headers, which are needed when +building custom plugins and other extensions for Mitsuba. +%prep +%setup -q +%build +cp build/config-linux.py config.py +scons +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT%{_libdir} +mkdir -p $RPM_BUILD_ROOT%{_bindir} +mkdir -p $RPM_BUILD_ROOT%{_libdir}/python2.7/lib-dynload +mkdir -p $RPM_BUILD_ROOT/usr/share/mitsuba/plugins +mkdir -p $RPM_BUILD_ROOT/usr/share/pixmaps +mkdir -p $RPM_BUILD_ROOT/usr/share/applications +mkdir -p $RPM_BUILD_ROOT/usr/include +strip dist/lib* dist/mtsgui dist/mitsuba dist/mtssrv dist/mtsutil +strip dist/plugins/* dist/python/* +cp dist/libmitsuba-*.so $RPM_BUILD_ROOT%{_libdir} +cp dist/mtsgui $RPM_BUILD_ROOT%{_bindir} +cp dist/mitsuba $RPM_BUILD_ROOT%{_bindir} +cp dist/mtssrv $RPM_BUILD_ROOT%{_bindir} +cp dist/mtsutil $RPM_BUILD_ROOT%{_bindir} +cp dist/python/mitsuba.so $RPM_BUILD_ROOT%{_libdir}/python2.7/lib-dynload +cp dist/plugins/* $RPM_BUILD_ROOT/usr/share/mitsuba/plugins +cp -Rdp dist/data $RPM_BUILD_ROOT/usr/share/mitsuba/data +cp src/mtsgui/resources/mitsuba48.png $RPM_BUILD_ROOT/usr/share/pixmaps +cp data/linux/mitsuba.desktop $RPM_BUILD_ROOT/usr/share/applications +cp -Rdp include/mitsuba $RPM_BUILD_ROOT/usr/include/mitsuba +%clean +rm -rf $RPM_BUILD_ROOT +%files +%defattr(-,root,root,-) +%{_libdir}/libmitsuba-*.so +%{_libdir}/python2.7/lib-dynload/mitsuba.so +%{_bindir}/* +/usr/share/pixmaps/mitsuba48.png +/usr/share/applications/mitsuba.desktop +/usr/share/mitsuba/* +%files devel +/usr/include/* +%changelog + +* Mon Aug 15 2010 Wenzel Jakob 0.3.0%{?dist} +- First official Fedora Core build diff --git a/doc/Doxyfile b/doc/Doxyfile index e94a0d74..abd0a969 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -25,20 +25,20 @@ DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. -PROJECT_NAME = Mitsuba +PROJECT_NAME = "Mitsuba Renderer" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.2.0 +PROJECT_NUMBER = 0.3.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = doc/apidocs +OUTPUT_DIRECTORY = /home/httpd/mitsuba-renderer.org/htdocs/api # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -236,7 +236,7 @@ EXTENSION_MAPPING = # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. -BUILTIN_STL_SUPPORT = NO +BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. @@ -590,7 +590,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = include/mitsuba/core include/mitsuba/render doc/doxyfiles +INPUT = include/mitsuba/core include/mitsuba/render include/mitsuba/hw include/mitsuba/bidir 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 @@ -718,7 +718,7 @@ INLINE_SOURCES = NO # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. -STRIP_CODE_COMMENTS = YES +STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented @@ -836,7 +836,7 @@ HTML_ALIGN_MEMBERS = YES # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). -HTML_DYNAMIC_SECTIONS = NO +HTML_DYNAMIC_SECTIONS = YES # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 @@ -978,7 +978,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. -DISABLE_INDEX = NO +DISABLE_INDEX = YES # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. @@ -993,7 +993,7 @@ ENUM_VALUES_PER_LINE = 4 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. @@ -1405,7 +1405,7 @@ MSCGEN_PATH = # inheritance and usage relations if the target is undocumented # or is not a class. -HIDE_UNDOC_RELATIONS = YES +HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization diff --git a/doc/basics.tex b/doc/basics.tex index 99670aad..ca082d74 100644 --- a/doc/basics.tex +++ b/doc/basics.tex @@ -190,6 +190,7 @@ might start the with parameters such as the following $\texttt{\$}$ mitsuba -xj 2 -c machine1;machine2;... animation/frame_*.xml \end{shell} \subsection{Direct connection server} +\label{sec:mtssrv} A Mitsuba compute node can be created using the \code{mtssrv} executable. By default, it will listen on port 7554: \begin{shell} diff --git a/doc/compiling.tex b/doc/compiling.tex index 3c53f63a..4551f955 100644 --- a/doc/compiling.tex +++ b/doc/compiling.tex @@ -8,7 +8,7 @@ software construction tool. There are some differences between the different ope more details, please refer to one of the next sections depending on which one you use. \subsection{Common steps} -To get started, you will need to download a recent version of Mitsuba. Make sure that you have the Mercurial (\url{http://mercurial.selenic.com/}) versioning system installed\footnote{On Windows, you might also want the convenient TortoiseHG shell extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.} and enter the following at the command prompt: +To get started, you will need to download a recent version of Mitsuba. Make sure that you have the Mercurial (\url{http://mercurial.selenic.com/}) versioning system installed\footnote{On Windows, you might want to use the convenient TortoiseHG shell extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.} and enter the following at the command prompt: \begin{shell} $\texttt{\$}$ hg clone https://www.mitsuba-renderer.org/hg/mitsuba \end{shell} @@ -32,6 +32,8 @@ build/config-msvc2010-win32.py build/config-msvc2010-win64.py build/config-icl12-msvc2010-win32.py build/config-icl12-msvc2010-win64.py +build/config-icl12-darwin-x86_64.py +build/config-icl12-darwin-x86.py \end{shell} \subsection{Compilation flags} @@ -77,7 +79,7 @@ First, run $\text{\$}$ sudo apt-get install build-essential scons mercurial qt4-dev-tools libpng12-dev libjpeg62-dev libilmbase-dev libxerces-c3-dev libboost1.42-all-dev libopenexr-dev libglewmx1.5-dev libxxf86vm-dev libpcrecpp0 - libboost-system-dev libboost-filesystem-dev libboost-dev + libboost-system-dev libboost-filesystem-dev libboost-python-dev libboost-dev \end{shell} Please ensure that the installed version of the boost libraries is 1.42 or later. To get COLLADA support, you will also need to install the \texttt{collada-dom} packages or build it from scratch. Here, we install the \code{x86\_64} binaries and development headers that can be found in the \texttt{dependencies/linux} directory\footnote{The directory also contains source packages in case these binaries don't work for you.}: @@ -93,7 +95,7 @@ If all goes well, SCons should finish successfully within a few minutes: \begin{shell} scons: $\texttt{done}$ building targets. \end{shell} -To be able to run the renderer from the command line, you will also have to import it into your path: +To be able to run the renderer from the command line, you will first have to import it into your path: \begin{shell} $\text{\$}$ . setpath.sh \end{shell} @@ -155,16 +157,14 @@ into the \code{/etc/apt/sources.list} file. \subsection{Building on Fedora Core} You'll first need to install a number of dependencies. It is assumed here -that you are using Fedora Core, hence some of the package may be named differently if you are -using another distribution. +that you are using FC15, hence some of the package may be named differently if you are +using another version. First, run \begin{shell} -$\text{\$}$ yum install mercurial gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel +$\text{\$}$ yum install mercurial gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel \end{shell} -You will also need the \texttt{glew-mx} and \texttt{collada-dom} packages, which are not included in the Fedora package repository. -You can grab source, \texttt{i386}, and \text{x86\_64} \texttt{RPM} files at the following location: \texttt{http://www.mitsuba-renderer.org/releases}. -After installing them, simply run +Afterwards, simply run \begin{shell} $\text{\$}$ scons \end{shell} @@ -173,71 +173,68 @@ If all goes well, SCons should finish successfully within a few minutes: \begin{shell} scons: $\texttt{done}$ building targets. \end{shell} -To be able to run the renderer from the command line, you will also have to import it into your path: +To be able to run the renderer from the command line, you will first have to import it into your path: \begin{shell} $\text{\$}$ . setpath.sh \end{shell} (note the period at the beginning -- this assumes that you are using \code{bash}). Having set up everything, you can now move on to \secref{basics}. - +\subsubsection{Creating Fedora Core packages} +To create \code{RPM} packages, you will need to install the \code{RPM} development tools: +\begin{shell} +$\text{\$}$ yum install rpmdevtools +\end{shell} +Once this is done, run the following command in your home directory: +\begin{shell} +$\text{\$}$ rpmdev-setuptree +\end{shell} +and create a Mitsuba source package in the appropriate directory: +\begin{shell} +$\text{\$}$ ln -s mitsuba mitsuba-$\code{\MitsubaVersion}$ +$\text{\$}$ tar czvf rpmbuild/SOURCES/mitsuba-$\code{\MitsubaVersion}$.tar.gz mitsuba-$\code{\MitsubaVersion}$/. +\end{shell} +Finally, \code{rpmbuilder} can be invoked to create the package: +\begin{shell} +$\text{\$}$ rpmbuild -bb mitsuba-$\code{\MitsubaVersion}$/data/linux/fedora/mitsuba.spec +\end{shell} +After this command finishes, its output can be found in the directory \code{rpmbuild/RPMS}. \subsection{Building on Arch Linux} -There are two ways to install Mitsuba on Archlinux, the Arch way, and the other way. - -The Arch Way is to use the Aur software repository. -Accessing software in the Aur repository is easiest when using a script called \texttt{packer}. - -First download packer then use \texttt{makepkg} to build and install it. -The \texttt{-is} flags will prompt you for your sudo password and then install the package after it has finished building as well as install any needed dependencies. +You'll first need to install a number of dependencies: \begin{shell} -$\text{\$}$ mkdir packer && cd packer -$\text{\$}$ wget http://aur.archlinux.org/packages/packer/packer/PKGBUILD -$\text{\$}$ makepkg -is +$\text{\$}$ sudo pacman -S gcc xerces-c glew openexr boost libpng libjpeg qt scons mercurial python \end{shell} - -Next, use packer to automatically download, build, and install Mitsuba as well as any needed dependencies. -The optional \code{--noedit} flag is used if you do not wish to edit the files after they are downloaded. -The optional \code{--noconfirm} flag is used if you do not wish to confirm each step of the installation. +For COLLADA support, you will also have to install the \code{collada-dom} +library. For this, you can either install the binary package available on +the Mitsuba website, or you can compile it yourself using the \code{PKGBUILD} +supplied with Mitsuba, i.e. \begin{shell} -$\text{\$}$ sudo packer -S --noedit --noconfirm mitsuba-hg glewmx collada-dom +$\text{\$}$ cd +$\text{\$}$ cp /data/linux/arch/collada-dom/PKGBUILD . +$\text{\$}$ makepkg PKGBUILD +<..compiling..> +$\text{\$}$ sudo pacman -U \end{shell} - -Periodically you may wish to update Mitsuba to the latest version. -To do this simply reinstall it and packer will pull and build the latest version. +Once all dependencies are taken care of, simply run \begin{shell} -$\text{\$}$ sudo packer -S --noedit --noconfirm mitsuba-hg +$\text{\$}$ scons \end{shell} - -Alternatively you can skip using packer and manually download the files and install them one at a time yourself. -First install glewmx +inside the Mitsuba directory. In the case that you have multiple processors, you might want to parallelize the build by appending \code{-j }\emph{core count} to the command. +If all goes well, SCons should finish successfully within a few minutes: \begin{shell} -$\text{\$}$ mkdir glewmx && cd glewmx -$\text{\$}$ wget http://aur.archlinux.org/packages/glewmx/glewmx/PKGBUILD -$\text{\$}$ makepkg -is +scons: $\texttt{done}$ building targets. \end{shell} - -And then collada-dom +To be able to run the renderer from the command line, you will first have to import it into your path: \begin{shell} -$\text{\$}$ mkdir collada-dom && cd collada-dom -$\text{\$}$ wget http://aur.archlinux.org/packages/collada-dom/collada-dom/PKGBUILD -$\text{\$}$ makepkg -is +$\text{\$}$ . setpath.sh \end{shell} - -And finally Mitsuba -\begin{shell} -$\text{\$}$ mkdir mitsuba-hg && cd mitsuba-hg -$\text{\$}$ wget http://aur.archlinux.org/packages/mitsuba-hg/mitsuba-hg/PKGBUILD -$\text{\$}$ makepkg -is -\end{shell} - -To uninstall do this -\begin{shell} -$\text{\$}$ sudo pacman -R mitsuba-hg glewmx collada-dom -\end{shell} -After installing you will be able to run the renderer from the command line. +(note the period at the beginning -- this assumes that you are using \code{bash}). Having set up everything, you can now move on to \secref{basics}. - -If for some reason you are unable access the Aur files, they are also hosted at -(\url{https://www.mitsuba-renderer.org/releases/contrib/archlinux/}). +\subsubsection{Creating Arch Linux packages} +Mitsuba ships with a \code{PKGBUILD} file, which automatically builds +a package from the most recent repository version: +\begin{shell} +$\text{\$}$ makepkg data/linux/arch/mitsuba/PKGBUILD +\end{shell} \subsection{Building on Windows} On the Windows platform, Mitsuba already includes most of the dependencies in precompiled form. diff --git a/doc/development.tex b/doc/development.tex index e2462eb0..09acf5ee 100644 --- a/doc/development.tex +++ b/doc/development.tex @@ -1,12 +1,30 @@ -\section{Development Guide} +\part{Development guide} This chapter and the subsequent ones will provide an overview of the the coding conventions and general architecture of Mitsuba. You should only read them if if you wish to interface with the API in some way (e.g. by developing your own plugins). The coding style -section is only relevant if you plan to submit patches, which should -go into the main codebase. +section is only relevant if you plan to submit patches that are meant +to become part of the main codebase. -\subsection{Coding style} +\section{Code structure} +Mitsuba is split into four basic support libraries: +\begin{itemize} +\item The core library (\code{libcore}) implements basic functionality such as + cross-platform file and bitmap I/O, data structures, scheduling, as well as logging and plugin management. +\item The rendering library (\code{librender}) contains abstractions + needed to load and represent scenes containing light sources, shapes, materials, and participating media. +\item The hardware acceleration library (\code{libhw}) + implements a cross-platform display library, an object-oriented OpenGL + wrapper, as well as support for rendering interactive previews of scenes. +\item Finally, the bidirectional library (\code{libbidir}) + contains a support layer that is used to implement bidirectional rendering algorithms such as + Bidirectional Path Tracing and Metropolis Light Transport. +\end{itemize} +A detailed reference of these APIs is available at +\url{http://www.mitsuba-renderer.org/api}. The next sections +present a few basic examples to get familiar with them. + +\section{Coding style} \paragraph{Indentation:} The Mitsuba codebase uses tabs for indentation, which expand to \emph{four} spaces. Please make sure that you configure your editor this way, otherwise the source code layout will look garbled. @@ -74,10 +92,10 @@ However, anything pertaining to the API should go into the header file. \paragraph{Boost:} Use the boost libraries whenever this helps to save time or write more compact code. -\paragraph{Classes vs structures:}In Mitsuba, classes \emph{always} go onto the heap, +\paragraph{Classes vs structures:}In Mitsuba, classes usually go onto the heap, whereas structures may be allocated both on the stack and the heap. -Classes that derive from \code{Object} usually implement a protected virtual +Classes that derive from \code{Object} implement a protected virtual deconstructor, which explicitly prevents them from being allocated on the stack. The only way they can be deallocated is using the built-in reference counting. This is done using the \code{ref<>} template, e.g. diff --git a/doc/doxyfiles/mainpage.dox b/doc/doxyfiles/mainpage.dox index fdd417da..ea68c9a9 100644 --- a/doc/doxyfiles/mainpage.dox +++ b/doc/doxyfiles/mainpage.dox @@ -1,36 +1,64 @@ /** \defgroup libcore Core library - This module contains the core support API of Mitsuba + This library contains the core support API of Mitsuba */ /** \defgroup librender Render library - This module contains the rendering-related API of Mitsuba + This library contains the rendering-related API of Mitsuba + */ +/** + \defgroup libhw Hardware acceleration library + This library contains the hardware acceleration API of Mitsuba + */ +/** + \defgroup libbidir Bidirectional support library + This library contains a support layer used to develop bidirectional + rendering techniques. + */ +/** + \defgroup libpython Python bindings + This module references all classes that have Python bindings */ /** \mainpage Mitsuba Renderer API Documentation +
Warning: The generated API documentation is still very new and currently incomplete.
+

Basic Information

+

Welcome to the Mitsuba API documentation. Mitsuba + is a modular open-source rendering framework, which consists of a small set of core libraries + and over 100 different plugins that implement functionality ranging from materials and light + sources to complete rendering algorithms. This page provides information on the interface to these core + libraries needed to develop custom plugins.

-
+

The API documentation tracks the current development branch and is automatically + regenerated every hour. Note that it is not a substitute for the reference manual! + If you are planning to do any kind of serious development with Mitsuba, it is recommended that you + first read one the following documents (preferably the latter)

+ - Reference Manual (Current release) + - Reference Manual (Development version) - www.mitsuba-renderer.org +

API Structure

+

Mitsuba is split into four basic support libraries. Please use the links below to view their + contents: +

+ The core library (libcore) implements basic + functionality such as cross-platform file and bitmap I/O, data structures, scheduling, as well as logging + and plugin management.

+

The rendering library (librender) contains abstractions + needed to load and represent scenes containing light sources, shapes, materials, and participating media.

+

The hardware acceleration library (libhw) + implements a cross-platform display library, an object-oriented OpenGL + wrapper, as well as support for rendering interactive previews of scenes. +

Finally, the bidirectional library (libbidir) + contains a support layer that is used to implement bidirectional rendering algorithms such as + Bidirectional Path Tracing and Metropolis Light Transport.

+

Mitsuba also exposes a subset of these libraries via Python bindings. To see + a listing of all exported classes, click here.

-
- -
Basic Information
- - Reference Manual (PDF) - -
API Documentation
- - Annotated Class List - - Alphabetical Class List - - Class Hierarchy - -
Community
+

Community

- Development Blog - Bug Tracker - - List of repositories - -
-
+ - List of repositories */ diff --git a/doc/images/logo_plain.pdf b/doc/images/logo_plain.pdf new file mode 100644 index 00000000..74b57e9e --- /dev/null +++ b/doc/images/logo_plain.pdf @@ -0,0 +1,674 @@ +%PDF-1.4 %âãÏÓ +1 0 obj <> endobj 2 0 obj <>stream + + + + + application/pdf + + + logo_plain + + + + + 2011-08-19T00:29:30-04:00 + 2011-08-19T00:29:30-04:00 + 2011-08-19T00:29:30-04:00 + Adobe Illustrator CS5 + + + + 256 + 256 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq8X/ADD1+98y+Y73QI7h4fLejssF7DCxQ3t4yCR0ldSG9GBXVeA2Z68qhQM1+t1Jh6Y8 3D1Wcx2HNjdron6Hl+ueVpToOopQq9qONvJT9m4txSOVT3qOXgQcwcWsnE7mw4mPUyid9w68t9U8 03Dat5wpLfSf7z6fDJJ9WsoxQBIKMPjNOTS/aJ9gMs1GtkZeg0GebVEn07Bm35d/mJ+jrk+V/Nmp qZaK2hateyBHu42cJ9XlkcgPcRMygd3Ug9Q2bHS6jxI+bm4M3GPN6tmS3uxV2KuxV2KuxV2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVLfMuuW+geXtS1u4UyQ6bbS3LRKaM/pIW CL13YjiPfFXitt5i/MxZl1g6+RqkvxzaXLEj6YFO4gWJQsqhfs+osnM9TXpmp/lE8XL0uu/Oni5e lA6KdSkGoXepWq2d5f393ePAkglUCeZnHFxTkKGgqAfYZiavIJzscnH1ExKVhMsxmh2KpP5vtYbj yzqnNQXjtJ3hkIqyOsZKsp7EEVy7TyImK7w24SRIe96V5y/NKewhs9J0KGO58z31tHczc6tbWEMq giWehBZm39OMGrdTQdd9mzxxxsu3y5RAWXn8lvrzzHUG8xam2uV5pqP1mRUVxvxFohW29Ll1i9Oh H35qfz+Tivp3Ou/OTu+j2P8AL7zTN5m8q2up3MawagrS2uowRklEubaRoZeNf2WZOS/5JGbqMhIA jq7SMrFsjySXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXnv53apEnl IeX0Qy6j5glW3tE6IqQss00sjHoiIlPEkgAZVmyCESS15ZiMSSwnOadG7FXYq7FUFrdpNeaNf2cB UT3NtLDEXrx5yIVXlTtU5PHLhkCehZwNSBWaLpCaZaemZWubqU+peXkm8k0pABdvuoo6AUAyebMc krKcuQzNlMMpa0DpH6V8va9p17p2rXiW95rVot1pxkH1Vk1C5jtJh6QABNJAwZqkEbUzaaPVSMhD o5+mzkkR6PobNs7F2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoDVPMGg6 Rw/SupWun+p/d/Wp44eX+r6jLXFWDfm/aw6h5Xs/NWlyJdjy/ObySSBhIr2TqYrviU5A8EPq/wCw ynUY+OBDVmhxRIYcrK6hlIZWFVYbgg9xnOOlbwIdirsVdirsVdiqFvP96tH/AO21o3/dUtsy9F/e j4/c5Gl/vA901DXdD011TUdRtrJ3FUW4mjiLDpUBytc37uEarKyhlIZWFVYbgg9xireKuxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KpX5r1O40rytrGqWwDXFhY3N1CrCql4YWdQR4VXF XgelaHpzQpf3SLqGp3aLJd6lcgTTzO61Yl25EKa7KPhHbOezaicpHd0uXNKR3K5/LOmo0smnGTSZ 51KTS2DegJFbZlmiAMMysNiJEYY49Xkj1v3phqJx6onRtPfTdKtNPadrk2sawrO4ozKgovKnfjTK ck+KRPK2ucrNo3IMHYq7FXYq7FXYqhtQ0601C1NrdqXhZo5KK7xsGidZEYMhVgVdAdjk4TMTY5so yMTYQlv5W8twBvT0y25P9t2iR3b/AFnYFm+k5OWeZ5ksjlkepelfkfPJ/hS9007W+kanc2dmnZIC EuEQf5KevxXwG3bN9p5GUAT3O3wyuAL0LLm12KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV 2KuxVhn5m+bxoenW2nQ2MepX2uGa1htZ5DFCIliJmklZVZuCggUUVJbt1yvLlEI2WGTIICy8l8rQ ajbaBZ2moxiO7tE+rvRuYYRHgjhqCvJAD0Hyzns5BmSORdNlIMiRyTXKmt2KuxV2KuxV2KuxV2Ku xV2Kpx+VepXGlecrrQfU56brcM+qRIwq8d5btDFKAwFeEsUimjdCm3Wmbvs/LxR4T/C7TR5LjXc9 gzPcx2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV59+cmh3Nxo1p5hso/WvPL0jzyQ A/FLaTLwuY08XACyKO5WnfKdRi8SBDVmx8caYHaXVvd2sV1bSCW3nRZIZF6MjCoI+YznJRINF0pF Giq4EOxV2KuxV2KuxV2KuxV2KuxVPvyg06bUfMeqeZjUafZxNo+mt2lcyLLeyL/kq8UcYI7q3hm9 0OHhhZ5l22kx8MbPV61ma5TsVdiqU+Z/NWh+WdNOoavcejCWEcMagvNNK32YoYlq0jt2AH4YCQNy gmmAT/ndqElrJFZ+VruLVJXpZC7kiFqISKia4mhMhjK/tRBS3gepGMdZjAJtoOqhV2kFx5h/MO/J e98yy2nI8vq2l29vBEpp0DzJczkD3kzBn2lLoHFlrZdAzb8pfNeoapa6po+sXv1zVtHuQqSyBFml spo1kglcIEViGLxlgoqU33zZafLxwEnNw5OOILPsubXYqpLd2rXDWyzIblByeEMC4XbcrWtNxiqr irsVdirsVdirsVdirsVdirwfz7bprP5i61a61W9t9K+q/ouwn+O3iimtkdpViPwF3mEg5kE/CBXN Z2hlnEgA0HA1mSQIA5LY44441jjUJGgCoigAAAUAAHQDNSTbr12BDsVdirsVdirsVdirsVdirsVR f5c6hf8Alzzbpeg2UzP5d1l7iFdMclltJ44Jbv1bcndI39Fg8f2eTAim+bnQ6mU/TLo7PSZzLYvb c2LmuxVLfMnmDTvLuhXmtaixW0so/UcKKsxJCpGg7u7kKo7k4q8OaXVda1U+YvMFG1SRStpaA8or GBtxBF/lEf3snVj/AJNBmi1eqOQ0PpdTqM5maH0ovMJxXYqoaZqej6N+YGg6xqc8Vna28F+Li8lI ULH6FeJbqatSi9z03zadmncufoTuWQaz+avmfWWeLyxbDRtNrRdXv4/UupV/mgtGosQ22aapofsD MjNrox2G5bsurjHYblil3oo1I8tcv73WpCan69cSPHX/ACbdDHbr/sYxmunrckutOHLVTPV2hnSf J/m/Sdbs9GpZRxXdveJptvH6lJkUo3FfTr8Uf45kaLU0Txy+bbpc9E8Reif8rv0bYtoGtqh/b+rw H/hVnL/hmf8Amsfe5n5iHeybyr588s+aPWj0q5b65agG6sLiOS3uYg32WaKUK3E9mFVPjl0ZCQsN okDuGQZJLsVdirsVdirsVdiryv8AObR3srqw86Qj9xaoNP1wDtaSvyhn+UEznl/kux7Zi6zDxw25 hx9Ti44+YY313Gc+6d2KuxV2KuxV2KuxV2KuxV2KuxVOvyo0ZtY8zXPmmQV03SVl07SCRtJcuR9b nU+EYUQr7883mhw8EbPMu10mLhjZ5l61c3FvbW8tzcSLDbwI0k0rkKqIg5MzE7AACpzOct4L5k16 88/XX1q5aa18rRNXSNOR3heYqapezshR+R+1ElfgFG+101er1pB4YdHA1GqINRQt7cecdRbTNJ1f UF1LQNNlN7FPMKXjzRrwgjuHFFlWPmXV6BiwHKpocqya7ixkfxNc9XxQrqmGa5wnYq7FUHeaTp17 c2tzdwLNLZM0lqX3COwpyA6VHbwycchiCB1ZCRAIHVGZBi7FXYq7FVXyuTF+ZvlmWL4ZZ1vrecr1 aD6s0vFv8kSxRn55s+zSbI6OfoSbIe55t3YuxV2KuxV2KuxV2KqV3a213azWl1Es1tcI0U8Ljkrx uCrKwPUEGhxV4JfaPP5T8yt5UlkNzZmBrzRbonk4sw4T0LjqQ8LHir9HWh+0GGabXafhPEORdZq8 PCeIdURmucJ2KuxV2KuxV2KuxV2KuxVQvgjWVwHmNshjcNcKQrRjiauGOwK9a5KPMdWUeb1H8oxO Py18vCa2S0Is0EcUaemDFU+jIUq1Glj4yPv9pjnTjk70MV/N7XjqmoQ+SbV/9FCpeeY2XvCWrb2h P/FzKXkH8i06PmLrM/hx25lx9Tl4I7cyx/psM0DqHYq7FXYq7FXYq7FXYq7FXYqmn5RQ22sedtW1 b1YyugwnTLa25KZfWuCslxMUryVQsaRoxX4vjoc3mgxcML/nO10mPhjfe9kzOct2KuxV2KuxV2Ku xV2KvE/zH0fU/L/mu/8AM9/yvNC1UQo2ogb6d6ShEgmUdLdmJZZANmY8+zZga7TymAR06OHqsMpb joglZXUMpDKwqrDcEHuM0rrG8CHYq7FXYq7FXYq7FXYqp6ToL+cPMqeXwpOjWfC58xS7gNETWKzB G/KcrV/CMH+YZs9Bp7PGfg52jw2eIvU/PnnaDyjplq0Fn+kNSvplttN0xZBB6hA5SMX4vwSKNSxP E9h3zaZMggLPJ2E5iIsvI9MS/k+s6jqgH6X1SZrzUCp5BZH2WJW7rDGFjX2XNBqc3iTvo6fPk45X 0RuY7S7FXYq7FXYq7FXYq7FXYq7FUR+X+lyaz+Y1rqllEFtPLizJqGogU9Sa4haJbJWH2uPqerIP 2Sqdzm47PxSA4jyP4t2WjxkCzye4ZsnOdirsVdiqXQ+Y/L09z9Vh1S0luqgegk8TSVJAHwhq9xir DdQ/OWxttVu7S10LUNQtLCeW0ub23NqAZoGMcoijlmjdwjqVJ23BpXvRPU44mid2mWeETRO6e+Wv zI8n+Yp/qdjfejqYFW0u7Rra7HXpFKFLgU+0nJffLYzEhYLbGQPJMNf83eWPLqwNrmqW2nC5JEAu JFQvx+0QCa0Woqeg75JKNt7nTdVsBNbSw3+n3SELJGyTQyo1VNCOSsp6Yq8c/MTyTB5HsX13y/Oq 6U0qRN5amLGsszcVXT3AZkYk19JgU60KAZh6nSwmL5HvcXPp4yF8iggSQCRQnseo+7NC6pvFDsVd irsVdirsVQ+o3kVlYXF3NIsMUEbSNK4JVQorUgEE/LJQjZAZRFmnqf5VaAdF8i6XHNC8Op3sKX+r +qayte3KK83PZd1PwAU+FQF7Z00YgCg72MQBQYL+Yt0l7+ZxiWT1U0fSok9OtVhnvZpHkFP5nihi J9qZru0pekBwtdLYBLs1DrXYq7FXYq7FXYq7FXYq7FXYqoaXp+p+a9bm0DRZfq8dpwOt6qKH6qkg qscQOzXEij4eyj4j2B2Gj0nH6pfS5mm03FueT2/y/oGleX9HttI0qAW9jaLxijqSdyWZmY7szMSz Mdyc3TtEwxV2KuxV82wTah5v0+DU/M99PqbXQ9RtNdyljC1SDEtrHwjb0/s8pAzHxzTarV5BIxG1 Osz6ifEQNldvLHltovRbSrMxf77NvFx39uOYfjT/AJx+bjeJLvKJ07TLHTbUWljCILZWZliWvEF2 LNSpPViTkZzMjZ5sZSMjZa1HStO1KEQ31uk6KeSch8SMOjIwoysPFTXGGSUTYNJjMxNhTtdNuUv2 vb3UbnU5lgS0tJLxhJJDbozSemJKBnq7klnJY7AnbLs+plkAB6NmXPKYAK6wt9T0G9bUvKtyNMun bnc2ZBaxuqdp4BQBj/vxKOPE9Mswa2UNjuGeLVSjz3DJ9Y/Mv8ufM3l46T50WfRNSWRHe1X1Xlt5 Erxvba4hQj0k3/ekADo4FaHcRyQnG+hdkJxmPJjuqWeseV7qC21uVLzS7wquk+Y4QBBccxVI5wpK xTEfZoeD/s0+zmr1Wi4fVHk4GfS8O8eSIzXOE7FXYq7FXYq7FVfyh5bHm/zOBOnPy5oEqSXtRWO6 vlo8Vt4FIdpJB48V8c2+g09es/B2Ojw/xF635r8yWPlry9e63egtDZx8liX7csrEJFCnX4pJGVF9 zmyJpzyXiGlQXyxTXepSerq2oyvealKOhnl6ovX4I1Cxp/kqM53U5vEmT0dLmyccrRuUNLsVdirs VdirsVdirsVdirsVQctjPHfx6rpV1JpetQrxi1CChLJWvpzRn4Joif2H+ih3zIwamWM7cu5vxZ5Q 5cnp35d/mDP5ge40jWLdLPzDYxrLKkJLQXEDHiLiAn4gOWzI26mnWoOb3DmjkFh2uLKJiwzbLWxL 9V8xeX9H4fpbU7TTvVr6f1ueODlTrx9RlrirCn/O7QnnmXTdG1TVbWKR401C1FkLeUxsULRNPdQM 6VXZgtD1G2Y89VjgaJ3aZ6iETRLzGw1i0m81azaWljeWGn3UralYRXsQjKmc1uolKF4yFnJdeLHZ /bNbrRGR44m+9wdVwk8USnea9w3Yq7FXYq7FVrxxuCHUMCCpDAGqt1G/Y4QU23oXmKHy1ZS6Br9q dW8gXQMbRunrtp6N1Vo6M0lr32+KPtVfs7jSawS9MubstPqb2lzTO9/LbVbO0TU/I9/H5g0KZRJb 6ZcTqZRGen1S+JKyKOyzf8jMnn0MZ7jYs8ukjLcbFjkeu2QvP0ferJpmqdTp1+ht7jf+VX2kH+VG WHvmry6acOYdfkwTjzCY5jtLsVdiqDvn1Ce5s9H0kBta1aT0LHkOSRgCstxIP99wp8TeOy9TmTpc HiSroObfgxccvJ7h5X8uad5b0K00bTwfq9qtDI5rJLIxLSSyHu8jksx8TnQAU7kB5L548x/4s81C 2tmD+XfLkzLG6mq3WpKCkj+6WoJRT/OWP7IzXa/UUOAcy4OszUOEIXNO612KuxV2KuxV2KuxV2Ku xV2KuxVDahqNpp9sbi5YqnIIiqpd3dzRI40UFndjsqqKnJ48ZmaHNnCBkaDO/wArfJmrWd1ceaNe j+q6lewC2sdNrU2toWEhExGxmlYKXA2XiAO+b/TYBjjXV2+DCICur0bMhufPWsjR7n8yfNCtLbaj eGWCeG5Vo52W2eBYxDUFynpSxSApt2NPizU9o8QIIOzrtbxAjuRgAUBVFANgB0AzVuC3ih2KuxV2 KuxV2KuxV2KofSpdd8t3TXfla6S1SRi9zo9wGbT52b7TcF+KGQ/zx/7JWzPwa6UNpbhy8OrMdjuG cWP5heRPNaJovm/TIdPvnPw6frCRTWsr/wDLtcODDKfb4X/yc22PNGYsF2MMsZ8io+YfybgtoTd+ SZv0bdRiraRPJJJYXA7qA5d7d/5Wj+HxU5DNpYZBuN+9jlwRn72E2eoGW5nsLuCSw1ezIF7ps9BL GT0YU2eNuqutVYZpM+CWM0XVZcMoHdGZQ1J9+UNtBJ508y3ciBrm3s9PggkO5SKZ7h5FXwDtGpbx oPDN52eP3fxdrox6Ew/M/wA93CyP5R8uz8dXmUfpbUIz/wAc+2ffY0p9YmWojXqo+M9q3ajUDHG+ rbmzCA82FWVla2NpDZ2sYit4FCRRjoFH+fXOflIyNnm6eRJNlXyLF2KuxV2KuxV2KuxV2KuxV2Kq F7f2Vjbtc3s8dtbp9qWVgij6TkoxMjQFshEnYMk/KbyydT1i783anYv9VjSKHyybxCroKObm6iiY DgJeSKjsOdAafCc3ujweHHfmXbabFwR35vW8y3IeCeYPMt/58uZppJ5IfJ/IppumxM0QvYwafWbo jizpJTlHGfh40LAk5q9XrCDwxcDU6kg8MVO0srKziENnbx20I6RwoqKPoUAZq5SJ5m3AMieavkWL sVdirsVdirsVdirsVdirsVUrq1tbuB7e6hSeCQUeKRQ6MPdTUYYyINhIJHJrSLvzV5bCr5b1Zks0 pTR9QDXdnQD7MZLLPD1/Yk4/5ObDF2hIbS3czHrJDnuivMnm7QfMlrGPNmmXPlvXbNT+j/M1ipvr aJutHaILN6LsPjjli40/ar8QzhnxZRR+1yhlx5BRSXy9rQ1KKeGSS3lvLJxFcy2contpKqGSWCRa 1SRTWh+JTVW3BzU6nB4cq6Ovz4uCVdFey1bzhpGr6xHoaxWqaxBZq2sy0ka3FuZw6xQHZ5T6oIZ/ hXwbpmTp9XHHjr+K27DqBCFdVXTtNttPgMUHJmkZpbieQl5ZpXNXllc7u7HqTmDkySmbLizmZGyi srYOxV2KuxV2KuxV2KuxV2KoHVE1wx10qW1STut1HI6nr+1G6U+7LIcH8V/BnHh6pLYjzOtw3+Jz eNZb1by2bTlQ9KrfL6lP9Q1zOxflut/Fysfgdften/l3pn5M3t+sukL9c8x26h3TWTNJqMVN+axX m6U/mhUL75tMYhXpqvJ2EBGvTyeo5Yzdir5+1XRZ/I2p/oS+BXQZZCvl/U2/ujG5LLZyv0SWIfCl ac1ApvUZqNbpTfHH4uu1WnN8QROaxwHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqpxQQRFzFGsZlY vIVULyY7Fmp1O3XCSSklUwIdirsVdirsVdirsVdirsVdirsVdirsVQGq6dJciC5tHSDVbCaO6028 ZeRimiYOOlDxenFwDupIy/T5jjlfRtw5TCVvW/IPn+180W8ttcRCw8wWIH6R0wtyoDss0LED1IX/ AGWpt0NDm/x5BMWHcQmJCwyzLGaQef8AR7/WvJOt6Tp8UE19e2csNtHdANEZGWi1rUAg7qTsGocV eKaVqNqSNKdZbPU7JFS40y8Hp3UYUUBZT9pT2daq3Y5zufDOB9QdLlxSid0yzHaXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FWmZUUsxCqoqzHYADucKUJp+r2F9pMOqwSAWU0QnEj0XilKnl4ce+SljMZcP VlKBBrq7TNX0zVIDPp9ylxGp4uUO6mlaMpoymniMZ45QNSFLKBiaKMyDB2KuxV2KuxV2KuxV2Kux V2KuxV2KtaF65/MfyyNN/wCOkJJzdla0Gm+i3r+rT9j1PSC1/wB2cc2fZvFxH+a52iuz3Pec27sn Yqk3mTyd5Y8ywxxa5p0V56JrBK1UmiJ6mKZCssZ/1WGAi1It4hcWMdh5z1DS9G1K6v8AQdMUQXL3 xjmcXx3aGGZVR2SJKczIWPI0rsc1GuhjjsB6nWauEI8humGa1wnYq7FXYq7FXYq7FXYq7FXYq7FX Yqlmvwz3lnFo9s4S61qeHTIHP7P1pxHI+38kXN/ozK0ePiyDy3b9NDimFcaRbaVrPmPy6karZWOo Si3t1HwLbXsaXiIB/Kv1kpT2pluvjw5LHVs1YqdqZ0pbfyJ5W82KpFzY3E3l7WJxT97ZQ3c1jaPM 3cwywxKrHejHM7UQ8TDfWrcvNHjx315phmidS7FXYq7FXYq7FXYq7FXYq7FULqmow6dYS3syPJHE BVIwC5LMFAUEqOp8cnjgZyADOEDI0Eyt/KP5l6hJ6cGhxaShFfrWqXMLBf8AnjZPcsx9i6/MZsYd mn+I/JzIaE9S9H8jfl/p3lSG4lE76hrF+VbUdUmAV5OH2URBVYokqeKD6STvmzx4xAUHPhARFBlO TZOxVKfNs+vW/lnVJvL8K3Gtx20h0+FiAGm4nh9rYkHcA7HpUdcVeDeWZ9L/AEalpZTNJJbVW7jm qtys5JMpuEb41lZyS3LvnOaiM+MmQdLmEuImSb5Q0uxV2KtBgRUGo8RilvFDsVdirsVdirsVdirs VR/5f6d+lvzHjmZeVr5btGuWbt9bvuUEI/2MCzE/6wzb9m49jJ2WihsZLfO1sLf8z9Zp/wAfen6d dn5lrm3/AFWwyHaY+n4/oY64ck7/AC00TT/MH5b65oV+CbW81DU7ecLQOnqTMysta8XXkHU9jQ5s NP8A3cfcHLw/QPcwW4n1Ty6w07zVbzWt3A4g/SQglayuQWCpPHcKpiUPyXkrsCpNDmpz6KUSTEXF 1+bSyBJHJMswXEdirsVdirsVdiqT+aLnVbPTlvdPlSIW0iSXnqRGYfVq0lYIrRsSi/HswrSmX6eM ZSqXVtwxiZVLqyCXyj+ZFtHHImlWetW8gDpcaXeopZGFQwjuxAu48JSPfM6fZv8ANLly0PcUueTX IWK3XlrWoSOvGxluB99r64P0ZjnQZB3NJ0cwgtX03zLr2mXWk6T5e1SS5u4zHFLdWctjApP7Ukl4 IKKPbfwBy3T6PIJgnameHTTEgS+js3Ds3Yq7FXYq7FUh8w+QvJvmJ/V1nSLe6uRQLd8fTuQAKALP HwlA9g2Ai0EW821L8rvN2k63qA8t2kN9ody0UljHealcmS34wokkR+sJcHiZFZxRj9r2AzBz6ETN j0/BxculEjY2V4fyv8/zh21DVNK0eBQWL26T3zgDc/HL9SQU8Sh+WRj2dAcySxjoo9S881fy5p+u 6mkNjrGoaloVo9LzUpZVhivpU2MdrDbLCgt1OxkbkW/ZNByNeeePDtADi+5hmlDHtEeplEMMMEKQ woscMahI40ACqoFAAB0AzVk3uXAJtfgQ7FXYq7FXYq7FXYqpzzxW8Ek8zBIYlLyOeiqoqSfkMIFm gkC3of5O6JPY+Uhql5GY9R8wStqdwjAc0jkULbRE9fgt0SoPRuWdLhx8ERF3mOHDEBin5j/+TQP/ AGxLX/qLucwO0uQcPXcgyH8kVP8AhzVnp8L6zelD4hSiH/hlIzM0393H3OVg+ge5nl/YWWoWM9jf QpcWd1G0VxBIOSOjijKw8CMvbXhGo6PeeUddHly+d5rGcNJ5f1CQ1M0CbtbyN3mgH/BrRvHNNrdN wniHJ1mqwcJ4hycby0F2tmZoxdshlW3LD1CgNCwWtaV75gcJq+jh0atWyKHYq7FXYq0yq6lWAZWF GU7gg9jhSzr8ldRlk8qzaJOxaXy7dPp8bMeTG14rPa9eywzLH/sc6PBk44Au7wz4ogs/y5sdirsV dirsVdirsVdirsVeafn292vlbT4vWZdJutRhttWtIXCT3MMwZUhTu6mXi0iLuUB7A5VnJECRsWvK SImmIRxxxRrHGoSNAFRFACqoFAAB0AzmybdIuwIdirsVdirsVdirsVdiqjYaGfNvmO38tKC2mxcL vzDIOi2qmsduf8q5deNK14Bj4ZstBgs8Z5BzdHis8R6PfgAAABQDYAZuHZvGPP0iS/mffcan6tpG nxH2Zri9kYD/AGLJmq7TP0/F1+u6Mt/JSNf8BQ3QJJvr7Ubnfpxe+mCU/wCearmxwioAeTm4hUQP JnWWM0o81eVtH8z6PJpWqxs0DsskUsbcJoZozVJoZBujoeh+g1BIwEXsUEWxU/kl5TGh3NiJbiTV ppvrSeYpjG1/HOq8Y2Dokaemi/D6QUIVJFNycgMUeHhrZiMceHhrZij/AJc/mnDbvcH9F3Ulr8H1 CKSRGvB1MqSyKqwN0CxsGBNauNjmCezo0d3EOiG+6Rw61aG7ksLxZNN1WEVn029X0Z1HXkFbZ1pv zQlffNfl004cw4eTBKHMLrKXzHqcE+p6LoU+q6DbsYjf2zx85JF2kNvA5UzxofhLId2qFBpl8NBO Ub5HubY6ORjfVCS+btAgkMN1cNa3ani1jcRSxXXIdV+ruglLewXKTpMgNU1nTzuqT/T/ACr+ZWqW yXNroltYwXFfQ/Sd28E6qOjzW8cErJy7Ly5fzccy49mnqXIjoT1L0b8vfI83le0vZL28F9q2qSpP fTRp6UKlIxGkUKEs3BAOrGp6nwGyxYxCPCHOxwERQZZljN2KuxV2KuxV2KuxV2KuxV49+alzJdfm JpthMwNtpumNfWsXjPczNA8lO5SOLiPDmfHNf2jIiAHe4etkREBKM0rq3Yq7FXYq7FXYq7FXYqre T/J03nm6ur6W9u9P8uWXK3sbiykEUl1dg0llDMrq0MFCgqpDPX+XNxpNIOG5jcuz0+mHDchzeqeT fJumeVNLays3kuZ7iRri+v7gqZ7iZ9i78QqigAVVUAKoAGbCMREUOTmRiAKCfZJLwjzVcoPzA833 rmsVq9pblhvQQWMczDr2M5zUdo7zjF1ut3kA9O/Kuy+p/lv5ZhO0jadbTTf8ZJ4xLJ/w7nNsHZBl OFXYq7FXYqgNY8v6DrUSQ6zptrqcMZ5Rx3kEc6q3iokVgDtiqMgt4LeCOC3jWGCJQkUUahUVQKBV UUAAxVfirsVdirsVdirsVdirsVdirsVdirsVSPzV5J8t+aIIY9YtTJLbFmtLuKR4LiBmFCYpoijr WgqK0NNwcEogiiggHmw2f8lJ46DTPNV/Gg/YvYba7p7BlSCT/gmOYstFiPRoOlxnoxDzXoWs+UNa 0WDUtahvrLVRdLyFqLXjLAiOi8jNNXkrMe32cxdTo4whcebj59NGMbCAl8y6Is62sV0t5evtHZWY N1cOewWGEO5r8swYabJLkHEjhnLkHeaPLPndvKl1rt5z8u6ZbyWoitSwN/cCa6iiJkKErboFkrxq XPQ8embHFohAGUty5sNKIgk7lNM07rVCS/sY/X9S4jX6qoe5q6j01IJBff4QQO+SETttzZcJXWPk HzD540K71WGWXTdPjiaby5F/dy3t3GOcFxNy4lLYOo4KaF/tGi0ruNLoxEXLmXZYNKALlzRGj+Sv OXmp4rW80+48uaOaDVLq4ZFunAoXgtURmI5fZMzUAG68jkMGg4ZXJji0dG5PbdN06x0ywt9PsIFt rK0jWG3gjFFREFFUfRmzc5EYq7FXzJ5gvWuNH84anC3M6jfamLVxXcGZ7SA+O4jU5qM/q1AHdX63 W5fVmA9z6VsbOGysrezgFIbaNIYgafZjUKvQAdBm3dkrYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FUJqmj6Rq1sLXVbG31C2DCQQXUSTIHAIDcZAwqATvirtN0jSdLhMOm2UFjCa VjtokhXbpsgUYqo+Y9BsfMGhX2i33L6rfwtDIyGjryHwuhNaMjUZT4jFXmkX5QedHmFrc+Y7VLBa Br63s2W8de4CSSyQxt/l0Yf5OYI7Px3e7iDRwu0/078jvy4sruK7GnyXUqcWmW6uJp4p50JIuLiJ 2Mcsu53ZaeA2FMwQA6cnJEQOjPckydirsVdiqC13VItI0TUNVmHKLT7aa6kHisMZkP4Lir500fT2 Ok+VNImBke9vtLjuh3b9/HcXH/BLG+abB6tQT7/1Osw+rNfvfTGbl2bsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVYL+dV76P5f3lkrcZdYmttMQeK 3UyrMD7eh6hOQyy4Yk9zDJKoksH8sW7Xv5keW7YKHSzF5qcykAgLDbm2VjXwkvFp75q+zY+olwND Hcl7lm3dk7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXmH503Je+8qabSqPeXN+/8A0a2rRL/w12DmJrpViLjas1jKB/Kq19fz/rF5XbT9LtrcD/Kv LiV2/C0X78q7OHoJ82GiHpJ83rubBzHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq8i/NW4Mvn/RrY7iz0q7lHsbm4gWv3W36/HNf2ifQPe4etPpHv R/5L23K982X/AGa9trMH/mHs45v13WW6Efugz0g/dh6dmW5LsVdirsVdirsVdirsVdirsVdirsVd irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVeN/mNV/zPfwh0S069vWu7vp/yJ3+jNZ2 kdohwNcdgyH8kYyPL2rzn/j51m8YfKIRwf8AMnMzTCscfc5OAVAPQ8vbnYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8V87yPJ+Z2r8j/dadp0Kf6o e6k/4lK2artP+H4/odfrujMvyXVf+Vf20oABnvdUlJ7nnqVwVr7haDNhhFQA8g5mIeke5nGWtjsV dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVeIebXL /mb5hPT04NPiHvSJ5K/8lKZqe0+cfi67Xcwzj8l//Jc6d/xnv/8AqPnzZ4vpHuc7H9IZvk2bsVdi rsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVeCectQjg /NPzFbpBc3d1LHYtFbWdvNdSsFt9zxhR6D3NBmu1uCeQjhDharFKZFPSPygs9RsvIlra6hZzWM8d zfMkFyvCX0pryaaIsvY+nItQe+Z2MERAPOnLgCIgFmeTZOxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2Kv//Z + + + + + + uuid:27c651cd-ea0d-6b40-8d7e-d2dbe366797f + xmp.did:01801174072068118083DFBB3572BBEF + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:ae9148ef-3000-a144-9ee3-ddb3557e196e + xmp.did:8AF5709C0E20681188C6A12CE4B46A4D + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:01801174072068118083DFBB3572BBEF + 2011-08-19T00:29:26-04:00 + Adobe Illustrator CS5 + / + + + + + + Print + + + False + False + 1 + + 62.333496 + 62.333496 + Points + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + Black + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 100.000000 + + + CMYK Red + CMYK + PROCESS + 0.000000 + 100.000000 + 100.000000 + 0.000000 + + + CMYK Yellow + CMYK + PROCESS + 0.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Green + CMYK + PROCESS + 100.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Cyan + CMYK + PROCESS + 100.000000 + 0.000000 + 0.000000 + 0.000000 + + + CMYK Blue + CMYK + PROCESS + 100.000000 + 100.000000 + 0.000000 + 0.000000 + + + CMYK Magenta + CMYK + PROCESS + 0.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=15 M=100 Y=90 K=10 + CMYK + PROCESS + 14.999998 + 100.000000 + 90.000000 + 10.000002 + + + C=0 M=90 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 90.000000 + 85.000000 + 0.000000 + + + C=0 M=80 Y=95 K=0 + CMYK + PROCESS + 0.000000 + 80.000000 + 95.000000 + 0.000000 + + + C=0 M=50 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 50.000000 + 100.000000 + 0.000000 + + + C=0 M=35 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 35.000004 + 85.000000 + 0.000000 + + + C=5 M=0 Y=90 K=0 + CMYK + PROCESS + 5.000001 + 0.000000 + 90.000000 + 0.000000 + + + C=20 M=0 Y=100 K=0 + CMYK + PROCESS + 19.999998 + 0.000000 + 100.000000 + 0.000000 + + + C=50 M=0 Y=100 K=0 + CMYK + PROCESS + 50.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=75 M=0 Y=100 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=85 M=10 Y=100 K=10 + CMYK + PROCESS + 85.000000 + 10.000002 + 100.000000 + 10.000002 + + + C=90 M=30 Y=95 K=30 + CMYK + PROCESS + 90.000000 + 30.000002 + 95.000000 + 30.000002 + + + C=75 M=0 Y=75 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 75.000000 + 0.000000 + + + C=80 M=10 Y=45 K=0 + CMYK + PROCESS + 80.000000 + 10.000002 + 45.000000 + 0.000000 + + + C=70 M=15 Y=0 K=0 + CMYK + PROCESS + 70.000000 + 14.999998 + 0.000000 + 0.000000 + + + C=85 M=50 Y=0 K=0 + CMYK + PROCESS + 85.000000 + 50.000000 + 0.000000 + 0.000000 + + + C=100 M=95 Y=5 K=0 + CMYK + PROCESS + 100.000000 + 95.000000 + 5.000001 + 0.000000 + + + C=100 M=100 Y=25 K=25 + CMYK + PROCESS + 100.000000 + 100.000000 + 25.000000 + 25.000000 + + + C=75 M=100 Y=0 K=0 + CMYK + PROCESS + 75.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=50 M=100 Y=0 K=0 + CMYK + PROCESS + 50.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=35 M=100 Y=35 K=10 + CMYK + PROCESS + 35.000004 + 100.000000 + 35.000004 + 10.000002 + + + C=10 M=100 Y=50 K=0 + CMYK + PROCESS + 10.000002 + 100.000000 + 50.000000 + 0.000000 + + + C=0 M=95 Y=20 K=0 + CMYK + PROCESS + 0.000000 + 95.000000 + 19.999998 + 0.000000 + + + C=25 M=25 Y=40 K=0 + CMYK + PROCESS + 25.000000 + 25.000000 + 39.999996 + 0.000000 + + + C=40 M=45 Y=50 K=5 + CMYK + PROCESS + 39.999996 + 45.000000 + 50.000000 + 5.000001 + + + C=50 M=50 Y=60 K=25 + CMYK + PROCESS + 50.000000 + 50.000000 + 60.000004 + 25.000000 + + + C=55 M=60 Y=65 K=40 + CMYK + PROCESS + 55.000000 + 60.000004 + 65.000000 + 39.999996 + + + C=25 M=40 Y=65 K=0 + CMYK + PROCESS + 25.000000 + 39.999996 + 65.000000 + 0.000000 + + + C=30 M=50 Y=75 K=10 + CMYK + PROCESS + 30.000002 + 50.000000 + 75.000000 + 10.000002 + + + C=35 M=60 Y=80 K=25 + CMYK + PROCESS + 35.000004 + 60.000004 + 80.000000 + 25.000000 + + + C=40 M=65 Y=90 K=35 + CMYK + PROCESS + 39.999996 + 65.000000 + 90.000000 + 35.000004 + + + C=40 M=70 Y=100 K=50 + CMYK + PROCESS + 39.999996 + 70.000000 + 100.000000 + 50.000000 + + + C=50 M=70 Y=80 K=70 + CMYK + PROCESS + 50.000000 + 70.000000 + 80.000000 + 70.000000 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 100.000000 + + + C=0 M=0 Y=0 K=90 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 89.999405 + + + C=0 M=0 Y=0 K=80 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 79.998795 + + + C=0 M=0 Y=0 K=70 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 69.999702 + + + C=0 M=0 Y=0 K=60 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 59.999104 + + + C=0 M=0 Y=0 K=50 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 50.000000 + + + C=0 M=0 Y=0 K=40 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 39.999401 + + + C=0 M=0 Y=0 K=30 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 29.998802 + + + C=0 M=0 Y=0 K=20 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 19.999701 + + + C=0 M=0 Y=0 K=10 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 9.999103 + + + C=0 M=0 Y=0 K=5 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 4.998803 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 100.000000 + 100.000000 + 0.000000 + + + C=0 M=75 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 75.000000 + 100.000000 + 0.000000 + + + C=0 M=10 Y=95 K=0 + CMYK + PROCESS + 0.000000 + 10.000002 + 95.000000 + 0.000000 + + + C=85 M=10 Y=100 K=0 + CMYK + PROCESS + 85.000000 + 10.000002 + 100.000000 + 0.000000 + + + C=100 M=90 Y=0 K=0 + CMYK + PROCESS + 100.000000 + 90.000000 + 0.000000 + 0.000000 + + + C=60 M=90 Y=0 K=0 + CMYK + PROCESS + 60.000004 + 90.000000 + 0.003099 + 0.003099 + + + + + + + + + Adobe PDF library 9.90 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Properties<>>>>>/TrimBox[0.0 0.0 62.3335 62.3335]/Type/Page>> endobj 6 0 obj <
>stream +H‰L—Ë®dGEçõçê83ò=µ‘Ä€1º2 h#ÙHõß³öŽªv«¥[ù:ñܱã‡?ÿãëÏ¿]?üå§rýø‡Ÿ®Ç¯r͸[kïŸçë÷·Ÿ¿þó(÷ˆ}•«Ü{ë÷ßþø·rýë¿_¯ªuþ¶rϾÎUï=N¿>~yh]Y)ëz–»Ô~­{íÁC+ÚUë]c]z÷±¯Úï¾ê÷:ãŠz¹c¬+Æ=æá`ႶvL=¸:ß;wÙýz¢ðèW]wëzòÙî:¦ä¹ë%‰›Hã\_Ï~ÇáñÁ q=ŸÚ’êŒëó¼æ:c³;û½WÓ݉²C§O¯×—ÇsßeYùZÏ…´¥Ú}øoI»!ycRp‰³­6I…+/³?ôÒ:SòÄ+ÏZ°èªÁK’êÝ0„‡fña6ʱ^¥çþÚi’ÔØlÓÍÇë=OXmôÑí=ÂßÆ/O–ßDt<$ŸaE£ïë›8pÛ°¸q9?}¤.ón„˜…F$ˆÈhÇÛ˜#qq˜#³ûð¹¶×¯Ó!ïãÆm©[¤^çë´Ã78Ib/ÃAŸ‘¢.gäñžIQ‹¾½x®*czt/ŠCÎOt%Mu""’…p±púÔ…Šó%n"ÅOÄð}Ûü`ãÂ3ðŸžSµlßgOðÓe¿utl9ñÈäMøiJá˜v0?*„OïŸá…]uŸãKÒ"X:ÝIÛX¤¶ƒªÿÕ¥…1¤íº>ŽM¥8»8‡oäñNr²ÐW÷sgºp»o“ÿ$r“‡ìK)‰Ö ç)[¥+©Ó‚TIÓ#ÞÒ‡-ßßoã¾ÕTÍÝ¢ BÜ(ŽbáX®ßÖî°ÝB„éÛq|œ¸Á¦[ÛÇ65Ò˨!Ž:^Çk.ì¢×ÁHR#OeÒnꮊˆý*(AÜz}¡³r I8ÞKÖµ^B *òÜï:Þ×tÝ*¶u#è‡ ` œžYÕoÊMò‹m*b;Ÿ$[ʤP2…%|›E³ÆÝi.wN£Û”/«õx +ò¶\µ³à0ƒàL¯miwê°:U9 œÈ"0W”v¼¯’ç€DLÙ是àö^íˆq"1ÐkÇ•5ð VDáâJDj [çÉîu… ±°FFaãÖNe)är:…Òù©ýuüÆ](®ýæh!ÛÙ”­Úlõý8žd!úùý5ÌͧõÜ—a!O=H©•!VÑÕÌ,n!Í·&UoSñz Èê˜9ÓêƒW4ÇÈI–¯Nb‰vøßÝÜ}y|­kÞ»cäÀuG€µ#ajYïÃõdkø©ƒE®ÖÓ-¬/µ­.y"“1ƒ&ŸJ"Û_’ó©Sè¿ï2g¢¶še4Îâ +«Ëû ¢Ü©¤­BЊVR–\Êp¯î‹ê“a´Û_z +l«Ž–¬nÐXR=[4Îñ3&ä•ì_ÍdA‚Mjy÷­"øGÓÚ*5›ÁB®¡»µ»Ñµ†›21ôñâŽ=£°°ƒŒQÔòµ~2¦úðÄaSÒm€hIÀÐ}™ÓE­+ IPŸ<ÙKÄè,g ,ŸG’ûìþú(fú¶þؤåŸØˆë×ã׫ú´9ýT›œcãÇ/­ë/+b0bê9 Í‹g …Ð ê½ßSi8¼ï½cرcë¨ò¬&Ñê½9wÉHú·êP0šÌ× §’Š_’RY4Q3QÏڞ̠ %<¸Vlý…Xð$4qF@|xèÝKÕ…¬ÙEó)aù"#DA§"ÌjÎefxô–´’Õ5¢{ÆmoNQšŒˆ S½DÒvEÜm,Ó.¡ºXa©ow¬—:ƒö×N“¤†Äf›vÎmjcÀŒÔÞI}·ŠRÀ"†8²jðKÒ8ÍVT³â7‘ü>âF*~D¦u|fZÒÄnaÛgZTŽŠÎ'W=nU¤,OG¸5e)š‚À¦Î×éѾ!Ä.ô8fXc¿s ÷L +‘ƒ§p)ŒvL'xQr~¢wOqJÄ(fÝŸ÷X§aNŒQ©F¤„¥1|_4ݶ‘i×sa`ÿÌ}<¶gÐÚ]×*¯p÷q‡iž"§¬¶ã?½†¶‡Ò¡A,̧Å.ÔÉ2¨îiK cHÛe + þ)ÎãÆU >ZèaÕW÷sgºp»o'Ooò})%ÑZ ²Uº’:##M§½¤[¾¿ßn†·–ˆçÝj–·3P,ˆo²p¬K˜9Ó»Ãv ¦oç° ¸hàm&,:¾°‰2ü±ŒâHº®øåÂ.z]Ü„³mGjeû©»("ö« qëuµE 9®ñNÇ©uºU.òÜ÷ Ú×tÝ*RÒÜF5P œžYÕoÊMò‹m*b;Ÿ.ž%“6BÉ–ðÍüDüïC¦4—;§ÑmÊ—‰çÏ•BÓsxRsB>‚3½¶¥ÝñŠÊáD p½šp•v¼¯’禺ma¾fÔb bakr¬ÿgºÜq㈠šÏ)ö2øiþbáÃGPâ@±ÝÞõªg½‚ Ëáìfõ«š-o™hÞnTîÇ +•’5 ¶“ªýP¸R‘º”- Ýs{Ú¢¤E±‘à”ñfr¦¬G{ø†ëjOÛ-ÐÖûìT+?öúœhVÅyÍÌuÆ=Ʋ,äp L6 +AXAlš™#ð9à¹{pençž l>n¥ìóÌ4ns<…[G«>DŠ˜Ðnǘµç‰‹Xò¬MŽfï Á'l[YÏÁ¿X›§:¶¦\rZO8y¿h[iO«b†šˆ^\W"Uû¹žBýõëQåŒiFRs´_ÕQx¹°í"ä8)ÚJÐV­ŠÅª–2Ý`Ž_¤O6«ýØþÒb[ZòvK‰ª8GfˆÀ˜Æ@ ºbÿ«í‰V!!¿UºIéänkKŠ’Xp4ên",u­bƒ[HŸf´‡Ü\O[¤¾ÔŸãt×O攋ïÕ|F17K¢•È­>–™FUÔ#é’ê«NpP:£å +dçÓ∥Û9P© ˜ó<¶[‰®ÁÑ2Õ´U¹¬Rš?¬mE±[v^ +€ðÒÅ,ÞÈpwëälµËÚu@o–ébWó7MÒ|„Ünî<˜wŠ[I·žw÷Ûû7-»¤ïR1)ݤåV¦Î•pûд=ö7½ƒ5e€Ù©n•få–±Òõs±5pÙîí31oý0¹ Vm©”Œî0 j»Ã;TàMr1«{—ÅW¼èïóúsý¾~]?~~èñO€ô­òs endstream endobj 7 0 obj <> endobj 8 0 obj <> endobj xref 0 9 0000000000 65535 f +0000000016 00000 n +0000000076 00000 n +0000054201 00000 n +0000000000 00000 f +0000054252 00000 n +0000054617 00000 n +0000058383 00000 n +0000058495 00000 n +trailer <<9F90F14542EF4ED5A96724F195B23308>]>> startxref 58668 %%EOF \ No newline at end of file diff --git a/doc/introduction.tex b/doc/introduction.tex index 1b0ec442..b090e049 100644 --- a/doc/introduction.tex +++ b/doc/introduction.tex @@ -1,14 +1,17 @@ -\section{Introduction} +\part{Using Mitsuba} \textbf{Disclaimer:} This is manual documents the usage, file format, and internal design of the Mitsuba rendering system. It is currently a work in progress, hence some parts may still be incomplete or missing. -\subsection{About Mitsuba} +\section{About Mitsuba} Mitsuba is a research-oriented rendering system in the style of PBRT (\url{www.pbrt.org}), from which it derives much inspiration. It is written in portable C++, implements unbiased as well as biased techniques, and contains heavy optimizations targeted -towards current CPU architectures. +towards current CPU architectures. +Mitsuba is extremely modular: it consists of a small set of core libraries +and over 100 different plugins that implement functionality ranging +from materials and light sources to complete rendering algorithms. In comparison to other open source renderers, Mitsuba places a strong emphasis on experimental rendering techniques, such as path-based @@ -46,13 +49,24 @@ it can get. The renderer also tries to be very conservative in its use of memory, which allows it to handle large scenes (>30 million triangles) and multi-gigabyte heterogeneous volumes on consumer hardware. +\parheader{Realism and accuracy:} Mitsuba comes with a large repository of physically-based +reflectance models for surfaces and participating media. These implementations +are designed so that they can be used to build complex shader networks, while +providing enough flexibility to be compatible with a wide range of different +rendering techniques, including path tracing, photon mapping, hardware-accelerated rendering +and bidirectional methods. + +The unbiased path tracers in Mitsuba are battle-proven and produce +reference-quality results that can be used for predictive rendering, and to verify +implementations of other rendering methods. + \parheader{Usability:} Mitsuba comes with a graphical user interface to interactively explore scenes. Once a suitable viewpoint has been found, it is straightforward to perform renderings using any of the implemented rendering techniques, while tweaking their parameters to find the most suitable settings. Experimental integration into Blender 2.5 is also available. -\subsection{License} +\section{License} Mitsuba is free software and can be redistributed and modified under the terms of the GNU General Public License (Version 3) as provided by the Free Software Foundation. diff --git a/doc/main.tex b/doc/main.tex index 8cb6c783..a1e34d57 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -81,6 +81,8 @@ % Listings settings \lstset{ basicstyle = \small\ttfamily\raggedright, + commentstyle=\color{lstcomment}\itshape, + stringstyle=\color{lstattrib}, mathescape = true, frame = lrtb, backgroundcolor = \color{lstshade}, @@ -111,6 +113,7 @@ }, } + % Set up textpos \TPGrid{68}{108} @@ -125,6 +128,8 @@ {} \lstnewenvironment{cpp}[1][]{\lstset{language=c++, #1}} {} +\lstnewenvironment{python}[1][]{\lstset{language=Python, #1}} + {} \lstnewenvironment{xml}[1][]{\lstset{language=xml, #1}} {} \lstnewenvironment{console}[1][]{\lstset{basicstyle=\footnotesize\ttfamily, float, #1}} @@ -133,6 +138,7 @@ % ----- 8< ----- 8< ------ \title{ + \includegraphics[width=4cm]{images/logo_plain.pdf}\\\vspace{2cm} Mitsuba Documentation\\\vspace{3mm} \large Version \MitsubaVersion } @@ -152,9 +158,10 @@ \include{format} \IfFileExists{plugins_generated.tex}{\include{plugins_generated}}{} %\include{import} -%\include{development} -%\include{integrator} -%\include{parallelization} +\include{development} +\include{integrator} +\include{parallelization} +\include{python} \include{acknowledgements} \bibliographystyle{acm} diff --git a/doc/python.tex b/doc/python.tex new file mode 100644 index 00000000..e45756cc --- /dev/null +++ b/doc/python.tex @@ -0,0 +1,295 @@ +\section{Python integration} +\label{sec:python} +A recent feature of Mitsuba is a simple Python interface to the renderer API. +While the interface is still limited at this point, it can already be +used for many useful purposes. To access the API, start your Python +interpreter and enter +\begin{python} +import mitsuba +\end{python} +For this to work on MacOS X, you will first have to run the ``\emph{Apple +Menu}$\to$\emph{Command-line access}'' menu item from within Mitsuba. +On Windows and non-packaged Linux builds, you may have to update the extension +search path before issuing the \code{import} command, e.g.: +\begin{python} +import sys + +# Update the extension search path +# (may vary depending on your setup) +sys.path.append('dist/python') + +import mitsuba +\end{python} +For an overview of the currently exposed API subset, please refer +to the following page: \url{http://www.mitsuba-renderer.org/api/group__libpython.html}. + +\subsection{Basics} +Generally, the Python API tries to mimic the C++ API as closely as possible. +Where applicable, the Python classes and methods replicate overloaded operators, +overridable virtual function calls, and default arguments. Under rare circumstances, +some features are inherently non-portable due to fundamental differences between the +two programming languages. In this case, the API documentation will contain further +information. + +Mitsuba's linear algebra-related classes are usable with essentially the +same syntax as their C++ versions --- for example, the following snippet +creates and rotates a unit vector. +\begin{python} +import mitsuba +from mitsuba.core import * + +# Create a normalized direction vector +myVector = normalize(Vector(1.0, 2.0, 3.0)) + +# 90 deg. rotation around the Y axis +trafo = Transform.rotate(Vector(0, 1, 0), 90) + +# Apply the rotation and display the result +print(trafo * myVector) +\end{python} + +\subsection{Recipes} +The following section contains a series of ``recipes'' on how to do +certain things with the help of the Python bindings. + +\subsubsection{Loading a scene} +The following script demonstrates how to use the +\code{FileResolver} and \code{SceneHandler} classes to +load a Mitsuba scene from an XML file: +\begin{python} +import mitsuba + +from mitsuba.core import * +from mitsuba.render import SceneHandler + +# Get a reference to the thread's file resolver +fileResolver = Thread.getThread().getFileResolver() + +# Add the search path needed to load plugins +fileResolver.addPath('') + +# Add the search path needed to load scene resources +fileResolver.addPath('') + +# Optional: supply parameters that can be accessed +# by the scene (e.g. as $\text{\color{lstcomment}\itshape\texttt{\$}}$myParameter) +paramMap = StringMap() +paramMap['myParameter'] = 'value' + +# Load the scene from an XML file +scene = SceneHandler.loadScene(fileResolver, paramMap) + +# Display a textual summary of the scene's contents +print(scene) +\end{python} + +\subsubsection{Rendering a loaded scene} +Once a scene has been loaded, it can be rendered as follows: +\begin{python} +from mitsuba.core import * +from mitsuba.render import RenderQueue, RenderJob +import multiprocessing + +scheduler = Scheduler.getInstance() + +# Start up the scheduling system with one worker per local core +for i in range(0, multiprocessing.cpu_count()): + scheduler.registerWorker(LocalWorker('wrk%i' % i)) +scheduler.start() + +# Create a queue for tracking render jobs +queue = RenderQueue() + +scene.setDestinationFile('renderedResult') + +# Create a render job and insert it into the queue +job = RenderJob('myRenderJob', scene, queue) +job.start() + +# Wait for all jobs to finish and release resources +queue.waitLeft(0) +queue.join() + +# Print some statistics about the rendering process +print(Statistics.getInstance().getStats()) +\end{python} + +\subsubsection{Rendering over the network} +To render over the network, you must first set up one or +more machines that run the \code{mtssrv} server (see \secref{mtssrv}). +A network node can then be registered with the scheduler as follows: +\begin{python} +# Connect to a socket on a named host or IP address +# 7554 is the default port of 'mtssrv' +stream = SocketStream('128.84.103.222', 7554) + +# Create a remote worker instance that communicates over the stream +remoteWorker = RemoteWorker('netWorker', stream) + +scheduler = Scheduler.getInstance() +# Register the remote worker (and any other potential workers) +scheduler.registerWorker(remoteWorker) +scheduler.start() +\end{python} + +\subsubsection{Constructing custom scenes from Python} +Dynamically constructing Mitsuba scenes entails loading a series of external +plugins, instantiating them with custom parameters, and finally assembling +them into an object graph. +For instance, the following snippet shows how to create a basic +perspective camera with a film that writes PNG images: +\begin{python} +from mitsuba.core import * +pmgr = PluginManager.getInstance() + +# Encodes parameters on how to instantiate the 'perspective' plugin +cameraProps = Properties('perspective') +cameraProps['toWorld'] = Transform.lookAt( + Point(0, 0, -10), # Camera origin + Point(0, 0, 0), # Camera target + Vector(0, 1, 0) # 'up' vector +) +cameraProps['fov'] = 45.0 + +# Encodes parameters on how to instantiate the 'pngfilm' plugin +filmProps = Properties('pngfilm') +filmProps['width'] = 1920 +filmProps['height'] = 1080 + +# Load and instantiate the plugins +camera = pmgr.createObject(cameraProps) +film = pmgr.createObject(filmProps) + +# First configure the film and then add it to the camera +film.configure() +camera.addChild('film', film) + +# Now, the camera can be configured +camera.configure() +\end{python} +The above code fragment uses the plugin manager to construct a +\code{Camera} instance from an external plugin named +\texttt{perspective.so/dll/dylib} and adds a child object +named \texttt{film}, which is a \texttt{Film} instance loaded from the +plugin \texttt{pngfilm.so/dll/dylib}. +Each time after instantiating a plugin, all child objects are added, and +finally the plugin's \code{configure()} method must be called. + +Creating scenes in this manner ends up being rather laborious. +Since Python comes with a powerful dynamically-typed dictionary +primitive, Mitsuba additionally provides a more ``pythonic'' +alternative that makes use of this facility: +\begin{python} +from mitsuba.core import * + +pmgr = PluginManager.getInstance() +camera = pmgr.create({ + 'type' : 'perspective', + 'toWorld' : Transform.lookAt( + Point(0, 0, -10), + Point(0, 0, 0), + Vector(0, 1, 0) + ), + 'film' : { + 'type' : 'pngfilm', + 'width' : 1920, + 'height' : 1080 + } +}) +\end{python} +This code does exactly the same as the previous snippet. +By the time \code{PluginManager.create} returns, the object +hierarchy has already been assembled, and the +\code{configure()} method of every object +has been called. + +Finally, here is an full example that creates a basic scene +which can be rendered. It describes a sphere lit by a point +light, rendered using the direct illumination integrator. +\begin{python} +from mitsuba.core import * +from mitsuba.render import Scene + +scene = Scene() + +# Create a camera, film & sample generator +scene.addChild(pmgr.create({ + 'type' : 'perspective', + 'toWorld' : Transform.lookAt( + Point(0, 0, -10), + Point(0, 0, 0), + Vector(0, 1, 0) + ), + 'film' : { + 'type' : 'pngfilm', + 'width' : 1920, + 'height' : 1080 + }, + 'sampler' : { + 'type' : 'ldsampler', + 'sampleCount' : 2 + } +})) + +# Set the integrator +scene.addChild(pmgr.create({ + 'type' : 'direct' +})) + +# Add a light source +scene.addChild(pmgr.create({ + 'type' : 'point', + 'position' : Point(5, 0, -10), + 'intensity' : Spectrum(100) +})) + +# Add a shape +scene.addChild(pmgr.create({ + 'type' : 'sphere', + 'center' : Point(0, 0, 0), + 'radius' : 1.0, + 'bsdf' : { + 'type' : 'diffuse', + 'reflectance' : Spectrum(0.4) + } +})) +\end{python} + +\subsubsection{Taking control of the logging system} +Many operations in Mitsuba will print one or more log messages +during their execution. By default, they will be printed to the console, +which may be undesirable. Similar to the C++ side, it is possible to define +custom \code{Formatter} and \code{Appender} classes to interpret and direct +the flow of these messages. + +Roughly, a \code{Formatter} turns detailed +information about a logging event into a human-readable string, and a +\code{Appender} routes it to some destination (e.g. by appending it to +a file or a log viewer in a graphical user interface). Here is an example +of how to activate such extensions: +\begin{python} +import mitsuba +from mitsuba.core import * + +class MyFormatter(Formatter): + def format(self, logLevel, sourceClass, sourceThread, message, filename, line): + return '%s (log level: %s, thread: %s, class %s, file %s, line %i)' % \ + (message, str(logLevel), sourceThread.getName(), sourceClass, + filename, line) + +class MyAppender(Appender): + def append(self, logLevel, message): + print(message) + + def logProgress(self, progress, name, formatted, eta): + print('Progress message: ' + formatted) + +# Get the logger associated with the current thread +logger = Thread.getThread().getLogger() +logger.setFormatter(MyFormatter()) +logger.clearAppenders() +logger.addAppender(MyAppender()) +logger.setLogLevel(EDebug) + +Log(EInfo, 'Test message') +\end{python} diff --git a/include/mitsuba/bidir/rsampler.h b/include/mitsuba/bidir/rsampler.h index 790b9abe..8e26457a 100644 --- a/include/mitsuba/bidir/rsampler.h +++ b/include/mitsuba/bidir/rsampler.h @@ -24,12 +24,15 @@ MTS_NAMESPACE_BEGIN /** - * Specialized sampler implementation used to seed MLT-style algorithm. Allows - * to query for the current sample index, which can later be used to rewind + * \brief Specialized sampler implementation used to seed MLT-style algorithm. + * + * Allows to query for the current sample index, which can later be used to rewind * back to this state. In the case of MLT, this makes it possible to sample paths * approximately proportional to their contribution without actually having * to store millions of path. Note that `rewinding' is naive -- it just * resets & regenerates the whole random number sequence, which might be slow. + * + * \ingroup libbidir */ class MTS_EXPORT_BIDIR ReplayableSampler : public Sampler { public: @@ -52,7 +55,7 @@ public: virtual void generate(); /// Manually set the current sample index - virtual void setSampleIndex(uint64_t sampleIndex); + virtual void setSampleIndex(size_t sampleIndex); /// Retrieve the next component value from the current sample virtual Float next1D(); diff --git a/include/mitsuba/core/aabb.h b/include/mitsuba/core/aabb.h index d6607e12..0b654f2e 100644 --- a/include/mitsuba/core/aabb.h +++ b/include/mitsuba/core/aabb.h @@ -295,6 +295,7 @@ template struct TAABB { * various convenience functions to query or change them. * * \ingroup libcore + * \ingroup libpython */ struct MTS_EXPORT_CORE AABB : public TAABB { public: @@ -345,6 +346,10 @@ public: /** \brief Calculate the near and far ray-AABB intersection * points (if they exist). + * + * \remark In the Python bindings, this function returns the + * \c nearT and \c farT values as a tuple (or \c None, when no + * intersection was found) */ FINLINE bool rayIntersect(const Ray &ray, Float &nearT, Float &farT) const { nearT = -std::numeric_limits::infinity(); diff --git a/include/mitsuba/core/aabb_sse.h b/include/mitsuba/core/aabb_sse.h index b0fd1cd8..e04c711e 100644 --- a/include/mitsuba/core/aabb_sse.h +++ b/include/mitsuba/core/aabb_sse.h @@ -22,8 +22,9 @@ MTS_NAMESPACE_BEGIN /** - * NaN-aware slab test using SSE by Thierry Berger-Perrin (Intersects against - * 4 rays simultaneously). Returns false if none of the rays intersect. + * NaN-aware slab test using SSE by Thierry Berger-Perrin (Intersects + * against 4 rays simultaneously). Returns false if none of the rays + * intersect. */ FINLINE bool AABB::rayIntersectPacket(const RayPacket4 &ray, RayInterval4 &interval) const { diff --git a/include/mitsuba/core/appender.h b/include/mitsuba/core/appender.h index f4e7b2c8..e04d10e9 100644 --- a/include/mitsuba/core/appender.h +++ b/include/mitsuba/core/appender.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN * for logging-relevant information * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Appender : public Object { public: @@ -39,10 +40,14 @@ public: * \param name Title of the progress message * \param formatted Formatted string representation of the message * \param eta Estimated time until 100% is reached. - * \param ptr Custom pointer payload + * \param ptr Custom pointer payload. This is used to express the + * context of a progress message. When rendering a scene, it + * will usually contain a pointer to the associated \c RenderJob. + * \remark The \c ptr argument is missing in the Python bindings */ virtual void logProgress(Float progress, const std::string &name, - const std::string &formatted, const std::string &eta, const void *ptr) = 0; + const std::string &formatted, const std::string &eta, + const void *ptr) = 0; MTS_DECLARE_CLASS() protected: diff --git a/include/mitsuba/core/bitmap.h b/include/mitsuba/core/bitmap.h index 16d513fc..01bf0b80 100644 --- a/include/mitsuba/core/bitmap.h +++ b/include/mitsuba/core/bitmap.h @@ -31,6 +31,7 @@ MTS_NAMESPACE_BEGIN * This class can efficiently handle 1-bit masks * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Bitmap : public Object { public: @@ -66,7 +67,7 @@ public: void save(EFileFormat format, Stream *stream, int compression = 5) const; /// Return the image's title identifier - inline const std::string &getTile() const { return m_title; } + inline const std::string &getTitle() const { return m_title; } /// Return the image's author identifier inline const std::string &getAuthor() const { return m_author; } @@ -89,29 +90,41 @@ public: /// Set the image's gamma identifier (-1: sRGB) inline void setGamma(Float gamma) { m_gamma = gamma; } - /// Access the underlying raster + /** + * \brief Access the underlying raster + * \remark This function is not exposed in the Python bindings + */ inline unsigned char *getData() { return m_data; } - /// Access the underlying bit raster + /** + * \brief Access the underlying raster + * \remark This function is not exposed in the Python bindings + */ inline const unsigned char *getData() const { return m_data; } - /// Access the underlying raster (only meant for 128bpp images) + /** + * \brief Access the underlying raster (128bpp images) + * \remark This function is not exposed in the Python bindings + */ inline float *getFloatData() { return (float *) m_data; } - /// Access the underlying raster (only meant for 128bpp images) + /** + * \brief Access the underlying raster (128bpp images) + * \remark This function is not exposed in the Python bindings + */ inline const float *getFloatData() const { return (const float *) m_data; } /// Return the bitmap width - inline const int getWidth() const { return m_width; } + inline int getWidth() const { return m_width; } /// Return the bitmap height - inline const int getHeight() const { return m_height; } + inline int getHeight() const { return m_height; } /// Return the bitmap's bits per pixel - inline const int getBitsPerPixel() const { return m_bpp; } + inline int getBitsPerPixel() const { return m_bpp; } /// Return the bitmap size in bytes - inline const size_t getSize() const { return m_size; } + inline size_t getSize() const { return m_size; } /// Return some human-readable information about this bitmap std::string toString() const; diff --git a/include/mitsuba/core/bsphere.h b/include/mitsuba/core/bsphere.h index f9b27304..6ab79435 100644 --- a/include/mitsuba/core/bsphere.h +++ b/include/mitsuba/core/bsphere.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** \brief Bounding sphere data structure in three dimensions * * \ingroup libcore + * \ingroup libpython */ struct BSphere { Point center; @@ -59,7 +60,6 @@ struct BSphere { /// Expand the bounding sphere radius to contain another point. inline void expandBy(const Point p) { - Vector dir = p - center; radius = std::max(radius, (p-center).length()); } @@ -81,6 +81,10 @@ struct BSphere { /** * \brief Calculate the intersection points with the given ray * \return \c true if the ray intersects the bounding sphere + * + * \remark In the Python bindings, this function returns the + * \c nearT and \c farT values as a tuple (or \c None, when no + * intersection was found) */ inline bool rayIntersect(const Ray &ray, Float &nearHit, Float &farHit) const { Vector originToCenter = center - ray.o; diff --git a/include/mitsuba/core/chisquare.h b/include/mitsuba/core/chisquare.h index f2e0cdd5..b6f855fc 100644 --- a/include/mitsuba/core/chisquare.h +++ b/include/mitsuba/core/chisquare.h @@ -46,7 +46,7 @@ MTS_NAMESPACE_BEGIN * * 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 @@ -56,11 +56,11 @@ MTS_NAMESPACE_BEGIN * /// Compute the probability density for the specified direction and measure * Float pdf(const Vector &direction, EMeasure) const; * }; - * + * \endcode * * the code in this class might be used as follows * - * + * \code * MyDistribution myDistrInstance; * ChiSquare chiSqr; * @@ -75,7 +75,8 @@ MTS_NAMESPACE_BEGIN * * if (!chiSqr.runTest()) * Log(EError, "Uh oh -- test failed, the implementation is probably incorrect!"); - * + * \endcode + * \ingroup libcore */ class MTS_EXPORT_CORE ChiSquare : public Object { public: @@ -129,8 +130,7 @@ public: * errors in a system based on finite-precision arithmetic, it * may be a good idea to tolerate at least a few samples without * immediately rejecting the null hypothesis. This parameter - * sets this threshold. The default value is * 1e-4f + * sets this threshold. The default value is \c number-of-samples*1e-4f */ inline void setTolerance(Float tolerance) { m_tolerance = tolerance; } diff --git a/include/mitsuba/core/class.h b/include/mitsuba/core/class.h index db38e67d..7e7ea0df 100644 --- a/include/mitsuba/core/class.h +++ b/include/mitsuba/core/class.h @@ -37,6 +37,7 @@ MTS_NAMESPACE_BEGIN * * \sa ref, Object * \ingroup libcore + * \ingroup librender */ class MTS_EXPORT_CORE Class { public: @@ -124,11 +125,34 @@ private: /*! @{ */ +/** + * \brief Return the \ref Class object corresponding to a named class. + * + * Call the Macro without quotes, e.g. \c MTS_CLASS(SerializableObject) + */ #define MTS_CLASS(x) x::m_theClass /** - * \brief This macro must be used in the declaration of - * all classes derived from \ref Object. + * \brief This macro must be used in the initial definition in + * classes that derive from \ref Object. + * + * This is needed for the basic RTTI support provided by Mitsuba objects. + * For instance, a class definition might look like the following: + * + * \code + * class MyObject : public Object { + * public: + * MyObject(); + * + * /// Important: declare RTTI data structures + * MTS_DECLARE_CLASS() + * protected: + * /// Important: needs to declare a protected virtual destructor + * virtual ~MyObject(); + * + * }; + * \endcode + * */ #define MTS_DECLARE_CLASS() \ virtual const Class *getClass() const; \ @@ -137,6 +161,17 @@ public: \ /** * \brief Creates basic RTTI support for a class + * + * This macro or one of its variants should be invoked in the main + * implementation \c .cpp file of any class that derives from \ref Object. + * This is needed for the basic RTTI support provided by Mitsuba objects. + * For instance, the corresponding piece for the example shown in the + * documentation of \ref MTS_DECLARE_CLASS might look like this: + * + * \code + * MTS_IMPLEMENT_CLASS(MyObject, false, Object) + * \endcode + * * \param name Name of the class * \param abstract \c true if the class contains pure virtual methods * \param super Name of the parent class @@ -148,8 +183,13 @@ public: \ } /** - * \brief Creates basic RTTI support for a class. Assumes that - * the class can be instantiated by name. + * \brief Creates basic RTTI support for a class. To be used when the class + * has a \a simple constructor (i.e. one wich does not take any arguments) + * + * This macro or one of its variants should be invoked in the main + * implementation \c .cpp file of any class that derives from \ref Object. + * This is needed for the basic RTTI support provided by Mitsuba objects. + * * \param name Name of the class * \param abstract \c true if the class contains pure virtual methods * \param super Name of the parent class @@ -164,8 +204,13 @@ public: \ } /** - * \brief Creates basic RTTI support for a class. Assumes that - * the class can be unserialized from a binary data stream. + * \brief Creates basic RTTI support for a class. To be used when the class + * can be unserialized from a binary data stream. + * + * This macro or one of its variants should be invoked in the main + * implementation \c .cpp file of any class that derives from \ref Object. + * This is needed for the basic RTTI support provided by Mitsuba objects. + * * \param name Name of the class * \param abstract \c true if the class contains pure virtual methods * \param super Name of the parent class @@ -180,9 +225,14 @@ public: \ } /** - * \brief Creates basic RTTI support for a class. Assumes that - * the class can be unserialized from a binary data stream as well - * as instantiated by name. + * \brief Creates basic RTTI support for a class. To be used when the class + * can be unserialized from a binary data stream as well as instantiated + * by a constructor that does not take any arguments. + * + * This macro or one of its variants should be invoked in the main + * implementation \c .cpp file of any class that derives from \ref Object. + * This is needed for the basic RTTI support provided by Mitsuba objects. + * * \param name Name of the class * \param abstract \c true if the class contains pure virtual methods * \param super Name of the parent class diff --git a/include/mitsuba/core/cobject.h b/include/mitsuba/core/cobject.h index f1e29a65..ec1dba10 100644 --- a/include/mitsuba/core/cobject.h +++ b/include/mitsuba/core/cobject.h @@ -33,6 +33,7 @@ MTS_NAMESPACE_BEGIN * requests in the XML file. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE ConfigurableObject : public SerializableObject { public: @@ -48,6 +49,9 @@ public: /// Add a child (default implementation throws an error) virtual void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } + /** \brief Configure the object (called \a once after construction and addition of all child ConfigurableObjects) */ virtual void configure(); diff --git a/include/mitsuba/core/constants.h b/include/mitsuba/core/constants.h index 9a179954..26e8ab04 100644 --- a/include/mitsuba/core/constants.h +++ b/include/mitsuba/core/constants.h @@ -21,13 +21,8 @@ /* Choice of precision */ #ifdef DOUBLE_PRECISION -#define Float double #define Epsilon 1e-6 #else -#ifndef SINGLE_PRECISION -#define SINGLE_PRECISION -#endif -#define Float float #define Epsilon 1e-4f #endif diff --git a/include/mitsuba/core/frame.h b/include/mitsuba/core/frame.h index ebd2b89b..a1466cb1 100644 --- a/include/mitsuba/core/frame.h +++ b/include/mitsuba/core/frame.h @@ -31,6 +31,7 @@ MTS_NAMESPACE_BEGIN * quantities (e.g. \ref cosTheta(), \ref tanTheta, ..). * * \ingroup libcore + * \ingroup libpython */ struct Frame { Vector s, t; @@ -62,7 +63,7 @@ struct Frame { } /// Serialize to a binary data stream - inline void serialize (Stream *stream) const { + inline void serialize(Stream *stream) const { s.serialize(stream); t.serialize(stream); n.serialize(stream); @@ -133,14 +134,14 @@ struct Frame { /** \brief Assuming that the given direction is in the local coordinate * system, return the squared sine of the phi parameter in spherical * coordinates */ - inline static Float sinPhiSquared(const Vector &v) { + inline static Float sinPhi2(const Vector &v) { return clamp(v.y * v.y / sinTheta2(v), 0.0f, 1.0f); } /** \brief Assuming that the given direction is in the local coordinate * system, return the squared cosine of the phi parameter in spherical * coordinates */ - inline static Float cosPhiSquared(const Vector &v) { + inline static Float cosPhi2(const Vector &v) { return clamp(v.x * v.x / sinTheta2(v), 0.0f, 1.0f); } diff --git a/include/mitsuba/core/fresolver.h b/include/mitsuba/core/fresolver.h index f9df468c..f3bedc4a 100644 --- a/include/mitsuba/core/fresolver.h +++ b/include/mitsuba/core/fresolver.h @@ -36,6 +36,7 @@ MTS_NAMESPACE_BEGIN * operating systems). * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE FileResolver : public Object { public: @@ -61,6 +62,8 @@ public: * * In comparison to \ref resolve(), this funtion returns all * matches instead of only the first one. + * + * \remark This function is not exposed in the Python bindings */ std::vector resolveAll(const fs::path &path) const; @@ -75,10 +78,10 @@ public: /// Add a search path to the resolver void addPath(const fs::path &path); - + /// Clear all stored search paths void clear(); - + /// Return a human-readable string representation std::string toString() const; diff --git a/include/mitsuba/core/fstream.h b/include/mitsuba/core/fstream.h index bf9918e4..9f0b4692 100644 --- a/include/mitsuba/core/fstream.h +++ b/include/mitsuba/core/fstream.h @@ -33,6 +33,7 @@ MTS_NAMESPACE_BEGIN * WIN32 API when used on Windows. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE FileStream : public Stream { public: diff --git a/include/mitsuba/core/fwd.h b/include/mitsuba/core/fwd.h index 97b0d6d6..96c91382 100644 --- a/include/mitsuba/core/fwd.h +++ b/include/mitsuba/core/fwd.h @@ -89,25 +89,36 @@ template struct TPoint2; template struct TPoint3; template struct TPoint4; template struct TQuaternion; +/// \ingroup libpython typedef TVector2 Vector2; +/// \ingroup libpython typedef TVector2 Vector2i; typedef TVector2 Vector2f; typedef TVector2 Vector2d; +/// \ingroup libpython typedef TVector3 Vector; +/// \ingroup libpython typedef TVector3 Vector3; +/// \ingroup libpython typedef TVector3 Vector3i; typedef TVector3 Vector3f; typedef TVector3 Vector3d; +/// \ingroup libpython typedef TVector4 Vector4; typedef TVector4 Vector4i; typedef TVector4 Vector4f; typedef TVector4 Vector4d; +/// \ingroup libpython typedef TPoint2 Point2; +/// \ingroup libpython typedef TPoint2 Point2i; typedef TPoint2 Point2f; typedef TPoint2 Point2d; +/// \ingroup libpython typedef TPoint3 Point; +/// \ingroup libpython typedef TPoint3 Point3; +/// \ingroup libpython typedef TPoint3 Point3i; typedef TPoint3 Point3f; typedef TPoint3 Point3d; diff --git a/include/mitsuba/core/grid.h b/include/mitsuba/core/grid.h deleted file mode 100644 index 4da9a665..00000000 --- a/include/mitsuba/core/grid.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - 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 . -*/ - -#if !defined(__GRID_H) -#define __GRID_H - -#include - -MTS_NAMESPACE_BEGIN - -/** - * \brief Uniform 3D grid for storing and manipulating arbitrary quantities - * - * \ingroup libcore - */ -template class Grid { -public: - /// Construct a new grid with the given resolution (initialized to zero) - Grid(const Vector3i &res, const AABB &aabb) : m_res(res), m_aabb(aabb) { - m_slab = res.x*res.y; - m_numCells = m_slab*res.z; - m_cells = new ValueType[m_numCells]; - for (int i=0; i<3; ++i) - m_cellWidth[i] = m_aabb.getExtents()[i] / (Float) res[i]; - clear(); - } - - /// Unserialize a grid from a binary data stream - Grid(Stream *stream) { - m_res = Vector3i(stream); - m_aabb = AABB(stream); - m_slab = m_res.x*m_res.y; - m_numCells = m_slab*m_res.z; - m_cells = new ValueType[m_numCells]; - stream->read(m_cells, sizeof(ValueType)*m_numCells); - for (int i=0; i<3; ++i) - m_cellWidth[i] = m_aabb.getExtents()[i] / (Float) m_res[i]; - } - - /// Serialize a grid to a binary data stream - inline void serialize(Stream *stream) const { - m_res.serialize(stream); - m_aabb.serialize(stream); - for (int i=0; i<3; ++i) - stream->writeSingle((float) m_aabb.min[i]); - for (int i=0; i<3; ++i) - stream->writeSingle((float) m_aabb.max[i]); - stream->write(m_cells, sizeof(ValueType)*m_numCells); - } - - /// Reset everything to zero - inline void clear() { - memset(m_cells, 0, sizeof(ValueType) * m_numCells); - } - - /// Add the values from another grid of identical shape and type - inline void operator+=(const Grid &grid) { - SAssert(grid.m_numCells == m_numCells); - for (size_t i=0; i void apply(const Point &p, const Functor &functor) { - /* Intersect with the voxel grid */ - if (!m_aabb.contains(p)) { - std::ostringstream oss; - oss << "The grid " << m_aabb.toString() << " does not contain the " - "position " << p.toString() << "!" << endl; - throw std::runtime_error(oss.str()); - } - Vector pos = p - m_aabb.min; - Vector3i dpos( - std::max(0, std::min((int) (pos.x / m_cellWidth.x), m_res.x-1)), - std::max(0, std::min((int) (pos.y / m_cellWidth.y), m_res.y-1)), - std::max(0, std::min((int) (pos.z / m_cellWidth.z), m_res.z-1)) - ); - int index = dpos.x + dpos.y * m_res.x + dpos.z * m_slab; - m_cells[index] = functor(m_cells[index]); - } - - /** - * Apply the given functor to a grid cell - don't throw an error if - * the point is not part of the grid. Returns 'true' upon success - */ - template bool applyIfContained(const Point &p, const Functor &functor) { - if (!m_aabb.contains(p)) - return false; - - Vector pos = p - m_aabb.min; - Vector3i dpos( - std::max(0, std::min((int) (pos.x / m_cellWidth.x), m_res.x-1)), - std::max(0, std::min((int) (pos.y / m_cellWidth.y), m_res.y-1)), - std::max(0, std::min((int) (pos.z / m_cellWidth.z), m_res.z-1)) - ); - int index = dpos.x + dpos.y * m_res.x + dpos.z * m_slab; - m_cells[index] = functor(m_cells[index]); - return true; - } - - /** - * \brief Rasterize a ray to the grid and apply the functor to - * every traversed cell - */ - template void rasterize(const Ray &ray, Functor &functor) { - Float mint, maxt, t; - - /* Intersect with the voxel grid */ - if (!m_aabb.rayIntersect(ray, mint, maxt)) - return; - - /* Find the covered range in the ray space */ - mint = std::max(mint, ray.mint); maxt = std::max(mint, std::min(maxt, ray.maxt)); - if (mint == maxt) - return; - - /* Compute the discrete coordinates of the first intersected voxel */ - Vector pos = ray(mint) - m_aabb.min; - Vector3i dpos( - std::max(0, std::min((int) (pos.x / m_cellWidth.x), m_res.x-1)), - std::max(0, std::min((int) (pos.y / m_cellWidth.y), m_res.y-1)), - std::max(0, std::min((int) (pos.z / m_cellWidth.z), m_res.z-1)) - ); - t = mint; - - /* Precompute useful traversal information */ - Vector corner1 = Vector(dpos.x * m_cellWidth.x, - dpos.y * m_cellWidth.y, dpos.z * m_cellWidth.z); - Vector corner2 = Vector((dpos.x+1) * m_cellWidth.x, - (dpos.y+1) * m_cellWidth.y, (dpos.z+1) * m_cellWidth.z); - Vector delta, next; - Vector3i step, bounds; - for (int i=0; i<3; ++i) { - if (std::abs(ray.d[i]) < Epsilon) { - delta[i] = 0; step[i] = 0; next[i] = - std::numeric_limits::infinity(); - } else if (ray.d[i] > 0) { - delta[i] = m_cellWidth[i]/ray.d[i]; - next[i] = mint + (corner2[i] - pos[i]) / ray.d[i]; - step[i] = 1; - bounds[i] = m_res[i]; - } else { - delta[i] = -m_cellWidth[i]/ray.d[i]; - next[i] = mint + (corner1[i] - pos[i]) / ray.d[i]; - step[i] = -1; - bounds[i] = -1; - } - } - - /* Walk through the voxel grid (3D DDA) */ - while (true) { - Float nextT = std::min(std::min(std::min(next.x, next.y), next.z), maxt); - - const int arrayIdx = dpos.x + dpos.y * m_res.x + dpos.z * m_slab; - m_cells[arrayIdx] = functor(m_cells[arrayIdx], nextT - t); - t = nextT; - - if (next.x <= next.y && next.x <= next.z) { - if (next.x > maxt) - break; - dpos.x += step.x; - if (dpos.x == bounds.x) - break; - next.x += delta.x; - } else if (next.y <= next.x && next.y <= next.z) { - if (next.y > maxt) - break; - dpos.y += step.y; - if (dpos.y == bounds.y) - break; - next.y += delta.y; - } else { - if (next.z > maxt) - break; - dpos.z += step.z; - if (dpos.z == bounds.z) - break; - next.z += delta.z; - } - } - } - - /// Return a string representation (MATLAB format) - std::string toStringMATLAB() const { - std::ostringstream oss; - - oss << "v=reshape(["; - for (int z=0; z= m_res.x-1 || - j >= m_res.y || k >= m_res.z) - return ValueType(); - - const Float alpha = x-i, - beta = y-j, - gamma = z-k; - - const ValueType - A1 = m_cells[pos], - B1 = (i+1 { inline Matrix4x4() { } @@ -678,6 +686,10 @@ template inline Matrix return result; } +template inline Matrix operator*(T f, const Matrix &m) { + return m*f; +} + /** * \brief Fast 3x3 eigenvalue decomposition * diff --git a/include/mitsuba/core/mempool.h b/include/mitsuba/core/mempool.h index bbfe8367..7e57148a 100644 --- a/include/mitsuba/core/mempool.h +++ b/include/mitsuba/core/mempool.h @@ -24,10 +24,12 @@ MTS_NAMESPACE_BEGIN /** - * Basic memory pool -- allows repeated allocation & deallocation - * of objects of the same type, while attempting to keep them - * contiguous in memory and having only minimal interaction with the - * underlying allocator. + * \brief Basic memory pool for efficient allocation and deallocation + * of objects of the same type. + * + * This class attempts to keep most instances contiguous in memory, while + * having only minimal interaction with the underlying allocator. + * * \ingroup libcore */ template class MemoryPool { diff --git a/include/mitsuba/core/mmap.h b/include/mitsuba/core/mmap.h index 9de5b8a6..cc22adfe 100644 --- a/include/mitsuba/core/mmap.h +++ b/include/mitsuba/core/mmap.h @@ -16,7 +16,6 @@ along with this program. If not, see . */ - #if !defined(__MMAP_H) #define __MMAP_H diff --git a/include/mitsuba/core/netobject.h b/include/mitsuba/core/netobject.h index 15498ce0..b7c29330 100644 --- a/include/mitsuba/core/netobject.h +++ b/include/mitsuba/core/netobject.h @@ -23,13 +23,16 @@ MTS_NAMESPACE_BEGIN -/** \brief Abstract interface for objects that reference shared network resources. +/** \brief Abstract interface for objects that reference shared network + * resources. * - * When a networked object is serialized as part of a parallel process executed on - * multiple machines, the object is first given the opportunity to bind named resources - * to the process (by a call to \ref bindUsedResources()). These will then be - * distributed to all participating compute servers. Once unserialized on the remote side, - * \ref wakeup() is called to let the object re-associate with the shared resources. + * When a networked object is serialized as part of a parallel process + * executed on multiple machines, the object is first given the + * opportunity to bind named resources to the process (by a call to + * \ref bindUsedResources()). These will then be distributed to all + * participating compute servers. Once unserialized on the remote side, + * \ref wakeup() is called to let the object re-associate with the + * shared resources. * * \ingroup libcore */ diff --git a/include/mitsuba/core/normal.h b/include/mitsuba/core/normal.h index e38de693..cb78ce9d 100644 --- a/include/mitsuba/core/normal.h +++ b/include/mitsuba/core/normal.h @@ -32,6 +32,7 @@ MTS_NAMESPACE_BEGIN * is in how instances of Normal are treated by linear transformations. * * \ingroup libcore + * \ingroup libpython */ struct Normal : public TVector3 { /** \brief Construct a new normal without initializing it. diff --git a/include/mitsuba/core/object.h b/include/mitsuba/core/object.h index e14af4ae..140803c3 100644 --- a/include/mitsuba/core/object.h +++ b/include/mitsuba/core/object.h @@ -33,6 +33,7 @@ MTS_NAMESPACE_BEGIN * * \sa ref, Class * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Object { public: diff --git a/include/mitsuba/core/platform.h b/include/mitsuba/core/platform.h index 41f33fe8..f6e082ba 100644 --- a/include/mitsuba/core/platform.h +++ b/include/mitsuba/core/platform.h @@ -74,6 +74,7 @@ #define MTS_MODULE_RENDER 2 #define MTS_MODULE_HW 3 #define MTS_MODULE_BIDIR 4 + #define MTS_MODULE_PYTHON 5 #define MTS_EXPORT __declspec(dllexport) #define MTS_IMPORT __declspec(dllimport) @@ -98,6 +99,11 @@ #else #define MTS_EXPORT_BIDIR __declspec(dllimport) #endif + #if MTS_BUILD_MODULE == MTS_MODULE_PYTHON + #define MTS_EXPORT_PYTHON __declspec(dllexport) + #else + #define MTS_EXPORT_PYTHON __declspec(dllimport) + #endif #define SIZE_T_FMT "%Iu" #define BOOST_FILESYSTEM_NO_LIB @@ -108,6 +114,7 @@ #define MTS_EXPORT_RENDER #define MTS_EXPORT_HW #define MTS_EXPORT_BIDIR + #define MTS_EXPORT_PYTHON #include #define SIZE_T_FMT "%zd" @@ -123,19 +130,25 @@ /* Compile with Boost filesystem v2 */ #define BOOST_FILESYSTEM_VERSION 2 +/* Use ELF support for thread-local storage on Linux? This + * is potentially faster but causes problems when dynamically + * loading Mitsuba from Python, so let's keep it disabled for now + */ +#define MTS_USE_ELF_TLS 0 + #include MTS_NAMESPACE_BEGIN #if defined(__OSX__) -extern void __ubi_autorelease_init(); -extern void __ubi_autorelease_shutdown(); -extern void __ubi_autorelease_begin(); -extern void __ubi_autorelease_end(); -extern std::string __ubi_bundlepath(); -extern void __ubi_chdir_to_bundlepath(); -extern void __ubi_init_cocoa(); -#define MTS_AUTORELEASE_BEGIN() __ubi_autorelease_begin(); -#define MTS_AUTORELEASE_END() __ubi_autorelease_end(); +extern void __mts_autorelease_init(); +extern void __mts_autorelease_shutdown(); +extern void __mts_autorelease_begin(); +extern void __mts_autorelease_end(); +extern std::string __mts_bundlepath(); +extern void __mts_chdir_to_bundlepath(); +extern void __mts_init_cocoa(); +#define MTS_AUTORELEASE_BEGIN() __mts_autorelease_begin(); +#define MTS_AUTORELEASE_END() __mts_autorelease_end(); #define MTS_AMBIGUOUS_SIZE_T 1 #else #define MTS_AUTORELEASE_BEGIN() diff --git a/include/mitsuba/core/plugin.h b/include/mitsuba/core/plugin.h index efc6a799..31ecda7e 100644 --- a/include/mitsuba/core/plugin.h +++ b/include/mitsuba/core/plugin.h @@ -30,8 +30,8 @@ MTS_NAMESPACE_BEGIN * \brief Abstract plugin class -- represents loadable configurable objects * and utilities. * - * Please see the \ref ConfigurableObject and - * \ref Utility classes for details + * Please see the \ref ConfigurableObject and \ref Utility classes for + * details. * * \ingroup libcore */ @@ -82,12 +82,50 @@ private: CreateUtilityFunc m_createUtility; }; - /** * \brief The plugin manager is responsible for resolving and * loading external plugins. * + * Ordinarily, this class will be used by making repeated calls to + * the \ref createObject() methods. The generated instances are then + * assembled into a final object graph, such as a scene. One such + * examples is the \ref SceneHandler class, which parses an XML + * scene file by esentially translating the XML elements into calls + * to \ref createObject(). + * + * Since this kind of construction method can be tiresome when + * dynamically building scenes from Python, this class has an + * additional Python-only method \c create(), which works as follows: + * + * \code + * from mitsuba.core import * + * + * pmgr = PluginManager.getInstance() + * camera = pmgr.create({ + * "type" : "perspective", + * "toWorld" : Transform.lookAt( + * Point(0, 0, -10), + * Point(0, 0, 0), + * Vector(0, 1, 0) + * ), + * "film" : { + * "type" : "pngfilm", + * "width" : 1920, + * "height" : 1080 + * } + * }) + * \endcode + * + * The above snippet constructs a \ref Camera instance from a + * plugin named \c perspective.so/dll/dylib and adds a child object + * named \c film, which is a \ref Film instance loaded from the + * plugin \c pngfilm.so/dll/dylib. By the time the function + * returns, the object hierarchy has already been assembled, and the + * \ref ConfigurableObject::configure() methods of every object + * has been called. + * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE PluginManager : public Object { public: @@ -103,7 +141,9 @@ public: std::vector getLoadedPlugins() const; /** - * \brief Instantiate an object using a plugin + * \brief Instantiate a plugin, verify its type, + * and return the newly created instance. + * * \param classType Expected type of the plugin. An * exception will be thrown if it turns out not * to derive from this class. @@ -116,6 +156,18 @@ public: const Properties &props ); + /** + * \brief Instantiate a plugin and return the new + * instance (without verifying its type). + * + * \param props A \ref Properties instance containing + * all information required to find and construct + * the plugin. + */ + ConfigurableObject *createObject( + const Properties &props + ); + /// Initializes the global plugin manager instance static void staticInitialization(); diff --git a/include/mitsuba/core/properties.h b/include/mitsuba/core/properties.h index f3af3644..57b79fc5 100644 --- a/include/mitsuba/core/properties.h +++ b/include/mitsuba/core/properties.h @@ -21,12 +21,25 @@ #include #include +#include MTS_NAMESPACE_BEGIN -/** \brief Associative map for values of various types. Used to - * construct subclasses of ConfigurableObject. +/** \brief Associative parameter map for constructing + * subclasses of \ref ConfigurableObject. + * + * Note that the Python bindings for this class do not implement + * the various type-dependent getters and setters. Instead, they + * are accessed just like a normal Python map, e.g: + * + * \code + * myProps = mitsuba.core.Properties("pluginName") + * myProps["stringProperty"] = "hello" + * myProps["spectrumProperty"] = mitsuba.core.Spectrum(1.0) + * \endcode + * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Properties { public: @@ -40,6 +53,8 @@ public: EFloat, /// 3D point EPoint, + /// 3D vector + EVector, /// 4x4 transform for homogeneous coordinates ETransform, /// Discretized color spectrum @@ -73,43 +88,46 @@ public: inline void setID(const std::string &id) { m_id = id; } /// Set a boolean value - void setBoolean(const std::string &name, bool value, bool warnDuplicates = true); + void setBoolean(const std::string &name, const bool &value, bool warnDuplicates = true); /// Get an boolean value bool getBoolean(const std::string &name) const; /// Get an boolean value (with default); - bool getBoolean(const std::string &name, bool defVal) const; + bool getBoolean(const std::string &name, const bool &defVal) const; /// Set an integer value - void setInteger(const std::string &name, int value, bool warnDuplicates = true); + void setInteger(const std::string &name, const int &value, bool warnDuplicates = true); /// Get an integer value int getInteger(const std::string &name) const; /// Get an integer value (with default); - int getInteger(const std::string &name, int defVal) const; + int getInteger(const std::string &name, const int &defVal) const; /// Set an integer value - void setLong(const std::string &name, int64_t value, bool warnDuplicates = true); + void setLong(const std::string &name, const int64_t &value, bool warnDuplicates = true); /// 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; + int64_t getLong(const std::string &name, const int64_t &defVal) const; + + /// Set a size value + void setSize(const std::string &name, const size_t &value, bool warnDuplicates = true); /// 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; + size_t getSize(const std::string &name, const size_t &defVal) const; /// Set a single precision floating point value - void setFloat(const std::string &name, Float value, bool warnDuplicates = true); + void setFloat(const std::string &name, const Float &value, bool warnDuplicates = true); /// Get a single precision floating point value Float getFloat(const std::string &name) const; /// Get a single precision floating point value (with default) - Float getFloat(const std::string &name, Float defVal) const; + Float getFloat(const std::string &name, const Float &defVal) const; /// Set an arbitrary data value - void setData(const std::string &name, Data value, bool warnDuplicates = true); + void setData(const std::string &name, const Data &value, bool warnDuplicates = true); /// Get an arbitrary data value Data getData(const std::string &name) const; /// Get an arbitrary data value (with default) - Data getData(const std::string &name, Data defVal) const; + Data getData(const std::string &name, const Data &defVal) const; /// Set a linear transformation void setTransform(const std::string &name, const Transform &value, bool warnDuplicates = true); @@ -131,6 +149,9 @@ public: Point getPoint(const std::string &name) const; /// Get a 3d point (with default) Point getPoint(const std::string &name, const Point &defVal) const; + + /// Set a 3d vector + void setVector(const std::string &name, const Vector &value, bool warnDuplicates = true); /// Get a 3d vector Vector getVector(const std::string &name) const; /// Get a 3d vector (with default) @@ -144,11 +165,18 @@ public: std::string getString(const std::string &name, const std::string &defVal) const; /// Store an array containing the names of all stored properties - inline void putPropertyNames(std::vector &results) const { + inline void putNames(std::vector &results) const { for (std::map::const_iterator it = m_elements.begin(); it != m_elements.end(); ++it) results.push_back((*it).first); } + + /// Return an array containing the names of all stored properties + inline std::vector getNames() const { + std::vector results; + putNames(results); + return results; + } /// Manually mark a certain property as queried void markQueried(const std::string &name) const; @@ -169,20 +197,12 @@ public: std::string toString() const; private: /// \cond + typedef boost::variant< + bool, int64_t, Float, Point, Vector, Transform, + Spectrum, std::string, Data> ElementData; + struct Element { - EPropertyType type; - union { - bool v_boolean; - int64_t v_long; - Float v_float; - Data v_data; - }; - // not allowed in union (constructor) - Point v_point; - Vector v_vector; - Transform v_transform; - Spectrum v_spectrum; - std::string v_string; + ElementData data; mutable bool queried; }; /// \endcond diff --git a/include/mitsuba/core/quad.h b/include/mitsuba/core/quad.h index 40e7edc2..f4e82290 100644 --- a/include/mitsuba/core/quad.h +++ b/include/mitsuba/core/quad.h @@ -16,7 +16,6 @@ along with this program. If not, see . */ - #if !defined(__QUADRATURE_H) #define __QUADRATURE_H diff --git a/include/mitsuba/core/random.h b/include/mitsuba/core/random.h index faeea48a..622e2883 100644 --- a/include/mitsuba/core/random.h +++ b/include/mitsuba/core/random.h @@ -90,6 +90,7 @@ MTS_NAMESPACE_BEGIN /** * \brief %Random number generator based on Mersenne Twister * by Takuji Nishimura and Makoto Matsumoto. + * \ingroup libpython */ class MTS_EXPORT_CORE Random : public SerializableObject { public: @@ -117,11 +118,15 @@ public: /// Seed the random generator with a single 64bit value void seed(uint64_t value = 5489ULL); - + /// Seed the random generator from another random generator void seed(Random *random); - - /// Seed the random generator from an array + + /** + * \brief Seed the random generator from an array + * \remark This function is currently not exposed + * by the Python bindings + */ void seed(uint64_t *values, uint64_t length); /// Return an integer on the [0, 2^63-1]-interval @@ -141,6 +146,9 @@ public: * given STL container. * * See Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2. + * + * \remark This function is currently not exposed + * by the Python bindings */ template void shuffle(Iterator it1, Iterator it2) { for (Iterator it = it2 - 1; it > it1; --it) diff --git a/include/mitsuba/core/ray.h b/include/mitsuba/core/ray.h index 54b2b04f..065b61a6 100644 --- a/include/mitsuba/core/ray.h +++ b/include/mitsuba/core/ray.h @@ -30,6 +30,7 @@ MTS_NAMESPACE_BEGIN * to alignment purposes and should not be changed. * * \ingroup libcore + * \ingroup libpython */ struct Ray { Point o; ///< Ray origin @@ -107,7 +108,13 @@ struct Ray { #endif } - /// Return 3d coordinates of a point on the ray + /** + * \brief Return 3D coordinates of a point along the ray + * + * \remark In the Python bindings, this operator is + * exposed as a function named \c eval -- i.e. + * position lookups should be written as \c ray.eval(t) + */ inline Point operator() (Float t) const { return o + t * d; } /// Return a string representation of this ray diff --git a/include/mitsuba/core/sched.h b/include/mitsuba/core/sched.h index 62d4e029..f7655e3c 100644 --- a/include/mitsuba/core/sched.h +++ b/include/mitsuba/core/sched.h @@ -33,8 +33,16 @@ MTS_NAMESPACE_BEGIN /** * \brief Abstract work unit -- represents a small amount of information - * that encodes part of a larger processing task. + * that encodes part of a larger processing task. + * + * Instead of the usual serialization function and unserialization + * constructor, implementations of this class supply \ref load() + * and \ref save() methods that can be used for essentially the + * same purpose, but without requiring any memory allocations. + * + * \sa WorkProcessor * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE WorkUnit : public Object { public: @@ -58,8 +66,16 @@ protected: /** * \brief Abstract work result -- represents the result of a - * processed \ref WorkUnit instance. + * processed \ref WorkUnit instance. + * + * Instead of the usual serialization function and unserialization + * constructor, implementations of this class supply \ref load() + * and \ref save() methods that can be used for essentially the + * same purpose, but without requiring any memory allocations. + * + * \sa WorkProcessor * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE WorkResult : public Object { public: @@ -80,16 +96,24 @@ protected: /** * \brief Abstract work processor -- takes work units and turns them into - * WorkResult instances. + *\ref WorkResult instances. * + * When executing a parallel task using Mitsuba's scheduling system, the + * actual work is done in an implementation of this interface. + * * The class is serializable so that it can be sent over the network if - * required. It is possible to keep local state in WorkProcessor + * required. It is possible to keep local state in \ref WorkProcessor * instances (e.g. scratch space for computations), though anything not - * returned in the form of WorkResults will eventually be lost. - * Each worker (both locally and remotely) has its own WorkProcessor, + * returned in the form of a \ref WorkResult will eventually be lost. + * Each \ref Worker (both locally and remotely) has its own \ref WorkProcessor, * and therefore no form of locking is required within instances of this class. * + * \sa WorkUnit + * \sa WorkResult + * \sa ParallelProcess + * \sa Scheduler * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE WorkProcessor : public SerializableObject { friend class Scheduler; @@ -102,10 +126,11 @@ public: /** * \brief Create a copy of this work processor instance. - * - * Note: Before the cloned work processor is used, its - * prepare() method will be called - therefore, state - * that is initialized there does not have to be copied. + * + * \remark In practice, before the cloned work processor + * is actually used, its \ref prepare() method will be called. + * Therefore, any state that is initialized in \ref prepeare() + * does not have to be copied. */ virtual ref clone() const = 0; @@ -154,18 +179,20 @@ protected: /** * \brief Abstract parallelizable task. * - * Models a larger piece of work that can be split into independent - * `units' and subsequently farmed out over a cluster or processed locally. - * After the work units have been completed, the results are pieced back - * together to a solution of the original large-scale problem. This class - * implements the core logic running on the central scheduling server, - * i.e. the part that is responsible for generating work units and + * Instances of this class model a larger piece of work that can be split + * into independent `units' and subsequently farmed out over a cluster or + * processed locally. After the work units have been completed, the results + * are pieced back together to a solution of the original large-scale problem. + * + * This class implements the core logic running on the central scheduling + * server, i.e. the part that is responsible for generating work units and * accepting their results. The module that performs the actual computation - * is an instance of WorkProcessor, which is also specified here. + * is an instance of \ref WorkProcessor, which is also specified here. * Finally, the this class references `resources', which denote * chunks of globally shared read-only data required during execution. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE ParallelProcess : public Object { friend class Scheduler; @@ -184,18 +211,18 @@ public: /** * \brief Generate a piece of work. * - * Takes a pre-allocated \ref WorkUnit instance of + * Takes a pre-allocated \ref WorkUnit instance of * the appropriate sub-type and size (as specified by - * \ref ParallelProcess::getWorkUnitName()) and + * \ref ParallelProcess::getWorkUnitName()) and * fills it with the appropriate content. Returns ESuccess * on success and EFailure or EPause when no more work is * left -- in that case, the work unit will be ignored and * the process completed (\ref EFailure) or temporarily * paused (\ref EPause). When \ref EPause was used, - * resubmission via \ref Scheduler::schedule() will + * resubmission via \ref Scheduler::schedule() will * be required once more work is available. In some cases, it * is useful to distribute 'nearby' pieces of work to the same - * processor -- the worker parameter can be used to + * processor -- the \c worker parameter can be used to * implement this. * This function should run as quickly as possible, since it * will be executed while the scheduler mutex is held. A @@ -216,7 +243,7 @@ public: * in \ref generateWork(). * * When a work unit is only partially completed due to - * a call to Scheduler::cancel, the second + * a call to \ref Scheduler::cancel(), the second * parameter is set to true. * A thrown exception will lead to the termination of * the parallel process. @@ -239,7 +266,7 @@ public: * \brief Query the return status of a process after its * execution has finished. * - * Returns one of \ref Success, \ref Failure or \ref Unknown + * Returns one of \ref Success, \ref Failure or \ref Unknown. * (\ref EUnknown means that the process is either still running * or has never been scheduled). */ @@ -314,11 +341,12 @@ class Worker; * * Accepts parallelizable jobs and distributes their computational load * both locally and remotely. This is done by associating different types - * of \ref Workers with the scheduler. These try to acquire work + * of \ref Worker instances with the scheduler. These try to acquire work * units from the scheduler, which are then executed on the current machine * or sent to remote nodes over a network connection. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Scheduler : public Object { friend class Worker; @@ -338,7 +366,7 @@ public: * or canceled prematurely. * * Returns false if the process does not exist or has already - * finished by the time \ref wait() is invoked. + * finished by the time \ref wait() is invoked. */ bool wait(const ParallelProcess *process); @@ -369,8 +397,8 @@ public: * \a Manifold means that in comparison to the previous method, a separate * instance is provided for every core. An example where this is useful * is to distribute random generator state when performing parallel - * Monte Carlo simulations. resources must be a vector whose - * length is equal to \ref getCoreCount(). + * Monte Carlo simulations. \c resources must be a vector whose + * length is equal to \ref getCoreCount(). */ int registerManifoldResource(std::vector &resources); @@ -422,7 +450,7 @@ public: * running workers. * * Any currently scheduled work units are still completed. - * Processing can be resumed via \ref start(). + * Processing can be resumed via \ref start(). */ void pause(); @@ -464,7 +492,7 @@ public: int inflight; /* Is the parallel process still generating work */ bool morework; - /* Was the process cancelled using cancel()?*/ + /* Was the process cancelled using \c cancel()?*/ bool cancelled; /* Is the process currently in the queue? */ bool active; @@ -642,6 +670,7 @@ private: /** * \brief Base class of all worker implementations + * \ingroup libpython */ class MTS_EXPORT_CORE Worker : public Thread { friend class Scheduler; @@ -727,6 +756,7 @@ protected: * it locally. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE LocalWorker : public Worker { public: diff --git a/include/mitsuba/core/sched_remote.h b/include/mitsuba/core/sched_remote.h index 0e6be587..e7243d53 100644 --- a/include/mitsuba/core/sched_remote.h +++ b/include/mitsuba/core/sched_remote.h @@ -43,6 +43,7 @@ class StreamBackend; * it to a processing node reachable through a \ref Stream. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE RemoteWorker : public Worker { friend class RemoteWorkerReader; diff --git a/include/mitsuba/core/serialization.h b/include/mitsuba/core/serialization.h index c507ac80..d74e4265 100644 --- a/include/mitsuba/core/serialization.h +++ b/include/mitsuba/core/serialization.h @@ -29,6 +29,7 @@ MTS_NAMESPACE_BEGIN * RTTI macros \ref MTS_IMPLEMENT_CLASS_S or \ref MTS_IMPLEMENT_CLASS_IS. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE SerializableObject : public Object { public: @@ -58,6 +59,7 @@ protected: * object graph has the same structure. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE InstanceManager : public Object { friend class SerializableObject; diff --git a/include/mitsuba/core/shvector.h b/include/mitsuba/core/shvector.h index 82b04051..5b85c24b 100644 --- a/include/mitsuba/core/shvector.h +++ b/include/mitsuba/core/shvector.h @@ -33,7 +33,9 @@ namespace ublas = boost::numeric::ublas; struct SHVector; /** - * \brief Stores the diagonal blocks of a spherical harmonic rotation matrix + * \brief Stores the diagonal blocks of a spherical harmonic + * rotation matrix + * * \ingroup libcore */ struct MTS_EXPORT_CORE SHRotation { @@ -65,14 +67,14 @@ struct MTS_EXPORT_CORE SHRotation { * * The Mathematica equivalent of the basis functions implemented here is: * - *
+ * \code
  * SphericalHarmonicQ[l_, m_, \[Theta]_, \[Phi]_] :=
  *   Piecewise[{
  *      {SphericalHarmonicY[l, m, \[Theta], \[Phi]], m == 0},
  *      {Sqrt[2]*Re[SphericalHarmonicY[l, m, \[Theta], \[Phi]]], m > 0},
  *      {Sqrt[2]*Im[SphericalHarmonicY[l, -m, \[Theta], \[Phi]]], m < 0}
  *  }]
- * 
+ * \endcode * * \ingroup libcore */ @@ -338,10 +340,10 @@ public: */ static void rotation(const Transform &t, SHRotation &rot); - /** \brief Precomputes normalization coefficients for the first few bands */ + /// Precomputes normalization coefficients for the first few bands static void staticInitialization(); - /// Free the memory taken by staticInitialization() + /// Free the memory taken up by staticInitialization() static void staticShutdown(); protected: /// Helper function for rotation() -- computes a diagonal block based on the previous level diff --git a/include/mitsuba/core/shvector4d.h b/include/mitsuba/core/shvector4d.h deleted file mode 100644 index 68712e07..00000000 --- a/include/mitsuba/core/shvector4d.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - 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 . -*/ - -#if !defined(__SHEXP4D_H) -#define __SHEXP4D_H - -#include - -MTS_NAMESPACE_BEGIN - -/** - * \brief Stores a 4D function f(wi, wo) (such as a BRDF or phase function) - * using a 2D table of spherical harmonics expansions. - * - * Discretization occurs in the 'wi' space. Lookups interpolate amongst - * the 4 adjacent samples. - * - * \ingroup libcore - */ -struct SHVector4D { -public: - /// Construct an invalid expandion - inline SHVector4D() : m_resTheta(0), m_resPhi(0), m_bands(0) { - } - - /// Allocate memory for the specified resolution and number of bands - inline SHVector4D(int resTheta, int resPhi, int bands) - : m_resTheta(resTheta), m_resPhi(resPhi), m_bands(bands), m_data((resTheta+1)*resPhi) { - for (size_t i=0; ireadInt(); - m_resPhi = stream->readInt(); - m_bands = stream->readInt(); - m_data.resize((m_resTheta+1)*m_resPhi); - for (size_t i=0; i void project(const Functor &f, int res = 32) { - SAssert(res % 2 == 0); - /* Nested composite Simpson's rule */ - Float hExt = M_PI / res, - hInt = (2*M_PI)/(res*2); - - Vector *wi = new Vector[(m_resTheta+1) * m_resPhi]; - Float *values = new Float[(m_resTheta+1) * m_resPhi]; - for (int o=0; o<=m_resTheta; ++o) - for (int p=0; pwriteInt(m_resTheta); - stream->writeInt(m_resPhi); - stream->writeInt(m_bands); - for (size_t i=0; i m_data; -}; - -MTS_NAMESPACE_END - -#endif /* __SHEXP4D_H */ diff --git a/include/mitsuba/core/spectrum.h b/include/mitsuba/core/spectrum.h index 41fac5c6..6eff9ca0 100644 --- a/include/mitsuba/core/spectrum.h +++ b/include/mitsuba/core/spectrum.h @@ -45,6 +45,7 @@ MTS_NAMESPACE_BEGIN * that it is a function over the reals (as opposed to the discrete * spectrum, which only stores samples for a discrete set of wavelengths). * + * \ingroup libpython * \ingroup libcore */ class MTS_EXPORT_CORE ContinuousSpectrum { @@ -74,6 +75,9 @@ public: * implementation will return zero. */ virtual Float average(Float lambdaMin, Float lambdaMax) const; + + /// \brief Return a string representation + virtual std::string toString() const = 0; /// Virtual destructor virtual ~ContinuousSpectrum() { } @@ -106,6 +110,9 @@ public: * per unit wavelength (nm^-1) per steradian (sr^-1) */ virtual Float eval(Float lambda) const; + + /// Return a string representation + std::string toString() const; private: Float m_temperature; }; @@ -147,6 +154,9 @@ public: * The returned value is in units of 1/meter. */ virtual Float eval(Float lambda) const; + + /// Return a string representation + std::string toString() const; private: Float m_precomp; }; @@ -171,6 +181,9 @@ public: /// Virtual destructor virtual ~ProductSpectrum() { } + + /// Return a string representation + std::string toString() const; private: const ContinuousSpectrum &m_spec1; const ContinuousSpectrum &m_spec2; @@ -187,6 +200,7 @@ private: * spectrum. * * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE InterpolatedSpectrum : public ContinuousSpectrum { public: @@ -194,10 +208,7 @@ public: * \brief Create a new interpolated spectrum with space * for the specified number of samples */ - inline InterpolatedSpectrum(size_t size = 0) { - m_wavelengths.reserve(size); - m_values.reserve(size); - } + InterpolatedSpectrum(size_t size = 0); /** * \brief Create a interpolated spectrum instance from @@ -269,7 +280,7 @@ public: /// Virtual destructor virtual ~InterpolatedSpectrum() { } -private: +protected: std::vector m_wavelengths, m_values; }; @@ -290,6 +301,7 @@ private: * The implementation of this class is based on PBRT. * * \ingroup libcore + * \ingroup libpython */ struct MTS_EXPORT_CORE Spectrum { public: @@ -398,7 +410,7 @@ public: s[i] *= spd.s[i]; return *this; } - + /// Perform a component-wise division by another spectrum inline Spectrum& operator/=(const Spectrum &spd) { for (int i=0; i +/// \cond +// (Don't include in the documentation) namespace std { - /// \cond - // (Don't include in the documentation) template struct _Select1st : public unary_function<_Pair, typename _Pair::first_type> { const typename _Pair::first_type& operator()(const _Pair& __x) const { return __x.first; @@ -59,7 +59,6 @@ namespace std { template inline unary_compose<_Operation1,_Operation2> compose1(const _Operation1& __fn1, const _Operation2& __fn2) { return unary_compose<_Operation1,_Operation2>(__fn1, __fn2); } - /// @endcond #if defined(_MSC_VER) #include @@ -122,5 +121,6 @@ inline bool mts_isnan(double f) { return std::fpclassify(f) == FP_NAN; } #endif +/// @endcond #endif diff --git a/include/mitsuba/core/stream.h b/include/mitsuba/core/stream.h index 43c93811..d49e1537 100644 --- a/include/mitsuba/core/stream.h +++ b/include/mitsuba/core/stream.h @@ -50,6 +50,7 @@ private: * \sa FileStream, MemoryStream, SocketStream, * ConsoleStream, SSHStream, ZStream * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Stream : public Object { public: diff --git a/include/mitsuba/core/thread.h b/include/mitsuba/core/thread.h index f204fb0b..c20e82ef 100644 --- a/include/mitsuba/core/thread.h +++ b/include/mitsuba/core/thread.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN * \headerfile mitsuba/core/thread.h mitsuba/mitsuba.h * \brief Cross-platform thread implementation * \ingroup libcore + * \ingroup libpython */ class MTS_EXPORT_CORE Thread : public Object { public: @@ -47,6 +48,8 @@ public: * (will be shown in debug messages) * \param stackSize Initial stack size of the thread * (0 = default) + * \remark Note that it is currently not possible to + * construct Thread instances from Python */ Thread(const std::string &name, unsigned int stackSize = 0); @@ -61,6 +64,9 @@ public: */ bool setPriority(EThreadPriority priority); + /// Return the thread priority + inline EThreadPriority getPriority() const { return m_priority; } + /** * \brief Specify whether or not this thread is critical * @@ -73,19 +79,16 @@ public: /// Return the value of the critical flag inline bool getCritical() const { return m_critical; } - /// Return the thread priority - inline EThreadPriority getPriority() const { return m_priority; } - /// Return the thread's stack size inline int getStackSize() const { return m_stackSize; } /// Return the thread ID -#if defined(__OSX__) - inline static int getID() { return getThread()->m_id; } -#elif defined(WIN32) +#if defined(WIN32) inline static int getID() { return (int) GetCurrentThreadId(); } -#else +#elif MTS_USE_ELF_TLS == 1 inline static int getID() { return m_id; } +#else + inline static int getID() { return getThread()->m_id; } #endif /// Return the name of this thread @@ -184,11 +187,12 @@ private: #if defined(__LINUX__) || defined(__OSX__) static int m_idCounter; static ref m_idMutex; -#endif -#if defined(__OSX__) +#if MTS_USE_ELF_TLS == 1 + static __thread int m_id + __attribute__((tls_model("global-dynamic"))); +#else int m_id; -#elif defined(__LINUX__) - static int __thread m_id; +#endif #endif }; diff --git a/include/mitsuba/core/transform.h b/include/mitsuba/core/transform.h index 39ab43ea..1f533f19 100644 --- a/include/mitsuba/core/transform.h +++ b/include/mitsuba/core/transform.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Encapsulates a 4x4 linear transformation and its inverse * \ingroup libcore + * \ingroup libpython */ struct MTS_EXPORT_CORE Transform { public: @@ -98,7 +99,12 @@ public: return true; } - /// Matrix-vector multiplication for points in 3d space + /** + * \brief Matrix-vector multiplication for points in 3d space + * + * \remark In the Python bindings, this is function implemented as + * the multiplication operator (\c __mul__). + */ inline Point operator()(const Point &p) const { Float x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y + m_transform.m[0][2] * p.z + m_transform.m[0][3]; @@ -129,7 +135,10 @@ public: return Point(x,y,z); } - /// Matrix-vector multiplication for points in 3d space (no temporaries) + /** + * \brief Matrix-vector multiplication for points in 3d space (no temporaries) + * \remark This function is not available in the Python bindings + */ inline void operator()(const Point &p, Point &dest) const { dest.x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y + m_transform.m[0][2] * p.z + m_transform.m[0][3]; @@ -148,7 +157,11 @@ public: dest /= w; } - /// Matrix-vector multiplication for vectors in 3d space + /** + * \brief Matrix-vector multiplication for vectors in 3d space + * \remark In the Python bindings, this is function implemented as + * the multiplication operator (\c __mul__). + */ inline Vector operator()(const Vector &v) const { Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y + m_transform.m[0][2] * v.z; @@ -159,7 +172,10 @@ public: return Vector(x, y, z); } - /// Matrix-vector multiplication for vectors in 3d space (no temporaries) + /** + * \brief Matrix-vector multiplication for vectors in 3d space (no temporaries) + * \remark This function is not available in the Python bindings + */ inline void operator()(const Vector &v, Vector &dest) const { dest.x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y + m_transform.m[0][2] * v.z; @@ -169,7 +185,11 @@ public: + m_transform.m[2][2] * v.z; } - /// Matrix-normal multiplication + /** + * \brief Matrix-normal multiplication + * \remark In the Python bindings, this is function implemented as + * the multiplication operator (\c __mul__). + */ inline Normal operator()(const Normal &v) const { Float x = m_invTransform.m[0][0] * v.x + m_invTransform.m[1][0] * v.y + m_invTransform.m[2][0] * v.z; @@ -180,7 +200,10 @@ public: return Normal(x, y, z); } - /// Matrix-normal multiplication (no temporaries) + /** + * \brief Matrix-normal multiplication (no temporaries) + * \remark This function is not available in the Python bindings + */ inline void operator()(const Normal &v, Normal &dest) const { dest.x = m_invTransform.m[0][0] * v.x + m_invTransform.m[1][0] * v.y + m_invTransform.m[2][0] * v.z; @@ -190,7 +213,11 @@ public: + m_invTransform.m[2][2] * v.z; } - /// 4D matrix-vector multiplication + /** + * \brief 4D matrix-vector multiplication + * \remark In the Python bindings, this is function implemented as + * the multiplication operator (\c __mul__). + */ inline Vector4 operator()(const Vector4 &v) const { Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y + m_transform.m[0][2] * v.z + m_transform.m[0][3] * v.w; @@ -203,7 +230,10 @@ public: return Vector4(x,y,z,w); } - /// 4D matrix-vector multiplication + /** + * \brief 4D matrix-vector multiplication (no temporaries) + * \remark This function is not available in the Python bindings + */ inline void operator()(const Vector4 &v, Vector4 &dest) const { dest.x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y + m_transform.m[0][2] * v.z + m_transform.m[0][3] * v.w; @@ -215,7 +245,21 @@ public: + m_transform.m[3][2] * v.z + m_transform.m[3][3] * v.w; } - /// Transform a ray. Assumes that there is no scaling + /** + * \brief Transform a ray. Assumes that there is no scaling + * \remark In the Python bindings, this is function implemented as + * the multiplication operator (\c __mul__). + */ + inline Ray operator()(const Ray &a) const { + Ray result; + operator()(a, result); + return result; + } + + /** + * \brief Transform a ray. Assumes that there is no scaling (no temporaries) + * \remark This function is not available in the Python bindings + */ inline void operator()(const Ray &a, Ray &b) const { b.mint = a.mint; b.maxt = a.maxt; diff --git a/include/mitsuba/core/util.h b/include/mitsuba/core/util.h index abf17fc1..9fc942bb 100644 --- a/include/mitsuba/core/util.h +++ b/include/mitsuba/core/util.h @@ -49,7 +49,7 @@ extern MTS_EXPORT_CORE std::string indent(const std::string &string, int amount= extern MTS_EXPORT_CORE std::string formatString(const char *pFmt, ...); /** - * Convert a time difference (in ms) to a string representation + * \brief Convert a time difference (in ms) to a string representation * \param time Time value in milliseconds * \param precise When set to true, a higher-precision string representation * is generated. @@ -104,9 +104,10 @@ extern MTS_EXPORT_CORE std::string getHostName(); extern MTS_EXPORT_CORE std::string getFQDN(); /** - * Enable floating point exceptions (to catch NaNs, overflows, - * arithmetic with infinity). On Intel processors, this applies - * to both x87 and SSE2 math + * \brief Enable floating point exceptions (to catch NaNs, overflows, + * arithmetic with infinity). + * + * On Intel processors, this applies to both x87 and SSE2 math * * \return \c true if floating point exceptions were active * before calling the function @@ -114,7 +115,7 @@ extern MTS_EXPORT_CORE std::string getFQDN(); extern MTS_EXPORT_CORE bool enableFPExceptions(); /** - * Disable floating point exceptions + * \brief Disable floating point exceptions * * \return \c true if floating point exceptions were active * before calling the function @@ -149,6 +150,8 @@ template inline T endianness_swap(T value) { } /** + * \brief Apply an arbitrary permutation to an array in linear time + * * This algorithm is based on Donald Knuth's book * "The Art of Computer Programming, Volume 3: Sorting and Searching" * (1st edition, section 5.2, page 595) @@ -256,6 +259,7 @@ extern MTS_EXPORT_CORE uint32_t roundToPowerOfTwo(uint32_t i); extern MTS_EXPORT_CORE uint64_t roundToPowerOfTwo(uint64_t i); #if defined(MTS_AMBIGUOUS_SIZE_T) +/// Round an integer to the next power of two inline size_t roundToPowerOfTwo(size_t value) { if (sizeof(size_t) == 8) /// will be optimized away return (size_t) roundToPowerOfTwo((uint64_t) value); @@ -264,7 +268,7 @@ inline size_t roundToPowerOfTwo(size_t value) { } #endif -//// Windowed sinc filter (Lanczos envelope, tau=number of cycles) +/// Windowed sinc filter (Lanczos envelope, tau=number of cycles) extern MTS_EXPORT_CORE Float lanczosSinc(Float t, Float tau = 2); /** @@ -275,7 +279,8 @@ extern MTS_EXPORT_CORE bool solveQuadratic(Float a, Float b, Float c, Float &x0, Float &x1); /** - * Calculate the radical inverse function + * \brief Calculate the radical inverse function + * * (Implementation based on "Instant Radiosity" by Alexander Keller * in Computer Graphics Proceedings, Annual Conference Series, * SIGGRAPH 97, pp. 49-56. @@ -283,7 +288,8 @@ extern MTS_EXPORT_CORE bool solveQuadratic(Float a, Float b, extern MTS_EXPORT_CORE Float radicalInverse(int b, size_t i); /** - * Incrementally calculate the radical inverse function + * \brief Incrementally calculate the radical inverse function + * * (Implementation based on "Instant Radiosity" by Alexander Keller * in Computer Graphics Proceedings, Annual Conference Series, * SIGGRAPH 97, pp. 49-56. @@ -426,7 +432,7 @@ extern MTS_EXPORT_CORE Point2 squareToStdNormal(const Point2 &sample); // ----------------------------------------------------------------------- /** - * Calculates the unpolarized fresnel reflection coefficient for a + * \brief Calculates the unpolarized fresnel reflection coefficient for a * dielectric material * * \param cosThetaI @@ -442,7 +448,7 @@ extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosThetaI, Float cosThetaT, Float etaI, Float etaT); /** - * Calculates the unpolarized fresnel reflection coefficient for a + * \brief Calculates the unpolarized fresnel reflection coefficient for a * dielectric material. Handles incidence from either sides. * * \param cosThetaI @@ -456,7 +462,7 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float extIOR, Float intIOR); /** - * Calculates the unpolarized fresnel reflection coefficient on + * \brief Calculates the unpolarized fresnel reflection coefficient on * an interface to a conductor. * * \param cosThetaI diff --git a/include/mitsuba/core/version.h b/include/mitsuba/core/version.h index d8b6bee4..3f3ef391 100644 --- a/include/mitsuba/core/version.h +++ b/include/mitsuba/core/version.h @@ -21,15 +21,23 @@ MTS_NAMESPACE_BEGIN -/// Current release of Mitsuba +/** + * \brief Current release of Mitsuba + * \ingroup libcore + */ #define MTS_VERSION "0.3.0" -// Year of this release +/** + * \brief Year of the current release + * \ingroup libcore + */ #define MTS_YEAR "2011" /** - * \brief A simple data structure for representing and comparing - * Mitsuba version strings + * \brief A simple data structure for representing and + * comparing Mitsuba version strings + * + * \ingroup libcore */ struct MTS_EXPORT_CORE Version { public: diff --git a/include/mitsuba/hw/basicshader.h b/include/mitsuba/hw/basicshader.h index 35b0145c..61581b5d 100644 --- a/include/mitsuba/hw/basicshader.h +++ b/include/mitsuba/hw/basicshader.h @@ -34,6 +34,7 @@ MTS_NAMESPACE_BEGIN * \brief Constant spectrum-valued texture * * Includes a \ref Shader implementation for hardware rendering + * \ingroup libhw */ class MTS_EXPORT_HW ConstantSpectrumTexture : public Texture { public: @@ -82,6 +83,7 @@ protected: * \brief Constant float-valued texture * * Includes a \ref Shader implementation for hardware rendering + * \ingroup libhw */ class MTS_EXPORT_HW ConstantFloatTexture : public Texture { public: @@ -130,6 +132,7 @@ protected: * \brief Componentwise addition of two textures * * Includes a \ref Shader implementation for hardware rendering + * \ingroup libhw */ class MTS_EXPORT_HW SpectrumAdditionTexture : public Texture { public: @@ -181,6 +184,7 @@ protected: * \brief Componentwise subtraction of two textures * * Includes a \ref Shader implementation for hardware rendering + * \ingroup libhw */ class MTS_EXPORT_HW SpectrumSubtractionTexture : public Texture { public: @@ -232,6 +236,7 @@ protected: * \brief Componentwise product of two textures * * Includes a \ref Shader implementation for hardware rendering + * \ingroup libhw */ class MTS_EXPORT_HW SpectrumProductTexture : public Texture { public: diff --git a/include/mitsuba/hw/device.h b/include/mitsuba/hw/device.h index 79334b8c..ff403046 100644 --- a/include/mitsuba/hw/device.h +++ b/include/mitsuba/hw/device.h @@ -28,6 +28,7 @@ class Renderer; /** \brief The device event structure encapsulates event * information such as mouse movement or key presses + * \ingroup libhw */ struct MTS_EXPORT_HW DeviceEvent { public: @@ -114,6 +115,7 @@ private: }; /** \brief Abstract device event callback + * \ingroup libhw */ class MTS_EXPORT_HW DeviceEventListener { public: @@ -128,6 +130,7 @@ protected: }; /** \brief An abstract drawing device + * \ingroup libhw */ class MTS_EXPORT_HW Device : public Object { public: diff --git a/include/mitsuba/hw/font.h b/include/mitsuba/hw/font.h index 3e90f8f6..2b01eb8d 100644 --- a/include/mitsuba/hw/font.h +++ b/include/mitsuba/hw/font.h @@ -28,6 +28,7 @@ MTS_NAMESPACE_BEGIN * * A FreeType2-based generation tool is located in the directory * 'tools/linux/fontgen'. Only Latin-1 is supported at the moment. + * \ingroup libhw */ class MTS_EXPORT_HW Font : public Object { public: diff --git a/include/mitsuba/hw/glgeometry.h b/include/mitsuba/hw/glgeometry.h index 98e7743a..fa418fd0 100644 --- a/include/mitsuba/hw/glgeometry.h +++ b/include/mitsuba/hw/glgeometry.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief OpenGL-based GPUGeometry implementation + * \ingroup libhw */ class MTS_EXPORT_HW GLGeometry : public GPUGeometry { friend class GLRenderer; diff --git a/include/mitsuba/hw/glprogram.h b/include/mitsuba/hw/glprogram.h index bce3d773..6e53950c 100644 --- a/include/mitsuba/hw/glprogram.h +++ b/include/mitsuba/hw/glprogram.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** \brief OpenGL shader class -- responsible from compiling * and linking GLSL fragments + * \ingroup libhw */ class MTS_EXPORT_HW GLProgram : public GPUProgram { public: diff --git a/include/mitsuba/hw/glrenderer.h b/include/mitsuba/hw/glrenderer.h index 450c56ef..b479808d 100644 --- a/include/mitsuba/hw/glrenderer.h +++ b/include/mitsuba/hw/glrenderer.h @@ -46,6 +46,7 @@ MTS_NAMESPACE_BEGIN /** * \brief OpenGL implementation of the \ref Renderer interface + * \ingroup libhw */ class MTS_EXPORT_HW GLRenderer : public Renderer { public: diff --git a/include/mitsuba/hw/glsync.h b/include/mitsuba/hw/glsync.h index 56b672c0..eec90639 100644 --- a/include/mitsuba/hw/glsync.h +++ b/include/mitsuba/hw/glsync.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief OpenGL-based GPUSync implementation + * \ingroup libhw */ class MTS_EXPORT_HW GLSync : public GPUSync { public: diff --git a/include/mitsuba/hw/gltexture.h b/include/mitsuba/hw/gltexture.h index 4a9f9428..2b07a060 100644 --- a/include/mitsuba/hw/gltexture.h +++ b/include/mitsuba/hw/gltexture.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief OpenGL-based GPUTexture implementation + * \ingroup libhw */ class MTS_EXPORT_HW GLTexture : public GPUTexture { public: diff --git a/include/mitsuba/hw/glxdevice.h b/include/mitsuba/hw/glxdevice.h index a4350b81..8369bb9e 100644 --- a/include/mitsuba/hw/glxdevice.h +++ b/include/mitsuba/hw/glxdevice.h @@ -24,6 +24,7 @@ MTS_NAMESPACE_BEGIN /** \brief X Windows OpenGL-capable (GLX) device + * \ingroup libhw */ class MTS_EXPORT_HW GLXDevice : public X11Device { public: diff --git a/include/mitsuba/hw/glxrenderer.h b/include/mitsuba/hw/glxrenderer.h index 2e9f0fa9..a6b4eb4b 100644 --- a/include/mitsuba/hw/glxrenderer.h +++ b/include/mitsuba/hw/glxrenderer.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief GLX (XFree86) renderer + * \ingroup libhw */ class MTS_EXPORT_HW GLXRenderer : public GLRenderer { public: diff --git a/include/mitsuba/hw/gpugeometry.h b/include/mitsuba/hw/gpugeometry.h index 0f4cd704..7bb638c2 100644 --- a/include/mitsuba/hw/gpugeometry.h +++ b/include/mitsuba/hw/gpugeometry.h @@ -24,10 +24,11 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract geometry storage on a graphics card + * \ingroup libhw */ class MTS_EXPORT_HW GPUGeometry : public Object { public: - /// Create an empty program + /// Create an empty geometry object GPUGeometry(const TriMesh *mesh); /// Return the name of this geometry object diff --git a/include/mitsuba/hw/gpuprogram.h b/include/mitsuba/hw/gpuprogram.h index 79a9e3b7..a9a1f64a 100644 --- a/include/mitsuba/hw/gpuprogram.h +++ b/include/mitsuba/hw/gpuprogram.h @@ -24,6 +24,7 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract shader program (for fragment/vertex shading) + * \ingroup libhw */ class MTS_EXPORT_HW GPUProgram : public Object { public: diff --git a/include/mitsuba/hw/gpusync.h b/include/mitsuba/hw/gpusync.h index 52610a42..e053a049 100644 --- a/include/mitsuba/hw/gpusync.h +++ b/include/mitsuba/hw/gpusync.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract GPU synchronization object implementing * a memory fence operation. + * \ingroup libhw */ class MTS_EXPORT_HW GPUSync : public Object { public: diff --git a/include/mitsuba/hw/gputexture.h b/include/mitsuba/hw/gputexture.h index c1d91f7b..2a165d09 100644 --- a/include/mitsuba/hw/gputexture.h +++ b/include/mitsuba/hw/gputexture.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** \brief A data structure for 1/2/3D and cube texture mapping. Also * has optional render-to-texture functionality. + * \ingroup libhw */ class MTS_EXPORT_HW GPUTexture : public Object { public: diff --git a/include/mitsuba/hw/nsglrenderer.h b/include/mitsuba/hw/nsglrenderer.h index 061bf9f4..9f2580e2 100644 --- a/include/mitsuba/hw/nsglrenderer.h +++ b/include/mitsuba/hw/nsglrenderer.h @@ -29,6 +29,7 @@ MTS_NAMESPACE_BEGIN /** \brief A MacOS X (NSGL) OpenGL Renderer + * \ingroup libhw */ class MTS_EXPORT_HW NSGLRenderer : public GLRenderer { public: diff --git a/include/mitsuba/hw/nsglsession.h b/include/mitsuba/hw/nsglsession.h index 47703edd..ae92d7f1 100644 --- a/include/mitsuba/hw/nsglsession.h +++ b/include/mitsuba/hw/nsglsession.h @@ -24,6 +24,7 @@ MTS_NAMESPACE_BEGIN /** \brief A MacOS X (NSGL) windowing environment session + * \ingroup libhw */ class MTS_EXPORT_HW NSGLSession : public Session { public: diff --git a/include/mitsuba/hw/renderer.h b/include/mitsuba/hw/renderer.h index 92d646d1..c591b1f0 100644 --- a/include/mitsuba/hw/renderer.h +++ b/include/mitsuba/hw/renderer.h @@ -33,7 +33,8 @@ class Bitmap; class Font; /** - * Helper class, which documents the capabilities of a renderer implementation + * \brief Helper class, which documents the capabilities of a renderer implementation + * \ingroup libhw */ class MTS_EXPORT_HW RendererCapabilities : public Object { public: @@ -71,6 +72,7 @@ protected: }; /** \brief Abstract renderer implementation + * \ingroup libhw */ class MTS_EXPORT_HW Renderer : public Object { public: diff --git a/include/mitsuba/hw/session.h b/include/mitsuba/hw/session.h index cfd067f0..f4a842dc 100644 --- a/include/mitsuba/hw/session.h +++ b/include/mitsuba/hw/session.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN class Device; /** \brief Abstract windowing environment session + * \ingroup libhw */ class MTS_EXPORT_HW Session : public Object { friend class Device; diff --git a/include/mitsuba/hw/viewer.h b/include/mitsuba/hw/viewer.h index 5ec99316..593e671c 100644 --- a/include/mitsuba/hw/viewer.h +++ b/include/mitsuba/hw/viewer.h @@ -30,6 +30,8 @@ MTS_NAMESPACE_BEGIN * * This class makes it possible to rapidly prototype simple OpenGL * applications, which can be started using the 'mtsutil' launcher. + * + * \ingroup libhw */ class MTS_EXPORT_HW Viewer : public Utility, public DeviceEventListener { public: diff --git a/include/mitsuba/hw/vpl.h b/include/mitsuba/hw/vpl.h index ef6bcbe0..4a582ad0 100644 --- a/include/mitsuba/hw/vpl.h +++ b/include/mitsuba/hw/vpl.h @@ -36,6 +36,8 @@ MTS_NAMESPACE_BEGIN * properties using uniforms, in which case already existing code * can be reused and we get something more like lower case n squared * (where lower n is the number of material types). + * + * \ingroup libhw */ class MTS_EXPORT_HW VPLShaderManager : public Object { public: diff --git a/include/mitsuba/hw/wgldevice.h b/include/mitsuba/hw/wgldevice.h index 30c4f61a..f8e7dd88 100644 --- a/include/mitsuba/hw/wgldevice.h +++ b/include/mitsuba/hw/wgldevice.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief Windows (WGL) device implementation + * \ingroup libhw */ class MTS_EXPORT_HW WGLDevice : public Device { public: diff --git a/include/mitsuba/hw/wglrenderer.h b/include/mitsuba/hw/wglrenderer.h index ed4818dd..4dccedaa 100644 --- a/include/mitsuba/hw/wglrenderer.h +++ b/include/mitsuba/hw/wglrenderer.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief Windows (WGL) renderer implementation + * \ingroup libhw */ class MTS_EXPORT_HW WGLRenderer : public GLRenderer { public: diff --git a/include/mitsuba/hw/wglsession.h b/include/mitsuba/hw/wglsession.h index acf75a22..af7d0da4 100644 --- a/include/mitsuba/hw/wglsession.h +++ b/include/mitsuba/hw/wglsession.h @@ -24,6 +24,7 @@ MTS_NAMESPACE_BEGIN /** \brief Windows (WGL) windowing environment session + * \ingroup libhw */ class MTS_EXPORT_HW WGLSession : public Session { friend class WGLDevice; diff --git a/include/mitsuba/hw/x11device.h b/include/mitsuba/hw/x11device.h index e6e3b8f4..d70ebd4d 100644 --- a/include/mitsuba/hw/x11device.h +++ b/include/mitsuba/hw/x11device.h @@ -25,6 +25,7 @@ MTS_NAMESPACE_BEGIN /** \brief X Window System (X11R6) device / software surface + * \ingroup libhw */ class MTS_EXPORT_HW X11Device : public Device { friend class X11Session; diff --git a/include/mitsuba/hw/x11session.h b/include/mitsuba/hw/x11session.h index 8632d4bc..5d54b2b5 100644 --- a/include/mitsuba/hw/x11session.h +++ b/include/mitsuba/hw/x11session.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** \brief X Window System (X11R6) session + * \ingroup libhw */ class MTS_EXPORT_HW X11Session : public Session { friend class X11Device; diff --git a/include/mitsuba/mitsuba.h b/include/mitsuba/mitsuba.h index cd062bce..cfbbc4f9 100644 --- a/include/mitsuba/mitsuba.h +++ b/include/mitsuba/mitsuba.h @@ -38,6 +38,14 @@ using std::cout; using std::cerr; using std::endl; +#if defined(DOUBLE_PRECISION) +typedef double Float; +#elif defined(SINGLE_PRECISION) +typedef float Float; +#else +#error No precision flag was defined! +#endif + /** * Include a basic subset of the core classes */ diff --git a/include/mitsuba/render/bsdf.h b/include/mitsuba/render/bsdf.h index 21eab531..b2e9ae2b 100644 --- a/include/mitsuba/render/bsdf.h +++ b/include/mitsuba/render/bsdf.h @@ -33,6 +33,7 @@ MTS_NAMESPACE_BEGIN * * \sa BSDF::f() * \sa BSDF::sample() + * \ingroup librender */ struct MTS_EXPORT_RENDER BSDFQueryRecord { public: @@ -179,7 +180,7 @@ public: /** - * \brief Abstract BSDF base-class. + * \brief Abstract %BSDF base-class. * * This class implements an abstract interface to all BSDF plugins in Mitsuba. * It exposes functions for evaluating and sampling the model, and it allows @@ -191,7 +192,9 @@ public: * this class can sample and evaluate a complete BSDF, but it also allows to * pick and choose individual components of multi-lobed BSDFs based on their * properties and component indices. This selection is done using a + * * \ref BSDFQueryRecord. + * \ingroup librender */ class MTS_EXPORT_RENDER BSDF : public ConfigurableObject, public HWResource { public: @@ -419,6 +422,8 @@ public: /// Add a child object virtual void addChild(const std::string &string, ConfigurableObject *obj); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } /// Serialize this object to a stream virtual void serialize(Stream *stream, InstanceManager *manager) const; diff --git a/include/mitsuba/render/camera.h b/include/mitsuba/render/camera.h index 895c4f9a..a0590e1b 100644 --- a/include/mitsuba/render/camera.h +++ b/include/mitsuba/render/camera.h @@ -26,6 +26,8 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract camera base class. A camera turns a sample on * the image plane into a 3D ray. It uses two supporting child * objects: a \re Sampler and a \ref Film instance. + * + * \ingroup librender */ class MTS_EXPORT_RENDER Camera : public ConfigurableObject { public: @@ -165,6 +167,8 @@ public: /// Add a child ConfigurableObject virtual void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } /// Serialize this camera to a binary data stream virtual void serialize(Stream *stream, InstanceManager *manager) const; @@ -201,7 +205,13 @@ protected: Float m_shutterOpen, m_shutterClose, m_shutterOpenTime; ref m_medium; }; - + + +/** + * Projective camera base class + * + * \ingroup librender + */ class MTS_EXPORT_RENDER ProjectiveCamera : public Camera { public: /// Return the projection transformation @@ -237,8 +247,12 @@ protected: }; /** - * Base class of all pinhole cameras. Provides solid angle computation - * routines useful for importance-based integrators. + * \brief Base class of all perspective cameras + * + * Provides solid angle computation routines useful + * for importance-based integrators. + * + * \ingroup librender */ class MTS_EXPORT_RENDER PerspectiveCamera : public ProjectiveCamera { public: diff --git a/include/mitsuba/render/common.h b/include/mitsuba/render/common.h index 24728122..d83c4533 100644 --- a/include/mitsuba/render/common.h +++ b/include/mitsuba/render/common.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Specifies the transported quantity when * sampling or evaluating a scattering function + * \ingroup librender */ enum ETransportQuantity { ERadiance = 1, @@ -34,6 +35,7 @@ enum ETransportQuantity { /** * \brief Specifies the measure associated with * a scattering function + * \ingroup librender */ enum EMeasure { ESolidAngle = 1, diff --git a/include/mitsuba/render/film.h b/include/mitsuba/render/film.h index 59e8cd44..abd9a86c 100644 --- a/include/mitsuba/render/film.h +++ b/include/mitsuba/render/film.h @@ -29,6 +29,7 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract Film base class - used to store samples * generated by the Integrator. + * \ingroup librender */ class MTS_EXPORT_RENDER Film : public ConfigurableObject { public: @@ -82,6 +83,8 @@ public: /// Add a child node virtual void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } /// Configure the film virtual void configure(); diff --git a/include/mitsuba/render/gatherproc.h b/include/mitsuba/render/gatherproc.h index b4e4bd50..45d96ca3 100644 --- a/include/mitsuba/render/gatherproc.h +++ b/include/mitsuba/render/gatherproc.h @@ -25,9 +25,11 @@ MTS_NAMESPACE_BEGIN /** - * Process for parallel photon map construction. Given a number and - * type (surface/caustic/volume) of photons, it distributes the work - * over an arbitrary number of machines. + * \brief Process for parallel photon map construction + * + * Given a number and type (surface/caustic/volume) of photons, this + * class distributes the work over an arbitrary number of machines. + * \ingroup librender */ class MTS_EXPORT_RENDER GatherPhotonProcess : public ParticleProcess { public: diff --git a/include/mitsuba/render/gkdtree.h b/include/mitsuba/render/gkdtree.h index 7454ab06..68839633 100644 --- a/include/mitsuba/render/gkdtree.h +++ b/include/mitsuba/render/gkdtree.h @@ -480,7 +480,7 @@ public: /// Initialize a leaf kd-Tree node inline void initLeafNode(unsigned int offset, unsigned int numPrims) { - leaf.combined = ETypeMask | offset; + leaf.combined = (uint32_t) ETypeMask | offset; leaf.end = offset + numPrims; } @@ -514,17 +514,17 @@ public: /// Is this a leaf node? FINLINE bool isLeaf() const { - return leaf.combined & ETypeMask; + return leaf.combined & (uint32_t) ETypeMask; } /// Is this an indirection node? FINLINE bool isIndirection() const { - return leaf.combined & EIndirectionMask; + return leaf.combined & (uint32_t) EIndirectionMask; } /// Assuming this is a leaf node, return the first primitive index FINLINE index_type getPrimStart() const { - return leaf.combined & ELeafOffsetMask; + return leaf.combined & (uint32_t) ELeafOffsetMask; } /// Assuming this is a leaf node, return the last primitive index @@ -534,13 +534,13 @@ public: /// Return the index of an indirection node FINLINE index_type getIndirectionIndex() const { - return(inner.combined & EInnerOffsetMask) >> 2; + return(inner.combined & (uint32_t) EInnerOffsetMask) >> 2; } /// Return the left child (assuming that this is an interior node) FINLINE const KDNode * __restrict getLeft() const { return this + - ((inner.combined & EInnerOffsetMask) >> 2); + ((inner.combined & (uint32_t) EInnerOffsetMask) >> 2); } /// Return the sibling of the current node @@ -551,7 +551,7 @@ public: /// Return the left child (assuming that this is an interior node) FINLINE KDNode * __restrict getLeft() { return this + - ((inner.combined & EInnerOffsetMask) >> 2); + ((inner.combined & (uint32_t) EInnerOffsetMask) >> 2); } /// Return the left child (assuming that this is an interior node) @@ -569,7 +569,7 @@ public: /// Return the split axis (assuming that this is an interior node) FINLINE int getAxis() const { - return inner.combined & EInnerAxisMask; + return inner.combined & (uint32_t) EInnerAxisMask; } /// Return a string representation @@ -640,6 +640,7 @@ MTS_NAMESPACE_BEGIN * can theoretically support any kind of shape. However, subclasses still * need to provide the following signatures for a functional implementation: * + * \code * /// Return the total number of primitives * inline size_type getPrimitiveCount() const; * @@ -648,6 +649,7 @@ MTS_NAMESPACE_BEGIN * * /// Return the AABB of a primitive when clipped to another AABB * inline AABB getClippedAABB(index_type primIdx, const AABBType &aabb) const; + * \endcode * * This class follows the "Curiously recurring template" design pattern * so that the above functions can be inlined (in particular, no virtual @@ -681,6 +683,7 @@ MTS_NAMESPACE_BEGIN * in parallel. * * \author Wenzel Jakob + * \ingroup librender */ template class GenericKDTree : public KDTreeBase { @@ -920,10 +923,6 @@ protected: KDLog(EError, "The query cost must be > 0"); if (m_emptySpaceBonus <= 0 || m_emptySpaceBonus > 1) KDLog(EError, "The empty space bonus must be in [0, 1]"); - if (m_stopPrims < 0) - KDLog(EError, "The stopping primitive count must be >= 0"); - if (m_exactPrimThreshold < 0) - KDLog(EError, "The exact primitive threshold must be >= 0"); if (m_minMaxBins <= 1) KDLog(EError, "The number of min-max bins must be > 2"); diff --git a/include/mitsuba/render/imageblock.h b/include/mitsuba/render/imageblock.h index 26041d76..557cd3fb 100644 --- a/include/mitsuba/render/imageblock.h +++ b/include/mitsuba/render/imageblock.h @@ -25,6 +25,8 @@ MTS_NAMESPACE_BEGIN /** + * \brief Storage for an image sub-block (a.k.a render bucket) + * * This class is used by image-based parallel processes and encapsulates * the resulting information in a rectangular region of an image. Such * blocks may also include a border storing contributions that are slightly @@ -34,6 +36,8 @@ MTS_NAMESPACE_BEGIN * This is important to avoid bias when using large-extent reconstruction * filters, while at the same time placing significantly different amounts * of samples into nearby pixels. + * + * \ingroup librender */ class MTS_EXPORT_RENDER ImageBlock : public WorkResult { public: diff --git a/include/mitsuba/render/imageproc.h b/include/mitsuba/render/imageproc.h index b17aed3a..33b77706 100644 --- a/include/mitsuba/render/imageproc.h +++ b/include/mitsuba/render/imageproc.h @@ -28,6 +28,8 @@ MTS_NAMESPACE_BEGIN * the subclass) on the pixels of an image where work on adjacent pixels * is independent. For preview purposes, a spiraling pattern of square * pixel blocks is generated. + * + * \ingroup librender */ class MTS_EXPORT_RENDER BlockedImageProcess : public ParallelProcess { public: diff --git a/include/mitsuba/render/integrator.h b/include/mitsuba/render/integrator.h index 7a7a48e0..88c168c4 100644 --- a/include/mitsuba/render/integrator.h +++ b/include/mitsuba/render/integrator.h @@ -33,6 +33,8 @@ MTS_NAMESPACE_BEGIN * rasterization that directly operates on the camera's film and has * no global knowledge about radiance within the scene. Other possibilities * are sampling- or particle tracing-based integrators. + * + * \ingroup librender */ class MTS_EXPORT_RENDER Integrator : public NetworkedObject { public: @@ -109,6 +111,7 @@ protected: /** * \brief Radiance query record data structure used by \ref SampleIntegrator + * \ingroup librender */ struct MTS_EXPORT_RENDER RadianceQueryRecord { public: @@ -278,6 +281,7 @@ public: /** \brief Abstract base class, which describes integrators * capable of computing samples of the scene's radiance function. + * \ingroup librender */ class MTS_EXPORT_RENDER SampleIntegrator : public Integrator { public: @@ -402,6 +406,7 @@ protected: * \brief Base class of all recursive Monte Carlo integrators, which compute * unbiased solutions to the rendering equation (and optionally * the radiative transfer equation). + * \ingroup librender */ class MTS_EXPORT_RENDER MonteCarloIntegrator : public SampleIntegrator { public: diff --git a/include/mitsuba/render/irrcache.h b/include/mitsuba/render/irrcache.h index 69311cd0..3bfdb69d 100644 --- a/include/mitsuba/render/irrcache.h +++ b/include/mitsuba/render/irrcache.h @@ -38,6 +38,7 @@ typedef Spectrum TranslationalGradient[3]; * (Proceedings of SCCG 2005) * * \author Wenzel Jakob + * \ingroup librender */ class MTS_EXPORT_RENDER HemisphereSampler : public Object { public: @@ -140,6 +141,7 @@ private: * by E. Tabellion and A. Lamorlette (SIGGRAPH 2004) * * \author Wenzel Jakob + * \ingroup librender */ class MTS_EXPORT_RENDER IrradianceCache : public SerializableObject { public: diff --git a/include/mitsuba/render/luminaire.h b/include/mitsuba/render/luminaire.h index c59a9027..d1548743 100644 --- a/include/mitsuba/render/luminaire.h +++ b/include/mitsuba/render/luminaire.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Data structure used by the direct illumination / shadow ray * sampling methods in the class \ref Luminaire. + * \ingroup librender */ struct MTS_EXPORT_RENDER LuminaireSamplingRecord { public: @@ -66,6 +67,7 @@ public: /** * \brief Data structure used to record information associated with * emission sampling in the class \ref Luminaire. + * \ingroup librender */ struct MTS_EXPORT_RENDER EmissionRecord { public: @@ -119,6 +121,7 @@ public: /** * \brief Abstract implementation of a luminaire. Supports emission and * direct illumination sampling strategies, and computes related probabilities. + * \ingroup librender */ class MTS_EXPORT_RENDER Luminaire : public ConfigurableObject, public HWResource { public: @@ -362,6 +365,8 @@ public: /// Add a child (e.g. a medium reference) to this luminaire void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } //! @} // ============================================================= diff --git a/include/mitsuba/render/medium.h b/include/mitsuba/render/medium.h index 5e7f0540..f5bd122b 100644 --- a/include/mitsuba/render/medium.h +++ b/include/mitsuba/render/medium.h @@ -28,6 +28,7 @@ MTS_NAMESPACE_BEGIN * integral of the RTE * * \sa Medium::sampleDistance() + * \ingroup librender */ struct MTS_EXPORT_RENDER MediumSamplingRecord { public: @@ -89,6 +90,7 @@ public: }; /** \brief Abstract participating medium + * \ingroup librender */ class MTS_EXPORT_RENDER Medium : public NetworkedObject { public: @@ -172,6 +174,8 @@ public: /// Add a child ConfigurableObject virtual void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } /// Return a string representation virtual std::string toString() const = 0; diff --git a/include/mitsuba/render/mipmap.h b/include/mitsuba/render/mipmap.h index 077f3ac7..a939e7a5 100644 --- a/include/mitsuba/render/mipmap.h +++ b/include/mitsuba/render/mipmap.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN #define MIPMAP_LUTSIZE 128 /** \brief Isotropic/anisotropic EWA mip-map texture map class based on PBRT + * \ingroup librender */ class MTS_EXPORT_RENDER MIPMap : public Object { public: diff --git a/include/mitsuba/render/mipmap3d.h b/include/mitsuba/render/mipmap3d.h index e2950994..cda464e6 100644 --- a/include/mitsuba/render/mipmap3d.h +++ b/include/mitsuba/render/mipmap3d.h @@ -25,7 +25,8 @@ MTS_NAMESPACE_BEGIN /** - * Sparse mipmap data structure based on an adaptive octree representation + * \brief Sparse mipmap data structure based on an adaptive octree representation + * \ingroup librender */ class MTS_EXPORT_RENDER SparseMipmap3D : public SerializableObject { public: diff --git a/include/mitsuba/render/noise.h b/include/mitsuba/render/noise.h index 2573e755..1b346272 100644 --- a/include/mitsuba/render/noise.h +++ b/include/mitsuba/render/noise.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN * \brief Contains a few useful noise functions * * The implementations in this class are based on PBRT + * \ingroup librender */ class MTS_EXPORT_RENDER Noise { public: diff --git a/include/mitsuba/render/particleproc.h b/include/mitsuba/render/particleproc.h index 7f4760ea..107252c1 100644 --- a/include/mitsuba/render/particleproc.h +++ b/include/mitsuba/render/particleproc.h @@ -38,6 +38,8 @@ MTS_NAMESPACE_BEGIN * of \ref ParticleTracer with overridden functions * \ref ParticleTracer::handleSurfaceInteraction and * \ref ParticleTracer::handleMediumInteraction. + * + * \ingroup librender */ class MTS_EXPORT_RENDER ParticleProcess : public ParallelProcess { public: @@ -119,6 +121,8 @@ protected: * * Traces particles and performs a customizable action every time a * surface or volume interaction occurs. + * + * \ingroup librender */ class MTS_EXPORT_RENDER ParticleTracer : public WorkProcessor { public: diff --git a/include/mitsuba/render/phase.h b/include/mitsuba/render/phase.h index 754ecd2d..35ff4455 100644 --- a/include/mitsuba/render/phase.h +++ b/include/mitsuba/render/phase.h @@ -27,6 +27,8 @@ MTS_NAMESPACE_BEGIN /** * \brief Data structure, which contains information * required to sample or query a phase function. + * + * \ingroup librender */ struct MTS_EXPORT_RENDER PhaseFunctionQueryRecord { /** @@ -97,6 +99,7 @@ struct MTS_EXPORT_RENDER PhaseFunctionQueryRecord { }; /** \brief Abstract phase function. + * \ingroup librender */ class MTS_EXPORT_RENDER PhaseFunction : public ConfigurableObject { public: diff --git a/include/mitsuba/render/photon.h b/include/mitsuba/render/photon.h index f3e877d4..36d65d98 100644 --- a/include/mitsuba/render/photon.h +++ b/include/mitsuba/render/photon.h @@ -28,6 +28,8 @@ MTS_NAMESPACE_BEGIN * * Requires 24 bytes when Mitsuba is compiled with single precision * and RGB-based color spectra. + * + * \ingroup librender */ struct MTS_EXPORT_RENDER Photon { friend class PhotonMap; diff --git a/include/mitsuba/render/photonmap.h b/include/mitsuba/render/photonmap.h index cb159f9b..a16e4ab2 100644 --- a/include/mitsuba/render/photonmap.h +++ b/include/mitsuba/render/photonmap.h @@ -39,6 +39,7 @@ MTS_NAMESPACE_BEGIN * estimate. The bug has been fixed in this re-implementation. * * \author Wenzel Jakob + * \ingroup librender */ class MTS_EXPORT_RENDER PhotonMap : public SerializableObject { public: diff --git a/include/mitsuba/render/preview.h b/include/mitsuba/render/preview.h index 579cb9eb..53d0e9f0 100644 --- a/include/mitsuba/render/preview.h +++ b/include/mitsuba/render/preview.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN * Preview worker - can be used to render a quick preview of a scene * (illuminated by a VPL). The implementation uses coherent ray tracing * when compiled in single precision and SSE is available. + * \ingroup librender */ class MTS_EXPORT_RENDER PreviewWorker : public WorkProcessor { public: diff --git a/include/mitsuba/render/range.h b/include/mitsuba/render/range.h index 826023e6..4fa98fa1 100644 --- a/include/mitsuba/render/range.h +++ b/include/mitsuba/render/range.h @@ -28,6 +28,8 @@ MTS_NAMESPACE_BEGIN * * An example usage is in \ref ParticleProcess, where this class specifies * sequences of particles to be traced. + * + * \ingroup librender */ class MTS_EXPORT_RENDER RangeWorkUnit : public WorkUnit { public: diff --git a/include/mitsuba/render/rectwu.h b/include/mitsuba/render/rectwu.h index fa2ee5f5..4acb086f 100644 --- a/include/mitsuba/render/rectwu.h +++ b/include/mitsuba/render/rectwu.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN * \brief Work unit that specifies a rectangular region in an image. * * Used for instance in \ref BlockedImageProcess + * \ingroup librender */ class MTS_EXPORT_RENDER RectangularWorkUnit : public WorkUnit { public: diff --git a/include/mitsuba/render/renderjob.h b/include/mitsuba/render/renderjob.h index 0b219a64..89cc66e9 100644 --- a/include/mitsuba/render/renderjob.h +++ b/include/mitsuba/render/renderjob.h @@ -26,29 +26,54 @@ MTS_NAMESPACE_BEGIN /** - * Render job - coordinates the process of rendering a single - * image. Implemented as a thread so that multiple jobs can + * \brief Coordinates the process of rendering a single image. + * + * Implemented as a thread so that multiple jobs can * be executed concurrently. + * + * \ingroup librender + * \ingroup libpython */ class MTS_EXPORT_RENDER RenderJob : public Thread { public: /** - * Create a new render job for the given scene. When the - * scene, sampler or camera are already registered with the scheduler, - * the last parameters can optionally be specified (that way - * they do not have to be re-sent to network rendering servers). + * \brief Create a new render job for the given scene. + * + * When the Resource ID parameters (\c sceneResID, \c cameraResID, ..) are + * set to \c -1, the implementation will automatically register the + * associated objects (scene, camera, sampler) with the scheduler and + * forward copies to all involved network rendering workers. When some + * of these resources have already been registered with + * the scheduler, their IDs can be provided to avoid this extra + * communication cost. + * + * \param threadName + * Thread name identifier for this render job + * \param scene + * Scene to be rendered + * \param queue + * Pointer to a queue, to which this job should be added + * \param sceneResID + * Resource ID of \c scene (or \c -1) + * \param cameraResID + * Resource ID of \c scene->getCamera() (or \c -1) + * \param samplerResID + * Resource ID of the sample generator (or \c -1) + * \param threadIsCritical + * When set to \c true, the entire program will terminate + * if this thread fails unexpectedly. + * \param testSupervisor + * When this image is being rendered as part of a test suite, + * this parameter points to the associated \ref TestSupervisor + * instance. */ RenderJob(const std::string &threadName, Scene *scene, RenderQueue *queue, - TestSupervisor *testSupervisor, int sceneResID = -1, int cameraResID = -1, int samplerResID = -1, bool threadIsCritical = true, - bool visualFeedback = false); - - /// Should visual feedback be provided (true when rendering using the GUI) - inline bool hasVisualFeedback() const { return m_visualFeedback; } + TestSupervisor *testSupervisor = NULL); /// Write out the current (partially rendered) image inline void flush() { m_scene->flush(); } @@ -73,7 +98,6 @@ private: bool m_ownsSceneResource; bool m_ownsCameraResource; bool m_ownsSamplerResource; - bool m_visualFeedback; bool m_cancelled; }; diff --git a/include/mitsuba/render/renderproc.h b/include/mitsuba/render/renderproc.h index ecc74892..ba0c6e63 100644 --- a/include/mitsuba/render/renderproc.h +++ b/include/mitsuba/render/renderproc.h @@ -32,6 +32,7 @@ MTS_NAMESPACE_BEGIN * then rendered in parallel. * * \sa SampleIntegrator + * \ingroup librender */ class MTS_EXPORT_RENDER BlockedRenderProcess : public BlockedImageProcess { public: diff --git a/include/mitsuba/render/renderqueue.h b/include/mitsuba/render/renderqueue.h index a2dcaf27..ab1d16bc 100644 --- a/include/mitsuba/render/renderqueue.h +++ b/include/mitsuba/render/renderqueue.h @@ -27,6 +27,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Abstract render listener - can be used to react to * progress messages (e.g. in a GUI) + * \ingroup librender */ class MTS_EXPORT_RENDER RenderListener : public Object { public: @@ -52,9 +53,13 @@ protected: }; /** - * Render queue - used to keep track of a number of scenes - * that are simultaneously being rendered. Also distributes - * events regarding these scenes to registered listeners. + * \brief Render queue - used to keep track of a number of scenes + * that are simultaneously being rendered. + * + * This class is also responsible for distributing events about + * in-progress renderings to registered listeners. + * + * \ingroup librender */ class MTS_EXPORT_RENDER RenderQueue : public Object { public: diff --git a/include/mitsuba/render/rfilter.h b/include/mitsuba/render/rfilter.h index 32b9f183..cd6adf85 100644 --- a/include/mitsuba/render/rfilter.h +++ b/include/mitsuba/render/rfilter.h @@ -25,7 +25,8 @@ MTS_NAMESPACE_BEGIN /** - * Abstract image reconstruction filter + * \brief Abstract image reconstruction filter + * \ingroup librender */ class MTS_EXPORT_RENDER ReconstructionFilter : public ConfigurableObject { public: @@ -58,11 +59,16 @@ protected: Properties m_properties; }; -/** - * Tabulates expensive-to-evaluate filters so that they become - * simple array lookups. Only works for symmetric filters! - */ +/// Filter resolution for \ref TabulatedFilter #define FILTER_RESOLUTION 15 + +/** + * \brief Tabulates expensive-to-evaluate filters so that they become + * simple array lookups. + * + * Only works for symmetric filters! + * \ingroup librender + */ class TabulatedFilter : public Object { public: /// Tabulate a reconstruction filter diff --git a/include/mitsuba/render/sahkdtree3.h b/include/mitsuba/render/sahkdtree3.h index 8390b330..7b473fef 100644 --- a/include/mitsuba/render/sahkdtree3.h +++ b/include/mitsuba/render/sahkdtree3.h @@ -31,6 +31,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Implements the surface area heuristic for use * by the \ref GenericKDTree construction algorithm. + * \ingroup librender */ class SurfaceAreaHeuristic { public: @@ -79,21 +80,24 @@ private: }; /** - * This class specializes \ref GenericKDTree to a three-dimensional - * tree to be used for ray tracing. One additional function call - * must be implemented by subclasses: + * \brief Specializes \ref GenericKDTree to a three-dimensional + * tree to be used for ray tracing. * + * One additional function call must be implemented by subclasses: + * \code * /// Check whether a primitive is intersected by the given ray. * /// Some temporary space is supplied, which can be used to cache * /// information about the intersection * bool intersect(const Ray &ray, index_type idx, * Float mint, Float maxt, Float &t, void *tmp); + * \endcode * * This class implements an epsilon-free version of the optimized ray * traversal algorithm (TA^B_{rec}), which is explained in Vlastimil * Havran's PhD thesis "Heuristic Ray Shooting Algorithms". * * \author Wenzel Jakob + * \ingroup librender */ template class SAHKDTree3D : public GenericKDTree { diff --git a/include/mitsuba/render/sampler.h b/include/mitsuba/render/sampler.h index 7e4c62ae..3ef80228 100644 --- a/include/mitsuba/render/sampler.h +++ b/include/mitsuba/render/sampler.h @@ -58,6 +58,8 @@ MTS_NAMESPACE_BEGIN * stratify over all of the rays that are ultimately generated, and the * \ref next1DArray() and \ref next2DArray() methods allow to do this. * See the file \c direct.cpp for an example. + * + * \ingroup librender */ class MTS_EXPORT_RENDER Sampler : public ConfigurableObject { public: diff --git a/include/mitsuba/render/scene.h b/include/mitsuba/render/scene.h index ac24ac3b..cf4587ad 100644 --- a/include/mitsuba/render/scene.h +++ b/include/mitsuba/render/scene.h @@ -39,9 +39,12 @@ MTS_NAMESPACE_BEGIN /** * \brief Principal scene data structure * - * Holds information on surfaces, luminaires and participating media and - * coordinates rendering jobs. This class also provides useful query routines - * that are mostly used by the \ref Integrator implementations. + * This class holds information on surfaces, luminaires and participating media + * and coordinates rendering jobs. It also provides useful query routines that + * are mostly used by the \ref Integrator implementations. + * + * \ingroup librender + * \ingroup libpython */ class MTS_EXPORT_RENDER Scene : public NetworkedObject { public: @@ -63,6 +66,9 @@ public: // ============================================================= //! @{ \name Initialization and rendering // ============================================================= + + /// Construct a new, empty scene (with the default properties) + Scene(); /// Construct a new, empty scene Scene(const Properties &props); @@ -84,7 +90,7 @@ public: * before rendering the scene. This might do a variety of things, * such as constructing photon maps or executing distributed overture * passes. Progress is tracked by sending status messages to a provided - * render queue. The parameter job is required to discern + * render queue. The parameter \c job is required to discern * multiple render jobs occurring in parallel. The last three parameters * are resource IDs of the associated scene, camera and sample generator, * which have been made available to all local and remote workers. @@ -96,14 +102,14 @@ public: /** * Render the scene as seen by the scene's main camera. Progress is tracked * by sending status messages to a provided render queue. The parameter - * job is required to discern multiple render jobs occurring in + * \c job is required to discern multiple render jobs occurring in * parallel. The last three parameters are resource IDs of the associated * scene, camera and sample generator, which have been made available to * all local and remote workers. Returns true upon successful completion. */ bool render(RenderQueue *queue, const RenderJob *job, int sceneResID, int cameraResID, int samplerResID); - + /// Post-process step after rendering. Parameters are explained above void postprocess(RenderQueue *queue, const RenderJob *job, int sceneResID, int cameraResID, int samplerResID); @@ -123,6 +129,9 @@ public: /// Add a child node to the scene void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } + /** \brief Configure this object (called _once_ after construction and addition of all child ConfigurableObjects.) */ void configure(); @@ -424,12 +433,14 @@ public: inline Float getTestThreshold() const { return m_testThresh; } /** - * Set the scene's camera. Note that the camera is not included - * when this Scene instance is serialized -- the camera field - * will be NULL after unserialization. This is intentional - * so that the camera can be changed without having to re-transmit - * the whole scene. Hence, the camera needs to be submitted separately - * and re-attached on the remote side using setCamera. + * \brief Set the scene's camera. + * + * Note that the camera is not included when this Scene instance + * is serialized -- the camera field will be \c NULL after + * unserialization. This is intentional so that the camera can + * be changed without having to re-transmit the whole scene. + * Hence, the camera needs to be submitted separately + * and re-attached on the remote side using \ref setCamera(). **/ inline void setCamera(Camera *camera) { m_camera = camera; } /// Return the scene's camera @@ -438,12 +449,14 @@ public: inline const Camera *getCamera() const { return m_camera.get(); } /** - * Set the scene's integrator. Note that the integrator is not included - * when this Scene instance is serialized -- the integrator field - * will be NULL after unserialization. This is intentional - * so that the integrator can be changed without having to re-transmit - * the whole scene. Hence, the integrator needs to be submitted separately - * and re-attached on the remote side using setIntegrator. + * \brief Set the scene's integrator. + * + * Note that the integrator is not included when this Scene instance + * is serialized -- the integrator field will be \c NULL after + * unserialization. This is intentional so that the integrator can + * be changed without having to re-transmit the whole scene. Hence, + * the integrator needs to be submitted separately and re-attached + * on the remote side using \ref setIntegrator(). **/ inline void setIntegrator(Integrator *integrator) { m_integrator = integrator; } /// Return the scene's integrator @@ -452,22 +465,26 @@ public: inline const Integrator *getIntegrator() const { return m_integrator.get(); } /** - * Set the scene's sampler. Note that the sampler is not included - * when this Scene instance is serialized -- the sampler field - * will be NULL after unserialization. This is intentional - * so that the sampler can be changed without having to re-transmit - * the whole scene. Hence, the sampler needs to be submitted separately - * and re-attached on the remote side using setSampler. + * \brief Set the scene's sampler. + * + * Note that the sampler is not included when this Scene instance + * is serialized -- the sampler field will be \c NULL after + * unserialization. This is intentional so that the sampler can + * be changed without having to re-transmit the whole scene. + * Hence, the sampler needs to be submitted separately + * and re-attached on the remote side using \ref setSampler(). **/ inline void setSampler(Sampler *sampler) { m_sampler = sampler; } /** - * Return the scene's sampler. Note that when rendering using multiple - * different threads, each thread will be passed a shallow copy of the - * scene, which has a different sampler instance. This helps to avoid - * locking/contention issues and ensures that different threads render - * with different random number sequences. The sampler instance provided - * here is a clone of the original sampler specified in the camera. + * \brief Return the scene's sampler. + * + * Note that when rendering using multiple different threads, each + * thread will be passed a shallow copy of the scene, which has a + * different sampler instance. This helps to avoid locking/contention + * issues and ensures that different threads render with different + * random number sequences. The sampler instance provided here is a + * clone of the original sampler specified in the camera. */ inline Sampler *getSampler() { return m_sampler; } /// Return the scene's sampler diff --git a/include/mitsuba/render/scenehandler.h b/include/mitsuba/render/scenehandler.h index 986fbfce..36b6fedd 100644 --- a/include/mitsuba/render/scenehandler.h +++ b/include/mitsuba/render/scenehandler.h @@ -34,7 +34,10 @@ XERCES_CPP_NAMESPACE_END XERCES_CPP_NAMESPACE_USE MTS_NAMESPACE_BEGIN -/// \brief This exception is thrown when attempting to load an outdated file +/** + * \brief This exception is thrown when attempting to load an outdated file + * \ingroup librender + */ class VersionException : public std::runtime_error { public: inline VersionException(const std::string &str, const Version &version) @@ -47,7 +50,12 @@ private: /** * \brief XML parser for Mitsuba scene files. To be used with the - * SAX interface Xerces-C++. + * SAX interface of Xerces-C++. + * + * \remark In the Python bindings, only the static function + * \ref loadScene() is exposed. + * \ingroup librender + * \ingroup libpython */ class MTS_EXPORT_RENDER SceneHandler : public HandlerBase { public: @@ -58,6 +66,16 @@ public: NamedObjectMap *objects = NULL, bool isIncludedFile = false); virtual ~SceneHandler(); + /// Convenience method -- load a scene from a given filename + static ref loadScene(const fs::path &filename, + const ParameterMap ¶ms= ParameterMap()); + + /// Initialize Xerces-C++ (needs to be called once at program startup) + static void staticInitialization(); + + /// Free the memory taken up by staticInitialization() + static void staticShutdown(); + // ----------------------------------------------------------------------- // Implementation of the SAX DocumentHandler interface // ----------------------------------------------------------------------- diff --git a/include/mitsuba/render/shader.h b/include/mitsuba/render/shader.h index c92b272a..46936f20 100644 --- a/include/mitsuba/render/shader.h +++ b/include/mitsuba/render/shader.h @@ -47,6 +47,8 @@ public: * * Subclasses can implement one of various things, such as a BSDF, * a light source, or a texture. + * + * \ingroup librender */ class MTS_EXPORT_RENDER Shader : public Object { public: diff --git a/include/mitsuba/render/shape.h b/include/mitsuba/render/shape.h index bd4c7d0d..d4e5c33e 100644 --- a/include/mitsuba/render/shape.h +++ b/include/mitsuba/render/shape.h @@ -28,6 +28,7 @@ MTS_NAMESPACE_BEGIN /** \brief Data record, which holds sampling-related information * for a shape. + * \ingroup librender */ struct MTS_EXPORT_RENDER ShapeSamplingRecord { public: @@ -53,6 +54,7 @@ public: /** \brief Container for all information related to * a surface intersection + * \ingroup librender */ struct MTS_EXPORT_RENDER Intersection { public: @@ -173,6 +175,7 @@ public: }; /** \brief Abstract base class of all shapes + * \ingroup librender */ class MTS_EXPORT_RENDER Shape : public ConfigurableObject { public: @@ -364,6 +367,8 @@ public: /// Add a child (e.g. a luminaire/sub surface integrator) to this shape void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } //! @} // ============================================================= diff --git a/include/mitsuba/render/skdtree.h b/include/mitsuba/render/skdtree.h index bdc35105..515a7807 100644 --- a/include/mitsuba/render/skdtree.h +++ b/include/mitsuba/render/skdtree.h @@ -62,6 +62,7 @@ typedef const Shape * ConstShapePtr; * tends to be quite a bit slower. * * \sa GenericKDTree + * \ingroup librender */ class MTS_EXPORT_RENDER ShapeKDTree : public SAHKDTree3D { diff --git a/include/mitsuba/render/spiral.h b/include/mitsuba/render/spiral.h index 7e8c924d..a8d3de5e 100644 --- a/include/mitsuba/render/spiral.h +++ b/include/mitsuba/render/spiral.h @@ -26,7 +26,10 @@ MTS_NAMESPACE_BEGIN -/// Block listener callback for use with the Spiral class +/** + * \brief Block listener callback for use with the \ref Spiral class + * \ingroup librender + */ class MTS_EXPORT_RENDER BlockListener { public: /// Called whenever an image block is acquired @@ -52,7 +55,8 @@ protected: * Aug 25, 2005 * RayTracer.java * Copyright 2005 Program of Computer Graphics, Cornell University - */ + * \ingroup librender + */ class MTS_EXPORT_RENDER Spiral : public Object { public: diff --git a/include/mitsuba/render/subsurface.h b/include/mitsuba/render/subsurface.h index 9b0b924d..20873241 100644 --- a/include/mitsuba/render/subsurface.h +++ b/include/mitsuba/render/subsurface.h @@ -31,6 +31,8 @@ MTS_NAMESPACE_BEGIN * completely up to the implementation. It might for instance * recursively trace rays or perform lookups into a precomputed * point cloud radiance representation. + * + * \ingroup librender */ class MTS_EXPORT_RENDER Subsurface : public NetworkedObject { public: diff --git a/include/mitsuba/render/testcase.h b/include/mitsuba/render/testcase.h index 7b2aba15..0082a648 100644 --- a/include/mitsuba/render/testcase.h +++ b/include/mitsuba/render/testcase.h @@ -40,6 +40,7 @@ MTS_NAMESPACE_BEGIN * declared using the MTS_DECLARE_TEST() macro are executed. Finally, * the shutdown() method is called. See the files in 'mitsuba/src/tests' * for examples. + * \ingroup librender */ class MTS_EXPORT_RENDER TestCase : public Utility { public: @@ -123,6 +124,7 @@ protected: * the actual generated results and a user-specified type of test is executed * to decide between equality or inequality. Any problems are kept in a log, * which can later be printed using printSummary(). + * \ingroup librender */ class MTS_EXPORT_RENDER TestSupervisor : public Object { public: diff --git a/include/mitsuba/render/texture.h b/include/mitsuba/render/texture.h index a2a7e519..bcd59d79 100644 --- a/include/mitsuba/render/texture.h +++ b/include/mitsuba/render/texture.h @@ -28,6 +28,7 @@ MTS_NAMESPACE_BEGIN /** * \brief Base class of all textures. Computes values for an arbitrary surface * point. \ref Texture2D is a specialization to UV-based textures. + * \ingroup librender */ class MTS_EXPORT_RENDER Texture : public ConfigurableObject, public HWResource { public: @@ -63,6 +64,10 @@ protected: virtual ~Texture(); }; +/** + * \brief Base class of all 2D textures + * \ingroup librender + */ class MTS_EXPORT_RENDER Texture2D : public Texture { public: /// Return the texture value at \a its diff --git a/include/mitsuba/render/track.h b/include/mitsuba/render/track.h index 17fa5209..f14233b1 100644 --- a/include/mitsuba/render/track.h +++ b/include/mitsuba/render/track.h @@ -25,7 +25,10 @@ MTS_NAMESPACE_BEGIN template class AnimationTrack; -/// Base class of animation tracks +/** + * \brief Base class of animation tracks + * \ingroup librender + */ class MTS_EXPORT_RENDER AbstractAnimationTrack : public Object { template friend class AnimationTrack; public: @@ -63,7 +66,10 @@ protected: std::vector m_times; }; -/// Parameterizable animation track +/** + * \brief Parameterizable animation track + * \ingroup librender + */ template class AnimationTrack : public AbstractAnimationTrack { public: typedef T value_type; @@ -155,7 +161,10 @@ template<> void AnimationTrack::serialize(Stream *stream, const Quat value.serialize(stream); } -/// Animated transformation with an underlying keyframe representation +/** + * \brief Animated transformation with an underlying keyframe representation + * \ingroup librender + */ class MTS_EXPORT_RENDER AnimatedTransform : public Object { public: /// Create a new animated transform diff --git a/include/mitsuba/render/triaccel.h b/include/mitsuba/render/triaccel.h index 97fb076b..89151f51 100644 --- a/include/mitsuba/render/triaccel.h +++ b/include/mitsuba/render/triaccel.h @@ -30,6 +30,7 @@ static const uint32_t KNoTriangleFlag = 0xFFFFFFFF; * Pre-computed triangle representation using Ingo Wald's TriAccel layout. * Fits into three 16-byte cache lines if single precision floats are used. * The k parameter is also used for classification during kd-tree construction. + * \ingroup librender */ struct TriAccel { uint32_t k; diff --git a/include/mitsuba/render/trimesh.h b/include/mitsuba/render/trimesh.h index a61cc41d..44f8d655 100644 --- a/include/mitsuba/render/trimesh.h +++ b/include/mitsuba/render/trimesh.h @@ -28,6 +28,10 @@ namespace fs = boost::filesystem; MTS_NAMESPACE_BEGIN +/** + * \brief Simple tangent space storage for surfaces + * \ingroup librender + */ struct TangentSpace { /// Position partials wrt. the UV parameterization Vector dpdu; @@ -45,6 +49,7 @@ struct TangentSpace { }; /** \brief Abstract triangle mesh base class + * \ingroup librender */ class MTS_EXPORT_RENDER TriMesh : public Shape { public: diff --git a/include/mitsuba/render/util.h b/include/mitsuba/render/util.h index 31170fe9..8b0a1b18 100644 --- a/include/mitsuba/render/util.h +++ b/include/mitsuba/render/util.h @@ -26,6 +26,7 @@ MTS_NAMESPACE_BEGIN /** \brief Abstract utility class -- can be used to implement * loadable utility plugins that perform various actions. They * can be started using the 'mtsutil' launcher. + * \ingroup librender */ class MTS_EXPORT_RENDER Utility : public Object { public: diff --git a/include/mitsuba/render/volume.h b/include/mitsuba/render/volume.h index 2d2f917b..6c46dce0 100644 --- a/include/mitsuba/render/volume.h +++ b/include/mitsuba/render/volume.h @@ -25,7 +25,8 @@ MTS_NAMESPACE_BEGIN /** - * Generalized source of volumetric information + * \brief Generalized source of volumetric information + * \ingroup librender */ class MTS_EXPORT_RENDER VolumeDataSource : public ConfigurableObject { public: diff --git a/include/mitsuba/render/vpl.h b/include/mitsuba/render/vpl.h index d9f58017..43aaca2e 100644 --- a/include/mitsuba/render/vpl.h +++ b/include/mitsuba/render/vpl.h @@ -31,6 +31,7 @@ enum EVPLType { /** * Support routines for rendering algorithms based on VPLs (virtual * point lights) + * \ingroup librender */ struct VPL { inline VPL(EVPLType type, const Spectrum &P) diff --git a/src/bsdfs/SConscript b/src/bsdfs/SConscript index 147283db..75587c59 100644 --- a/src/bsdfs/SConscript +++ b/src/bsdfs/SConscript @@ -20,10 +20,15 @@ plugins += env.SharedLibrary('bump', ['bump.cpp']) # Other materials plugins += env.SharedLibrary('ward', ['ward.cpp']) plugins += env.SharedLibrary('phong', ['phong.cpp']) -plugins += env.SharedLibrary('irawan', ['irawan.cpp']) plugins += env.SharedLibrary('difftrans', ['difftrans.cpp']) plugins += env.SharedLibrary('hk', ['hk.cpp']) plugins += env.SharedLibrary('dipolebrdf', ['dipolebrdf.cpp']) plugins += env.SharedLibrary('sssbrdf', ['sssbrdf.cpp']) +# The Irawan-Marschner plugin uses a Boost::Spirit parser, which makes it +# pretty heavy stuff to compile. Go easy on the compiler flags: +irawanEnv = env.Clone() +irawanEnv.RelaxCompilerSettings() +plugins += irawanEnv.SharedLibrary('irawan', ['irawan.cpp']) + Export('plugins') diff --git a/src/bsdfs/dipolebrdf.cpp b/src/bsdfs/dipolebrdf.cpp index f8ace01a..4734615f 100644 --- a/src/bsdfs/dipolebrdf.cpp +++ b/src/bsdfs/dipolebrdf.cpp @@ -122,7 +122,6 @@ public: Spectrum getDiffuseReflectance(const Intersection &its) const { Spectrum sigmaA = m_sigmaA->getValue(its), sigmaS = m_sigmaS->getValue(its), - sigmaT = sigmaA + sigmaS, reducedAlbedo; /* ==================================================================== */ diff --git a/src/bsdfs/microfacet.h b/src/bsdfs/microfacet.h index e1d159d8..47fad885 100644 --- a/src/bsdfs/microfacet.h +++ b/src/bsdfs/microfacet.h @@ -379,7 +379,8 @@ public: ); } break; - default: + default: + pdf = 0; SLog(EError, "Invalid distribution function!"); } diff --git a/src/bsdfs/roughplastic.cpp b/src/bsdfs/roughplastic.cpp index a6a960a6..64a51b25 100644 --- a/src/bsdfs/roughplastic.cpp +++ b/src/bsdfs/roughplastic.cpp @@ -317,7 +317,7 @@ public: bool choseSpecular = hasSpecular; Point2 sample(_sample); - Float probSpecular, probDiffuse; + Float probSpecular; if (hasSpecular && hasDiffuse) { /* Find the probability of sampling the diffuse component */ probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi)); @@ -327,8 +327,6 @@ public: (probSpecular*m_specularSamplingWeight + (1-probSpecular) * (1-m_specularSamplingWeight)); - probDiffuse = 1 - probSpecular; - if (sample.x <= probSpecular) { sample.x /= probSpecular; } else { diff --git a/src/bsdfs/sssbrdf.cpp b/src/bsdfs/sssbrdf.cpp index afe41f95..501f5217 100644 --- a/src/bsdfs/sssbrdf.cpp +++ b/src/bsdfs/sssbrdf.cpp @@ -88,7 +88,7 @@ public: hkProps.setFloat("thickness", std::numeric_limits::infinity()); m_hk = static_cast (PluginManager::getInstance()-> createObject(MTS_CLASS(BSDF), hkProps)); - m_hk->addChild("", hg); + m_hk->addChild(hg); Properties coatingProps(props); coatingProps.setPluginName("coating"); @@ -130,10 +130,10 @@ public: m_configured = true; m_hk->configure(); m_dipole->configure(); - m_mixture->addChild("", m_hk); - m_mixture->addChild("", m_dipole); + m_mixture->addChild(m_hk); + m_mixture->addChild(m_dipole); m_mixture->configure(); - m_coating->addChild("", m_mixture); + m_coating->addChild(m_mixture); m_coating->configure(); m_components.clear(); diff --git a/src/converter/mtsimport.cpp b/src/converter/mtsimport.cpp index c3fce045..efc3f2d2 100644 --- a/src/converter/mtsimport.cpp +++ b/src/converter/mtsimport.cpp @@ -153,7 +153,7 @@ int colladaMain(int argc, char **argv) { return 0; } -int ubi_main(int argc, char **argv) { +int mts_main(int argc, char **argv) { int retval; /* Initialize Xerces-C */ @@ -234,7 +234,7 @@ int ubi_main(int argc, char **argv) { #if !defined(__OSX__) int main(int argc, char **argv) { - return ubi_main(argc, argv); + return mts_main(argc, argv); } #endif diff --git a/src/libbidir/SConscript b/src/libbidir/SConscript index 1e374621..916daed2 100644 --- a/src/libbidir/SConscript +++ b/src/libbidir/SConscript @@ -6,7 +6,7 @@ bidirEnv.Append(CPPDEFINES = [['MTS_BUILD_MODULE', 'MTS_MODULE_BIDIR']] ) libbidir = bidirEnv.SharedLibrary('mitsuba-bidir', ['rsampler.cpp']) if sys.platform == "darwin": - bidirEnv.AddPostAction(libbidir, 'install_name_tool -id @executable_path/../Frameworks/libmitsuba-bidir.dylib $TARGET') + bidirEnv.AddPostAction(libbidir, 'install_name_tool -id @loader_path/../Frameworks/libmitsuba-bidir.dylib $TARGET') env.Append(LIBS=['mitsuba-bidir']) env.Append(LIBPATH=[os.path.join(env['BUILDDIR'], 'libbidir')]) diff --git a/src/libbidir/rsampler.cpp b/src/libbidir/rsampler.cpp index 56567b4d..afc43c21 100644 --- a/src/libbidir/rsampler.cpp +++ b/src/libbidir/rsampler.cpp @@ -65,7 +65,7 @@ void ReplayableSampler::request2DArray(unsigned int size) { void ReplayableSampler::generate() { } void ReplayableSampler::advance() { } -void ReplayableSampler::setSampleIndex(uint64_t sampleIndex) { +void ReplayableSampler::setSampleIndex(size_t sampleIndex) { if (sampleIndex < m_sampleIndex) { m_sampleIndex = 0; m_random->set(m_initial); diff --git a/src/libcore/SConscript b/src/libcore/SConscript index e88b988d..5416e864 100644 --- a/src/libcore/SConscript +++ b/src/libcore/SConscript @@ -39,9 +39,7 @@ libcore_objects = [ # Add some platform-specific components if sys.platform == 'darwin': coreEnv_osx = coreEnv.Clone() - coreEnv_osx['CXXFLAGS'].remove('-fstrict-aliasing') - coreEnv_osx['CXXFLAGS'].remove('-ftree-vectorize') - coreEnv_osx['CXXFLAGS'].append('-fno-strict-aliasing') + coreEnv_osx.ConfigureForObjectiveCPP() libcore_objects += coreEnv_osx.SharedObject('platform_darwin.mm') elif sys.platform == 'win32': libcore_objects += coreEnv.SharedObject('getopt.c') @@ -50,7 +48,7 @@ elif sys.platform == 'win32': libcore = coreEnv.SharedLibrary('mitsuba-core', libcore_objects) if sys.platform == "darwin": - coreEnv.AddPostAction(libcore, 'install_name_tool -id @executable_path/../Frameworks/libmitsuba-core.dylib $TARGET') + coreEnv.AddPostAction(libcore, 'install_name_tool -id @loader_path/../Frameworks/libmitsuba-core.dylib $TARGET') env.Append(LIBS=['mitsuba-core']) env.Append(LIBPATH=[os.path.join(env['BUILDDIR'], 'libcore')]) diff --git a/src/libcore/fresolver.cpp b/src/libcore/fresolver.cpp index 65ac251a..5f74b255 100644 --- a/src/libcore/fresolver.cpp +++ b/src/libcore/fresolver.cpp @@ -20,7 +20,7 @@ FileResolver::FileResolver() { } #elif defined(__OSX__) MTS_AUTORELEASE_BEGIN() - addPath(__ubi_bundlepath()); + addPath(__mts_bundlepath()); MTS_AUTORELEASE_END() #elif defined(WIN32) char lpFilename[1024]; @@ -86,8 +86,12 @@ std::string FileResolver::toString() const { std::ostringstream oss; oss << "FileResolver[" << endl << " paths = {" << endl; - for (size_t i=0; idecRef(); } @@ -99,7 +99,7 @@ void Logger::log(ELogLevel level, const Class *theClass, m_mutex->lock(); if (level >= EWarn) m_warningCount++; - for (unsigned int i=0; iappend(level, text); m_mutex->unlock(); } else { @@ -141,7 +141,7 @@ void Logger::log(ELogLevel level, const Class *theClass, void Logger::logProgress(Float progress, const std::string &name, const std::string &formatted, const std::string &eta, const void *ptr) { m_mutex->lock(); - for (unsigned int i=0; ilogProgress( progress, name, formatted, eta, ptr); m_mutex->unlock(); @@ -162,6 +162,14 @@ void Logger::removeAppender(Appender *appender) { appender->decRef(); } +void Logger::clearAppenders() { + m_mutex->lock(); + for (size_t i=0; idecRef(); + m_appenders.clear(); + m_mutex->unlock(); +} + void Logger::staticInitialization() { Logger *logger = new Logger(EInfo); ref appender = new StreamAppender(&std::cout); diff --git a/src/libcore/object.cpp b/src/libcore/object.cpp index 74915535..20a4fc70 100644 --- a/src/libcore/object.cpp +++ b/src/libcore/object.cpp @@ -18,7 +18,7 @@ #include -//#define DEBUG_ALLOCATIONS 1 +#define DEBUG_REFCOUNTS 0 MTS_NAMESPACE_BEGIN @@ -29,7 +29,7 @@ Object::Object() } void Object::incRef() const { -#if defined(DEBUG_ALLOCATIONS) +#if DEBUG_REFCOUNTS == 1 if (Class::rttiIsInitialized()) cout << this << ": Increasing reference count (" << getClass()->getName() << ") -> " << m_refCount + 1 << endl; @@ -42,7 +42,7 @@ void Object::incRef() const { } void Object::decRef() const { -#if defined(DEBUG_ALLOCATIONS) +#if DEBUG_REFCOUNTS == 1 if (Class::rttiIsInitialized()) { cout << this << ": Decreasing reference count (" << getClass()->getName() << ") -> " << m_refCount - 1 << endl; @@ -55,7 +55,7 @@ void Object::decRef() const { #endif AssertEx(count >= 0, "Reference count is below zero!"); if (count == 0) { -#if defined(DEBUG_ALLOCATIONS) +#if DEBUG_REFCOUNTS == 1 if (Class::rttiIsInitialized()) cout << this << ": Deleting an instance of " << getClass()->getName() << endl; diff --git a/src/libcore/platform_darwin.mm b/src/libcore/platform_darwin.mm index 34e22c19..c0eea13f 100644 --- a/src/libcore/platform_darwin.mm +++ b/src/libcore/platform_darwin.mm @@ -21,41 +21,41 @@ MTS_NAMESPACE_BEGIN -static pthread_key_t __ubi_autorelease_key; -static bool __ubi_cocoa_initialized = false; +static pthread_key_t __mts_autorelease_key; +static bool __mts_cocoa_initialized = false; -void __ubi_autorelease_init() { - pthread_key_create(&__ubi_autorelease_key, NULL); +void __mts_autorelease_init() { + pthread_key_create(&__mts_autorelease_key, NULL); } -void __ubi_autorelease_shutdown() { - pthread_key_delete(__ubi_autorelease_key); +void __mts_autorelease_shutdown() { + pthread_key_delete(__mts_autorelease_key); } -void __ubi_autorelease_begin() { +void __mts_autorelease_begin() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - pthread_setspecific(__ubi_autorelease_key, pool); + pthread_setspecific(__mts_autorelease_key, pool); } -void __ubi_autorelease_end() { +void __mts_autorelease_end() { NSAutoreleasePool *pool = - static_cast(pthread_getspecific(__ubi_autorelease_key)); + static_cast(pthread_getspecific(__mts_autorelease_key)); [pool release]; } -void __ubi_chdir_to_bundlepath() { +void __mts_chdir_to_bundlepath() { chdir([[[NSBundle mainBundle] bundlePath] fileSystemRepresentation]); } -std::string __ubi_bundlepath() { +std::string __mts_bundlepath() { return [[[NSBundle mainBundle] bundlePath] fileSystemRepresentation]; } -void __ubi_init_cocoa() { - if (!__ubi_cocoa_initialized) { +void __mts_init_cocoa() { + if (!__mts_cocoa_initialized) { [NSApplication sharedApplication]; /* Creates a connection to the windowing environment */ [NSApp activateIgnoringOtherApps:YES]; /* Pop to front */ - __ubi_cocoa_initialized = true; + __mts_cocoa_initialized = true; } } diff --git a/src/libcore/plugin.cpp b/src/libcore/plugin.cpp index 94bb8297..8b86e2df 100644 --- a/src/libcore/plugin.cpp +++ b/src/libcore/plugin.cpp @@ -163,7 +163,28 @@ ConfigurableObject *PluginManager::createObject(const Class *classType, props.getPluginName().c_str()); return object; } - + +ConfigurableObject *PluginManager::createObject(const Properties &props) { + ConfigurableObject *object; + + m_mutex->lock(); + try { + ensurePluginLoaded(props.getPluginName()); + object = m_plugins[props.getPluginName()]->createInstance(props); + } catch (std::runtime_error &e) { + m_mutex->unlock(); + throw e; + } catch (std::exception &e) { + m_mutex->unlock(); + throw e; + } + m_mutex->unlock(); + if (object->getClass()->isAbstract()) + Log(EError, "Error when loading plugin \"%s\": Identifies itself as an abstract class", + props.getPluginName().c_str()); + return object; +} + std::vector PluginManager::getLoadedPlugins() const { std::vector list; m_mutex->lock(); diff --git a/src/libcore/properties.cpp b/src/libcore/properties.cpp index 63fb7d4b..302e6865 100644 --- a/src/libcore/properties.cpp +++ b/src/libcore/properties.cpp @@ -21,6 +21,63 @@ MTS_NAMESPACE_BEGIN +#define DEFINE_PROPERTY_ACCESSOR(Type, BaseType, TypeName, ReadableName) \ + void Properties::set##TypeName(const std::string &name, const Type &value, bool warnDuplicates) { \ + if (hasProperty(name) && warnDuplicates) \ + SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); \ + m_elements[name].data = (BaseType) value; \ + m_elements[name].queried = false; \ + } \ + \ + Type Properties::get##TypeName(const std::string &name) const { \ + std::map::const_iterator it = m_elements.find(name); \ + if (it == m_elements.end()) \ + SLog(EError, "Property \"%s\" missing", name.c_str()); \ + const BaseType *result = boost::get(&it->second.data); \ + if (!result) \ + SLog(EError, "The property \"%s\" has the wrong type (expected <" #ReadableName ">). The " \ + "complete property record is :\n%s", name.c_str(), toString().c_str()); \ + it->second.queried = true; \ + return (Type) *result; \ + } \ + \ + Type Properties::get##TypeName(const std::string &name, const Type &defVal) const { \ + std::map::const_iterator it = m_elements.find(name); \ + if (it == m_elements.end()) \ + return defVal; \ + const BaseType *result = boost::get(&it->second.data); \ + if (!result) \ + SLog(EError, "The property \"%s\" has the wrong type (expected <" #ReadableName ">). The " \ + "complete property record is :\n%s", name.c_str(), toString().c_str()); \ + it->second.queried = true; \ + return (Type) *result; \ + } + +DEFINE_PROPERTY_ACCESSOR(bool, bool, Boolean, bool) +DEFINE_PROPERTY_ACCESSOR(int64_t, int64_t, Long, integer) +DEFINE_PROPERTY_ACCESSOR(int, int64_t, Integer, integer) +DEFINE_PROPERTY_ACCESSOR(size_t, int64_t, Size, integer) +DEFINE_PROPERTY_ACCESSOR(Float, Float, Float, float) +DEFINE_PROPERTY_ACCESSOR(Point, Point, Point, point) +DEFINE_PROPERTY_ACCESSOR(Vector, Vector, Vector, vector) +DEFINE_PROPERTY_ACCESSOR(Transform, Transform, Transform, transform) +DEFINE_PROPERTY_ACCESSOR(Spectrum, Spectrum, Spectrum, spectrum) +DEFINE_PROPERTY_ACCESSOR(std::string, std::string, String, string) +DEFINE_PROPERTY_ACCESSOR(Properties::Data, Properties::Data, Data, data) + +class type_visitor : public boost::static_visitor { +public: + Properties::EPropertyType operator()(const bool &) const { return Properties::EBoolean; } + Properties::EPropertyType operator()(const int64_t &) const { return Properties::EInteger; } + Properties::EPropertyType operator()(const Float &) const { return Properties::EFloat; } + Properties::EPropertyType operator()(const Point &) const { return Properties::EPoint; } + Properties::EPropertyType operator()(const Vector &) const { return Properties::EVector; } + Properties::EPropertyType operator()(const Transform &) const { return Properties::ETransform; } + Properties::EPropertyType operator()(const Spectrum &) const { return Properties::ESpectrum; } + Properties::EPropertyType operator()(const std::string &) const { return Properties::EString; } + Properties::EPropertyType operator()(const Properties::Data &) const { return Properties::EData; } +}; + bool Properties::hasProperty(const std::string &name) const { return m_elements.find(name) != m_elements.end(); } @@ -30,7 +87,7 @@ std::vector Properties::getUnqueried() const { std::vector result; for (; it != m_elements.end(); ++it) { - if ((*it).second.queried == false) + if (!(*it).second.queried) result.push_back((*it).first); } @@ -41,311 +98,9 @@ Properties::EPropertyType Properties::getType(const std::string &name) const { std::map::const_iterator it = m_elements.find(name); if (it == m_elements.end()) SLog(EError, "Property \"%s\" has not been specified!", name.c_str()); - return (*it).second.type; -} - -void Properties::setBoolean(const std::string &name, bool value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EBoolean; - m_elements[name].v_boolean = value; - m_elements[name].queried = false; -} - -bool Properties::getBoolean(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EBoolean) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_boolean; -} - -bool Properties::getBoolean(const std::string &name, bool defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EBoolean) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_boolean; -} - -void Properties::setInteger(const std::string &name, int value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EInteger; - m_elements[name].v_long = value; - m_elements[name].queried = false; -} - -int Properties::getInteger(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (int) (*it).second.v_long; -} - -int Properties::getInteger(const std::string &name, int defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (int) (*it).second.v_long; -} - -void Properties::setLong(const std::string &name, int64_t value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EInteger; - m_elements[name].v_long = value; - m_elements[name].queried = false; -} - -int64_t Properties::getLong(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_long; -} - -int64_t Properties::getLong(const std::string &name, int64_t defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_long; -} - -size_t Properties::getSize(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - if ((*it).second.v_long < 0) - SLog(EError, "Size property \"%s\": expected a nonnegative value!"); - (*it).second.queried = true; - return (size_t) (*it).second.v_long; -} - -size_t Properties::getSize(const std::string &name, size_t defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EInteger) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - if ((*it).second.v_long < 0) - SLog(EError, "Size property \"%s\": expected a nonnegative value!"); - (*it).second.queried = true; - return (size_t) (*it).second.v_long; -} - -void Properties::setData(const std::string &name, Data value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EData; - m_elements[name].v_data = value; - m_elements[name].queried = false; -} - -Properties::Data Properties::getData(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EData) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_data; -} - -Properties::Data Properties::getData(const std::string &name, Data defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EData) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_data; -} - -void Properties::setFloat(const std::string &name, Float value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EFloat; - m_elements[name].v_float = value; - m_elements[name].queried = false; -} - -Float Properties::getFloat(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EFloat) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_float; -} - -Float Properties::getFloat(const std::string &name, Float defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EFloat) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_float; -} - -void Properties::setTransform(const std::string &name, const Transform &value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = ETransform; - m_elements[name].v_transform = value; - m_elements[name].queried = false; -} - -Transform Properties::getTransform(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != ETransform) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_transform; -} - -Transform Properties::getTransform(const std::string &name, const Transform &defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != ETransform) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_transform; -} - -void Properties::setSpectrum(const std::string &name, const Spectrum &value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = ESpectrum; - m_elements[name].v_spectrum = value; - m_elements[name].queried = false; -} - -Spectrum Properties::getSpectrum(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != ESpectrum) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_spectrum; -} - -Spectrum Properties::getSpectrum(const std::string &name, const Spectrum &defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != ESpectrum) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_spectrum; -} - -void Properties::setString(const std::string &name, const std::string &value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EString; - m_elements[name].v_string = value; - m_elements[name].queried = false; -} - -std::string Properties::getString(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EString) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_string; -} - -std::string Properties::getString(const std::string &name, const std::string &defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EString) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_string; -} - -void Properties::setPoint(const std::string &name, const Point &value, bool warnDuplicates) { - if (hasProperty(name) && warnDuplicates) - SLog(EWarn, "Property \"%s\" has already been specified!", name.c_str()); - m_elements[name].type = EPoint; - m_elements[name].v_point = value; - m_elements[name].queried = false; -} - -Vector Properties::getVector(const std::string &name) const { - return Vector(getPoint(name)); -} - -Vector Properties::getVector(const std::string &name, const Vector &defVal) const { - return Vector(getPoint(name, Point(defVal))); -} - -Point Properties::getPoint(const std::string &name) const { - if (!hasProperty(name)) - SLog(EError, "Property \"%s\" missing", name.c_str()); - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EPoint) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_point; -} - -Point Properties::getPoint(const std::string &name, const Point &defVal) const { - if (!hasProperty(name)) - return defVal; - std::map::const_iterator it = m_elements.find(name); - if ((*it).second.type != EPoint) - SLog(EError, "The property \"%s\" has the wrong type (expected ). The detailed " - "listing was:\n%s", name.c_str(), toString().c_str()); - (*it).second.queried = true; - return (*it).second.v_point; + + type_visitor myVisitor; + return boost::apply_visitor(myVisitor, it->second.data); } std::string Properties::toString() const { @@ -355,38 +110,42 @@ std::string Properties::toString() const { oss << "Properties[" << endl << " pluginName = \"" << m_pluginName << "\"," << endl << " elements = {" << endl; - for (; it != m_elements.end(); ++it) { + while (it != m_elements.end()) { oss << " \"" << (*it).first << "\" -> "; - const Element &el = (*it).second; - switch (el.type) { + const ElementData &data = (*it).second.data; + EPropertyType type = boost::apply_visitor(type_visitor(), data); + switch (type) { case EBoolean: - oss << (el.v_boolean ? "true" : "false"); + oss << (boost::get(data) ? "true" : "false"); break; case EInteger: - oss << el.v_long; + oss << boost::get(data); break; case EFloat: - oss << el.v_float; + oss << boost::get(data); break; case EPoint: - oss << el.v_point.toString(); + oss << boost::get(data).toString(); break; case ETransform: - oss << indent(el.v_transform.toString(), 2); + oss << boost::get(data).toString(); break; case ESpectrum: - oss << indent(el.v_spectrum.toString(), 2); + oss << boost::get(data).toString(); break; case EString: - oss << "\"" << el.v_string << "\""; + oss << "\"" << boost::get(data) << "\""; break; case EData: - oss << el.v_data.ptr << " (size=" << el.v_data.size << ")"; + oss << boost::get(data).ptr << " (size=" + << boost::get(data).size << ")"; break; default: SLog(EError, "Encountered an unknown property type!"); } - oss << "," << endl; + if (++it != m_elements.end()) + oss << ","; + oss << endl; } oss << " }" << endl << "]" << endl; diff --git a/src/libcore/sched.cpp b/src/libcore/sched.cpp index ea6b9315..f5112355 100644 --- a/src/libcore/sched.cpp +++ b/src/libcore/sched.cpp @@ -204,7 +204,7 @@ SerializableObject *Scheduler::getResource(int id, int coreIndex) { m_mutex->unlock(); Log(EError, "getResource(): tried to look up manifold resource %i without specifying a core index!", id); } - result = rec->resources[coreIndex]; + result = rec->resources.at(coreIndex); } else { result = rec->resources[0]; } diff --git a/src/libcore/spectrum.cpp b/src/libcore/spectrum.cpp index 61bb28a2..dfe18f69 100644 --- a/src/libcore/spectrum.cpp +++ b/src/libcore/spectrum.cpp @@ -440,10 +440,25 @@ Float BlackBodySpectrum::eval(Float l) const { return (Float) I; } +std::string BlackBodySpectrum::toString() const { + std::ostringstream oss; + oss << "BlackBodySpectrum[temperature=" << m_temperature << "]"; + return oss.str(); +} + Float ProductSpectrum::eval(Float lambda) const { return m_spec1.eval(lambda) * m_spec2.eval(lambda); } +std::string ProductSpectrum::toString() const { + std::ostringstream oss; + oss << "ProductSpectrum[" + << " spec1 = " << indent(m_spec1.toString()) << "," << endl + << " spec2 = " << indent(m_spec2.toString()) << endl + << "]"; + return oss.str(); +} + RayleighSpectrum::RayleighSpectrum(EMode mode, Float eta, Float height) { /* See ``Display of the Earth Taking into Account Atmospheric Scattering'', * by Nishita et al., SIGGRAPH 1993 */ @@ -465,6 +480,10 @@ RayleighSpectrum::RayleighSpectrum(EMode mode, Float eta, Float height) { } } +std::string RayleighSpectrum::toString() const { + return "RayleighSpectrum[]"; +} + Float RayleighSpectrum::eval(Float lambda) const { Float lambdaSqr = lambda*lambda; return m_precomp / (lambdaSqr*lambdaSqr); @@ -494,6 +513,11 @@ Float ContinuousSpectrum::average(Float lambdaMin, Float lambdaMax) const { return integral / (lambdaMax - lambdaMin); } +InterpolatedSpectrum::InterpolatedSpectrum(size_t size) { + m_wavelengths.reserve(size); + m_values.reserve(size); +} + InterpolatedSpectrum::InterpolatedSpectrum(const fs::path &path) { fs::ifstream is(path); if (is.bad() || is.fail()) @@ -613,8 +637,8 @@ Float InterpolatedSpectrum::eval(Float lambda) const { typedef std::vector::const_iterator iterator; if (m_wavelengths.size() < 2 || lambda < m_wavelengths[0] || - lambda > m_wavelengths[m_wavelengths.size()-1]) - return 0; + lambda > m_wavelengths[m_wavelengths.size()-1]) + return 0.0f; /* Find the associated table entries using binary search */ std::pair result = diff --git a/src/libcore/thread.cpp b/src/libcore/thread.cpp index 4996682a..ef6a3a86 100644 --- a/src/libcore/thread.cpp +++ b/src/libcore/thread.cpp @@ -62,8 +62,9 @@ int Thread::m_idCounter; ref Thread::m_idMutex; #endif -#if defined(__LINUX__) -int __thread Thread::m_id; +#if MTS_USE_ELF_TLS == 1 +__thread int Thread::m_id + __attribute__((tls_model("global-dynamic"))); #endif Thread::Thread(const std::string &name, unsigned int stackSize) @@ -72,7 +73,7 @@ Thread::Thread(const std::string &name, unsigned int stackSize) m_joinMutex = new Mutex(); memset(&m_thread, 0, sizeof(pthread_t)); } - + void Thread::start() { if (m_running) Log(EError, "Thread is already running!"); @@ -155,14 +156,14 @@ void *Thread::dispatch(void *par) { if (thread->getPriority() != ENormalPriority) thread->setPriority(thread->getPriority()); -#if defined(__OSX__) - m_idMutex->lock(); - thread->m_id = ++m_idCounter; - m_idMutex->unlock(); -#elif defined(__LINUX__) +#if MTS_USE_ELF_TLS == 1 m_idMutex->lock(); m_id = ++m_idCounter; m_idMutex->unlock(); +#elif defined(__LINUX__) or defined(__OSX__) + m_idMutex->lock(); + thread->m_id = ++m_idCounter; + m_idMutex->unlock(); #endif try { @@ -247,38 +248,40 @@ void Thread::exit() { std::string Thread::toString() const { std::ostringstream oss; oss << "Thread[" << endl - << " name=\"" << m_name << "\"," << endl - << " running=" << m_running << "," << endl - << " joined=" << m_joined << "," << endl - << " priority=" << m_priority << "," << endl - << " critical=" << m_critical << "," << endl - << " stackSize=" << m_stackSize << endl + << " name = \"" << m_name << "\"," << endl + << " running = " << m_running << "," << endl + << " joined = " << m_joined << "," << endl + << " priority = " << m_priority << "," << endl + << " critical = " << m_critical << "," << endl + << " stackSize = " << m_stackSize << endl << "]"; return oss.str(); } void Thread::staticInitialization() { #if defined(__OSX__) - __ubi_autorelease_init(); + __mts_autorelease_init(); #endif m_self = new ThreadLocal(); + Thread *mainThread = new MainThread(); #if defined(__LINUX__) || defined(__OSX__) m_idMutex = new Mutex(); m_idCounter = 0; + + #if MTS_USE_ELF_TLS == 1 + m_id = 0; + #else + mainThread->m_id = 0; + #endif #endif - Thread *mainThread = new MainThread(); mainThread->m_running = true; mainThread->m_thread = pthread_self(); mainThread->m_joinMutex = new Mutex(); mainThread->m_joined = false; mainThread->m_fresolver = new FileResolver(); m_self->set(mainThread); -#if defined(__OSX__) - mainThread->m_id = 0; -#elif defined(__LINUX__) - m_id = 0; -#endif + } static std::vector __ompThreads; @@ -295,7 +298,7 @@ void Thread::staticShutdown() { m_idMutex = NULL; #endif #if defined(__OSX__) - __ubi_autorelease_shutdown(); + __mts_autorelease_shutdown(); #endif } diff --git a/src/libhw/SConscript b/src/libhw/SConscript index 0f3debf9..0d9ab15a 100644 --- a/src/libhw/SConscript +++ b/src/libhw/SConscript @@ -30,15 +30,13 @@ if glEnv.has_key('GLINCLUDE'): if sys.platform == 'darwin': glEnv_osx = glEnv.Clone() - glEnv_osx['CXXFLAGS'].remove('-fstrict-aliasing') - glEnv_osx['CXXFLAGS'].remove('-ftree-vectorize') - glEnv_osx['CXXFLAGS'].append('-fno-strict-aliasing') + glEnv_osx.ConfigureForObjectiveCPP() libhw_objects += glEnv_osx.SharedObject(['nsglsession.mm', 'nsgldevice.mm', 'nsglrenderer.mm']) libhw = glEnv.SharedLibrary('mitsuba-hw', libhw_objects) if sys.platform == "darwin": - glEnv.AddPostAction(libhw, 'install_name_tool -id @executable_path/../Frameworks/libmitsuba-hw.dylib $TARGET') + glEnv.AddPostAction(libhw, 'install_name_tool -id @loader_path/../Frameworks/libmitsuba-hw.dylib $TARGET') env.Append(LIBS=['mitsuba-hw']) env.Append(LIBPATH=[os.path.join(env['BUILDDIR'], 'libhw')]) diff --git a/src/libhw/nsgldevice.mm b/src/libhw/nsgldevice.mm index c8c6d897..463a5547 100644 --- a/src/libhw/nsgldevice.mm +++ b/src/libhw/nsgldevice.mm @@ -391,7 +391,7 @@ NSGLDevice::~NSGLDevice() { void NSGLDevice::init(Device *other) { Device::init(other); - __ubi_init_cocoa(); + __mts_init_cocoa(); NSOpenGLPixelFormatAttribute attribs[32]; uint i=0; diff --git a/src/libpython/SConscript b/src/libpython/SConscript new file mode 100644 index 00000000..6984ac84 --- /dev/null +++ b/src/libpython/SConscript @@ -0,0 +1,16 @@ +Import('env', 'sys', 'os', 'hasPython') + +pythonEnv = env.Clone() +pythonEnv.Append(CPPDEFINES = [['MTS_BUILD_MODULE', 'MTS_MODULE_PYTHON']]) +pythonEnv['SHLIBPREFIX']='' +pythonEnv.RelaxCompilerSettings() + +if pythonEnv.has_key('PYTHONINCLUDE'): + pythonEnv.Prepend(CPPPATH=pythonEnv['PYTHONINCLUDE']) +if pythonEnv.has_key('PYTHONLIBDIR'): + pythonEnv.Prepend(LIBPATH=pythonEnv['PYTHONLIBDIR']) +if pythonEnv.has_key('PYTHONLIB'): + pythonEnv.Prepend(LIBS=pythonEnv['PYTHONLIB']) + +if hasPython: + libpython = pythonEnv.SharedLibrary('mitsuba', ['core.cpp', 'render.cpp']); diff --git a/src/libpython/base.h b/src/libpython/base.h new file mode 100644 index 00000000..67a2eb42 --- /dev/null +++ b/src/libpython/base.h @@ -0,0 +1,158 @@ +/* + 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 . +*/ + +#if !defined(__PYTHON_BASE_H) +#define __PYTHON_BASE_H + +#include + +#define BP_STRUCT(Name, Init) \ + bp::class_ Name ##_struct(#Name, Init); \ + bp::register_ptr_to_python(); \ + Name ##_struct + +#define BP_CLASS(Name, Base, Init) \ + bp::class_, bp::bases, boost::noncopyable> Name ##_class(#Name, Init); \ + bp::register_ptr_to_python(); \ + Name ##_class + +#define BP_WRAPPED_CLASS(Name, Wrapper, Base, Init) \ + bp::class_, bp::bases, boost::noncopyable> Name ##_class(#Name, Init); \ + bp::register_ptr_to_python(); \ + bp::implicitly_convertible, ref >(); \ + Name ##_class + +#define BP_IMPLEMENT_VECTOR_OPS(Name, Scalar, Size) \ + Name ##_struct \ + .def(bp::init()) \ + .def(bp::init()) \ + .def(bp::self != bp::self) \ + .def(bp::self == bp::self) \ + .def(-bp::self) \ + .def(bp::self + bp::self) \ + .def(bp::self += bp::self) \ + .def(bp::self - bp::self) \ + .def(bp::self -= bp::self) \ + .def(bp::self *= Scalar()) \ + .def(bp::self * Scalar()) \ + .def(Scalar() * bp::self) \ + .def(bp::self / Scalar()) \ + .def(bp::self /= Scalar()) \ + .def("serialize", &Name::serialize) \ + .def("__str__", &Name::toString) \ + .def("__len__", &FixedSizeSupport::len) \ + .def("__getitem__", &FixedSizeSupport::get) \ + .def("__setitem__", &FixedSizeSupport::set) + +#define BP_IMPLEMENT_POINT_OPS(Name, Scalar, Size) \ + Name ##_struct \ + .def(bp::init()) \ + .def(bp::init()) \ + .def(bp::self != bp::self) \ + .def(bp::self == bp::self) \ + .def(Scalar() * bp::self) \ + .def(-bp::self) \ + .def(bp::self + Name::vector_type()) \ + .def(bp::self += Name::vector_type()) \ + .def(bp::self - Name::vector_type()) \ + .def(bp::self -= Name::vector_type()) \ + .def(bp::self - bp::self) \ + .def(bp::self *= Scalar()) \ + .def(bp::self * Scalar()) \ + .def(bp::self / Scalar()) \ + .def(bp::self /= Scalar()) \ + .def("serialize", &Name::serialize) \ + .def("__str__", &Name::toString) \ + .def("__len__", &FixedSizeSupport::len) \ + .def("__getitem__", &FixedSizeSupport::get) \ + .def("__setitem__", &FixedSizeSupport::set) + +#define BP_SETSCOPE(value) do { \ + bp::detail::current_scope = value.ptr(); \ + } while (0); + +#define BP_RETURN_CONSTREF bp::return_value_policy() +#define BP_RETURN_NONCONSTREF bp::return_value_policy() +#define BP_RETURN_VALUE bp::return_value_policy() +#define BP_RETURN_INTREF bp::return_internal_reference<>() + +namespace boost { + namespace python { + template T* get_pointer(mitsuba::ref & p) { + return p.get(); + } + template const T* get_pointer(const mitsuba::ref & p) { + return p.get(); + } + } +} + +#include +#include +#include + +namespace bp = boost::python; + +/* Support ref<..> smart pointers */ +namespace boost { + namespace python { + template struct pointee< mitsuba::ref > { + typedef T type; + }; + } +} + +template class FixedSizeSupport { +public: + static Scalar get(const T &value, int i) { + using namespace mitsuba; + + if (i < 0 || i >= Size) { + SLog(EError, "Index %i is out of range!", i); + return 0.0f; + } + return value[i]; + } + + static void set(T &value, int i, Scalar arg) { + using namespace mitsuba; + + if (i < 0 || i >= Size) + SLog(EError, "Index %i is out of range!", i); + else + value[i] = arg; + } + + static int len(const T &) { + return Size; + } +}; + +namespace mitsuba { + class SerializableObject; +}; + +typedef std::vector StringVector; +typedef std::vector SerializableObjectVector; +typedef std::map StringMap; + +extern void export_core(); +extern void export_render(); + +#endif /* __PYTHON_BASE_H */ + diff --git a/src/libpython/core.cpp b/src/libpython/core.cpp new file mode 100644 index 00000000..1f80f6f0 --- /dev/null +++ b/src/libpython/core.cpp @@ -0,0 +1,1078 @@ +#include "base.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mitsuba; + +void initializeFramework() { + /* Initialize the core framework */ + Class::staticInitialization(); + PluginManager::staticInitialization(); + Statistics::staticInitialization(); + Thread::staticInitialization(); + Logger::staticInitialization(); + Spectrum::staticInitialization(); + Scheduler::staticInitialization(); + SHVector::staticInitialization(); + SceneHandler::staticInitialization(); +} + +void shutdownFramework() { + /* Shutdown the core framework */ + SceneHandler::staticShutdown(); + SHVector::staticShutdown(); + Scheduler::staticShutdown(); + Spectrum::staticShutdown(); + Logger::staticShutdown(); + Thread::staticShutdown(); + Statistics::staticShutdown(); + PluginManager::staticShutdown(); + Class::staticShutdown(); +} + +class spectrum_wrapper { +public: + static Float get(const Spectrum &spec, int i) { + if (i < 0 || i >= SPECTRUM_SAMPLES) { + SLog(EError, "Index %i is out of range!", i); + return 0.0f; + } + return spec[i]; + } + + static void set(Spectrum &spec, int i, Float value) { + if (i < 0 || i >= SPECTRUM_SAMPLES) + SLog(EError, "Index %i is out of range!", i); + else + spec[i] = value; + } + + static int len(Spectrum &) { + return SPECTRUM_SAMPLES; + } +}; + +class properties_wrapper { +public: + static bp::object get(const Properties &props, std::string name) { + if (!props.hasProperty(name)) + SLog(EError, "Properties: keyword \"%s\" not found!", name.c_str()); + + switch (props.getType(name)) { + case Properties::EBoolean: + return bp::object(props.getBoolean(name)); + case Properties::EString: + return bp::object(props.getString(name)); + case Properties::EInteger: + return bp::object(props.getInteger(name)); + case Properties::EFloat: + return bp::object(props.getFloat(name)); + case Properties::EVector: + return bp::object(props.getVector(name)); + case Properties::EPoint: + return bp::object(props.getPoint(name)); + case Properties::ETransform: + return bp::object(props.getTransform(name)); + case Properties::ESpectrum: + return bp::object(props.getSpectrum(name)); + default: + SLog(EError, "Properties: type of keyword \"%s\" is not supported!", name.c_str()); + return bp::object(); + } + } + + static void set(Properties &props, const std::string name, bp::object value) { + bp::extract extractString(value); + bp::extract extractBoolean(value); + bp::extract extractInteger(value); + bp::extract extractFloat(value); + bp::extract extractVector(value); + bp::extract extractPoint(value); + bp::extract extractTransform(value); + bp::extract extractSpectrum(value); + + if (extractString.check()) { + props.setString(name, extractString()); + } else if (extractBoolean.check() && PyObject_IsInstance(value.ptr(), (PyObject *) &PyBool_Type)) { + props.setBoolean(name, extractBoolean()); + } else if (extractInteger.check()) { + props.setInteger(name, extractInteger()); + } else if (extractFloat.check()) { + props.setFloat(name, extractFloat()); + } else if (extractPoint.check()) { + props.setPoint(name, extractPoint()); + } else if (extractVector.check()) { + props.setVector(name, extractVector()); + } else if (extractTransform.check()) { + props.setTransform(name, extractTransform()); + } else if (extractSpectrum.check()) { + props.setSpectrum(name, extractSpectrum()); + } else { + SLog(EError, "Properties: type of keyword \"%s\" is not supported!", name.c_str()); + } + } +}; + +struct path_to_python_str { + static PyObject* convert(fs::path const& path) { + return boost::python::incref( + boost::python::object(path.file_string()).ptr()); + } +}; + + +static void Matrix4x4_setItem(Matrix4x4 *matrix, bp::tuple tuple, Float value) { + if (bp::len(tuple) != 2) + SLog(EError, "Invalid matrix indexing operation, required a tuple of length 2"); + int i = bp::extract(tuple[0]); + int j = bp::extract(tuple[1]); + + if (i < 0 || j < 0 || i >= 4 || j >= 4) + SLog(EError, "Index (%i, %i) is out of bounds!", i, j); + + matrix->operator()(i, j) = value; +} + +static Float Matrix4x4_getItem(Matrix4x4 *matrix, bp::tuple tuple) { + if (bp::len(tuple) != 2) + SLog(EError, "Invalid matrix indexing operation, required a tuple of length 2"); + int i = bp::extract(tuple[0]); + int j = bp::extract(tuple[1]); + + if (i < 0 || j < 0 || i >= 4 || j >= 4) + SLog(EError, "Index (%i, %i) is out of bounds!", i, j); + + return matrix->operator()(i, j); +} + +Class *object_getClass(Object *object) { + return const_cast(object->getClass()); +} + +Class *class_forName(const char *name) { + return const_cast(Class::forName(name)); +} + +Class *class_getSuperClass(Class *theClass) { + return const_cast(theClass->getSuperClass()); +} + +static ref instance_manager_getinstance(InstanceManager *manager, Stream *stream) { + return manager->getInstance(stream); +} + +void appender_logProgress(Appender *appender, Float progress, const std::string &name, + const std::string &formatted, const std::string &eta) { + appender->logProgress(progress, name, formatted, eta, NULL); +} + +void logger_logProgress(Logger *logger, Float progress, const std::string &name, + const std::string &formatted, const std::string &eta) { + logger->logProgress(progress, name, formatted, eta, NULL); +} + +void mts_log(ELogLevel level, const std::string &msg) { + bp::object traceback(bp::import("traceback")); + bp::object extract_stack(traceback.attr("extract_stack")); + bp::object stack = extract_stack(); + bp::object top(stack[bp::len(stack)-1]); + std::string module = bp::extract(top[2]); + Thread::getThread()->getLogger()->log(level, + NULL, bp::extract(top[0]), + bp::extract(top[1]), "%s%s: %s", + module.c_str(), module[0] == '<' ? "" : "()", + msg.c_str()); +} + +class FormatterWrapper : public Formatter { +public: + FormatterWrapper(PyObject *self) : m_self(self) { Py_INCREF(m_self); } + + std::string format(ELogLevel logLevel, const Class *theClass, + const Thread *thread, const std::string &text, + const char *file, int line) { + return bp::call_method(m_self, "format", logLevel, + bp::ptr(const_cast(theClass)), + bp::ptr(const_cast(thread)), text, file, line); + } + + virtual ~FormatterWrapper() { + Py_DECREF(m_self); + } +private: + PyObject *m_self; +}; + +class AppenderWrapper : public Appender { +public: + AppenderWrapper(PyObject *self) : m_self(self) { Py_INCREF(m_self); } + + void append(ELogLevel level, const std::string &text) { + bp::call_method(m_self, "append", level, text); + } + + void logProgress(Float progress, const std::string &name, + const std::string &formatted, const std::string &eta, + const void *ptr) { + bp::call_method(m_self, "logProgress", name, formatted, eta); + } + + virtual ~AppenderWrapper() { + Py_DECREF(m_self); + } +private: + PyObject *m_self; +}; + +static Spectrum *spectrum_array_constructor(bp::list list) { + Float spec[SPECTRUM_SAMPLES]; + if (bp::len(list) != SPECTRUM_SAMPLES) + SLog(EError, "Spectrum: expected %i arguments", SPECTRUM_SAMPLES); + + for (int i=0; i(list[i]); + + return new Spectrum(spec); +} + +static Point ray_eval(const Ray &ray, Float t) { + return ray(t); +} + +void aabb_expandby_aabb(AABB *aabb, const AABB &aabb2) { aabb->expandBy(aabb2); } +void aabb_expandby_point(AABB *aabb, const Point &p) { aabb->expandBy(p); } +Float aabb_distanceto_aabb(AABB *aabb, const AABB &aabb2) { return aabb->distanceTo(aabb2); } +Float aabb_distanceto_point(AABB *aabb, const Point &p) { return aabb->distanceTo(p); } +Float aabb_sqrdistanceto_aabb(AABB *aabb, const AABB &aabb2) { return aabb->squaredDistanceTo(aabb2); } +Float aabb_sqrdistanceto_point(AABB *aabb, const Point &p) { return aabb->squaredDistanceTo(p); } +bool aabb_contains_aabb(AABB *aabb, const AABB &aabb2) { return aabb->contains(aabb2); } +bool aabb_contains_point(AABB *aabb, const Point &p) { return aabb->contains(p); } +bp::object bsphere_rayIntersect(BSphere *bsphere, const Ray &ray) { + Float nearT, farT; + if (bsphere->rayIntersect(ray, nearT, farT)) + return bp::make_tuple(nearT, farT); + else + return bp::object(); + +} + +bp::object aabb_rayIntersect(AABB *aabb, const Ray &ray) { + Float nearT, farT; + if (aabb->rayIntersect(ray, nearT, farT)) + return bp::make_tuple(nearT, farT); + else + return bp::object(); + +} + +Vector transform_mul_vector(Transform *transform, const Vector &vector) { return transform->operator()(vector); } +Vector4 transform_mul_vector4(Transform *transform, const Vector4 &vector) { return transform->operator()(vector); } +Normal transform_mul_normal(Transform *transform, const Normal &normal) { return transform->operator()(normal); } +Point transform_mul_point(Transform *transform, const Point &point) { return transform->operator()(point); } +Ray transform_mul_ray(Transform *transform, const Ray &ray) { return transform->operator()(ray); } +Transform transform_mul_transform(Transform *transform, const Transform &other) { return *transform * other; } + +ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dict) { + Properties properties; + bp::list list = dict.items(); + std::map children; + + for (int i=0; i(list[i]); + std::string name = bp::extract(tuple[0]); + bp::extract extractDict(tuple[1]); + bp::extract extractString(tuple[1]); + bp::extract extractConfigurableObject(tuple[1]); + + if (name == "type") { + if (!extractString.check()) + SLog(EError, "'type' property must map to a string!"); + else + properties.setPluginName(extractString()); + } else if (extractDict.check()) { + children[name] = pluginmgr_create(manager, extractDict()); + } else if (extractConfigurableObject.check()) { + children[name] = extractConfigurableObject(); + } else { + properties_wrapper::set(properties, name, tuple[1]); + } + } + + ConfigurableObject *object = manager->createObject(properties); + for (std::map::iterator it = children.begin(); + it != children.end(); ++it) + object->addChild(it->first, it->second); + object->configure(); + return object; +} + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(fromLinearRGB_overloads, fromLinearRGB, 3, 4) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(fromXYZ_overloads, fromXYZ, 3, 4) + +void export_core() { + bp::to_python_converter(); + bp::implicitly_convertible(); + + bp::object coreModule( + bp::handle<>(bp::borrowed(PyImport_AddModule("mitsuba.core")))); + bp::scope().attr("core") = coreModule; + PyObject *oldScope = bp::detail::current_scope; + + BP_SETSCOPE(coreModule); + + /* Basic STL containers */ + bp::class_("StringVector") + .def(bp::vector_indexing_suite()); + bp::class_("StringMap") + .def(bp::map_indexing_suite()); + + bp::enum_("ELogLevel") + .value("ETrace", ETrace) + .value("EDebug", EDebug) + .value("EInfo", EInfo) + .value("EWarn", EWarn) + .value("EError", EError) + .export_values(); + + bp::def("Log", &mts_log); + + bp::class_("Class", bp::no_init) + .def("getName", &Class::getName, BP_RETURN_CONSTREF) + .def("isAbstract", &Class::isAbstract) + .def("isInstantiable", &Class::isInstantiable) + .def("isSerializable", &Class::isSerializable) + .def("derivesFrom", &Class::derivesFrom) + .def("getSuperClass", &class_getSuperClass, BP_RETURN_INTREF) + .def("forName", &class_forName, BP_RETURN_INTREF) + .def("unserialize", &Class::unserialize, BP_RETURN_VALUE) + .def("instantiate", &Class::instantiate, BP_RETURN_VALUE) + .staticmethod("forName"); + bp::register_ptr_to_python(); + + bp::class_, boost::noncopyable>("Object", bp::no_init) + .def("getRefCount", &Object::getRefCount) + .def("getClass", &object_getClass, BP_RETURN_INTREF) + .def("__str__", &Object::toString); + bp::register_ptr_to_python(); + + BP_CLASS(Stream, Object, bp::no_init) + .def("setByteOrder", &Stream::setByteOrder) + .def("getByteOrder", &Stream::getByteOrder) + .def("getHostByteOrder", &Stream::getHostByteOrder) + .def("truncate", &Stream::truncate) + .def("setPos", &Stream::setPos) + .def("getPos", &Stream::getPos) + .def("getSize", &Stream::getSize) + .def("flush", &Stream::flush) + .def("canWrite", &Stream::canWrite) + .def("canRead", &Stream::canRead) + .def("skip", &Stream::skip) + .def("copyTo", &Stream::copyTo) + .def("writeString", &Stream::writeString) + .def("readString", &Stream::readString) + .def("writeLine", &Stream::writeLine) + .def("readLine", &Stream::readLine) + .def("writeChar", &Stream::writeChar) + .def("readChar", &Stream::readChar) + .def("writeUChar", &Stream::writeUChar) + .def("readUChar", &Stream::readUChar) + .def("writeShort", &Stream::writeShort) + .def("readShort", &Stream::readShort) + .def("writeUShort", &Stream::writeUShort) + .def("readUShort", &Stream::readUShort) + .def("writeInt", &Stream::writeInt) + .def("readInt", &Stream::readInt) + .def("writeUInt", &Stream::writeUInt) + .def("readUInt", &Stream::readUInt) + .def("writeLong", &Stream::writeLong) + .def("readLong", &Stream::readLong) + .def("writeULong", &Stream::writeULong) + .def("readULong", &Stream::readULong) + .def("writeFloat", &Stream::writeFloat) + .def("readFloat", &Stream::readFloat) + .def("writeSingle", &Stream::writeSingle) + .def("readSingle", &Stream::readSingle) + .def("writeDouble", &Stream::writeDouble) + .def("readDouble", &Stream::readDouble); + + BP_SETSCOPE(Stream_class); + bp::enum_("EByteOrder") + .value("EBigEndian", Stream::EBigEndian) + .value("ELittleEndian", Stream::ELittleEndian) + .value("ENetworkByteOrder", Stream::ENetworkByteOrder) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_CLASS(FileStream, Stream, bp::init<>()) + .def(bp::init()) + .def("getPath", &FileStream::getPath, + BP_RETURN_CONSTREF) + .def("open", &FileStream::open) + .def("close", &FileStream::close) + .def("remove", &FileStream::remove); + + BP_CLASS(SocketStream, Stream, (bp::init())) + .def("getPeer", &SocketStream::getPeer, BP_RETURN_CONSTREF) + .def("getReceivedBytes", &SocketStream::getReceivedBytes) + .def("getSentBytes", &SocketStream::getSentBytes); + + BP_CLASS(SSHStream, Stream, (bp::init())) + .def(bp::init()) + .def(bp::init()) + .def("getUserName", &SSHStream::getUserName, BP_RETURN_CONSTREF) + .def("getHostName", &SSHStream::getHostName, BP_RETURN_CONSTREF) + .def("getReceivedBytes", &SSHStream::getReceivedBytes) + .def("getSentBytes", &SSHStream::getSentBytes); + + BP_SETSCOPE(FileStream_class); + bp::enum_("EFileMode") + .value("EReadOnly", FileStream::EReadOnly) + .value("EReadWrite", FileStream::EReadWrite) + .value("ETruncWrite", FileStream::ETruncWrite) + .value("ETruncReadWrite", FileStream::ETruncReadWrite) + .value("EAppendWrite", FileStream::EAppendWrite) + .value("EAppendReadWrite", FileStream::EAppendReadWrite) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_CLASS(SerializableObject, Object, bp::no_init) + .def("serialize", &SerializableObject::serialize); + + ConfigurableObject *(ConfigurableObject::*cobject_get_parent)() = &ConfigurableObject::getParent; + void (ConfigurableObject::*cobject_add_child_1)(ConfigurableObject *) = &ConfigurableObject::addChild; + void (ConfigurableObject::*cobject_add_child_2)(const std::string &, ConfigurableObject *) = &ConfigurableObject::addChild; + + BP_CLASS(ConfigurableObject, SerializableObject, bp::no_init) + .def("getParent", cobject_get_parent, BP_RETURN_VALUE) + .def("setParent", &ConfigurableObject::setParent) + .def("addChild", cobject_add_child_1) + .def("addChild", cobject_add_child_2) + .def("configure", &ConfigurableObject::configure); + + BP_CLASS(NetworkedObject, ConfigurableObject, bp::no_init) + .def("bindUsedResources", &NetworkedObject::bindUsedResources); + + Thread *(Thread::*thread_get_parent)() = &Thread::getParent; + BP_CLASS(Thread, Object, bp::no_init) + .def("getID", &Thread::getID) + .def("getStackSize", &Thread::getStackSize) + .def("setPriority", &Thread::setPriority) + .def("getPriority", &Thread::getPriority) + .def("setCritical", &Thread::setCritical) + .def("getCritical", &Thread::getCritical) + .def("setName", &Thread::setName) + .def("getName", &Thread::getName, BP_RETURN_CONSTREF) + .def("getParent", thread_get_parent, BP_RETURN_VALUE) + .def("setLogger", &Thread::setLogger) + .def("getLogger", &Thread::getLogger, BP_RETURN_VALUE) + .def("setFileResolver", &Thread::setFileResolver) + .def("getFileResolver", &Thread::getFileResolver, BP_RETURN_VALUE) + .def("getThread", &Thread::getThread, BP_RETURN_VALUE) + .def("isRunning", &Thread::isRunning) + .def("sleep", &Thread::sleep) + .def("detach", &Thread::detach) + .def("join", &Thread::join) + .def("start", &Thread::start) + .staticmethod("sleep") + .staticmethod("getThread"); + + BP_SETSCOPE(Thread_class); + bp::enum_("EThreadPriority") + .value("EIdlePriority", Thread::EIdlePriority) + .value("ELowestPriority", Thread::ELowestPriority) + .value("ELowPriority", Thread::ELowPriority) + .value("ENormalPriority", Thread::ENormalPriority) + .value("EHighPriority", Thread::EHighPriority) + .value("EHighestPriority", Thread::EHighestPriority) + .value("ERealtimePriority", Thread::ERealtimePriority) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_WRAPPED_CLASS(Appender, AppenderWrapper, Object, bp::init<>()) + .def("append", &Appender::append) + .def("logProgress", &appender_logProgress); + + BP_WRAPPED_CLASS(Formatter, FormatterWrapper, Object, bp::init<>()) + .def("format", &Formatter::format); + + Appender *(Logger::*logger_get_appender)(size_t) = &Logger::getAppender; + BP_CLASS(Logger, Object, bp::init()) + .def("logProgress", logger_logProgress) + .def("setLogLevel", &Logger::setLogLevel) + .def("getLogLevel", &Logger::getLogLevel) + .def("setErrorLevel", &Logger::setErrorLevel) + .def("getErrorLevel", &Logger::getErrorLevel) + .def("addAppender", &Logger::addAppender) + .def("removeAppender", &Logger::removeAppender) + .def("clearAppenders", &Logger::clearAppenders) + .def("getAppenderCount", &Logger::getAppenderCount) + .def("getAppender", logger_get_appender, BP_RETURN_VALUE) + .def("getFormatter", &Logger::getFormatter, BP_RETURN_VALUE) + .def("setFormatter", &Logger::setFormatter) + .def("getWarningCount", &Logger::getWarningCount); + + BP_CLASS(InstanceManager, Object, bp::init<>()) + .def("serialize", &InstanceManager::serialize) + .def("getInstance", &instance_manager_getinstance, BP_RETURN_VALUE); + + bp::class_("ContinuousSpectrum", bp::no_init) + .def("eval", &ContinuousSpectrum::eval) + .def("average", &ContinuousSpectrum::average) + .def("__str__", &ContinuousSpectrum::toString); + + bp::class_, boost::noncopyable> + ("InterpolatedSpectrum", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def("append", &InterpolatedSpectrum::append) + .def("clear", &InterpolatedSpectrum::clear) + .def("zeroExtend", &InterpolatedSpectrum::zeroExtend); + + BP_CLASS(Bitmap, Object, (bp::init())) + .def(bp::init()) + .def("clone", &Bitmap::clone, BP_RETURN_VALUE) + .def("clear", &Bitmap::clear) + .def("save", &Bitmap::save) + .def("setTitle", &Bitmap::setTitle) + .def("getTitle", &Bitmap::getTitle, BP_RETURN_INTREF) + .def("setAuthor", &Bitmap::setAuthor) + .def("getAuthor", &Bitmap::getAuthor, BP_RETURN_INTREF) + .def("setComment", &Bitmap::setComment) + .def("getComment", &Bitmap::getComment, BP_RETURN_INTREF) + .def("setGamma", &Bitmap::setGamma) + .def("getGamma", &Bitmap::getGamma) + .def("getWidth", &Bitmap::getWidth) + .def("getHeight", &Bitmap::getHeight) + .def("getBitsPerPixel", &Bitmap::getBitsPerPixel) + .def("getSize", &Bitmap::getSize); + + BP_SETSCOPE(Bitmap_class); + bp::enum_("EFileFormat") + .value("EPNG", Bitmap::EPNG) + .value("EEXR", Bitmap::EEXR) + .value("ETGA", Bitmap::ETGA) + .value("EBMP", Bitmap::EBMP) + .value("EJPEG", Bitmap::EJPEG) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_CLASS(FileResolver, Object, bp::init<>()) + .def("resolve", &FileResolver::resolve, BP_RETURN_VALUE) + .def("resolveAbsolute", &FileResolver::resolveAbsolute, BP_RETURN_VALUE) + .def("clone", &FileResolver::clone, BP_RETURN_VALUE) + .def("addPath", &FileResolver::addPath) + .def("clear", &FileResolver::clear); + + void (Random::*random_seed_random)(Random *) = &Random::seed; + void (Random::*random_seed_uint64_t)(uint64_t) = &Random::seed; + BP_CLASS(Random, Object, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def("set", &Random::set) + .def("seed", random_seed_random) + .def("seed", random_seed_uint64_t) + .def("nextULong", &Random::nextULong) + .def("nextUInt", &Random::nextUInt) + .def("nextSize", &Random::nextSize) + .def("nextFloat", &Random::nextFloat) + .def("serialize", &Random::serialize); + + ConfigurableObject *(PluginManager::*pluginmgr_createobject_1)(const Properties &) = &PluginManager::createObject; + ConfigurableObject *(PluginManager::*pluginmgr_createobject_2)(const Class *, const Properties &) = &PluginManager::createObject; + + BP_CLASS(PluginManager, Object, bp::no_init) + .def("ensurePluginLoaded", &PluginManager::ensurePluginLoaded) + .def("getLoadedPlugins", &PluginManager::getLoadedPlugins) + .def("create", pluginmgr_create, BP_RETURN_VALUE) + .def("createObject", pluginmgr_createobject_1, BP_RETURN_VALUE) + .def("createObject", pluginmgr_createobject_2, BP_RETURN_VALUE) + .def("getInstance", &PluginManager::getInstance, BP_RETURN_VALUE) + .staticmethod("getInstance"); + + BP_CLASS(Statistics, Object, bp::no_init) + .def("getStats", &Statistics::getStats, BP_RETURN_VALUE) + .def("printStats", &Statistics::printStats) + .def("getInstance", &Statistics::getInstance, BP_RETURN_VALUE) + .staticmethod("getInstance"); + + BP_CLASS(WorkUnit, Object, bp::no_init) + .def("set", &WorkUnit::set) + .def("load", &WorkUnit::load) + .def("save", &WorkUnit::save); + + BP_CLASS(WorkResult, Object, bp::no_init) + .def("load", &WorkResult::load) + .def("save", &WorkResult::save); + + BP_CLASS(WorkProcessor, SerializableObject, bp::no_init) + .def("createWorkUnit", &WorkProcessor::createWorkUnit, BP_RETURN_VALUE) + .def("createWorkResult", &WorkProcessor::createWorkResult, BP_RETURN_VALUE) + .def("clone", &WorkProcessor::clone, BP_RETURN_VALUE) + .def("prepare", &WorkProcessor::prepare) + .def("process", &WorkProcessor::process); + + BP_CLASS(ParallelProcess, Object, bp::no_init) + .def("generateWork", &ParallelProcess::generateWork) + .def("processResult", &ParallelProcess::processResult) + .def("handleCancellation", &ParallelProcess::handleCancellation) + .def("getReturnStatus", &ParallelProcess::getReturnStatus) + .def("createWorkProcessor", &ParallelProcess::createWorkProcessor) + .def("bindResource", &ParallelProcess::bindResource) + .def("isLocal", &ParallelProcess::isLocal) + .def("getLogLevel", &ParallelProcess::getLogLevel) + .def("getRequiredPlugins", &ParallelProcess::getRequiredPlugins, BP_RETURN_VALUE); + + BP_SETSCOPE(ParallelProcess_class); + bp::enum_("EStatus") + .value("EUnknown", ParallelProcess::EUnknown) + .value("EPause", ParallelProcess::EPause) + .value("ESuccess", ParallelProcess::ESuccess) + .value("EFailure", ParallelProcess::EFailure) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_CLASS(Worker, Thread, bp::no_init) + .def("getCoreCount", &Worker::getCoreCount) + .def("isRemoteWorker", &Worker::isRemoteWorker); + + BP_CLASS(LocalWorker, Worker, bp::init()) + .def(bp::init()); + + BP_CLASS(RemoteWorker, Worker, (bp::init())) + .def("getNodeName", &RemoteWorker::getNodeName, BP_RETURN_VALUE); + + bp::class_("SerializableObjectVector") + .def(bp::vector_indexing_suite()); + + bool (Scheduler::*scheduler_cancel)(ParallelProcess *)= &Scheduler::cancel; + BP_CLASS(Scheduler, Object, bp::no_init) + .def("schedule", &Scheduler::schedule) + .def("wait", &Scheduler::wait) + .def("cancel", scheduler_cancel) + .def("registerResource", &Scheduler::registerResource) + .def("registerManifoldResource", &Scheduler::registerManifoldResource) + .def("retainResource", &Scheduler::retainResource) + .def("unregisterResource", &Scheduler::unregisterResource) + .def("getResourceID", &Scheduler::getResourceID) + .def("registerWorker", &Scheduler::registerWorker) + .def("unregisterWorker", &Scheduler::unregisterWorker) + .def("getWorkerCount", &Scheduler::getWorkerCount) + .def("getLocalWorkerCount", &Scheduler::getLocalWorkerCount) + .def("getWorker", &Scheduler::getWorker, BP_RETURN_VALUE) + .def("start", &Scheduler::start) + .def("pause", &Scheduler::pause) + .def("stop", &Scheduler::stop) + .def("getCoreCount", &Scheduler::getCoreCount) + .def("hasLocalWorkers", &Scheduler::hasLocalWorkers) + .def("hasRemoteWorkers", &Scheduler::hasRemoteWorkers) + .def("getInstance", &Scheduler::getInstance, BP_RETURN_VALUE) + .def("isRunning", &Scheduler::isRunning) + .def("isBusy", &Scheduler::isBusy) + .staticmethod("getInstance"); + + BP_STRUCT(Spectrum, bp::init<>()) + .def("__init__", bp::make_constructor(spectrum_array_constructor)) + .def(bp::init()) + .def(bp::init()) + .def(bp::self != bp::self) + .def(bp::self == bp::self) + .def(-bp::self) + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self *= Float()) + .def(bp::self * Float()) + .def(bp::self *= bp::self) + .def(bp::self * bp::self) + .def(bp::self / Float()) + .def(bp::self /= Float()) + .def(bp::self /= bp::self) + .def(bp::self / bp::self) + .def("isValid", &Spectrum::isValid) + .def("isNaN", &Spectrum::isNaN) + .def("average", &Spectrum::average) + .def("sqrt", &Spectrum::sqrt) + .def("exp", &Spectrum::exp) + .def("pow", &Spectrum::pow) + .def("clampNegative", &Spectrum::clampNegative) + .def("min", &Spectrum::min) + .def("max", &Spectrum::max) + .def("isZero", &Spectrum::isZero) + .def("eval", &Spectrum::eval) + .def("getLuminance", &Spectrum::getLuminance) + .def("fromXYZ", &Spectrum::fromXYZ, fromXYZ_overloads()) + .def("toXYZ", &Spectrum::toXYZ) + .def("fromLinearRGB", &Spectrum::fromLinearRGB, fromLinearRGB_overloads()) + .def("toLinearRGB", &Spectrum::toLinearRGB) + .def("fromSRGB", &Spectrum::fromSRGB) + .def("toSRGB", &Spectrum::toSRGB) + .def("fromContinuousSpectrum", &Spectrum::fromContinuousSpectrum) + .def("serialize", &Spectrum::serialize) + .def("__str__", &Spectrum::toString) + .def("__len__", &spectrum_wrapper::len) + .def("__getitem__", &spectrum_wrapper::get) + .def("__setitem__", &spectrum_wrapper::set); + + BP_SETSCOPE(Spectrum_struct); + bp::enum_("EConversionIntent") + .value("EReflectance", Spectrum::EReflectance) + .value("EIlluminant", Spectrum::EIlluminant) + .export_values(); + BP_SETSCOPE(coreModule); + + bp::class_ properties("Properties"); + properties + .def(bp::init()) + .def("getPluginName", &Properties::getPluginName, BP_RETURN_CONSTREF) + .def("setPluginName", &Properties::setPluginName) + .def("getID", &Properties::getPluginName, BP_RETURN_CONSTREF) + .def("setID", &Properties::setPluginName) + .def("getType", &Properties::getType) + .def("getNames", &Properties::getNames) + .def("hasProperty", &Properties::hasProperty) + .def("wasQueried", &Properties::wasQueried) + .def("markQueried", &Properties::markQueried) + .def("__getitem__", &properties_wrapper::get) + .def("__setitem__", &properties_wrapper::set) + .def("__contains__", &Properties::hasProperty) + .def("__str__", &Properties::toString); + + BP_SETSCOPE(properties); + bp::enum_("EPropertyType") + .value("EBoolean", Properties::EBoolean) + .value("EInteger", Properties::EInteger) + .value("EFloat", Properties::EFloat) + .value("EPoint", Properties::EPoint) + .value("ETransform", Properties::ETransform) + .value("ESpectrum", Properties::ESpectrum) + .value("EString", Properties::EString) + .value("EData", Properties::EData) + .export_values(); + BP_SETSCOPE(coreModule); + + BP_STRUCT(Vector2, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector2::x) + .def_readwrite("y", &Vector2::y); + + BP_STRUCT(Vector2i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector2i::x) + .def_readwrite("y", &Vector2i::y); + + BP_STRUCT(Vector3, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector3::x) + .def_readwrite("y", &Vector3::y) + .def_readwrite("z", &Vector3::z); + + BP_STRUCT(Normal, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Normal::x) + .def_readwrite("y", &Normal::y) + .def_readwrite("z", &Normal::z); + + BP_STRUCT(Vector3i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector3i::x) + .def_readwrite("y", &Vector3i::y) + .def_readwrite("z", &Vector3i::z); + + BP_STRUCT(Vector4, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector4::x) + .def_readwrite("y", &Vector4::y) + .def_readwrite("z", &Vector4::z) + .def_readwrite("w", &Vector4::w); + + BP_STRUCT(Vector4i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Vector4i::x) + .def_readwrite("y", &Vector4i::y) + .def_readwrite("z", &Vector4i::z) + .def_readwrite("w", &Vector4i::w); + + BP_STRUCT(Point2, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point2::x) + .def_readwrite("y", &Point2::y); + + BP_STRUCT(Point2i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point2i::x) + .def_readwrite("y", &Point2i::y); + + BP_STRUCT(Point3, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point3::x) + .def_readwrite("y", &Point3::y) + .def_readwrite("z", &Point3::z); + + BP_STRUCT(Point3i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point3i::x) + .def_readwrite("y", &Point3i::y) + .def_readwrite("z", &Point3i::z); + + BP_STRUCT(Point4, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point4::x) + .def_readwrite("y", &Point4::y) + .def_readwrite("z", &Point4::z) + .def_readwrite("w", &Point4::w); + + BP_STRUCT(Point4i, bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("x", &Point4i::x) + .def_readwrite("y", &Point4i::y) + .def_readwrite("z", &Point4i::z) + .def_readwrite("w", &Point4i::w); + + BP_IMPLEMENT_VECTOR_OPS(Normal, Float, 3); + BP_IMPLEMENT_VECTOR_OPS(Vector2i, int, 2); + BP_IMPLEMENT_VECTOR_OPS(Vector3i, int, 3); + BP_IMPLEMENT_VECTOR_OPS(Vector4i, int, 3); + BP_IMPLEMENT_VECTOR_OPS(Vector2, Float, 2); + BP_IMPLEMENT_VECTOR_OPS(Vector3, Float, 3); + BP_IMPLEMENT_VECTOR_OPS(Vector4, Float, 3); + BP_IMPLEMENT_POINT_OPS(Point2i, int, 2); + BP_IMPLEMENT_POINT_OPS(Point3i, int, 3); + BP_IMPLEMENT_POINT_OPS(Point4i, int, 3); + BP_IMPLEMENT_POINT_OPS(Point2, Float, 2); + BP_IMPLEMENT_POINT_OPS(Point3, Float, 3); + BP_IMPLEMENT_POINT_OPS(Point4, Float, 3); + + Float (*dot2)(const Vector2 &, const Vector2 &) = ˙ + Float (*dot3)(const Vector3 &, const Vector3 &) = ˙ + Float (*dot4)(const Vector4 &, const Vector4 &) = ˙ + Float (*absDot2)(const Vector2 &, const Vector2 &) = &absDot; + Float (*absDot3)(const Vector3 &, const Vector3 &) = &absDot; + Float (*absDot4)(const Vector4 &, const Vector4 &) = &absDot; + Vector2 (*normalize2)(const Vector2 &) = &normalize; + Vector3 (*normalize3)(const Vector3 &) = &normalize; + Vector4 (*normalize4)(const Vector4 &) = &normalize; + Vector3 (*cross3)(const Vector3 &, const Vector3 &) = ✗ + bp::def("dot", dot2); + bp::def("dot", dot3); + bp::def("dot", dot4); + bp::def("absDot", absDot2); + bp::def("absDot", absDot3); + bp::def("absDot", absDot4); + bp::def("normalize", normalize2); + bp::def("normalize", normalize3); + bp::def("normalize", normalize4); + bp::def("cross", cross3); + + bp::scope().attr("Vector") = bp::scope().attr("Vector3"); + bp::scope().attr("Point") = bp::scope().attr("Point3"); + + bp::class_("Matrix4x4", bp::init()) + .def(bp::init()) + .def("__setitem__", &Matrix4x4_setItem) + .def("__getitem__", &Matrix4x4_getItem) + .def("setIdentity", &Matrix4x4::setIdentity) + .def("isZero", &Matrix4x4::isZero) + .def("trace", &Matrix4x4::trace) + .def("det", &Matrix4x4::det) + .def("serialize", &Matrix4x4::serialize) + .def(bp::self != bp::self) + .def(bp::self == bp::self) + .def(-bp::self) + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self + Float()) + .def(bp::self += Float()) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self - Float()) + .def(bp::self -= Float()) + .def(bp::self * Float()) + .def(Float() * bp::self) + .def(bp::self *= Float()) + .def(bp::self * bp::self) + .def(bp::self *= bp::self) + .def(bp::self / Float()) + .def(bp::self /= Float()) + .def("__str__", &Matrix4x4::toString); + + bp::class_("Ray", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("o", &Ray::o) + .def_readwrite("d", &Ray::d) + .def_readwrite("dRcp", &Ray::dRcp) + .def_readwrite("mint", &Ray::mint) + .def_readwrite("maxt", &Ray::maxt) + .def_readwrite("time", &Ray::time) + .def("setOrigin", &Ray::setOrigin) + .def("setDirection", &Ray::setDirection) + .def("setTime", &Ray::setTime) + .def("eval", &ray_eval, BP_RETURN_VALUE) + .def("__str__", &Ray::toString); + + bp::class_("BSphere", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("center", &BSphere::center) + .def_readwrite("radius", &BSphere::radius) + .def("isEmpty", &BSphere::isEmpty) + .def("expandBy", &BSphere::expandBy) + .def("contains", &BSphere::contains) + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def("rayIntersect", &bsphere_rayIntersect) + .def("serialize", &BSphere::serialize) + .def("__str__", &BSphere::toString); + + bp::class_("AABB", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("min", &AABB::min) + .def_readwrite("max", &AABB::max) + .def("getSurfaceArea", &AABB::getSurfaceArea) + .def("getVolume", &AABB::getVolume) + .def("getCorner", &AABB::getCorner, BP_RETURN_VALUE) + .def("overlaps", &AABB::overlaps) + .def("getCenter", &AABB::getCenter, BP_RETURN_VALUE) + .def("reset", &AABB::reset) + .def("clip", &AABB::clip) + .def("isValid", &AABB::isValid) + .def("expandBy", &aabb_expandby_aabb) + .def("expandBy", &aabb_expandby_point) + .def("distanceTo", &aabb_distanceto_aabb) + .def("distanceTo", &aabb_distanceto_point) + .def("squaredDistanceTo", &aabb_sqrdistanceto_aabb) + .def("squaredDistanceTo", &aabb_sqrdistanceto_point) + .def("contains", &aabb_contains_aabb) + .def("contains", &aabb_contains_point) + .def("getLargestAxis", &AABB::getLargestAxis) + .def("getShortestAxis", &AABB::getShortestAxis) + .def("getExtents", &AABB::getExtents, BP_RETURN_VALUE) + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def("rayIntersect", &aabb_rayIntersect) + .def("getBSphere", &AABB::getBSphere, BP_RETURN_VALUE) + .def("serialize", &AABB::serialize) + .def("__str__", &AABB::toString); + + bp::class_("Frame", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def_readwrite("s", &Frame::s) + .def_readwrite("t", &Frame::t) + .def_readwrite("n", &Frame::n) + .def("serialize", &Frame::serialize) + .def("toLocal", &Frame::toLocal, BP_RETURN_VALUE) + .def("toWorld", &Frame::toWorld, BP_RETURN_VALUE) + .def("__str__", &Frame::toString) + .def("cosTheta", &Frame::cosTheta) + .def("sinTheta", &Frame::sinTheta) + .def("sinTheta2", &Frame::sinTheta2) + .def("tanTheta", &Frame::tanTheta) + .def("sinPhi", &Frame::sinPhi) + .def("cosPhi", &Frame::cosPhi) + .def("sinPhi2", &Frame::sinPhi2) + .def("cosPhi2", &Frame::cosPhi2) + .staticmethod("cosTheta") + .staticmethod("sinTheta") + .staticmethod("sinTheta2") + .staticmethod("tanTheta") + .staticmethod("sinPhi") + .staticmethod("cosPhi") + .staticmethod("sinPhi2") + .staticmethod("cosPhi2"); + + bp::class_("Transform", bp::init<>()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def("inverse", &Transform::inverse, BP_RETURN_VALUE) + .def("getMatrix", &Transform::getMatrix, BP_RETURN_VALUE) + .def("getInverseMatrix", &Transform::getInverseMatrix, BP_RETURN_VALUE) + .def("det3x3", &Transform::det3x3) + .def("hasScale", &Transform::hasScale) + .def("isIdentity", &Transform::isIdentity) + .def("serialize", &Transform::serialize) + .def("__mul__", &transform_mul_transform, BP_RETURN_VALUE) + .def("__mul__", &transform_mul_point, BP_RETURN_VALUE) + .def("__mul__", &transform_mul_vector, BP_RETURN_VALUE) + .def("__mul__", &transform_mul_vector4, BP_RETURN_VALUE) + .def("__mul__", &transform_mul_normal, BP_RETURN_VALUE) + .def("__mul__", &transform_mul_ray, BP_RETURN_VALUE) + .def("__str__", &Transform::toString) + .def("translate", &Transform::translate, BP_RETURN_VALUE) + .def("rotate", &Transform::rotate, BP_RETURN_VALUE) + .def("scale", &Transform::scale, BP_RETURN_VALUE) + .def("lookAt", &Transform::lookAt, BP_RETURN_VALUE) + .def("perspective", &Transform::perspective, BP_RETURN_VALUE) + .def("orthographic", &Transform::orthographic, BP_RETURN_VALUE) + .def("glPerspective", &Transform::glPerspective, BP_RETURN_VALUE) + .def("glFrustum", &Transform::glFrustum, BP_RETURN_VALUE) + .def("glOrthographic", &Transform::glOrthographic, BP_RETURN_VALUE) + .def("fromFrame", &Transform::fromFrame, BP_RETURN_VALUE) + .staticmethod("translate") + .staticmethod("rotate") + .staticmethod("scale") + .staticmethod("lookAt") + .staticmethod("perspective") + .staticmethod("orthographic") + .staticmethod("glPerspective") + .staticmethod("glFrustum") + .staticmethod("glOrthographic") + .staticmethod("fromFrame"); + + bp::detail::current_scope = oldScope; +} + +BOOST_PYTHON_MODULE(mitsuba) { + bp::object package = bp::scope(); + package.attr("__path__") = "mitsuba"; + + /* Automatically take care of the framework + initialization / shutdown */ + initializeFramework(); + atexit(shutdownFramework); + + export_core(); + export_render(); +} diff --git a/src/librender/SConscript b/src/librender/SConscript index 418534e4..1509c8e8 100644 --- a/src/librender/SConscript +++ b/src/librender/SConscript @@ -23,7 +23,7 @@ librender = renderEnv.SharedLibrary('mitsuba-render', [ ]) if sys.platform == "darwin": - renderEnv.AddPostAction(librender, 'install_name_tool -id @executable_path/../Frameworks/libmitsuba-render.dylib $TARGET') + renderEnv.AddPostAction(librender, 'install_name_tool -id @loader_path/../Frameworks/libmitsuba-render.dylib $TARGET') env.Append(LIBS=['mitsuba-render']) env.Append(LIBPATH=[os.path.join(env['BUILDDIR'], 'librender')]) diff --git a/src/librender/bsdf.cpp b/src/librender/bsdf.cpp index 8c7cb965..761eae7f 100644 --- a/src/librender/bsdf.cpp +++ b/src/librender/bsdf.cpp @@ -87,7 +87,7 @@ Texture *BSDF::ensureEnergyConservation(Texture *texture, props.setFloat("scale", scale); Texture *scaleTexture = static_cast (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); - scaleTexture->addChild("", texture); + scaleTexture->addChild(texture); scaleTexture->configure(); return scaleTexture; } @@ -117,9 +117,9 @@ std::pair BSDF::ensureEnergyConservation( createObject(MTS_CLASS(Texture), props)); Texture *scaleTexture2 = static_cast (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); - scaleTexture1->addChild("", tex1); + scaleTexture1->addChild(tex1); scaleTexture1->configure(); - scaleTexture2->addChild("", tex2); + scaleTexture2->addChild(tex2); scaleTexture2->configure(); return std::make_pair(scaleTexture1, scaleTexture2); } diff --git a/src/librender/renderjob.cpp b/src/librender/renderjob.cpp index 9015f7d2..fee14093 100644 --- a/src/librender/renderjob.cpp +++ b/src/librender/renderjob.cpp @@ -22,10 +22,10 @@ MTS_NAMESPACE_BEGIN RenderJob::RenderJob(const std::string &threadName, - Scene *scene, RenderQueue *queue, TestSupervisor *testSupervisor, - int sceneResID, int cameraResID, int samplerResID, bool threadIsCritical, - bool visualFeedback) : Thread(threadName), m_scene(scene), m_queue(queue), - m_testSupervisor(testSupervisor), m_visualFeedback(visualFeedback) { + Scene *scene, RenderQueue *queue, int sceneResID, int cameraResID, + int samplerResID, bool threadIsCritical, TestSupervisor *supervisor) + : Thread(threadName), m_scene(scene), m_queue(queue), + m_testSupervisor(supervisor) { /* Optional: bring the process down when this thread crashes */ setCritical(threadIsCritical); diff --git a/src/librender/scene.cpp b/src/librender/scene.cpp index 47cc80e1..2a98dd99 100644 --- a/src/librender/scene.cpp +++ b/src/librender/scene.cpp @@ -20,10 +20,20 @@ #include #include +#define DEFAULT_BLOCKSIZE 32 + MTS_NAMESPACE_BEGIN +Scene::Scene() + : NetworkedObject(Properties()), m_blockSize(DEFAULT_BLOCKSIZE) { + m_kdtree = new ShapeKDTree(); + m_testType = ENone; + m_testThresh = 0.0f; + m_importanceSampleLuminaires = true; +} + Scene::Scene(const Properties &props) - : NetworkedObject(props), m_blockSize(32) { + : NetworkedObject(props), m_blockSize(DEFAULT_BLOCKSIZE) { m_kdtree = new ShapeKDTree(); /* When test case mode is active (Mitsuba is started with the -t parameter), this specifies the type of test performed. Mitsuba will expect a reference @@ -44,7 +54,7 @@ Scene::Scene(const Properties &props) Log(EError, "Unknown test mode \"%s\" specified (must be \"t-test\" or \"relerr\")", testType.c_str()); /* Error threshold for use with testType */ - m_testThresh = props.getFloat("testThresh", 0.01); + m_testThresh = props.getFloat("testThresh", 0.01f); /* By default, luminaire sampling chooses a luminaire with a probability dependent on the emitted power. Setting this parameter to false switches to uniform sampling. */ @@ -288,7 +298,7 @@ void Scene::initialize() { skyProps.setBoolean("extend", true); ref luminaire = static_cast( PluginManager::getInstance()->createObject(MTS_CLASS(Luminaire), skyProps)); - addChild("", luminaire); + addChild(luminaire); luminaire->configure(); } diff --git a/src/librender/scenehandler.cpp b/src/librender/scenehandler.cpp index b47ee311..9f93fcca 100644 --- a/src/librender/scenehandler.cpp +++ b/src/librender/scenehandler.cpp @@ -321,12 +321,18 @@ void SceneHandler::endElement(const XMLCh* const xmlName) { mtx.m[i][j] = parseFloat(name, tokens[index++]); m_transform = Transform(mtx) * m_transform; - } else if (name == "point" || name == "vector") { + } else if (name == "point") { Float x = parseFloat(name, context.attributes["x"]); Float y = parseFloat(name, context.attributes["y"]); Float z = parseFloat(name, context.attributes["z"]); context.parent->properties.setPoint(context.attributes["name"], Point(x, y, z)); + } else if (name == "vector") { + Float x = parseFloat(name, context.attributes["x"]); + Float y = parseFloat(name, context.attributes["y"]); + Float z = parseFloat(name, context.attributes["z"]); + + context.parent->properties.setVector(context.attributes["name"], Vector(x, y, z)); } else if (name == "rgb") { Spectrum::EConversionIntent intent = Spectrum::EReflectance; if (context.attributes.find("intent") != context.attributes.end()) { @@ -550,4 +556,48 @@ void SceneHandler::fatalError(const SAXParseException& e) { transcode(e.getMessage()).c_str()); } +// ----------------------------------------------------------------------- + +ref SceneHandler::loadScene(const fs::path &filename, const ParameterMap ¶ms) { + /* Prepare for parsing scene descriptions */ + FileResolver *resolver = Thread::getThread()->getFileResolver(); + SAXParser* parser = new SAXParser(); + fs::path schemaPath = resolver->resolveAbsolute("data/schema/scene.xsd"); + SLog(EDebug, "Loading scene \"%s\" ..", filename.file_string().c_str()); + + /* Check against the 'scene.xsd' XML Schema */ + parser->setDoSchema(true); + parser->setValidationSchemaFullChecking(true); + parser->setValidationScheme(SAXParser::Val_Always); + parser->setExternalNoNamespaceSchemaLocation(schemaPath.file_string().c_str()); + parser->setCalculateSrcOfs(true); + + SceneHandler *handler = new SceneHandler(parser, params); + parser->setDoNamespaces(true); + parser->setDocumentHandler(handler); + parser->setErrorHandler(handler); + + parser->parse(filename.file_string().c_str()); + ref scene = handler->getScene(); + + delete parser; + delete handler; + + return scene; +} + +void SceneHandler::staticInitialization() { + /* Initialize Xerces-C */ + try { + XMLPlatformUtils::Initialize(); + } catch(const XMLException &toCatch) { + SLog(EError, "Error during Xerces initialization: %s", + XMLString::transcode(toCatch.getMessage())); + } +} + +void SceneHandler::staticShutdown() { + XMLPlatformUtils::Terminate(); +} + MTS_NAMESPACE_END diff --git a/src/librender/shape.cpp b/src/librender/shape.cpp index 4fd70cc1..be973b11 100644 --- a/src/librender/shape.cpp +++ b/src/librender/shape.cpp @@ -49,7 +49,7 @@ void Shape::configure() { tracer implementation to work correctly. */ Properties props("diffuse"); props.setSpectrum("reflectance", Spectrum(0.0f)); - addChild("", static_cast (PluginManager::getInstance()-> + addChild(static_cast (PluginManager::getInstance()-> createObject(MTS_CLASS(BSDF), props))); } } diff --git a/src/librender/util.cpp b/src/librender/util.cpp index f7315848..3574b191 100644 --- a/src/librender/util.cpp +++ b/src/librender/util.cpp @@ -26,31 +26,7 @@ MTS_NAMESPACE_BEGIN ref Utility::loadScene(const std::string &filename, const ParameterMap ¶ms) { - /* Prepare for parsing scene descriptions */ - FileResolver *resolver = Thread::getThread()->getFileResolver(); - SAXParser* parser = new SAXParser(); - fs::path schemaPath = resolver->resolveAbsolute("data/schema/scene.xsd"); - Log(EDebug, "Loading scene \"%s\" ..", filename.c_str()); - - /* Check against the 'scene.xsd' XML Schema */ - parser->setDoSchema(true); - parser->setValidationSchemaFullChecking(true); - parser->setValidationScheme(SAXParser::Val_Always); - parser->setExternalNoNamespaceSchemaLocation(schemaPath.file_string().c_str()); - parser->setCalculateSrcOfs(true); - - SceneHandler *handler = new SceneHandler(parser, params); - parser->setDoNamespaces(true); - parser->setDocumentHandler(handler); - parser->setErrorHandler(handler); - - parser->parse(filename.c_str()); - ref scene = handler->getScene(); - - delete parser; - delete handler; - - return scene; + return SceneHandler::loadScene(filename, params); } MTS_IMPLEMENT_CLASS(Utility, true, Object) diff --git a/src/luminaires/point.cpp b/src/luminaires/point.cpp index c519a76b..7b04b94a 100644 --- a/src/luminaires/point.cpp +++ b/src/luminaires/point.cpp @@ -27,6 +27,12 @@ class PointLuminaire : public Luminaire { public: PointLuminaire(const Properties &props) : Luminaire(props) { m_intensity = props.getSpectrum("intensity", Spectrum(1)); + if (props.hasProperty("position")) { + if (props.hasProperty("toWorld")) + Log(EError, "Please specify either 'toWorld' or 'position'"); + m_luminaireToWorld = Transform::translate(Vector(props.getPoint("position"))); + m_worldToLuminaire = m_luminaireToWorld.inverse(); + } m_position = m_luminaireToWorld(Point(0,0,0)); m_type = EDeltaPosition | EDiffuseDirection; } diff --git a/src/mitsuba/SConscript b/src/mitsuba/SConscript index 5982f167..4ac8f392 100644 --- a/src/mitsuba/SConscript +++ b/src/mitsuba/SConscript @@ -20,9 +20,7 @@ if mainEnv.has_key('GLINCLUDE'): if sys.platform == 'darwin': # On OSX, we need this stub to access OpenGL from the command line mainEnv_osx = mainEnv.Clone() - mainEnv_osx['CXXFLAGS'].remove('-fstrict-aliasing') - mainEnv_osx['CXXFLAGS'].remove('-ftree-vectorize') - mainEnv_osx['CXXFLAGS'].append('-fno-strict-aliasing') + mainEnv_osx.ConfigureForObjectiveCPP() stubs += [mainEnv_osx.StaticObject('darwin_stub.mm')] mainEnv.Program('mtsutil', resources + stubs + ['mtsutil.cpp']) diff --git a/src/mitsuba/darwin_stub.mm b/src/mitsuba/darwin_stub.mm index 43ae081e..cf5930ea 100644 --- a/src/mitsuba/darwin_stub.mm +++ b/src/mitsuba/darwin_stub.mm @@ -18,11 +18,11 @@ #import -extern int ubi_main(int argc, char **argv); +extern int mts_main(int argc, char **argv); int main(int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - int retval = ubi_main(argc, argv); + int retval = mts_main(argc, argv); [pool release]; return retval; } diff --git a/src/mitsuba/mitsuba.cpp b/src/mitsuba/mitsuba.cpp index c3eec8a4..e83f2827 100644 --- a/src/mitsuba/mitsuba.cpp +++ b/src/mitsuba/mitsuba.cpp @@ -109,7 +109,7 @@ private: int m_timeout; }; -int ubi_main(int argc, char **argv) { +int mts_main(int argc, char **argv) { char optchar, *end_ptr = NULL; try { @@ -362,8 +362,7 @@ int ubi_main(int argc, char **argv) { continue; ref thr = new RenderJob(formatString("ren%i", jobIdx++), - scene, renderQueue, testSupervisor, -1, -1, -1, true, - flushTimer > 0); + scene, renderQueue, -1, -1, -1, true, testSupervisor); thr->start(); renderQueue->waitLeft(numParallelScenes-1); @@ -403,6 +402,7 @@ int main(int argc, char **argv) { Spectrum::staticInitialization(); Scheduler::staticInitialization(); SHVector::staticInitialization(); + SceneHandler::staticInitialization(); #ifdef WIN32 /* Initialize WINSOCK2 */ @@ -418,20 +418,10 @@ int main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); #endif - /* Initialize Xerces-C */ - try { - XMLPlatformUtils::Initialize(); - } catch(const XMLException &toCatch) { - SLog(EError, "Error during Xerces initialization: %s", - XMLString::transcode(toCatch.getMessage())); - return -1; - } - - int retval = ubi_main(argc, argv); - - XMLPlatformUtils::Terminate(); + int retval = mts_main(argc, argv); /* Shutdown the core framework */ + SceneHandler::staticShutdown(); SHVector::staticShutdown(); Scheduler::staticShutdown(); Spectrum::staticShutdown(); diff --git a/src/mitsuba/mtssrv.cpp b/src/mitsuba/mtssrv.cpp index 58403ec5..8f985d6a 100644 --- a/src/mitsuba/mtssrv.cpp +++ b/src/mitsuba/mtssrv.cpp @@ -87,7 +87,7 @@ void collect_zombies(int s) { } #endif -int ubi_main(int argc, char **argv) { +int mts_main(int argc, char **argv) { char optchar, *end_ptr = NULL; try { @@ -401,7 +401,7 @@ int main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); #endif - int retval = ubi_main(argc, argv); + int retval = mts_main(argc, argv); /* Shutdown the core framework */ SHVector::staticShutdown(); diff --git a/src/mitsuba/mtsutil.cpp b/src/mitsuba/mtsutil.cpp index 90b57dd8..bed81188 100644 --- a/src/mitsuba/mtsutil.cpp +++ b/src/mitsuba/mtsutil.cpp @@ -363,7 +363,7 @@ int mtsutil(int argc, char **argv) { return 0; } -int ubi_main(int argc, char **argv) { +int mts_main(int argc, char **argv) { /* Initialize the core framework */ Class::staticInitialization(); PluginManager::staticInitialization(); @@ -373,6 +373,7 @@ int ubi_main(int argc, char **argv) { Spectrum::staticInitialization(); Scheduler::staticInitialization(); SHVector::staticInitialization(); + SceneHandler::staticInitialization(); #ifdef WIN32 /* Initialize WINSOCK2 */ @@ -388,20 +389,10 @@ int ubi_main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); #endif - /* Initialize Xerces-C */ - try { - XMLPlatformUtils::Initialize(); - } catch(const XMLException &toCatch) { - SLog(EError, "Error during Xerces initialization: %s", - XMLString::transcode(toCatch.getMessage())); - return -1; - } - int retval = mtsutil(argc, argv); - XMLPlatformUtils::Terminate(); - /* Shutdown the core framework */ + SceneHandler::staticShutdown(); SHVector::staticShutdown(); Scheduler::staticShutdown(); Spectrum::staticShutdown(); @@ -421,7 +412,7 @@ int ubi_main(int argc, char **argv) { #if !defined(__OSX__) int main(int argc, char **argv) { - return ubi_main(argc, argv); + return mts_main(argc, argv); } #endif diff --git a/src/qtgui/SConscript b/src/mtsgui/SConscript similarity index 61% rename from src/qtgui/SConscript rename to src/mtsgui/SConscript index 937eb462..7924c583 100644 --- a/src/qtgui/SConscript +++ b/src/mtsgui/SConscript @@ -21,7 +21,7 @@ def scanFiles(dir, accept=["*.cpp"], reject=[]) : if hasQt: qtEnv = mainEnv.Clone() - qtEnv.Append(CPPPATH=['#src/qtgui']) + qtEnv.Append(CPPPATH=['#src/mtsgui']) qtEnv.EnableQt4Modules(['QtGui', 'QtCore', 'QtOpenGL', 'QtXml', 'QtXmlPatterns', 'QtNetwork']) if sys.platform == 'win32': index = qtEnv['CXXFLAGS'].index('_CONSOLE') @@ -33,9 +33,11 @@ if hasQt: qtEnv.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) qtEnv.Append(LIBS=['qtmain']) elif sys.platform == 'darwin': - qtEnv.Append(LINKFLAGS=['-Fdependencies/darwin', '-framework', 'BWToolkitFramework']) + qtEnv.Append(LINKFLAGS=['-Fdependencies/darwin', '-framework', + 'BWToolkitFramework', '-framework', 'Security']) + qtEnv.Append(CPPFLAGS=['-I', '/System/Library/Frameworks/Security.framework/Headers']) - bpath = env.GetBuildPath('#src/qtgui') + bpath = env.GetBuildPath('#src/mtsgui') qtInterfaces = [qtEnv.Uic4(uic) for uic in scanFiles(bpath, ['*.ui'])] qtResources = [qtEnv.Qrc(qrc) for qrc in scanFiles(bpath, ['*.qrc'])] qtSources = scanFiles(bpath, ['*.cpp']) + qtResources + resources @@ -46,23 +48,23 @@ if hasQt: qtEnv.Prepend(LIBPATH=env['COLLADALIBDIR']) if env.has_key('COLLADALIB'): qtEnv.Prepend(LIBS=env['COLLADALIB']) - + if sys.platform == 'darwin': + mainEnv_osx = mainEnv.Clone() qtEnv_osx = qtEnv.Clone() - # Objective C++ does not permit the following optimization flags - qtEnv_osx['CXXFLAGS'].remove('-fstrict-aliasing') - qtEnv_osx['CXXFLAGS'].remove('-ftree-vectorize') - qtEnv_osx['CXXFLAGS'].append('-fno-strict-aliasing') + mainEnv_osx.ConfigureForObjectiveCPP() + qtEnv_osx.ConfigureForObjectiveCPP() + mainEnv_osx.Program('symlinks_install', ['symlinks_install.c']) qtEnv_osx['CXXFLAGS'].append(['-Fdependencies/darwin', '-framework', 'BWToolkitFramework']) qtSources += qtEnv_osx.StaticObject('previewsettingsdlg_cocoa_impl.mm') else: qtSources = [x for x in qtSources if (not isinstance(x, str) or 'cocoa' not in x)] - qtgui = qtEnv.Program('mtsgui', qtSources) + mtsgui = qtEnv.Program('mtsgui', qtSources) if sys.platform == 'darwin': - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui $TARGET') - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore $TARGET') - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtOpenGL.framework/Versions/4/QtOpenGL @executable_path/../Frameworks/QtOpenGL $TARGET') - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtXml.framework/Versions/4/QtXml @executable_path/../Frameworks/QtXml $TARGET') - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork $TARGET') - qtEnv.AddPostAction(qtgui, 'install_name_tool -change QtXmlPatterns.framework/Versions/4/QtXmlPatterns @executable_path/../Frameworks/QtXmlPatterns $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @loader_path/../Frameworks/QtGui $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtOpenGL.framework/Versions/4/QtOpenGL @loader_path/../Frameworks/QtOpenGL $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtXml.framework/Versions/4/QtXml @loader_path/../Frameworks/QtXml $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @loader_path/../Frameworks/QtNetwork $TARGET') + qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtXmlPatterns.framework/Versions/4/QtXmlPatterns @loader_path/../Frameworks/QtXmlPatterns $TARGET') diff --git a/src/qtgui/aboutdlg.cpp b/src/mtsgui/aboutdlg.cpp similarity index 100% rename from src/qtgui/aboutdlg.cpp rename to src/mtsgui/aboutdlg.cpp diff --git a/src/qtgui/aboutdlg.h b/src/mtsgui/aboutdlg.h similarity index 100% rename from src/qtgui/aboutdlg.h rename to src/mtsgui/aboutdlg.h diff --git a/src/qtgui/aboutdlg.ui b/src/mtsgui/aboutdlg.ui similarity index 100% rename from src/qtgui/aboutdlg.ui rename to src/mtsgui/aboutdlg.ui diff --git a/src/qtgui/acknowledgmentdlg.cpp b/src/mtsgui/acknowledgmentdlg.cpp similarity index 100% rename from src/qtgui/acknowledgmentdlg.cpp rename to src/mtsgui/acknowledgmentdlg.cpp diff --git a/src/qtgui/acknowledgmentdlg.h b/src/mtsgui/acknowledgmentdlg.h similarity index 100% rename from src/qtgui/acknowledgmentdlg.h rename to src/mtsgui/acknowledgmentdlg.h diff --git a/src/qtgui/acknowledgmentdlg.ui b/src/mtsgui/acknowledgmentdlg.ui similarity index 100% rename from src/qtgui/acknowledgmentdlg.ui rename to src/mtsgui/acknowledgmentdlg.ui diff --git a/src/qtgui/addserverdlg.cpp b/src/mtsgui/addserverdlg.cpp similarity index 100% rename from src/qtgui/addserverdlg.cpp rename to src/mtsgui/addserverdlg.cpp diff --git a/src/qtgui/addserverdlg.h b/src/mtsgui/addserverdlg.h similarity index 100% rename from src/qtgui/addserverdlg.h rename to src/mtsgui/addserverdlg.h diff --git a/src/qtgui/addserverdlg.ui b/src/mtsgui/addserverdlg.ui similarity index 100% rename from src/qtgui/addserverdlg.ui rename to src/mtsgui/addserverdlg.ui diff --git a/src/qtgui/common.h b/src/mtsgui/common.h similarity index 100% rename from src/qtgui/common.h rename to src/mtsgui/common.h diff --git a/src/qtgui/glwidget.cpp b/src/mtsgui/glwidget.cpp similarity index 100% rename from src/qtgui/glwidget.cpp rename to src/mtsgui/glwidget.cpp diff --git a/src/qtgui/glwidget.h b/src/mtsgui/glwidget.h similarity index 100% rename from src/qtgui/glwidget.h rename to src/mtsgui/glwidget.h diff --git a/src/qtgui/importdlg.cpp b/src/mtsgui/importdlg.cpp similarity index 100% rename from src/qtgui/importdlg.cpp rename to src/mtsgui/importdlg.cpp diff --git a/src/qtgui/importdlg.h b/src/mtsgui/importdlg.h similarity index 100% rename from src/qtgui/importdlg.h rename to src/mtsgui/importdlg.h diff --git a/src/qtgui/importdlg.ui b/src/mtsgui/importdlg.ui similarity index 100% rename from src/qtgui/importdlg.ui rename to src/mtsgui/importdlg.ui diff --git a/src/qtgui/loaddlg.cpp b/src/mtsgui/loaddlg.cpp similarity index 100% rename from src/qtgui/loaddlg.cpp rename to src/mtsgui/loaddlg.cpp diff --git a/src/qtgui/loaddlg.h b/src/mtsgui/loaddlg.h similarity index 100% rename from src/qtgui/loaddlg.h rename to src/mtsgui/loaddlg.h diff --git a/src/qtgui/loaddlg.ui b/src/mtsgui/loaddlg.ui similarity index 100% rename from src/qtgui/loaddlg.ui rename to src/mtsgui/loaddlg.ui diff --git a/src/qtgui/locateresourcedlg.cpp b/src/mtsgui/locateresourcedlg.cpp similarity index 100% rename from src/qtgui/locateresourcedlg.cpp rename to src/mtsgui/locateresourcedlg.cpp diff --git a/src/qtgui/locateresourcedlg.h b/src/mtsgui/locateresourcedlg.h similarity index 100% rename from src/qtgui/locateresourcedlg.h rename to src/mtsgui/locateresourcedlg.h diff --git a/src/qtgui/locateresourcedlg.ui b/src/mtsgui/locateresourcedlg.ui similarity index 100% rename from src/qtgui/locateresourcedlg.ui rename to src/mtsgui/locateresourcedlg.ui diff --git a/src/qtgui/logwidget.cpp b/src/mtsgui/logwidget.cpp similarity index 100% rename from src/qtgui/logwidget.cpp rename to src/mtsgui/logwidget.cpp diff --git a/src/qtgui/logwidget.h b/src/mtsgui/logwidget.h similarity index 100% rename from src/qtgui/logwidget.h rename to src/mtsgui/logwidget.h diff --git a/src/qtgui/main.cpp b/src/mtsgui/main.cpp similarity index 93% rename from src/qtgui/main.cpp rename to src/mtsgui/main.cpp index 3269ba01..c14d1634 100644 --- a/src/qtgui/main.cpp +++ b/src/mtsgui/main.cpp @@ -16,7 +16,6 @@ along with this program. If not, see . */ -#include #include #include #include @@ -24,6 +23,7 @@ #include #include #include +#include #if defined(__OSX__) #include #endif @@ -88,15 +88,6 @@ void collect_zombies(int s) { int main(int argc, char *argv[]) { int retval; - /* Initialize Xerces-C */ - try { - XMLPlatformUtils::Initialize(); - } catch(const XMLException &toCatch) { - fprintf(stderr, "Error during Xerces initialization: %s", - XMLString::transcode(toCatch.getMessage())); - return -1; - } - /* Initialize the core framework */ Class::staticInitialization(); PluginManager::staticInitialization(); @@ -107,6 +98,7 @@ int main(int argc, char *argv[]) { Spectrum::staticInitialization(); Scheduler::staticInitialization(); SHVector::staticInitialization(); + SceneHandler::staticInitialization(); #if defined(__LINUX__) XInitThreads(); @@ -167,7 +159,7 @@ int main(int argc, char *argv[]) { /* Create a log file inside the application bundle */ MTS_AUTORELEASE_BEGIN() logger->addAppender(new StreamAppender(formatString("%s/mitsuba.%s.log", - __ubi_bundlepath().c_str(), getHostName().c_str()))); + __mts_bundlepath().c_str(), getHostName().c_str()))); MTS_AUTORELEASE_END() #else /* Create a log file inside the current working directory */ @@ -191,7 +183,6 @@ int main(int argc, char *argv[]) { } Statistics::getInstance()->printStats(); - XMLPlatformUtils::Terminate(); #ifdef WIN32 /* Shut down WINSOCK2 */ @@ -199,6 +190,7 @@ int main(int argc, char *argv[]) { #endif /* Shutdown the core framework */ + SceneHandler::staticShutdown(); SHVector::staticShutdown(); Scheduler::staticShutdown(); Spectrum::staticShutdown(); diff --git a/src/qtgui/mainwindow.cpp b/src/mtsgui/mainwindow.cpp similarity index 97% rename from src/qtgui/mainwindow.cpp rename to src/mtsgui/mainwindow.cpp index fc2c6ef2..f58d7bd9 100644 --- a/src/qtgui/mainwindow.cpp +++ b/src/mtsgui/mainwindow.cpp @@ -50,6 +50,8 @@ #include "previewsettingsdlg.h" #endif +extern bool create_symlinks(); + static int localWorkerCtr = 0, remoteWorkerCtr = 0; MainWindow::MainWindow(QWidget *parent) : @@ -61,7 +63,7 @@ MainWindow::MainWindow(QWidget *parent) : m_previewSettings = NULL; #endif - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); logger->setLogLevel((ELogLevel) settings.value("verbosity", EDebug).toInt()); m_logWidget = new LogWidget(NULL); @@ -85,6 +87,12 @@ MainWindow::MainWindow(QWidget *parent) : ui->actionUpdateCheck->setMenuRole(QAction::ApplicationSpecificRole); ui->actionFeedback->setMenuRole(QAction::ApplicationSpecificRole); ui->actionReportBug->setMenuRole(QAction::ApplicationSpecificRole); + ui->actionEnableCommandLine->setMenuRole(QAction::ApplicationSpecificRole); + +#if !defined(__OSX__) + ui->actionEnableCommandLine->setVisible(false); +#endif + m_progressWidget = new QWidget(centralWidget()); m_progressLabel = new QLabel(m_progressWidget); m_progress = new QProgressBar(m_progressWidget); @@ -194,7 +202,7 @@ MainWindow::MainWindow(QWidget *parent) : m_networkManager = new QNetworkAccessManager(this); -#if defined(__OSX__) +#if defined(__OSX__) && 0 // Disable crash reports for now /* Submit crash reports on OSX */ QDir crashDir = QDir::home(); crashDir.cd("Library/Logs/CrashReporter"); @@ -305,7 +313,7 @@ MainWindow::~MainWindow() { } void MainWindow::initWorkers() { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); ref scheduler = Scheduler::getInstance(); int localWorkerCount = settings.value("localWorkers", getProcessorCount()).toInt(); m_workerPriority = (Thread::EThreadPriority) @@ -398,7 +406,7 @@ void MainWindow::checkForUpdates(bool manualUpdateCheck) { void MainWindow::onNetworkFinished(QNetworkReply *reply) { if (reply->error() == QNetworkReply::NoError) { try { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); Version remote(QString(reply->readAll()).toStdString()); Version ignoredVersion(settings.value("ignoredVersion", "0.0.0").toString().toStdString()); Version local(MTS_VERSION); @@ -571,7 +579,7 @@ void MainWindow::on_actionOpen_triggered() { dialog->setAcceptMode(QFileDialog::AcceptOpen); dialog->setViewMode(QFileDialog::Detail); dialog->setWindowModality(Qt::WindowModal); - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); dialog->restoreState(settings.value("fileDialogState").toByteArray()); connect(dialog, SIGNAL(finished(int)), this, SLOT(onOpenDialogClose(int))); m_currentChild = dialog; @@ -583,7 +591,7 @@ void MainWindow::on_actionOpen_triggered() { } void MainWindow::onOpenDialogClose(int reason) { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); QFileDialog *dialog = static_cast(sender()); m_currentChild = NULL; if (reason == QDialog::Accepted) { @@ -605,7 +613,7 @@ void MainWindow::onOpenRecent() { } void MainWindow::onClearRecent() { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); for (int j = 0; j < MAX_RECENT_FILES; ++j) m_actRecent[j]->setVisible(false); settings.setValue("recentFileList", QStringList()); @@ -714,7 +722,7 @@ void MainWindow::loadFile(QString filename) { void MainWindow::addRecentFile(QString fileName) { /* Update recent files list */ - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); QStringList files = settings.value("recentFileList").toStringList(); files.removeAll(fileName); files.prepend(fileName); @@ -731,7 +739,7 @@ void MainWindow::addRecentFile(QString fileName) { } void MainWindow::updateRecentFileActions() { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); QStringList files = settings.value("recentFileList").toStringList(); int numRecentFiles = qMin(files.size(), MAX_RECENT_FILES); @@ -931,7 +939,7 @@ bool MainWindow::on_tabBar_tabCloseRequested(int index) { } void MainWindow::closeEvent(QCloseEvent *event) { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); settings.setValue("pos", pos()); for (int i=ui->tabBar->count()-1; i>=0; --i) { if (!on_tabBar_tabCloseRequested(i)) { @@ -1037,7 +1045,7 @@ void MainWindow::on_actionPreviewSettings_triggered() { connect(&d, SIGNAL(diffuseSourcesChanged(bool)), ui->glView, SLOT(setDiffuseSources(bool))); d.setMaximumSize(d.minimumSize()); d.exec(); - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); settings.setValue("preview_sRGB", context->srgb); settings.setValue("preview_gamma", context->gamma); settings.setValue("preview_exposure", context->exposure); @@ -1080,7 +1088,7 @@ void MainWindow::onPreviewSettingsClose() { ui->actionPreviewSettings->setEnabled(hasTab); if (hasTab) { SceneContext *context = m_context[index]; - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); settings.setValue("preview_sRGB", context->srgb); settings.setValue("preview_gamma", context->gamma); settings.setValue("preview_exposure", context->exposure); @@ -1135,7 +1143,7 @@ void MainWindow::on_actionSettings_triggered() { for (int i=0; iscene; scene->setBlockSize(m_blockSize); - context->renderJob = new RenderJob("rend", scene, m_renderQueue, NULL, - context->sceneResID, -1, -1, false, true); + context->renderJob = new RenderJob("rend", scene, m_renderQueue, + context->sceneResID, -1, -1, false); context->cancelMode = ERender; if (context->mode != ERender) ui->glView->downloadFramebuffer(); @@ -1292,7 +1300,7 @@ void MainWindow::on_actionExportImage_triggered() { "", tr("All supported formats (*.exr *.png *.jpg *.jpeg);;Linear EXR image (*.exr)" ";; Tonemapped 8-bit image (*.png *.jpg *.jpeg)")); - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); dialog->setViewMode(QFileDialog::Detail); dialog->setAcceptMode(QFileDialog::AcceptSave); @@ -1316,7 +1324,7 @@ void MainWindow::onExportDialogClose(int reason) { int currentIndex = ui->tabBar->currentIndex(); SceneContext *ctx = m_context[currentIndex]; - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); QFileDialog *dialog = static_cast(sender()); m_currentChild = NULL; @@ -1427,7 +1435,7 @@ void MainWindow::on_actionSaveAs_triggered() { "", tr("Mitsuba scenes (*.xml)")); m_currentChild = dialog; - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setViewMode(QFileDialog::Detail); dialog->setAcceptMode(QFileDialog::AcceptSave); @@ -1446,7 +1454,7 @@ void MainWindow::onSaveAsDialogClose(int reason) { int currentIndex = ui->tabBar->currentIndex(); SceneContext *context = m_context[currentIndex]; - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); QFileDialog *dialog = static_cast(sender()); m_currentChild = NULL; if (reason == QDialog::Accepted) { @@ -1518,6 +1526,19 @@ void MainWindow::on_actionStartServer_triggered() { m_serverWidget->show(); } +void MainWindow::on_actionEnableCommandLine_triggered() { + if (QMessageBox::question(this, tr("Enable command line access"), + tr("

If you proceed, Mitsuba will create symbolic links in /usr/bin and /Library/Python/2.6/site-packages, " + "which enable command line and Python usage. Note that you will have to " + "repeat this process every time the Mitsuba application is moved.

" + "

Create links?

"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + return; + if (!create_symlinks()) + QMessageBox::critical(this, tr("Authentication error"), + tr("Unable to create the symbolic links!"), QMessageBox::Ok); +} + void MainWindow::on_actionReportBug_triggered() { QDesktopServices::openUrl(QUrl("https://www.mitsuba-renderer.org/bugtracker/projects/mitsuba")); } @@ -1755,7 +1776,7 @@ SceneContext::SceneContext(SceneContext *ctx) { if (depth++ == 0) scene->setIntegrator(integrator); else - currentIntegrator->addChild("", integrator); + currentIntegrator->addChild(integrator); currentIntegrator = integrator; integratorList.push_back(integrator); oldIntegrator = oldIntegrator->getSubIntegrator(); @@ -1769,11 +1790,11 @@ SceneContext::SceneContext(SceneContext *ctx) { getReconstructionFilter()->getProperties())); rfilter->configure(); - film->addChild("", rfilter); + film->addChild(rfilter); film->configure(); sampler->configure(); - camera->addChild("", sampler); - camera->addChild("", film); + camera->addChild(sampler); + camera->addChild(film); camera->setViewTransform(oldCamera->getViewTransform()); camera->setFov(oldCamera->getFov()); camera->configure(); diff --git a/src/qtgui/mainwindow.h b/src/mtsgui/mainwindow.h similarity index 99% rename from src/qtgui/mainwindow.h rename to src/mtsgui/mainwindow.h index a467b5fd..bfd1c7a0 100644 --- a/src/qtgui/mainwindow.h +++ b/src/mtsgui/mainwindow.h @@ -127,6 +127,7 @@ private slots: void on_actionFeedback_triggered(); void on_actionShowKDTree_triggered(); void on_actionSceneDescription_triggered(); + void on_actionEnableCommandLine_triggered(); void on_tabBar_currentChanged(int index); bool on_tabBar_tabCloseRequested(int index); void on_tabBar_tabMoved(int from, int to); diff --git a/src/qtgui/mainwindow.ui b/src/mtsgui/mainwindow.ui similarity index 98% rename from src/qtgui/mainwindow.ui rename to src/mtsgui/mainwindow.ui index 07b7326f..b78ed014 100644 --- a/src/qtgui/mainwindow.ui +++ b/src/mtsgui/mainwindow.ui @@ -100,7 +100,7 @@ 0 0 605 - 25 + 27 @@ -157,6 +157,7 @@ + @@ -460,7 +461,12 @@ - Scene Information .. + Scene information .. + + + + + Command-line access diff --git a/src/qtgui/preview.cpp b/src/mtsgui/preview.cpp similarity index 100% rename from src/qtgui/preview.cpp rename to src/mtsgui/preview.cpp diff --git a/src/qtgui/preview.h b/src/mtsgui/preview.h similarity index 100% rename from src/qtgui/preview.h rename to src/mtsgui/preview.h diff --git a/src/qtgui/preview_proc.cpp b/src/mtsgui/preview_proc.cpp similarity index 100% rename from src/qtgui/preview_proc.cpp rename to src/mtsgui/preview_proc.cpp diff --git a/src/qtgui/preview_proc.h b/src/mtsgui/preview_proc.h similarity index 100% rename from src/qtgui/preview_proc.h rename to src/mtsgui/preview_proc.h diff --git a/src/qtgui/previewsettingsdlg.cpp b/src/mtsgui/previewsettingsdlg.cpp similarity index 100% rename from src/qtgui/previewsettingsdlg.cpp rename to src/mtsgui/previewsettingsdlg.cpp diff --git a/src/qtgui/previewsettingsdlg.h b/src/mtsgui/previewsettingsdlg.h similarity index 100% rename from src/qtgui/previewsettingsdlg.h rename to src/mtsgui/previewsettingsdlg.h diff --git a/src/qtgui/previewsettingsdlg.ui b/src/mtsgui/previewsettingsdlg.ui similarity index 100% rename from src/qtgui/previewsettingsdlg.ui rename to src/mtsgui/previewsettingsdlg.ui diff --git a/src/qtgui/previewsettingsdlg_cocoa.cpp b/src/mtsgui/previewsettingsdlg_cocoa.cpp similarity index 100% rename from src/qtgui/previewsettingsdlg_cocoa.cpp rename to src/mtsgui/previewsettingsdlg_cocoa.cpp diff --git a/src/qtgui/previewsettingsdlg_cocoa.h b/src/mtsgui/previewsettingsdlg_cocoa.h similarity index 100% rename from src/qtgui/previewsettingsdlg_cocoa.h rename to src/mtsgui/previewsettingsdlg_cocoa.h diff --git a/src/qtgui/previewsettingsdlg_cocoa_impl.mm b/src/mtsgui/previewsettingsdlg_cocoa_impl.mm similarity index 100% rename from src/qtgui/previewsettingsdlg_cocoa_impl.mm rename to src/mtsgui/previewsettingsdlg_cocoa_impl.mm diff --git a/src/qtgui/programsettingsdlg.cpp b/src/mtsgui/programsettingsdlg.cpp similarity index 100% rename from src/qtgui/programsettingsdlg.cpp rename to src/mtsgui/programsettingsdlg.cpp diff --git a/src/qtgui/programsettingsdlg.h b/src/mtsgui/programsettingsdlg.h similarity index 100% rename from src/qtgui/programsettingsdlg.h rename to src/mtsgui/programsettingsdlg.h diff --git a/src/qtgui/programsettingsdlg.ui b/src/mtsgui/programsettingsdlg.ui similarity index 100% rename from src/qtgui/programsettingsdlg.ui rename to src/mtsgui/programsettingsdlg.ui diff --git a/src/qtgui/rendersettingsdlg.cpp b/src/mtsgui/rendersettingsdlg.cpp similarity index 99% rename from src/qtgui/rendersettingsdlg.cpp rename to src/mtsgui/rendersettingsdlg.cpp index 3930bf6b..072b56c3 100644 --- a/src/qtgui/rendersettingsdlg.cpp +++ b/src/mtsgui/rendersettingsdlg.cpp @@ -331,7 +331,7 @@ void RenderSettingsDialog::apply(SceneContext *ctx) { m_icNode->putProperties(icProps); ref ic = static_cast (pluginMgr->createObject(MTS_CLASS(Integrator), icProps)); - ic->addChild("", integrator); + ic->addChild(integrator); ic->configure(); integrator = ic; } @@ -342,7 +342,7 @@ void RenderSettingsDialog::apply(SceneContext *ctx) { m_aiNode->putProperties(aiProps); ref ai = static_cast (pluginMgr->createObject(MTS_CLASS(Integrator), aiProps)); - ai->addChild("", integrator); + ai->addChild(integrator); ai->configure(); integrator = ai; } @@ -354,7 +354,7 @@ void RenderSettingsDialog::apply(SceneContext *ctx) { filmProps.setInteger("width", width, false); filmProps.setInteger("height", height, false); ref film = static_cast (pluginMgr->createObject(MTS_CLASS(Film), filmProps)); - film->addChild("", rFilter); + film->addChild(rFilter); film->configure(); if (width != ctx->framebuffer->getWidth() || height != ctx->framebuffer->getHeight()) { @@ -367,8 +367,8 @@ void RenderSettingsDialog::apply(SceneContext *ctx) { Properties cameraProps = oldCamera->getProperties(); ref camera = static_cast (pluginMgr->createObject(MTS_CLASS(Camera), cameraProps)); - camera->addChild("", sampler); - camera->addChild("", film); + camera->addChild(sampler); + camera->addChild(film); camera->setViewTransform(oldCamera->getViewTransform()); camera->setFov(oldCamera->getFov()); camera->setMedium(oldCamera->getMedium()); diff --git a/src/qtgui/rendersettingsdlg.h b/src/mtsgui/rendersettingsdlg.h similarity index 100% rename from src/qtgui/rendersettingsdlg.h rename to src/mtsgui/rendersettingsdlg.h diff --git a/src/qtgui/rendersettingsdlg.ui b/src/mtsgui/rendersettingsdlg.ui similarity index 100% rename from src/qtgui/rendersettingsdlg.ui rename to src/mtsgui/rendersettingsdlg.ui diff --git a/src/qtgui/resources.qrc b/src/mtsgui/resources.qrc similarity index 100% rename from src/qtgui/resources.qrc rename to src/mtsgui/resources.qrc diff --git a/src/qtgui/resources/about.svg b/src/mtsgui/resources/about.svg similarity index 100% rename from src/qtgui/resources/about.svg rename to src/mtsgui/resources/about.svg diff --git a/src/qtgui/resources/about16.png b/src/mtsgui/resources/about16.png similarity index 100% rename from src/qtgui/resources/about16.png rename to src/mtsgui/resources/about16.png diff --git a/src/qtgui/resources/add.png b/src/mtsgui/resources/add.png similarity index 100% rename from src/qtgui/resources/add.png rename to src/mtsgui/resources/add.png diff --git a/src/qtgui/resources/adjustsize.svg b/src/mtsgui/resources/adjustsize.svg similarity index 100% rename from src/qtgui/resources/adjustsize.svg rename to src/mtsgui/resources/adjustsize.svg diff --git a/src/qtgui/resources/adjustsize16.png b/src/mtsgui/resources/adjustsize16.png similarity index 100% rename from src/qtgui/resources/adjustsize16.png rename to src/mtsgui/resources/adjustsize16.png diff --git a/src/qtgui/resources/appicon.png b/src/mtsgui/resources/appicon.png similarity index 100% rename from src/qtgui/resources/appicon.png rename to src/mtsgui/resources/appicon.png diff --git a/src/qtgui/resources/branch-closed.png b/src/mtsgui/resources/branch-closed.png similarity index 100% rename from src/qtgui/resources/branch-closed.png rename to src/mtsgui/resources/branch-closed.png diff --git a/src/qtgui/resources/branch-open.png b/src/mtsgui/resources/branch-open.png similarity index 100% rename from src/qtgui/resources/branch-open.png rename to src/mtsgui/resources/branch-open.png diff --git a/src/qtgui/resources/clear.png b/src/mtsgui/resources/clear.png similarity index 100% rename from src/qtgui/resources/clear.png rename to src/mtsgui/resources/clear.png diff --git a/src/qtgui/resources/clone.png b/src/mtsgui/resources/clone.png similarity index 100% rename from src/qtgui/resources/clone.png rename to src/mtsgui/resources/clone.png diff --git a/src/qtgui/resources/close.svg b/src/mtsgui/resources/close.svg similarity index 100% rename from src/qtgui/resources/close.svg rename to src/mtsgui/resources/close.svg diff --git a/src/qtgui/resources/close16.png b/src/mtsgui/resources/close16.png similarity index 100% rename from src/qtgui/resources/close16.png rename to src/mtsgui/resources/close16.png diff --git a/src/qtgui/resources/controls.png b/src/mtsgui/resources/controls.png similarity index 100% rename from src/qtgui/resources/controls.png rename to src/mtsgui/resources/controls.png diff --git a/src/qtgui/resources/controls.svg b/src/mtsgui/resources/controls.svg similarity index 100% rename from src/qtgui/resources/controls.svg rename to src/mtsgui/resources/controls.svg diff --git a/src/qtgui/resources/docs.xml b/src/mtsgui/resources/docs.xml similarity index 100% rename from src/qtgui/resources/docs.xml rename to src/mtsgui/resources/docs.xml diff --git a/src/qtgui/resources/duplicatetab.png b/src/mtsgui/resources/duplicatetab.png similarity index 100% rename from src/qtgui/resources/duplicatetab.png rename to src/mtsgui/resources/duplicatetab.png diff --git a/src/qtgui/resources/duplicatetab.svg b/src/mtsgui/resources/duplicatetab.svg similarity index 100% rename from src/qtgui/resources/duplicatetab.svg rename to src/mtsgui/resources/duplicatetab.svg diff --git a/src/qtgui/resources/fpreview.png b/src/mtsgui/resources/fpreview.png similarity index 100% rename from src/qtgui/resources/fpreview.png rename to src/mtsgui/resources/fpreview.png diff --git a/src/qtgui/resources/help.svg b/src/mtsgui/resources/help.svg similarity index 100% rename from src/qtgui/resources/help.svg rename to src/mtsgui/resources/help.svg diff --git a/src/qtgui/resources/help16.png b/src/mtsgui/resources/help16.png similarity index 100% rename from src/qtgui/resources/help16.png rename to src/mtsgui/resources/help16.png diff --git a/src/qtgui/resources/import.svg b/src/mtsgui/resources/import.svg similarity index 100% rename from src/qtgui/resources/import.svg rename to src/mtsgui/resources/import.svg diff --git a/src/qtgui/resources/import16.png b/src/mtsgui/resources/import16.png similarity index 100% rename from src/qtgui/resources/import16.png rename to src/mtsgui/resources/import16.png diff --git a/src/qtgui/resources/log.png b/src/mtsgui/resources/log.png similarity index 100% rename from src/qtgui/resources/log.png rename to src/mtsgui/resources/log.png diff --git a/src/qtgui/resources/logo.png b/src/mtsgui/resources/logo.png similarity index 100% rename from src/qtgui/resources/logo.png rename to src/mtsgui/resources/logo.png diff --git a/src/qtgui/resources/mitsuba48.png b/src/mtsgui/resources/mitsuba48.png similarity index 100% rename from src/qtgui/resources/mitsuba48.png rename to src/mtsgui/resources/mitsuba48.png diff --git a/src/qtgui/resources/open.svg b/src/mtsgui/resources/open.svg similarity index 100% rename from src/qtgui/resources/open.svg rename to src/mtsgui/resources/open.svg diff --git a/src/qtgui/resources/open16.png b/src/mtsgui/resources/open16.png similarity index 100% rename from src/qtgui/resources/open16.png rename to src/mtsgui/resources/open16.png diff --git a/src/qtgui/resources/picture16.png b/src/mtsgui/resources/picture16.png similarity index 100% rename from src/qtgui/resources/picture16.png rename to src/mtsgui/resources/picture16.png diff --git a/src/qtgui/resources/play.png b/src/mtsgui/resources/play.png similarity index 100% rename from src/qtgui/resources/play.png rename to src/mtsgui/resources/play.png diff --git a/src/qtgui/resources/preferences.png b/src/mtsgui/resources/preferences.png similarity index 100% rename from src/qtgui/resources/preferences.png rename to src/mtsgui/resources/preferences.png diff --git a/src/qtgui/resources/preferences.svg b/src/mtsgui/resources/preferences.svg similarity index 100% rename from src/qtgui/resources/preferences.svg rename to src/mtsgui/resources/preferences.svg diff --git a/src/qtgui/resources/preview.png b/src/mtsgui/resources/preview.png similarity index 100% rename from src/qtgui/resources/preview.png rename to src/mtsgui/resources/preview.png diff --git a/src/qtgui/resources/refresh.png b/src/mtsgui/resources/refresh.png similarity index 100% rename from src/qtgui/resources/refresh.png rename to src/mtsgui/resources/refresh.png diff --git a/src/qtgui/resources/refresh.svg b/src/mtsgui/resources/refresh.svg similarity index 100% rename from src/qtgui/resources/refresh.svg rename to src/mtsgui/resources/refresh.svg diff --git a/src/qtgui/resources/remove.png b/src/mtsgui/resources/remove.png similarity index 100% rename from src/qtgui/resources/remove.png rename to src/mtsgui/resources/remove.png diff --git a/src/qtgui/resources/save.svg b/src/mtsgui/resources/save.svg similarity index 100% rename from src/qtgui/resources/save.svg rename to src/mtsgui/resources/save.svg diff --git a/src/qtgui/resources/save16.png b/src/mtsgui/resources/save16.png similarity index 100% rename from src/qtgui/resources/save16.png rename to src/mtsgui/resources/save16.png diff --git a/src/qtgui/resources/saveas.svg b/src/mtsgui/resources/saveas.svg similarity index 100% rename from src/qtgui/resources/saveas.svg rename to src/mtsgui/resources/saveas.svg diff --git a/src/qtgui/resources/saveas16.png b/src/mtsgui/resources/saveas16.png similarity index 100% rename from src/qtgui/resources/saveas16.png rename to src/mtsgui/resources/saveas16.png diff --git a/src/qtgui/resources/server.png b/src/mtsgui/resources/server.png similarity index 100% rename from src/qtgui/resources/server.png rename to src/mtsgui/resources/server.png diff --git a/src/qtgui/resources/settings.png b/src/mtsgui/resources/settings.png similarity index 100% rename from src/qtgui/resources/settings.png rename to src/mtsgui/resources/settings.png diff --git a/src/qtgui/resources/showStats.png b/src/mtsgui/resources/showStats.png similarity index 100% rename from src/qtgui/resources/showStats.png rename to src/mtsgui/resources/showStats.png diff --git a/src/qtgui/resources/stop.png b/src/mtsgui/resources/stop.png similarity index 100% rename from src/qtgui/resources/stop.png rename to src/mtsgui/resources/stop.png diff --git a/src/qtgui/resources/stylesheet.css b/src/mtsgui/resources/stylesheet.css similarity index 100% rename from src/qtgui/resources/stylesheet.css rename to src/mtsgui/resources/stylesheet.css diff --git a/src/qtgui/resources/update.png b/src/mtsgui/resources/update.png similarity index 100% rename from src/qtgui/resources/update.png rename to src/mtsgui/resources/update.png diff --git a/src/qtgui/save.cpp b/src/mtsgui/save.cpp similarity index 99% rename from src/qtgui/save.cpp rename to src/mtsgui/save.cpp index 09827fee..a280ecaa 100644 --- a/src/qtgui/save.cpp +++ b/src/mtsgui/save.cpp @@ -69,7 +69,7 @@ static void setProperties(QDomDocument &doc, QDomElement &element, element.setAttribute("type", props.getPluginName().c_str()); std::vector propertyNames; - props.putPropertyNames(propertyNames); + props.putNames(propertyNames); for (std::vector::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) { QDomElement property; diff --git a/src/qtgui/save.h b/src/mtsgui/save.h similarity index 100% rename from src/qtgui/save.h rename to src/mtsgui/save.h diff --git a/src/qtgui/sceneimporter.cpp b/src/mtsgui/sceneimporter.cpp similarity index 100% rename from src/qtgui/sceneimporter.cpp rename to src/mtsgui/sceneimporter.cpp diff --git a/src/qtgui/sceneimporter.h b/src/mtsgui/sceneimporter.h similarity index 100% rename from src/qtgui/sceneimporter.h rename to src/mtsgui/sceneimporter.h diff --git a/src/qtgui/sceneinfodlg.cpp b/src/mtsgui/sceneinfodlg.cpp similarity index 100% rename from src/qtgui/sceneinfodlg.cpp rename to src/mtsgui/sceneinfodlg.cpp diff --git a/src/qtgui/sceneinfodlg.h b/src/mtsgui/sceneinfodlg.h similarity index 100% rename from src/qtgui/sceneinfodlg.h rename to src/mtsgui/sceneinfodlg.h diff --git a/src/qtgui/sceneinfodlg.ui b/src/mtsgui/sceneinfodlg.ui similarity index 100% rename from src/qtgui/sceneinfodlg.ui rename to src/mtsgui/sceneinfodlg.ui diff --git a/src/qtgui/sceneloader.cpp b/src/mtsgui/sceneloader.cpp similarity index 99% rename from src/qtgui/sceneloader.cpp rename to src/mtsgui/sceneloader.cpp index 610121c9..a2fe9ec3 100644 --- a/src/qtgui/sceneloader.cpp +++ b/src/mtsgui/sceneloader.cpp @@ -42,7 +42,7 @@ void SceneLoader::run() { SceneHandler::ParameterMap()); m_result = new SceneContext(); try { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); m_result->srgb = settings.value("preview_sRGB", true).toBool(); m_result->gamma = (Float) settings.value("preview_gamma", 2.2).toDouble(); m_result->reinhardKey = (Float) settings.value("preview_reinhardKey", 0.18).toDouble(); diff --git a/src/qtgui/sceneloader.h b/src/mtsgui/sceneloader.h similarity index 100% rename from src/qtgui/sceneloader.h rename to src/mtsgui/sceneloader.h diff --git a/src/qtgui/server.cpp b/src/mtsgui/server.cpp similarity index 100% rename from src/qtgui/server.cpp rename to src/mtsgui/server.cpp diff --git a/src/qtgui/server.h b/src/mtsgui/server.h similarity index 100% rename from src/qtgui/server.h rename to src/mtsgui/server.h diff --git a/src/mtsgui/symlinks_auth.cpp b/src/mtsgui/symlinks_auth.cpp new file mode 100644 index 00000000..08804977 --- /dev/null +++ b/src/mtsgui/symlinks_auth.cpp @@ -0,0 +1,54 @@ +#if defined(__APPLE__) +#include +#include +#include +#include + +namespace mitsuba { + extern std::string __mts_bundlepath(); +}; + +bool create_symlinks() { + AuthorizationFlags flags = kAuthorizationFlagDefaults; + AuthorizationRef ref; + + OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, flags, &ref); + if (status != errAuthorizationSuccess) + return false; + + AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights rights = { 1, &items }; + flags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | + kAuthorizationFlagExtendRights; + status = AuthorizationCopyRights(ref, &rights, NULL, flags, NULL); + if (status != errAuthorizationSuccess) { + AuthorizationFree(ref, kAuthorizationFlagDefaults); + return false; + } + std::string bundlePath = mitsuba::__mts_bundlepath(); + std::string path = bundlePath + "/Contents/MacOS/symlinks_install"; + char *args[] = { const_cast(bundlePath.c_str()), NULL }; + FILE *pipe = NULL; + flags = kAuthorizationFlagDefaults; + status = AuthorizationExecuteWithPrivileges(ref, const_cast(path.c_str()), flags, args, &pipe); + if (status != errAuthorizationSuccess) { + AuthorizationFree(ref, kAuthorizationFlagDefaults); + return false; + } + char buffer[128]; + for (;;) { + int bytesRead = read(fileno(pipe), buffer, sizeof(buffer)); + if (bytesRead<1) + break; + write(fileno(stdout), buffer, bytesRead); + } + AuthorizationFree(ref, kAuthorizationFlagDefaults); + return true; +} + +#else +bool create_symlinks() { return false; } +#endif + diff --git a/src/mtsgui/symlinks_install.c b/src/mtsgui/symlinks_install.c new file mode 100644 index 00000000..5ec396f9 --- /dev/null +++ b/src/mtsgui/symlinks_install.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include + +void installPython(const char *basedir) { + const char *fname = "/Library/Python/2.6/site-packages/mitsuba.pth"; + + FILE *f = fopen(fname, "w"); + if (!f) { + fprintf(stderr, "Unable to write to file \"%s\"!\n", fname); + exit(-1); + } + + if (fprintf(f, "import sys; sys.path.append(\"%s/python\")\n", basedir) < 1) { + fprintf(stderr, "Unexpected I/O error while " + "writing to \"%s\"!\n", fname); + exit(-1); + } + + fclose(f); +} + +void install(const char *basedir, const char *name) { + char fname[MAXPATHLEN]; + FILE *f; + + snprintf(fname, sizeof(fname), "/usr/bin/%s", name); + + f = fopen(fname, "w"); + if (!f) { + fprintf(stderr, "Unable to write to file \"%s\"!\n", fname); + exit(-1); + } + + if (fprintf(f, "%s/Contents/MacOS/%s $@\n", basedir, name) < 1) { + fprintf(stderr, "Unexpected I/O error while " + "writing to \"%s\"!\n", fname); + exit(-1); + } + + fclose(f); + + if (chmod(fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + fprintf(stderr, "Unexpected I/O error while setting " + "the permssions of \"%s\"!\n", fname); + exit(-1); + } +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Incorrect number of arguments!\n"); + return -1; + } + + if (setuid(0) != 0) { + fprintf(stderr, "setuid(): failed!\n"); + return -1; + } + + install(argv[1], "mitsuba"); + install(argv[1], "mtsgui"); + install(argv[1], "mtssrv"); + install(argv[1], "mtsutil"); + install(argv[1], "mtsimport"); + installPython(argv[1]); + + return 0; +} + diff --git a/src/qtgui/tabbar.cpp b/src/mtsgui/tabbar.cpp similarity index 100% rename from src/qtgui/tabbar.cpp rename to src/mtsgui/tabbar.cpp diff --git a/src/qtgui/tabbar.h b/src/mtsgui/tabbar.h similarity index 100% rename from src/qtgui/tabbar.h rename to src/mtsgui/tabbar.h diff --git a/src/qtgui/updatedlg.cpp b/src/mtsgui/updatedlg.cpp similarity index 97% rename from src/qtgui/updatedlg.cpp rename to src/mtsgui/updatedlg.cpp index b0032329..9d7945bb 100644 --- a/src/qtgui/updatedlg.cpp +++ b/src/mtsgui/updatedlg.cpp @@ -49,7 +49,7 @@ UpdateDialog::~UpdateDialog() { } void UpdateDialog::on_skipButton_clicked() { - QSettings settings("mitsuba-renderer.org", "qtgui"); + QSettings settings("mitsuba-renderer.org", "mtsgui"); settings.setValue("ignoredVersion", m_remoteVersion); accept(); } diff --git a/src/qtgui/updatedlg.h b/src/mtsgui/updatedlg.h similarity index 100% rename from src/qtgui/updatedlg.h rename to src/mtsgui/updatedlg.h diff --git a/src/qtgui/updatedlg.ui b/src/mtsgui/updatedlg.ui similarity index 100% rename from src/qtgui/updatedlg.ui rename to src/mtsgui/updatedlg.ui diff --git a/src/qtgui/upgrade.cpp b/src/mtsgui/upgrade.cpp similarity index 100% rename from src/qtgui/upgrade.cpp rename to src/mtsgui/upgrade.cpp diff --git a/src/qtgui/upgrade.h b/src/mtsgui/upgrade.h similarity index 100% rename from src/qtgui/upgrade.h rename to src/mtsgui/upgrade.h diff --git a/src/qtgui/xmltreemodel.cpp b/src/mtsgui/xmltreemodel.cpp similarity index 99% rename from src/qtgui/xmltreemodel.cpp rename to src/mtsgui/xmltreemodel.cpp index a8d7c146..47aa66cb 100644 --- a/src/qtgui/xmltreemodel.cpp +++ b/src/mtsgui/xmltreemodel.cpp @@ -132,7 +132,7 @@ void TreeItem::setProperty(const std::string &name, const Properties &props) { void TreeItem::setProperties(const Properties &props) { std::vector propertyNames; - props.putPropertyNames(propertyNames); + props.putNames(propertyNames); for (std::vector::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) diff --git a/src/qtgui/xmltreemodel.h b/src/mtsgui/xmltreemodel.h similarity index 100% rename from src/qtgui/xmltreemodel.h rename to src/mtsgui/xmltreemodel.h diff --git a/src/shapes/obj.cpp b/src/shapes/obj.cpp index 372b5673..22060a6e 100644 --- a/src/shapes/obj.cpp +++ b/src/shapes/obj.cpp @@ -104,7 +104,6 @@ public: std::vector texcoords; std::vector triangles; bool hasNormals = false, hasTexcoords = false; - bool firstVertex = true; BSDF *currentMaterial = NULL; std::string name = m_name, line; std::set geomNames; @@ -151,7 +150,6 @@ public: geomIdx++; hasNormals = false; hasTexcoords = false; - firstVertex = false; } else { nameBeforeGeometry = true; } @@ -180,7 +178,6 @@ public: hasTexcoords = true; } else if (buf == "f") { std::string tmp; - firstVertex = true; OBJTriangle t; iss >> tmp; parse(t, 0, tmp); iss >> tmp; parse(t, 1, tmp); @@ -418,7 +415,7 @@ public: mesh->incRef(); if (currentMaterial) - mesh->addChild("", currentMaterial); + mesh->addChild(currentMaterial); m_meshes.push_back(mesh); Log(EInfo, "%s: Loaded " SIZE_T_FMT " triangles, " SIZE_T_FMT " vertices (merged " SIZE_T_FMT " vertices).", name.c_str(), diff --git a/src/shapes/ply/ply.cpp b/src/shapes/ply/ply.cpp index 7267c51a..9b630c4b 100644 --- a/src/shapes/ply/ply.cpp +++ b/src/shapes/ply/ply.cpp @@ -23,27 +23,8 @@ #include #include -#if defined(__clang__) -#define MTS_USE_BOOST_TR1 (!__has_feature(cxx_variadic_templates)) -#else -# if defined(_MSC_VER) && (_MSC_VER < 1600) -# define MTS_USE_BOOST_TR1 1 -# else -# define MTS_USE_BOOST_TR1 0 -# endif -#endif - #if MTS_USE_BOOST_TR1 -# if defined(Float) -# define MTS_Float -# pragma push_macro("Float") -# undef Float -# endif #include -# if defined(MTS_Float) -# pragma pop_macro("Float") -# undef MTS_Float -# endif #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) #include diff --git a/src/shapes/ply/ply/ply_parser.hpp b/src/shapes/ply/ply/ply_parser.hpp index a0f50a8d..30447273 100644 --- a/src/shapes/ply/ply/ply_parser.hpp +++ b/src/shapes/ply/ply/ply_parser.hpp @@ -12,31 +12,27 @@ #if defined(__clang__) #define MTS_USE_BOOST_TR1 (!__has_feature(cxx_variadic_templates)) #else -# if defined(_MSC_VER) && (_MSC_VER < 1600) -# define MTS_USE_BOOST_TR1 1 +# if defined(_MSC_VER) +# if _MSC_VER < 1600 +# define MTS_USE_BOOST_TR1 1 +# else +# define MTS_USE_BOOST_TR1 0 +# endif # else -# define MTS_USE_BOOST_TR1 0 +# define MTS_USE_BOOST_TR1 0 # endif -#define ADT_WORKAROUND 1 #endif #if defined(__INTEL_COMPILER) #define ADT_WORKAROUND 1 +#else +#define ADT_WORKAROUND 0 #endif #if MTS_USE_BOOST_TR1 -# if defined(Float) -# define MTS_Float -# pragma push_macro("Float") -# undef Float -# endif #include #include #include -# if defined(MTS_Float) -# pragma pop_macro("Float") -# undef MTS_Float -# endif #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) #include @@ -123,7 +119,7 @@ public: { return static_cast&>(callbacks_).callback; } -#if !defined(ADT_WORKAROUND) +#if ADT_WORKAROUND == 0 template friend typename scalar_property_definition_callback_type::type& at(scalar_property_definition_callbacks_type& scalar_property_definition_callbacks) { @@ -215,7 +211,7 @@ public: { return static_cast >&>(callbacks_).callback; } -#if !defined(ADT_WORKAROUND) +#if ADT_WORKAROUND == 0 template friend typename list_property_definition_callback_type::type& at(list_property_definition_callbacks_type& list_property_definition_callbacks) { @@ -411,7 +407,11 @@ inline void ply::ply_parser::parse_list_property_definition(const std::string& p #if !defined(__INTEL_COMPILER) typename #endif - list_property_definition_callback_type::type& list_property_definition_callback = list_property_definition_callbacks_.get(); + #if defined(__INTEL_COMPILER) && defined(__OSX__) + auto list_property_definition_callback = list_property_definition_callbacks_.get(); + #else + list_property_definition_callback_type::type& list_property_definition_callback = list_property_definition_callbacks_.get(); + #endif typedef typename list_property_begin_callback_type::type list_property_begin_callback_type; typedef typename list_property_element_callback_type::type list_property_element_callback_type; typedef typename list_property_end_callback_type::type list_property_end_callback_type; @@ -554,7 +554,7 @@ inline bool ply::ply_parser::parse_list_property(format_type format, std::istrea } } -#if defined(ADT_WORKAROUND) +#if ADT_WORKAROUND == 1 // Horrible workaround for ADT failure as of Clang 2.8 namespace ply { diff --git a/src/shapes/ply/ply_parser.cpp b/src/shapes/ply/ply_parser.cpp index c791925c..5e15eabf 100644 --- a/src/shapes/ply/ply_parser.cpp +++ b/src/shapes/ply/ply_parser.cpp @@ -1,3 +1,4 @@ +#include #include bool ply::ply_parser::parse(std::istream& istream) diff --git a/src/shapes/shapegroup.cpp b/src/shapes/shapegroup.cpp index f897f46f..d37f3d65 100644 --- a/src/shapes/shapegroup.cpp +++ b/src/shapes/shapegroup.cpp @@ -71,7 +71,7 @@ void ShapeGroup::addChild(const std::string &name, ConfigurableObject *child) { ref element = shape->getElement(index++); if (element == NULL) break; - addChild("", element); + addChild(element); } while (true); } else { m_kdtree->addShape(shape); diff --git a/src/shapes/shapegroup.h b/src/shapes/shapegroup.h index 9a52b10a..f6945e2b 100644 --- a/src/shapes/shapegroup.h +++ b/src/shapes/shapegroup.h @@ -47,6 +47,8 @@ public: /// Add a child object void addChild(const std::string &name, ConfigurableObject *child); + /// Add an unnamed child + inline void addChild(ConfigurableObject *child) { addChild("", child); } /// Return whether or not the shape is a compound object bool isCompound() const;