merge with the kd-tree rewrite
commit
1c1fea233d
54
.hgignore
54
.hgignore
|
@ -1,46 +1,64 @@
|
|||
^Mitsuba.app/.*$
|
||||
.*\.obj$
|
||||
.*\.os$
|
||||
.*\.so$
|
||||
.*\.pyc$
|
||||
.*\.o$
|
||||
.*\.exe$
|
||||
.*\.pdb$
|
||||
.*\.manifest$
|
||||
.*\.exp$
|
||||
.*\.dylib$
|
||||
# Documentation
|
||||
^doc/doxygen/.*$
|
||||
^doc/.*\.aux$
|
||||
^doc/.*\.log$
|
||||
^doc/.*\.out$
|
||||
^doc/.*\.pdf$
|
||||
^doc/.*\.toc$
|
||||
|
||||
# Qt-related
|
||||
.*ui_.*\.h$
|
||||
.*moc_.*\.cc$
|
||||
.*qrc_.*\.cc$
|
||||
.*/\.DS_Store^
|
||||
|
||||
# Build-related
|
||||
^\.sconf_temp/.*$
|
||||
^debian/.*$
|
||||
^.sconsign.dblite$
|
||||
^config.py$
|
||||
^config.log$
|
||||
^.sconsign.dblite$
|
||||
^src/utils/addimages$
|
||||
.*\.pyc$
|
||||
|
||||
# OSX binaries and byproducts
|
||||
^Mitsuba.app/.*$
|
||||
\.DS_Store
|
||||
.*\.dylib$
|
||||
|
||||
# Linux binaries and byproducts
|
||||
^src/utils/createvol$
|
||||
^src/utils/dumpimage$
|
||||
^src/utils/joinrgb$
|
||||
^src/utils/ssalbedo$
|
||||
^src/utils/ttest$
|
||||
^src/utils/utils_test$
|
||||
^dist/.*$
|
||||
^mitsuba$
|
||||
^mtssrv$
|
||||
^mtsgui$
|
||||
^mtsimport$
|
||||
^mtsutil$
|
||||
.*\.so$
|
||||
.*\.os$
|
||||
.*\.o$
|
||||
|
||||
|
||||
# Windows binaries and byproducts
|
||||
.*\.exe$
|
||||
.*\.obj$
|
||||
^src/.*\.lib$
|
||||
^src/.*\.dll$
|
||||
^plugins/.*\.lib$
|
||||
^plugins/.*\.dll$
|
||||
^dist/.*$
|
||||
tools/windows/mitsuba_res.res
|
||||
.*\.pdb$
|
||||
.*\.manifest$
|
||||
.*\.exp$
|
||||
|
||||
# Imported geometry
|
||||
^meshes/.*$
|
||||
^textures/.*$
|
||||
^mitsuba.*.log$
|
||||
^doc/doxygen/.*$
|
||||
|
||||
# Eclipse CDT project files
|
||||
^.externalToolBuilders/.*$
|
||||
^.settings/.*$
|
||||
^.cproject$
|
||||
^.project$
|
||||
|
|
177
ChangeLog
177
ChangeLog
|
@ -1,177 +0,0 @@
|
|||
2010-08-12 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* converter.cpp: Much better import of COLLADA scenes from
|
||||
blender.
|
||||
|
||||
* importdlg.cpp: User interface for importing scenes.
|
||||
|
||||
2010-08-09 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* rendersettingsdlg.cpp: Try to maintain the number of
|
||||
samples/pixel when switching between different samplers.
|
||||
|
||||
2010-08-05 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* constant.cpp, src/libhw/vpl.cpp: Support for image environment
|
||||
sources and spot lights in the real-time preview.
|
||||
|
||||
2010-08-03 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* mitsuba.cpp: Ability to run the 'mitsuba' execubable in arbitrary
|
||||
locations on OSX while ensuring that it still finds all plugins etc.
|
||||
|
||||
* mtsimport: COLLADA importer support for ambient lights and 'polylist' meshes.
|
||||
|
||||
* scene.cpp: Create a default camera when none is specified in the XML file.
|
||||
|
||||
* constant.cpp, src/libhw/vpl.cpp: Support for rendering constant environment
|
||||
sources in the real-time preview.
|
||||
|
||||
2010-07-21 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* glwidget.cpp, mainwindow.cpp: Support for Drag & Drop
|
||||
|
||||
* glwidget.cpp, mainwindow.cpp: The Mitsuba user interface now also
|
||||
doubles as an EXR viewer / tonemapper. Drag an EXR file onto the
|
||||
UI or open it using the File menu, and the image opens in a new
|
||||
tab. Afterwards, it is possible to export the image as a tonemapped
|
||||
8-bit PNG image.
|
||||
|
||||
2010-07-19 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* include/mitsuba/mitsuba.h: First semi-official external release 0.1.1
|
||||
|
||||
* rendersettingsdlg.cpp: Perform a sanity check when changing the rendering
|
||||
settings: if the configuration doesn't make any sense, prevent the
|
||||
user from continuing.
|
||||
|
||||
* mainwindow.cpp, many others: Numerous bugfixes for all platforms
|
||||
|
||||
2010-07-18 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* previewsettingsdlg_cocoa_impl.mm: When running on OSX, use a
|
||||
Cocoa-based settings tweaker using a 'HUD Layout' instead of
|
||||
the Qt version.
|
||||
|
||||
* debian/*: Finished debian package support
|
||||
|
||||
* glwidget.cpp: Fixed some crashes
|
||||
|
||||
2010-07-17 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* preview.cpp: Many bugfixes for standard ray tracing. The partial
|
||||
preview shown while moving through the scene now adapts to its
|
||||
complexity, making the interaction smoother.
|
||||
|
||||
* preview.cpp: Support for coherent ray tracing -- about 2-4x
|
||||
faster than standard ray tracing.
|
||||
|
||||
* glwidget.cpp: When rendering very complex scenes, it was possible
|
||||
that the UI required a long time to acquire a image containing
|
||||
the most recent preview. This part is now allowed to time out
|
||||
gracefully, leading to a more responsive user interface.
|
||||
|
||||
* mainwindow.cpp: "Resize to Fit" menu action.
|
||||
|
||||
* mainwindow.cpp: Open/Save dialogs now remember their position,
|
||||
layout and directory.
|
||||
|
||||
* debian/*: Support for generating Debian/Ubuntu packages
|
||||
|
||||
2010-07-15 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* preview.cpp: Very basic support for rendering the preview using
|
||||
standard ray tracing.
|
||||
|
||||
2010-07-14 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* errctrl.cpp: Added a feature that enables the error-controlling
|
||||
integrator to switch between an image-wide and a per-pixel based
|
||||
error criterion.
|
||||
|
||||
* glwidget.cpp, mainwindow.cpp, previewsettingsdlg.cpp: Added support
|
||||
for the tonemapping technique by Reinhard et al. from 2002. It
|
||||
dynamically adapts to the average luminance in the viewport.
|
||||
|
||||
2010-07-13 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* xmltreemodel.cpp: When showing the integrator/sampler/film properties
|
||||
in the render setting editor, the less important ones are now drawn
|
||||
using a light grey color.
|
||||
|
||||
* triangle.cpp: Fixed a numerical issue when primitive clipping/
|
||||
perfect splits were active while building the kd-tree -- in some
|
||||
rare cases, this could result in missing geometry.
|
||||
|
||||
* glwidget.cpp, preview.cpp: Nicer behavior when switching tabs.
|
||||
Previously, the preview would regenerate from scratch, which caused
|
||||
unpleasant flicker. Now, the preview stores the complete state just
|
||||
before switching away, and this is used to resume when switching
|
||||
back to the tab.
|
||||
|
||||
* sceneloader.cpp, mainwindow.cpp: The interactive preview now tries
|
||||
to detect the path length from the current scene configuration.
|
||||
|
||||
* rendersettingsdlg.cpp, save.cpp: It is now possible to configure the
|
||||
adaptive integrator & irradiance cache from within the GUI.
|
||||
|
||||
2010-07-11 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* mainwindow.cpp: Added a 'clone tab' feature, which is accessible
|
||||
in the File menu and using a context menu on the tabs
|
||||
|
||||
* many files: Changed the system how scenes are transmitted over the
|
||||
network. The camera and integrator are now serialized separately and
|
||||
reattached to a shallow scene copy on the remote side. This makes it
|
||||
possible to render a scene from multiple viewpoints & using different
|
||||
techniques, while not having to send the (potentially large) scene
|
||||
over the wire every time.
|
||||
|
||||
2010-07-10 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* mainwindow.cpp: Added a feature to export images (preview+rendered)
|
||||
from within the user interface.
|
||||
|
||||
* glwidget.cpp: Better-behaved UI when rendering tiny images (e.g. 100x100).
|
||||
The app now has a specified minimum size; smaller images will be
|
||||
surrounded by gray margins and frame highlights the image dimensions.
|
||||
|
||||
* mainwindow.cpp, glwidget.cpp: Better-behaved UI when rendering huge
|
||||
images. When the image does not fit on the screen, scroll bars appear.
|
||||
Scrolling is supported using either two-finger gestures (OSX), the
|
||||
mouse scroll wheel or by using the scroll bars themselves.
|
||||
|
||||
* mainwindow.cpp, glwidget.cpp: Got rid of numerous sources of flickering
|
||||
when switching between tabs. To make it all work, the OSX version now
|
||||
requires Qt 4.7.x (tech preview 2) or higher.
|
||||
|
||||
* glwidget.cpp: The field of view can now be changed using the right
|
||||
mouse button. It is also possible to move within the film plane using
|
||||
the middle mouse button.
|
||||
|
||||
2010-07-08 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* path.h, path.cpp, pathvertex.h, pathvertex.cpp: Reorganized path related
|
||||
code, switched away from the purely inline-based header files.
|
||||
|
||||
* save.cpp: The save feature now stores changes to the integrator, sampler
|
||||
and image reconstruction filter. The XML output has been made much
|
||||
more readable.
|
||||
|
||||
2010-07-07 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
|
||||
* mainwindow.cpp [OSX]: Detect crash reports and submit them
|
||||
over the web. This is only supported on OSX for now, since the
|
||||
other platforms don't collect them in a suitable way.
|
||||
|
||||
* renderjob.cpp: Fix for the missing plugin crashes on Steve's machine
|
||||
|
||||
* bidir_proc.cpp: Corrected sample positions for BDPT, which caused
|
||||
grid-like artifacts when rendering with the box filter.
|
||||
|
||||
* path.h, mlt_*.cpp: Consolidated lots of repeated code into a new
|
||||
PathVertex::connect() function.
|
||||
|
||||
2010-07-07 Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
* ChangeLog: starting to keep a change log of notable changes (it
|
||||
won't contain minor edits).
|
42
SConstruct
42
SConstruct
|
@ -45,7 +45,9 @@ vars.Add('GLLIB', 'OpenGL+GLEW libraries')
|
|||
vars.Add('GLINCLUDE', 'OpenGL+GLEW include path')
|
||||
vars.Add('GLFLAGS', 'OpenGL+GLEW-related compiler flags')
|
||||
vars.Add('GLLIBDIR', 'OpenGL+GLEW library path')
|
||||
vars.Add('BOOSTINCLUDE', 'BOOST include path')
|
||||
vars.Add('BOOSTINCLUDE', 'boost include path')
|
||||
vars.Add('BOOSTLIB', 'boost libraries')
|
||||
vars.Add('BOOSTLIBDIR', 'boost library path')
|
||||
vars.Add('TARGET_ARCH', 'Target architecture')
|
||||
|
||||
try:
|
||||
|
@ -64,12 +66,17 @@ env.Append(LIBPATH=[])
|
|||
env.Append(LIBS=env['BASELIB'])
|
||||
if env.has_key('BOOSTINCLUDE'):
|
||||
env.Append(CPPPATH=env['BOOSTINCLUDE'])
|
||||
if env.has_key('BOOSTLIBDIR'):
|
||||
env.Append(LIBPATH=env['BOOSTLIBDIR'])
|
||||
if env.has_key('BOOSTLIB'):
|
||||
env.Append(LIBS=env['BOOSTLIB'])
|
||||
if env.has_key('BASELIBDIR'):
|
||||
env.Append(LIBPATH=env['BASELIBDIR'])
|
||||
|
||||
env.Decider('MD5-timestamp')
|
||||
env.SetOption('implicit_cache', 1)
|
||||
|
||||
env.SetOption('num_jobs', multiprocessing.cpu_count())
|
||||
#env.SetOption('num_jobs', multiprocessing.cpu_count())
|
||||
|
||||
AddOption("--dist", dest="dist", type="string", nargs=0, action='store', help='Make an official release')
|
||||
|
||||
|
@ -267,14 +274,19 @@ libcore_objects = [
|
|||
'src/libcore/cstream.cpp', 'src/libcore/mstream.cpp',
|
||||
'src/libcore/sched.cpp', 'src/libcore/sched_remote.cpp',
|
||||
'src/libcore/sshstream.cpp', 'src/libcore/wavelet.cpp',
|
||||
'src/libcore/zstream.cpp', 'src/libcore/shvector.cpp'
|
||||
'src/libcore/zstream.cpp', 'src/libcore/shvector.cpp',
|
||||
'src/libcore/fresolver.cpp'
|
||||
]
|
||||
|
||||
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');
|
||||
libcore_objects += coreEnv_osx.SharedObject('src/libcore/darwin.mm')
|
||||
libcore_objects += coreEnv_osx.SharedObject('src/libcore/platform_darwin.mm')
|
||||
elif sys.platform == 'win32':
|
||||
libcore_objects += coreEnv.SharedObject('src/libcore/getopt.c')
|
||||
libcore_objects += coreEnv.SharedObject('src/libcore/platform_win32.cpp')
|
||||
|
||||
libcore = coreEnv.SharedLibrary('src/libcore/mitsuba-core', libcore_objects);
|
||||
|
||||
|
@ -297,8 +309,7 @@ if renderEnv.has_key('XERCESLIB'):
|
|||
librender = renderEnv.SharedLibrary('src/librender/mitsuba-render', [
|
||||
'src/librender/bsdf.cpp', 'src/librender/camera.cpp',
|
||||
'src/librender/film.cpp', 'src/librender/integrator.cpp',
|
||||
'src/librender/kdtree.cpp', 'src/librender/kdtree_coherent.cpp',
|
||||
'src/librender/kdtree_traversal.cpp', 'src/librender/kdtree_compiler.cpp',
|
||||
'src/librender/kdtree.cpp',
|
||||
'src/librender/luminaire.cpp', 'src/librender/medium.cpp',
|
||||
'src/librender/renderjob.cpp', 'src/librender/imageproc.cpp',
|
||||
'src/librender/imageproc_wu.cpp', 'src/librender/renderproc.cpp',
|
||||
|
@ -307,13 +318,13 @@ librender = renderEnv.SharedLibrary('src/librender/mitsuba-render', [
|
|||
'src/librender/scene.cpp', 'src/librender/subsurface.cpp',
|
||||
'src/librender/texture.cpp', 'src/librender/shape.cpp',
|
||||
'src/librender/trimesh.cpp', 'src/librender/rfilter.cpp',
|
||||
'src/librender/sampler.cpp', 'src/librender/records.cpp',
|
||||
'src/librender/sampler.cpp', 'src/librender/util.cpp',
|
||||
'src/librender/irrcache.cpp', 'src/librender/testcase.cpp',
|
||||
'src/librender/preview.cpp', 'src/librender/photonmap.cpp',
|
||||
'src/librender/gatherproc.cpp', 'src/librender/mipmap3d.cpp',
|
||||
'src/librender/volume.cpp', 'src/librender/vpl.cpp',
|
||||
'src/librender/shader.cpp', 'src/librender/shandler.cpp',
|
||||
'src/librender/util.cpp'
|
||||
'src/librender/intersection.cpp'
|
||||
])
|
||||
|
||||
if sys.platform == "darwin":
|
||||
|
@ -390,8 +401,7 @@ resources = []
|
|||
darwinStub = []
|
||||
|
||||
if sys.platform == 'win32':
|
||||
resources += [env.RES('tools/windows/mitsuba_res.rc'),
|
||||
env.StaticObject('src/mitsuba/getopt.c')]
|
||||
resources += [env.RES('tools/windows/mitsuba_res.rc')]
|
||||
|
||||
# Build the command-line+GUI interface
|
||||
mainEnv.Program('mtssrv', resources + ['src/mitsuba/mtssrv.cpp'])
|
||||
|
@ -480,6 +490,7 @@ plugins = []
|
|||
|
||||
# Build the plugins -- utilities
|
||||
plugins += env.SharedLibrary('plugins/addimages', ['src/utils/addimages.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/kdbench', ['src/utils/kdbench.cpp'])
|
||||
|
||||
# BSDFs
|
||||
plugins += env.SharedLibrary('plugins/lambertian', ['src/bsdfs/lambertian.cpp'])
|
||||
|
@ -503,10 +514,12 @@ plugins += env.SharedLibrary('plugins/kkay', ['src/phase/kkay.cpp'])
|
|||
|
||||
# Shapes and triangle mesh loaders
|
||||
plugins += env.SharedLibrary('plugins/obj', ['src/shapes/obj.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/ply', ['src/shapes/ply/ply.cpp', 'src/shapes/ply/ply_parser.cpp'],
|
||||
CPPPATH = env['CPPPATH'] + ['src/shapes/ply'])
|
||||
plugins += env.SharedLibrary('plugins/serialized', ['src/shapes/serialized.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/sphere', ['src/shapes/sphere.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp', 'src/shapes/miterseg.cpp'])
|
||||
#plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp', 'src/shapes/miterseg.cpp'])
|
||||
#plugins += env.SharedLibrary('plugins/group', ['src/shapes/group.cpp'])
|
||||
|
||||
# Samplers
|
||||
|
@ -556,6 +569,7 @@ plugins += env.SharedLibrary('plugins/exrtexture', ['src/textures/exrtexture.cpp
|
|||
plugins += env.SharedLibrary('plugins/ldrtexture', ['src/textures/ldrtexture.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/gridtexture', ['src/textures/gridtexture.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/checkerboard', ['src/textures/checkerboard.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/vertexcolors', ['src/textures/vertexcolors.cpp'])
|
||||
|
||||
# Light sources
|
||||
plugins += env.SharedLibrary('plugins/area', ['src/luminaires/area.cpp'])
|
||||
|
@ -565,7 +579,6 @@ plugins += env.SharedLibrary('plugins/spot', ['src/luminaires/spot.cpp'])
|
|||
plugins += env.SharedLibrary('plugins/point', ['src/luminaires/point.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/collimated', ['src/luminaires/collimated.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/directional', ['src/luminaires/directional.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/portal', ['src/luminaires/portal.cpp'])
|
||||
|
||||
# Integrators
|
||||
plugins += env.SharedLibrary('plugins/direct', ['src/integrators/direct/direct.cpp'])
|
||||
|
@ -703,7 +716,10 @@ elif sys.platform == 'darwin':
|
|||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/Xerces-C.framework/Resources/lib/libxerces-c-3.0.dylib')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/libpng.framework/Resources/lib/libpng.dylib')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/libjpeg.framework/Resources/lib/libjpeg.dylib')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/Collada14Dom.framework/Resources/lib/libCollada14Dom.dylib')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/libboost.framework/Resources/lib/libboost_system-xgcc42-mt-1_39.dylib')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/libboost.framework/Resources/lib/libboost_filesystem-xgcc42-mt-1_39.dylib')
|
||||
if hasCollada:
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', 'tools/darwin/Collada14Dom.framework/Resources/lib/libCollada14Dom.dylib')
|
||||
if hasQt:
|
||||
installTargets += env.Install('Mitsuba.app/Contents/MacOS', 'mtsgui')
|
||||
installTargets += env.OSXLibInst('Mitsuba.app/Contents/Frameworks', '/Library/Frameworks/QtCore.framework/Versions/4/QtCore')
|
||||
|
|
|
@ -20,6 +20,8 @@ GLLIBDIR = ['#tools/darwin/GLEW.framework/Resources/libs']
|
|||
GLLIB = ['GLEW', 'objc']
|
||||
GLFLAGS = ['-DGLEW_MX']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['boost_filesystem-xgcc42-mt-1_39', 'boost_system-xgcc42-mt-1_39']
|
||||
BOOSTLIBDIR = ['tools/darwin/libboost.framework/Resources/lib']
|
||||
COLLADAINCLUDE = ['#tools/windows/include/colladadom', '#tools/windows/include/colladadom/1.4']
|
||||
COLLADALIB = ['libCollada14Dom']
|
||||
COLLADALIBDIR = ['#tools/darwin/Collada14Dom.framework/Resources/lib']
|
||||
|
|
|
@ -20,6 +20,8 @@ GLLIBDIR = ['#tools/darwin/GLEW.framework/Resources/libs']
|
|||
GLLIB = ['GLEW', 'objc']
|
||||
GLFLAGS = ['-DGLEW_MX']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['boost_filesystem-xgcc42-mt-1_39', 'boost_system-xgcc42-mt-1_39']
|
||||
BOOSTLIBDIR = ['tools/darwin/libboost.framework/Resources/lib']
|
||||
COLLADAINCLUDE = ['#tools/windows/include/colladadom', '#tools/windows/include/colladadom/1.4']
|
||||
COLLADALIB = ['libCollada14Dom']
|
||||
COLLADALIBDIR = ['#tools/darwin/Collada14Dom.framework/Resources/lib']
|
||||
|
|
|
@ -20,6 +20,8 @@ GLLIBDIR = ['#tools/darwin/GLEW.framework/Resources/libs']
|
|||
GLLIB = ['GLEW', 'objc']
|
||||
GLFLAGS = ['-DGLEW_MX']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['boost_filesystem-xgcc42-mt-1_39', 'boost_system-xgcc42-mt-1_39']
|
||||
BOOSTLIBDIR = ['tools/darwin/libboost.framework/Resources/lib']
|
||||
COLLADAINCLUDE = ['#tools/windows/include/colladadom', '#tools/windows/include/colladadom/1.4']
|
||||
COLLADALIB = ['libCollada14Dom']
|
||||
COLLADALIBDIR = ['#tools/darwin/Collada14Dom.framework/Resources/lib']
|
||||
|
|
|
@ -10,8 +10,9 @@ PNGLIB = ['png']
|
|||
JPEGLIB = ['jpeg']
|
||||
XERCESINCLUDE = []
|
||||
XERCESLIB = ['xerces-c']
|
||||
GLLIB = ['GL', 'GLEWmx', 'Xxf86vm']
|
||||
GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11']
|
||||
GLFLAGS = ['-DGLEW_MX']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['libboost_system', 'libboost_filesystem']
|
||||
COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4']
|
||||
COLLADALIB = ['libcollada14dom', 'libboost_system', 'libboost_filesystem']
|
||||
COLLADALIB = ['libcollada14dom']
|
||||
|
|
|
@ -13,8 +13,9 @@ OEXRINCLUDE = ['#tools/windows/include/OpenEXR']
|
|||
OEXRFLAGS = ['/D', 'OPENEXR_DLL']
|
||||
OEXRLIB = ['IlmImf', 'IlmThread', 'Iex', 'zlib1', 'Half']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['libboost_system', 'libboost_filesystem']
|
||||
COLLADAINCLUDE = ['#tools/windows/include/colladadom', '#tools/windows/include/colladadom/1.4']
|
||||
COLLADALIB = ['libcollada14dom21', 'libboost_system', 'libboost_filesystem']
|
||||
COLLADALIB = ['libcollada14dom21']
|
||||
XERCESLIB = ['xerces-c_3']
|
||||
PNGLIB = ['libpng13']
|
||||
JPEGLIB = ['jpeg62']
|
||||
|
|
|
@ -13,8 +13,9 @@ OEXRINCLUDE = ['#tools/windows/include/OpenEXR']
|
|||
OEXRFLAGS = ['/D', 'OPENEXR_DLL']
|
||||
OEXRLIB = ['IlmImf', 'IlmThread', 'Iex', 'zlib1', 'Half']
|
||||
BOOSTINCLUDE = ['#tools/boost']
|
||||
BOOSTLIB = ['libboost_system', 'libboost_filesystem']
|
||||
COLLADAINCLUDE = ['#tools/windows/include/colladadom', '#tools/windows/include/colladadom/1.4']
|
||||
COLLADALIB = ['libcollada14dom21', 'libboost_system', 'libboost_filesystem']
|
||||
COLLADALIB = ['libcollada14dom21']
|
||||
XERCESLIB = ['xerces-c_3']
|
||||
PNGLIB = ['libpng13']
|
||||
JPEGLIB = ['jpeg62']
|
||||
|
|
42
doc/Doxyfile
42
doc/Doxyfile
|
@ -31,7 +31,7 @@ PROJECT_NAME = Mitsuba
|
|||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.1.1
|
||||
PROJECT_NUMBER = 0.1.3
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
@ -133,7 +133,7 @@ STRIP_FROM_PATH =
|
|||
# definition is used. Otherwise one should specify the include paths that
|
||||
# are normally passed to the compiler using the -I flag.
|
||||
|
||||
STRIP_FROM_INC_PATH =
|
||||
STRIP_FROM_INC_PATH = include
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
|
||||
# (but less readable) file names. This can be useful is your file systems
|
||||
|
@ -263,7 +263,7 @@ IDL_PROPERTY_SUPPORT = YES
|
|||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
DISTRIBUTE_GROUP_DOC = YES
|
||||
|
||||
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
|
||||
# the same type (for instance a group of public functions) to be put as a
|
||||
|
@ -590,7 +590,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = include
|
||||
INPUT = include/mitsuba/core 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
|
||||
|
@ -608,36 +608,10 @@ INPUT_ENCODING = UTF-8
|
|||
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
|
||||
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.f90 \
|
||||
*.f \
|
||||
*.vhd \
|
||||
*.vhdl
|
||||
*.dox
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
|
@ -1224,7 +1198,7 @@ MAN_LINKS = NO
|
|||
# generate an XML file that captures the structure of
|
||||
# the code including all documentation.
|
||||
|
||||
GENERATE_XML = NO
|
||||
GENERATE_XML = YES
|
||||
|
||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
|
@ -1311,7 +1285,7 @@ ENABLE_PREPROCESSING = YES
|
|||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
|
@ -1328,7 +1302,7 @@ SEARCH_INCLUDES = YES
|
|||
# contain include files that are not input files but should be processed by
|
||||
# the preprocessor.
|
||||
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_PATH = include
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
|
|
|
@ -8,13 +8,14 @@ Mitsuba makes heavy use of the following amazing libraries and tools:
|
|||
\begin{itemize}
|
||||
\item Qt 4 by Nokia
|
||||
\item OpenEXR by Industrial Light \& Magic
|
||||
\item Xerces-C++ by the Apache Foundation
|
||||
\item The Boost C++ class library
|
||||
\item Xerces-C+\!+ by the Apache Foundation
|
||||
\item The Boost C+\!+ class library
|
||||
\item GLEW by Milan Ikits, Marcelo E. Magallon and Lev Povalahev
|
||||
\item Mersenne Twister by Makoto Matsumoto and Takuji Nishimura
|
||||
\item COLLADA DOM by Sony Computer Entertainment
|
||||
\item libjpeg by the Independent JPEG Group
|
||||
\item libpng by Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and \mbox{others}
|
||||
\item libply by Ares Lagae
|
||||
\item BWToolkit by Brandon Walkin
|
||||
\item POSIX Threads for Win32 by Ross Johnson
|
||||
\item The SCons build system by the SCons Foundation
|
||||
|
|
|
@ -31,6 +31,10 @@ Some minor adjustments may have to be made to this file based on your configurat
|
|||
You may also set adjust certain compilation flags here:
|
||||
\begin{description}
|
||||
\item[\texttt{MTS\_DEBUG}] Enable assertions etc. Usually a good idea.
|
||||
\item[\texttt{MTS\_KD\_DEBUG}] Enable additional checks in the kd-Tree. This
|
||||
is quite slow and mainly useful to track down bugs when they are suspected.
|
||||
\item[\texttt{MTS\_KD\_CONSERVE\_MEMORY}] Use less memory for storing geometry (at the cost of speed).
|
||||
Off by default.
|
||||
\item[\texttt{SINGLE\_PRECISION}] Do all computation in single precision. This is usually sufficient.
|
||||
\item[\texttt{DOUBLE\_PRECISION}] Do all computation in double precision. Incompatible with
|
||||
\texttt{MTS\_SSE}, \texttt{MTS\_HAS\_COHERENT\_RT}, and \texttt{MTS\_DEBUG\_FP}.
|
||||
|
@ -41,18 +45,18 @@ You may also set adjust certain compilation flags here:
|
|||
All default configurations use the flags \code{MTS\_DEBUG}, \code{SINGLE\_PRECISION}, \code{MTS\_SSE}, \code{MTS\_HAS\_COHERENT\_RT}.
|
||||
Initially, it is a good idea to just leave the configuration the way it is.
|
||||
|
||||
\subsection{Building on Linux}
|
||||
On Linux, you'll first need to install a whole bunch of dependencies. It is assumed here
|
||||
\subsection{Building on Ubuntu Linux}
|
||||
You'll first need to install a number of dependencies. It is assumed here
|
||||
that you are using Ubuntu Linux, hence some of the package may be named differently if you are
|
||||
using another distribution.
|
||||
|
||||
First, run
|
||||
\begin{shell}
|
||||
$\text{\$}$ apt-get install build-essential scons qt4-dev-tools scons libpng12-dev libjpeg62-dev libilmbase-dev libopenexr-dev libxerces-c2-dev libboost-dev libglewmx1.5-dev libxxf86vm-dev libboost-system-dev libboost-filesystem-dev
|
||||
$\text{\$}$ sudo apt-get install build-essential scons qt4-dev-tools scons libpng12-dev libjpeg62-dev libilmbase-dev libopenexr-dev libxerces-c-dev libboost-dev libglewmx1.5-dev libxxf86vm-dev libboost-system-dev libboost-filesystem-dev
|
||||
\end{shell}
|
||||
To get COLLADA support, you will also need to install the \texttt{collada-dom} packages or build them from scratch. Here, we install the \code{x86\_64} binaries and development headers included with Mitsuba:
|
||||
\begin{shell}
|
||||
$\text{\$}$ dpkg --install tools/linux/collada-dom2.2_2.2-1_amd64.deb tools/linux/collada-dom-dev_2.2-1_amd64.deb
|
||||
$\text{\$}$ sudo dpkg --install tools/linux/collada-dom2.2_2.2-1_amd64.deb tools/linux/collada-dom-dev_2.2-1_amd64.deb
|
||||
\end{shell}
|
||||
Afterwards, simply run
|
||||
\begin{shell}
|
||||
|
@ -69,6 +73,63 @@ $\text{\$}$ . setpath.sh
|
|||
\end{shell}
|
||||
(note the period at the beginning -- this assumes that you are using \code{bash}).
|
||||
|
||||
\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.
|
||||
|
||||
First, run
|
||||
\begin{shell}
|
||||
$\text{\$}$ yum install mercurial gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-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 here: \texttt{http://www.mitsuba-renderer.org/releases}.
|
||||
Afterwards, simply run
|
||||
\begin{shell}
|
||||
$\text{\$}$ scons
|
||||
\end{shell}
|
||||
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}
|
||||
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:
|
||||
\begin{shell}
|
||||
$\text{\$}$ . setpath.sh
|
||||
\end{shell}
|
||||
(note the period at the beginning -- this assumes that you are using \code{bash}).
|
||||
|
||||
\subsection{Building on Arch Linux}
|
||||
You'll first need to install a number of dependencies.
|
||||
|
||||
First, run
|
||||
\begin{shell}
|
||||
$\text{\$}$ pacman -S mercurial openexr gcc xerces-c boost libjpeg libpng qt libxmu libxi mesa pcre libxml2 scons
|
||||
\end{shell}
|
||||
Some of the extra dependencies must be built manually:
|
||||
\begin{shell}
|
||||
$\text{\$}$ wget https://www.mitsuba-renderer.org/releases/contrib/archlinux/glewmx/PKGBUILD
|
||||
$\text{\$}$ makepkg
|
||||
$\text{\$}$ sudo pacman -U glewmx-*.xz
|
||||
\end{shell}
|
||||
and similar for \texttt{https://www.mitsuba-renderer.org/releases/contrib/archlin}-
|
||||
\texttt{ux/collada-dom/PKGBUILD}.
|
||||
Afterwards, simply run
|
||||
\begin{shell}
|
||||
$\text{\$}$ scons
|
||||
\end{shell}
|
||||
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}
|
||||
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:
|
||||
\begin{shell}
|
||||
$\text{\$}$ . setpath.sh
|
||||
\end{shell}
|
||||
(note the period at the beginning -- this assumes that you are using \code{bash}).
|
||||
|
||||
|
||||
\subsection{Building on Windows}
|
||||
This section assumes that Visual Studio 2008 is installed, but the instructions should work equally well with other versions.
|
||||
On the Windows platform, Mitsuba already includes most of the dependencies in precompiled form.
|
||||
|
@ -80,7 +141,7 @@ in the \code{\%PATH\%} environment variable so that entering \code{scons} on the
|
|||
C:\Users\Wenzel>scons
|
||||
scons: ** No SConstruct file found.
|
||||
\end{shell}
|
||||
\emph{Note: }On some setups, the precompiled SCons binaries generate a warning about not finding SCons in the registry. In this case, you can instead run \code{python setup.py install} within the source release of SCons.
|
||||
\emph{Note: }On some setups, the SCons installer generates a warning about not finding Python in the registry. In this case, you can instead run \code{python setup.py install} within the source release of SCons.
|
||||
Next, install Qt (\url{http://qt.nokia.com/downloads/windows-cpp-vs2008} -- you should get the release for Visual Studio 2008). Again, you need to make sure that the
|
||||
Qt utilities are reachable through the \code{\%PATH\%} environment variable so that you can for example launch \code{moc.exe} from the command line.
|
||||
|
||||
|
@ -99,8 +160,7 @@ All binaries are now located in the \code{dist} directory, and they should be ex
|
|||
|
||||
\subsection{Building on Mac OS X}
|
||||
On Mac OS X, you will need to install both scons (\code{www.scons.org}) and
|
||||
a recent release of XCode. You will also need to get Qt 4.7.0 Beta 2 or a newer version.
|
||||
As of this writing, 4.7.0 Beta 2 is still the most recent release and can be found here: \url{http://qt.nokia.com/developer/qt-qtcreator-prerelease#download}
|
||||
a recent release of XCode. You will also need to get Qt 4.7.0 or a newer version
|
||||
--- make sure that you get the normal Cocoa release (i.e. \emph{not} the one based on Carbon). All of the
|
||||
other dependencies are already included in precompiled form.
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
\mainpage Mitsuba Renderer API Documentation
|
||||
|
||||
<center>
|
||||
|
||||
<a href="http://www.mitsuba-renderer.org">www.mitsuba-renderer.org</a>
|
||||
|
||||
<table width=1000 border=0 style="border: 0px solid #EEEEEE"><tr><td>
|
||||
|
||||
<div class="featuretitle">Basic Information</div>
|
||||
- <a href="http://www.mitsuba-renderer.org/documentation.pdf">Reference Manual (PDF)</a>
|
||||
</div>
|
||||
|
||||
<div class="featuretitle">API Documentation</div>
|
||||
- <a href="annotated.html">Annotated Class List</a>
|
||||
- <a href="classes.html">Alphabetical Class List</a>
|
||||
- <a href="hierarchy.html">Class Hierarchy</a>
|
||||
</div>
|
||||
|
||||
<div class="featuretitle">Community</div>
|
||||
- <a href="http://www.mitsuba-renderer.org/devblog">Development Blog</a>
|
||||
- <a href="https://www.mitsuba-renderer.org/bugtracker/projects/mitsuba">Bug Tracker</a>
|
||||
- <a href="https://www.mitsuba-renderer.org/hg">List of repositories</a>
|
||||
</div>
|
||||
|
||||
</td></tr></table>
|
||||
</center>
|
||||
*/
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -200,7 +200,7 @@ To avoid having to do this every time \code{Li()} is called,
|
|||
we can override the \code{preprocess} function:
|
||||
\begin{cpp}
|
||||
/// Preprocess function -- called on the initiating machine
|
||||
void preprocess(const Scene *scene, RenderQueue *queue,
|
||||
bool preprocess(const Scene *scene, RenderQueue *queue,
|
||||
const RenderJob *job, int sceneResID, int cameraResID,
|
||||
int samplerResID) {
|
||||
SampleIntegrator::preprocess(scene, queue, job, sceneResID,
|
||||
|
@ -213,6 +213,8 @@ we can override the \code{preprocess} function:
|
|||
for (int i=0; i<8; ++i)
|
||||
m_maxDist = std::max(m_maxDist,
|
||||
(cameraPosition - sceneAABB.getCorner(i)).length());
|
||||
|
||||
return true;
|
||||
}
|
||||
\end{cpp}
|
||||
The bottom of this function should be relatively self-explanatory. The
|
||||
|
|
|
@ -23,25 +23,39 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Axis-aligned bounding box data structure
|
||||
/**
|
||||
* \brief Axis-aligned bounding box data structure in three dimensions
|
||||
*
|
||||
* Maintains a component-wise minimum and maximum position and provides
|
||||
* various convenience functions to query or change them.
|
||||
*/
|
||||
struct MTS_EXPORT_CORE AABB {
|
||||
public:
|
||||
Point min;
|
||||
Point max;
|
||||
Point min; ///< Component-wise minimum
|
||||
Point max; ///< Component-wise maximum
|
||||
|
||||
/// Construct an invalid bounding box
|
||||
/**
|
||||
* \brief Construct an invalid bounding box
|
||||
*
|
||||
* The minimum and maximum positions will be
|
||||
* initialized to \f$(\infty,\infty,\infty)\f$
|
||||
* and \f$(-\infty, -\infty, -\infty)\f$, respectively.
|
||||
*/
|
||||
inline AABB() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/// Unserialize an AABB from a stream
|
||||
/// Unserialize a bounding box from a binary data stream
|
||||
inline AABB(Stream *stream) {
|
||||
min = Point(stream);
|
||||
max = Point(stream);
|
||||
}
|
||||
|
||||
/// Create a collapsed AABB from a single point
|
||||
inline AABB(const Point &p)
|
||||
: min(p), max(p) { }
|
||||
|
||||
/// Create a bounding box from two 3-dimension vectors
|
||||
/// Create a bounding box from two 3D positions
|
||||
inline AABB(const Point &min, const Point &max)
|
||||
: min(min), max(max) {
|
||||
SAssert(min.x <= max.x
|
||||
|
@ -61,33 +75,30 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/// Equal operator
|
||||
/// Equality test
|
||||
inline bool operator==(const AABB &aabb) const {
|
||||
return min == aabb.min && max == aabb.max;
|
||||
}
|
||||
|
||||
/// Not equal operator
|
||||
/// Inequality test
|
||||
inline bool operator!=(const AABB &aabb) const {
|
||||
return min != aabb.min || max != aabb.max;
|
||||
}
|
||||
|
||||
/// Mark the bounding box as invalid
|
||||
/**
|
||||
* \brief Mark the bounding box as invalid.
|
||||
*
|
||||
* This operation sets the
|
||||
* minimum position to \f$(\infty,\infty,\infty)\f$ and the
|
||||
* maximum position to \f$(-\infty, -\infty, -\infty)\f$.
|
||||
*/
|
||||
inline void reset() {
|
||||
const Float inf = std::numeric_limits<Float>::infinity();
|
||||
min = Point(inf, inf, inf);
|
||||
max = Point(-inf, -inf, -inf);
|
||||
}
|
||||
|
||||
/// Calculate the volume of the bounding box
|
||||
inline Float getVolume() const {
|
||||
Float x = max.x - min.x;
|
||||
Float y = max.y - min.y;
|
||||
Float z = max.z - min.z;
|
||||
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
/// Clip to another AABB
|
||||
/// Clip to another bounding box
|
||||
inline void clip(const AABB &aabb) {
|
||||
min.x = std::max(min.x, aabb.min.x);
|
||||
min.y = std::max(min.y, aabb.min.y);
|
||||
|
@ -99,21 +110,33 @@ public:
|
|||
|
||||
/// Return the center point
|
||||
inline Point getCenter() const {
|
||||
return max*.5f + min*.5f;
|
||||
return (max + min) * (Float) 0.5;
|
||||
}
|
||||
|
||||
/// Calculate the volume of the bounding box
|
||||
inline Float getVolume() const {
|
||||
Float x = max.x - min.x;
|
||||
Float y = max.y - min.y;
|
||||
Float z = max.z - min.z;
|
||||
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
/// Calculate the surface area of the bounding box
|
||||
inline Float getSurfaceArea() const {
|
||||
Vector d = max - min;
|
||||
return 2.0f * (d.x*d.y + d.x*d.z + d.y*d.z);
|
||||
return (Float) 2.0 * (d.x*d.y + d.x*d.z + d.y*d.z);
|
||||
}
|
||||
|
||||
/// Calculate the AABB extents
|
||||
|
||||
/**
|
||||
* \brief Calculate the bounding box extents
|
||||
* \return max-min
|
||||
*/
|
||||
inline Vector getExtents() const {
|
||||
return max - min;
|
||||
}
|
||||
|
||||
/// Return the axis with the largest corresponding AABB side
|
||||
/// Return the axis index with the largest associated side length
|
||||
inline int getLargestAxis() const {
|
||||
Vector d = max - min;
|
||||
if (d.x >= d.y && d.x >= d.z)
|
||||
|
@ -124,7 +147,7 @@ public:
|
|||
return 2;
|
||||
}
|
||||
|
||||
/// Return the axis with the smallest corresponding AABB side
|
||||
/// Return the axis index with the smallest associated side length
|
||||
inline int getSmallestAxis() const {
|
||||
Vector d = max - min;
|
||||
if (d.x <= d.y && d.x <= d.z)
|
||||
|
@ -141,8 +164,8 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Return whether this bounding box covers a non-zero
|
||||
* amount of space
|
||||
* \brief Return whether or not this bounding box covers a
|
||||
* nonzero amount of space
|
||||
*/
|
||||
inline bool isEmpty() const {
|
||||
return max.x <= min.x
|
||||
|
@ -151,47 +174,44 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/// Return the minimum vector of the bounding box
|
||||
/// Return the component-wise minimum point of the bounding box
|
||||
inline const Point &getMinimum() const {
|
||||
return min;
|
||||
}
|
||||
|
||||
/// Return the maximum vector of the bounding box
|
||||
/// Return the component-wise maximum point of the bounding box
|
||||
inline const Point &getMaximum() const {
|
||||
return max;
|
||||
}
|
||||
|
||||
/// Return the middle point
|
||||
Point getMidPoint() const;
|
||||
|
||||
/** \brief Return the vector coordinates of a bounding
|
||||
* box corner
|
||||
* @param corner Corner index (0..7)
|
||||
/**
|
||||
* \brief Return the position of a bounding box corner
|
||||
* \param corner Requested corner index (0..7)
|
||||
*/
|
||||
Point getCorner(uint8_t corner) const;
|
||||
|
||||
/// Checks whether a vector is inside the bounding box
|
||||
/// Check whether a point lies on or inside the bounding box
|
||||
bool contains(const Point &vec) const;
|
||||
|
||||
/// Bounding sphere-AABB overlap test
|
||||
inline bool overlaps(const BSphere &sphere) const {
|
||||
Float distance = 0;
|
||||
for (int i=0; i<3; ++i) {
|
||||
if (sphere.center[i] < min[i]) {
|
||||
Float d = sphere.center[i]-min[i];
|
||||
distance += d*d;
|
||||
} else if (sphere.center[i] > max[i]) {
|
||||
Float d = sphere.center[i]-max[i];
|
||||
distance += d*d;
|
||||
}
|
||||
}
|
||||
return distance < sphere.radius*sphere.radius;
|
||||
}
|
||||
/// Check whether a given bounding box is contained within this one
|
||||
bool contains(const AABB &aabb) const;
|
||||
|
||||
/// Expands the bounding box to contain another vector
|
||||
/**
|
||||
* \brief Bounding sphere-box overlap test
|
||||
*
|
||||
* Implements the technique proposed by Jim Arvo in
|
||||
* "A simple method for box-sphere intersection testing"
|
||||
* (Graphics Gems, 1990)
|
||||
*/
|
||||
bool overlaps(const BSphere &sphere) const;
|
||||
|
||||
/// Axis-aligned bounding box overlap test
|
||||
bool overlaps(const AABB &saabb) const;
|
||||
|
||||
/// Expand the bounding box to contain another point
|
||||
void expandBy(const Point &vec);
|
||||
|
||||
/// Expands the bounding box to contain another bounding box
|
||||
/// Expand the bounding box to contain another bounding box
|
||||
void expandBy(const AABB &aabb);
|
||||
|
||||
/// Calculate the point-AABB distance
|
||||
|
@ -237,19 +257,22 @@ public:
|
|||
|
||||
#ifdef MTS_SSE
|
||||
/**
|
||||
* Intersect against a packet of four rays. Returns false if none of
|
||||
* the rays intersect.
|
||||
* \brief Intersect against a packet of four rays.
|
||||
* \return \a false if none of the rays intersect.
|
||||
*/
|
||||
FINLINE bool rayIntersectPacket(const RayPacket4 &ray, RayInterval4 &interval) const;
|
||||
#endif
|
||||
|
||||
/// Serialize this AABB to a stream
|
||||
/// Create a bounding sphere, which contains the axis-aligned box
|
||||
BSphere getBSphere() const;
|
||||
|
||||
/// Serialize this bounding box to a binary data stream
|
||||
inline void serialize(Stream *stream) const {
|
||||
min.serialize(stream);
|
||||
max.serialize(stream);
|
||||
}
|
||||
|
||||
/// Returns a string representation of the bounding box
|
||||
/// Return a string representation of the bounding box
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#if !defined(__APPENDER_H)
|
||||
#define __APPENDER_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief This class defines an abstract destination
|
||||
|
@ -26,16 +28,16 @@ MTS_NAMESPACE_BEGIN
|
|||
*/
|
||||
class MTS_EXPORT_CORE Appender : public Object {
|
||||
public:
|
||||
/// Append a line of text
|
||||
virtual void append(ELogLevel level, const std::string &pText) = 0;
|
||||
/// Append a line of text with the given log level
|
||||
virtual void append(ELogLevel level, const std::string &text) = 0;
|
||||
|
||||
/**
|
||||
* Process a progress message
|
||||
* @param progress Percentage value in [0,100]
|
||||
* @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
|
||||
* \brief Process a progress message
|
||||
* \param progress Percentage value in [0,100]
|
||||
* \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
|
||||
*/
|
||||
virtual void logProgress(Float progress, const std::string &name,
|
||||
const std::string &formatted, const std::string &eta, const void *ptr) = 0;
|
||||
|
@ -46,7 +48,7 @@ protected:
|
|||
virtual ~Appender() { }
|
||||
};
|
||||
|
||||
/** \brief Appender implementation which writes to an
|
||||
/** \brief Appender implementation, which writes to an
|
||||
* arbitrary C++ stream
|
||||
*/
|
||||
class MTS_EXPORT_CORE StreamAppender : public Appender {
|
||||
|
@ -82,7 +84,7 @@ private:
|
|||
bool m_lastMessageWasProgress;
|
||||
};
|
||||
|
||||
/** \brief Appender implementation which writes to an
|
||||
/** \brief Appender implementation, which writes to an
|
||||
* unbuffered file descriptor.
|
||||
*/
|
||||
class MTS_EXPORT_CORE UnbufferedAppender : public Appender {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__ATOMIC_H)
|
||||
#define __ATOMIC_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(__OSX__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
template <typename T> inline bool atomicCompareAndExchangePtr(T **v, T *newValue, T *oldValue) {
|
||||
#if defined(WIN32)
|
||||
return InterlockedCompareExchangePointer(
|
||||
reinterpret_cast<volatile PVOID *>(v), newValue, oldValue) == oldValue;
|
||||
#else
|
||||
return __sync_bool_compare_and_swap(v, oldValue, newValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __ATOMIC_H */
|
|
@ -104,7 +104,7 @@ public:
|
|||
inline const int getBitsPerPixel() const { return m_bpp; }
|
||||
|
||||
/// Return the bitmap size in bytes
|
||||
inline const int getSize() const { return m_size; }
|
||||
inline const size_t getSize() const { return m_size; }
|
||||
|
||||
/// Return some human-readable information about this bitmap
|
||||
std::string toString() const;
|
||||
|
|
|
@ -19,61 +19,62 @@
|
|||
#if !defined(__BSPHERE_H)
|
||||
#define __BSPHERE_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/ray.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Bounding sphere class
|
||||
/** \brief Bounding sphere data structure in three dimensions
|
||||
*/
|
||||
struct BSphere {
|
||||
Point center;
|
||||
Float radius;
|
||||
|
||||
/// Construct an empty bounding sphere
|
||||
/// Construct a bounding sphere at the origin having radius zero
|
||||
inline BSphere() {
|
||||
radius = 0.0f;
|
||||
}
|
||||
|
||||
/// Unserialize an AABB from a stream
|
||||
|
||||
/// Unserialize a bounding sphere from a binary data stream
|
||||
inline BSphere(Stream *stream) {
|
||||
center = Point(stream);
|
||||
radius = stream->readFloat();
|
||||
}
|
||||
|
||||
/// Create a bounding sphere from a given center point and a radius
|
||||
inline BSphere(const Point &pCenter, Float pRadius)
|
||||
: center(pCenter), radius(pRadius) {
|
||||
/// Create a bounding sphere from a given center point and radius
|
||||
inline BSphere(const Point ¢er, Float radius)
|
||||
: center(center), radius(radius) {
|
||||
}
|
||||
|
||||
/// Copy-constructor
|
||||
/// Copy constructor
|
||||
inline BSphere(const BSphere &boundingSphere)
|
||||
: center(boundingSphere.center), radius(boundingSphere.radius) {
|
||||
}
|
||||
|
||||
/// Return whether this bounding sphere is empty
|
||||
/// Return whether this bounding sphere has a radius of zero or less.
|
||||
inline bool isEmpty() const {
|
||||
return radius <= 0.0f;
|
||||
}
|
||||
|
||||
/** \brief Expands the bounding sphere to contain another point.
|
||||
* Does not move the center point
|
||||
*/
|
||||
/// 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());
|
||||
}
|
||||
|
||||
/// Comparison operator
|
||||
/// Equality test
|
||||
inline bool operator==(const BSphere &boundingSphere) const {
|
||||
return center == boundingSphere.center && radius == boundingSphere.radius;
|
||||
}
|
||||
|
||||
/// Comparison operator
|
||||
/// Inequality test
|
||||
inline bool operator!=(const BSphere &boundingSphere) const {
|
||||
return !operator==(boundingSphere);
|
||||
return center != boundingSphere.center || radius != boundingSphere.radius;
|
||||
}
|
||||
|
||||
/// Calculate the intersection points with the given ray
|
||||
/**
|
||||
* \brief Calculate the intersection points with the given ray
|
||||
* \return \a true if the ray intersects the bounding sphere
|
||||
*/
|
||||
inline bool rayIntersect(const Ray &ray, Float &nearHit, Float &farHit) const {
|
||||
Vector originToCenter = center - ray.o;
|
||||
Float distToRayClosest = dot(originToCenter, ray.d);
|
||||
|
@ -109,13 +110,13 @@ struct BSphere {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Serialize this AABB to a stream
|
||||
/// Serialize this bounding sphere to a binary data stream
|
||||
inline void serialize(Stream *stream) const {
|
||||
center.serialize(stream);
|
||||
stream->writeFloat(radius);
|
||||
}
|
||||
|
||||
/// Returns a string representation of the bounding sphere
|
||||
/// Return a string representation of the bounding sphere
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "BSphere[center = " << center.toString()
|
||||
|
|
|
@ -21,43 +21,63 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/* Forward declarations */
|
||||
class Stream;
|
||||
class Object;
|
||||
class InstanceManager;
|
||||
|
||||
/** \brief Universal class descriptor.
|
||||
* @see ref, Object
|
||||
/**
|
||||
* \headerfile mitsuba/core/class.h mitsuba/mitsuba.h
|
||||
* \brief Stores meta-information about \ref Object instances.
|
||||
*
|
||||
* This class provides a thin layer of RTTI (run-time type information),
|
||||
* which is useful for doing things like:
|
||||
*
|
||||
* <ul>
|
||||
* <li> Checking if an object derives from a certain class </li>
|
||||
* <li> Determining the parent of a class at runtime </li>
|
||||
* <li> Instantiating a class by name </li>
|
||||
* <li> Unserializing a class from a binary data stream </li>
|
||||
* </ul>
|
||||
*
|
||||
* \sa ref, Object
|
||||
*/
|
||||
class MTS_EXPORT_CORE Class {
|
||||
public:
|
||||
/// Construct a new class descriptor
|
||||
/**
|
||||
* \brief Construct a new class descriptor
|
||||
*
|
||||
* This method should never be called manually. Instead, use
|
||||
* one of the \ref MTS_IMPLEMENT_CLASS, \ref MTS_IMPLEMENT_CLASS_S,
|
||||
* \ref MTS_IMPLEMENT_CLASS_I or \ref MTS_IMPLEMENT_CLASS_IS macros
|
||||
* to automatically do this for you.
|
||||
*
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param superClassName Name of the parent class
|
||||
* \param instPtr Pointer to an instantiation function
|
||||
* \param unSerPtr Pointer to an unserialization function
|
||||
*/
|
||||
Class(const std::string &name, bool abstract, const std::string &superClassName,
|
||||
void *instPtr = NULL, void *unSerPtr = NULL);
|
||||
|
||||
/// Return the class' name
|
||||
/// Return the name of the represented class
|
||||
inline const std::string &getName() const { return m_name; }
|
||||
|
||||
/** \brief Return whether the class represented
|
||||
* by this Class object is abstract
|
||||
/**
|
||||
* \brief Return whether or not the class represented
|
||||
* by this Class object contains pure virtual methods
|
||||
*/
|
||||
inline bool isAbstract() const { return m_abstract; }
|
||||
|
||||
/** \brief Does the class support instantiation over RTTI?
|
||||
*/
|
||||
/// Does the class support instantiation over RTTI?
|
||||
inline bool isInstantiable() const { return m_instPtr != NULL; }
|
||||
|
||||
/** \brief Does the class support serialization?
|
||||
*/
|
||||
/// Does the class support serialization?
|
||||
inline bool isSerializable() const { return m_unSerPtr != NULL; }
|
||||
|
||||
/** \brief Return this class' super class or NULL
|
||||
* if it has no super class
|
||||
/** \brief Return the Class object associated with the parent
|
||||
* class of NULL if it does not have one.
|
||||
*/
|
||||
inline const Class *getSuperClass() const { return m_superClass; }
|
||||
|
||||
/// Check whether this class derives from pClass
|
||||
bool derivesFrom(const Class *pClass) const;
|
||||
/// Check whether this class derives from \a theClass
|
||||
bool derivesFrom(const Class *theClass) const;
|
||||
|
||||
/// Look up a class by its name
|
||||
static const Class *forName(const std::string &name);
|
||||
|
@ -68,11 +88,11 @@ public:
|
|||
static const Class *forName(const char *name);
|
||||
|
||||
/** \brief Unserialize an instance of the class (if this is
|
||||
* supported by the class).
|
||||
* supported).
|
||||
*/
|
||||
Object *unserialize(Stream *stream = NULL, InstanceManager *manager = NULL) const;
|
||||
|
||||
/// Generate an instance of this class (if supported)
|
||||
/// Generate an instance of this class (if this is supported)
|
||||
Object *instantiate() const;
|
||||
|
||||
/** \brief Initializes the built-in RTTI and creates
|
||||
|
@ -95,20 +115,34 @@ private:
|
|||
void *m_instPtr, *m_unSerPtr;
|
||||
};
|
||||
|
||||
/* Class instantiation macros */
|
||||
/**
|
||||
* \brief This macro must be used in the declaration of
|
||||
* all classes derived from \ref Object.
|
||||
*/
|
||||
#define MTS_DECLARE_CLASS() \
|
||||
virtual const Class *getClass() const; \
|
||||
public: \
|
||||
static Class *m_theClass;
|
||||
|
||||
// basic RTTI support for a class
|
||||
/**
|
||||
* \brief Creates basic RTTI support for a class
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS(name, abstract, super) \
|
||||
Class *name::m_theClass = new Class(#name, abstract, #super); \
|
||||
const Class *name::getClass() const { \
|
||||
return m_theClass;\
|
||||
}
|
||||
|
||||
// Extended version, records that the class supports instantiation by name
|
||||
/**
|
||||
* \brief Creates basic RTTI support for a class. Assumes that
|
||||
* the class can be instantiated by name.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_I(name, abstract, super) \
|
||||
Object *__##name ##_inst() { \
|
||||
return new name(); \
|
||||
|
@ -118,7 +152,13 @@ public: \
|
|||
return m_theClass;\
|
||||
}
|
||||
|
||||
// Extended version, records that the class can be unserialized from a binary data stream
|
||||
/**
|
||||
* \brief Creates basic RTTI support for a class. Assumes that
|
||||
* the class can be unserialized from a binary data stream.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_S(name, abstract, super) \
|
||||
Object *__##name ##_unSer(Stream *stream, InstanceManager *manager) { \
|
||||
return new name(stream, manager); \
|
||||
|
@ -128,7 +168,14 @@ public: \
|
|||
return m_theClass;\
|
||||
}
|
||||
|
||||
// Extended version, records 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. Assumes that
|
||||
* the class can be unserialized from a binary data stream as well
|
||||
* as instantiated by name.
|
||||
* \param name Name of the class
|
||||
* \param abstract \a true if the class contains pure virtual methods
|
||||
* \param super Name of the parent class
|
||||
*/
|
||||
#define MTS_IMPLEMENT_CLASS_IS(name, abstract, super) \
|
||||
Object *__##name ##_unSer(Stream *stream, InstanceManager *manager) { \
|
||||
return new name(stream, manager); \
|
||||
|
|
|
@ -24,45 +24,54 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Interface of a generic serializable object that can be
|
||||
* configured by an instance of the Properties class.
|
||||
/** \brief Generic serializable object, which supports construction
|
||||
* from a Properties instance.
|
||||
*
|
||||
* All plugins in Mitsuba derive from ConfigurableObject. This mechanism
|
||||
* lets them accept parameters specified in an external XML file. Additionally,
|
||||
* they can have child objects, which correspond to nested instantiation
|
||||
* requests in the XML file.
|
||||
*/
|
||||
class MTS_EXPORT_CORE ConfigurableObject : public SerializableObject {
|
||||
public:
|
||||
/// Constructor
|
||||
inline ConfigurableObject(const Properties &props) : SerializableObject(), m_configured(false), m_parent(NULL) { }
|
||||
|
||||
/// Unserialize a configurable object
|
||||
ConfigurableObject(Stream *stream, InstanceManager *manager);
|
||||
|
||||
/// Set the parent object
|
||||
virtual void setParent(ConfigurableObject *parent);
|
||||
|
||||
/// Get the parent object
|
||||
/// Return the parent object
|
||||
inline ConfigurableObject *getParent() { return m_parent; }
|
||||
|
||||
/// Get the parent object
|
||||
|
||||
/// Return the parent object (const version)
|
||||
inline const ConfigurableObject *getParent() const { return m_parent; }
|
||||
|
||||
/// Add a child (default implementation throws an error)
|
||||
virtual void addChild(const std::string &name, ConfigurableObject *child);
|
||||
|
||||
/** \brief Configure the object (called _once_ after construction
|
||||
and addition of all child ConfigurableObjects. */
|
||||
/** \brief Configure the object (called <em>once</em> after construction
|
||||
and addition of all child ConfigurableObjects) */
|
||||
virtual void configure();
|
||||
|
||||
/// Serialize this object to a stream
|
||||
/// Serialize this object to a binary data stream
|
||||
virtual void serialize(Stream *stream, InstanceManager *manager) const;
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~ConfigurableObject() { }
|
||||
|
||||
/// Construct a configurable object
|
||||
inline ConfigurableObject(const Properties &props)
|
||||
: SerializableObject(), m_parent(NULL), m_configured(false) { }
|
||||
|
||||
/// Unserialize a configurable object
|
||||
ConfigurableObject(Stream *stream, InstanceManager *manager);
|
||||
protected:
|
||||
bool m_configured;
|
||||
ConfigurableObject *m_parent;
|
||||
bool m_configured;
|
||||
};
|
||||
|
||||
/** \brief This macro creates the binary interface, which Mitsuba
|
||||
* requires to load a plugin.
|
||||
*/
|
||||
#define MTS_EXPORT_PLUGIN(name, descr) \
|
||||
extern "C" { \
|
||||
void MTS_EXPORT *CreateInstance(const Properties &props) { \
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
/* Choice of precision */
|
||||
#ifdef DOUBLE_PRECISION
|
||||
#define Float double
|
||||
#define Epsilon 1e-6
|
||||
#define Epsilon 1e-8
|
||||
#else
|
||||
#ifndef SINGLE_PRECISION
|
||||
#define SINGLE_PRECISION
|
||||
#endif
|
||||
#define Float float
|
||||
#define Epsilon 1e-4f
|
||||
#define Epsilon 1e-5f
|
||||
#endif
|
||||
|
||||
/// relative eps. for shadow rays
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Console stream
|
||||
/** \brief Interface to the default stdin/stdout console streams
|
||||
*/
|
||||
class MTS_EXPORT_CORE ConsoleStream : public Stream {
|
||||
public:
|
||||
|
@ -46,11 +46,7 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/** \brief Virtual destructor
|
||||
*
|
||||
* The destructor frees all resources and closes
|
||||
* the socket if it is still open
|
||||
*/
|
||||
/// Virtual destructor
|
||||
virtual ~ConsoleStream();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__FIFO_H)
|
||||
#define __FIFO_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <pthread.h>
|
||||
#include <deque>
|
||||
|
||||
#if defined(__OSX__)
|
||||
#include <mach/semaphore.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
#else
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Simple synchronized FIFO class with an underlying
|
||||
* deque container
|
||||
*/
|
||||
template <class T> class FIFO {
|
||||
public:
|
||||
FIFO() {
|
||||
#if defined(__OSX__)
|
||||
if (semaphore_create(::mach_task_self(), &m_available,
|
||||
SYNC_POLICY_FIFO, 0) != KERN_SUCCESS)
|
||||
SLog(EError, "Could not create a semaphore!");
|
||||
#else
|
||||
if (sem_init(&m_available, PTHREAD_PROCESS_PRIVATE, 0))
|
||||
SLog(EError, "Could not create a semaphore!");
|
||||
#endif
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
}
|
||||
|
||||
void put(T value) {
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
m_data.push_back(value);
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
#if defined(__OSX__)
|
||||
semaphore_signal(m_available);
|
||||
#else
|
||||
sem_post(&m_available);
|
||||
#endif
|
||||
}
|
||||
|
||||
T get() {
|
||||
T result;
|
||||
#if defined(__OSX__)
|
||||
semaphore_wait(m_available);
|
||||
#else
|
||||
while (sem_wait(&m_available) != 0)
|
||||
;
|
||||
#endif
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
result = m_data.front();
|
||||
m_data.pop_front();
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
int getSize() const {
|
||||
int result;
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
result = m_data.size();
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
~FIFO() {
|
||||
#if defined(__OSX__)
|
||||
semaphore_destroy(::mach_task_self(), m_available);
|
||||
#else
|
||||
sem_destroy(&m_available);
|
||||
#endif
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
private:
|
||||
std::deque<T> m_data;
|
||||
mutable pthread_mutex_t m_mutex;
|
||||
#if defined(__OSX__)
|
||||
semaphore_t m_available;
|
||||
#else
|
||||
sem_t m_available;
|
||||
#endif
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __FIFO_H */
|
|
@ -19,33 +19,37 @@
|
|||
#if !defined(__FORMATTER_H)
|
||||
#define __FORMATTER_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/// Available Log message types
|
||||
enum ELogLevel {
|
||||
/// Trace message, for extremely verbose debugging
|
||||
ETrace = 0,
|
||||
/// Debug message, usually turned off
|
||||
EDebug = 100,
|
||||
/// More relevant debug / information message
|
||||
EInfo = 200,
|
||||
/// Warning message
|
||||
EWarn = 300,
|
||||
/// Error message, causes an exception to be thrown
|
||||
EError = 400
|
||||
ETrace = 0, ///< Trace message, for extremely verbose debugging
|
||||
EDebug = 100, ///< Debug message, usually turned off
|
||||
EInfo = 200, ///< More relevant debug / information message
|
||||
EWarn = 300, ///< Warning message
|
||||
EError = 400 ///< Error message, causes an exception to be thrown
|
||||
};
|
||||
|
||||
class Thread;
|
||||
|
||||
/** \brief The Formatter class defines an interface for converting
|
||||
* log information into a human-readable format
|
||||
/** \brief Abstract interface for converting log information into
|
||||
* a human-readable format
|
||||
*/
|
||||
class MTS_EXPORT_CORE Formatter : public Object {
|
||||
public:
|
||||
/// Format a line of text
|
||||
virtual std::string format(ELogLevel pLogLevel, const Class *pClass,
|
||||
const Thread *pThread, const std::string &pText,
|
||||
const char *pFile, int pLine) = 0;
|
||||
/**
|
||||
* \brief Turn a log message into a human-readable format
|
||||
* \param logLevel The importance of the debug message
|
||||
* \param theClass Originating class or NULL
|
||||
* \param thread Thread, which is reponsible for creating the message
|
||||
* \param text Text content associated with the log message
|
||||
* \param file File, which is responsible for creating the message
|
||||
* \param line Associated line within the source file
|
||||
*/
|
||||
|
||||
virtual std::string format(ELogLevel logLevel, const Class *theClass,
|
||||
const Thread *thread, const std::string &text,
|
||||
const char *file, int line) = 0;
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
|
@ -53,27 +57,39 @@ protected:
|
|||
virtual ~Formatter() { }
|
||||
};
|
||||
|
||||
/** \brief The default formatter implementation
|
||||
/** \brief The default formatter used to turn log messages into
|
||||
* a human-readable form
|
||||
*/
|
||||
class MTS_EXPORT_CORE DefaultFormatter : public Formatter {
|
||||
public:
|
||||
/// Create a new default formatter
|
||||
DefaultFormatter();
|
||||
|
||||
/// Format a line of text
|
||||
std::string format(ELogLevel pLogLevel, const Class *pClass,
|
||||
const Thread *pThread, const std::string &pText,
|
||||
const char *pFile, int pLine);
|
||||
std::string format(ELogLevel logLevel, const Class *theClass,
|
||||
const Thread *thread, const std::string &text,
|
||||
const char *file, int line);
|
||||
|
||||
/// Should the date be included?
|
||||
/// Should date information be included? The default is yes.
|
||||
inline void setHaveDate(bool value) { m_haveDate = value; }
|
||||
|
||||
/// Should thread information be included? The default is yes.
|
||||
inline void setHaveThread(bool value) { m_haveThread = value; }
|
||||
|
||||
/// Should log level information be included? The default is yes.
|
||||
inline void setHaveLogLevel(bool value) { m_haveLogLevel = value; }
|
||||
|
||||
/// Should class information be included? The default is yes.
|
||||
inline void setHaveClass(bool value) { m_haveClass = value; }
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~DefaultFormatter() { }
|
||||
protected:
|
||||
bool m_haveDate;
|
||||
bool m_haveLogLevel;
|
||||
bool m_haveThread;
|
||||
bool m_haveClass;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -24,38 +24,34 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* This data structure stores an arbitrary three-dimensional cartesian
|
||||
* coordinate system and provides routines to convert coordinates and
|
||||
* efficiently compute several other quantities.
|
||||
* \brief Stores a three-dimensional orthonormal coordinate frame
|
||||
*
|
||||
* This class is mostly used to quickly convert between different
|
||||
* cartesian coordinate systems and to efficiently compute certain
|
||||
* quantities (e.g. \ref cosTheta(), \ref tanTheta, ..).
|
||||
*/
|
||||
struct Frame {
|
||||
Vector s, t;
|
||||
Normal n;
|
||||
|
||||
/// Default constructor
|
||||
inline Frame() {
|
||||
}
|
||||
/// Default constructor -- performs no initialization!
|
||||
inline Frame() { }
|
||||
|
||||
/// Given a normal and tangent vectors, construct a new coordinate frame
|
||||
inline Frame(const Vector &s, const Vector &t, const Normal &n)
|
||||
: s(s), t(t), n(n) {
|
||||
}
|
||||
|
||||
/// Construct a frame from the given cartesian coordinate system
|
||||
/// Construct a frame from the given orthonormal vectors
|
||||
inline Frame(const Vector &x, const Vector &y, const Vector &z)
|
||||
: s(x), t(y), n(Normal(z)) {
|
||||
: s(x), t(y), n(z) {
|
||||
}
|
||||
|
||||
/// Construct a new coordinate frame from a single vector
|
||||
inline Frame(const Vector &n) : n(Normal(n)) {
|
||||
inline Frame(const Vector &n) : n(n) {
|
||||
coordinateSystem(n, s, t);
|
||||
}
|
||||
|
||||
/// Construct a new coordinate frame from a single normal vector
|
||||
inline Frame(const Normal &n) : n(n) {
|
||||
coordinateSystem(Vector(n), s, t);
|
||||
}
|
||||
|
||||
/// Unserialize from a binary data stream
|
||||
inline Frame(Stream *stream) {
|
||||
s = Vector(stream);
|
||||
|
|
|
@ -19,236 +19,72 @@
|
|||
#if !defined(__FRESOLVER_H)
|
||||
#define __FRESOLVER_H
|
||||
|
||||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/tls.h>
|
||||
#if defined(WIN32)
|
||||
#include <direct.h>
|
||||
#define PATH_MAX 1024
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#define PATHSEP '/'
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Utility class that searchs for files within a set of user-defined
|
||||
* directories. Each thread has its own, unique file resolver, which
|
||||
* makes it possible to have per-thread current working directories.
|
||||
* \brief File resolution helper
|
||||
*
|
||||
* FileResolver is a convenience class that allows searching for files
|
||||
* within a set of specifiable search paths in a cross-platform
|
||||
* compatible manner (similar to the $PATH variable on various
|
||||
* operating systems).
|
||||
*/
|
||||
class MTS_EXPORT_CORE FileResolver : public Object {
|
||||
public:
|
||||
/// Return the current thread's resolver instance
|
||||
inline static FileResolver *getInstance() {
|
||||
FileResolver *resolver = m_tls.get();
|
||||
if (!resolver) {
|
||||
resolver = new FileResolver();
|
||||
m_tls.set(resolver);
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
/// Set the current thread's resolver instance
|
||||
inline static void setInstance(FileResolver *resolver) {
|
||||
m_tls.set(resolver);
|
||||
}
|
||||
|
||||
/// Clone a file resolver
|
||||
inline FileResolver *clone() {
|
||||
FileResolver *cloned = new FileResolver();
|
||||
cloned->m_paths = m_paths;
|
||||
cloned->m_currentDirectory = m_currentDirectory;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
/// Reset the search path
|
||||
inline void clear() {
|
||||
m_paths.clear();
|
||||
}
|
||||
|
||||
/// Add a search path
|
||||
inline void addPath(const std::string &path) {
|
||||
m_paths.push_back(path);
|
||||
}
|
||||
|
||||
/// Check if the list of search paths contains a certain entry
|
||||
inline bool contains(const std::string &path) const {
|
||||
return std::find(m_paths.begin(), m_paths.end(), path) != m_paths.end();
|
||||
}
|
||||
|
||||
/// Set the resolver's current working directory
|
||||
inline void setCurrentDirectory(const std::string &cwd) {
|
||||
m_currentDirectory = cwd;
|
||||
}
|
||||
|
||||
/// Return the resolver's current working directory
|
||||
inline const std::string &getCurrentDirectory() const {
|
||||
return m_currentDirectory;
|
||||
}
|
||||
|
||||
/// Set the current directory by stripping away the last component
|
||||
inline void setCurrentDirectoryFromFile(const std::string &cwd) {
|
||||
m_currentDirectory = getParentDirectory(cwd);
|
||||
}
|
||||
|
||||
/// Adds a path while stripping away the last component
|
||||
inline void addPathFromFile(const std::string &path) {
|
||||
addPath(getParentDirectory(path));
|
||||
}
|
||||
|
||||
/// Strip the last component from a path
|
||||
inline std::string getParentDirectory(const std::string &path) const {
|
||||
std::vector<std::string> components = tokenize(path, "/\\");
|
||||
if (components.size() == 1)
|
||||
return ".";
|
||||
std::string newPath = components[0];
|
||||
for (unsigned int i=1; i<components.size() - 1; i++)
|
||||
newPath += PATHSEP + components[i];
|
||||
if (path[0] == PATHSEP)
|
||||
newPath = PATHSEP + newPath;
|
||||
else if (path[0] == '\\')
|
||||
newPath = "\\" + newPath;
|
||||
return newPath;
|
||||
}
|
||||
|
||||
/// Return the last component of a path
|
||||
inline std::string getChild(const std::string &path) const {
|
||||
std::vector<std::string> components = tokenize(path, "/\\");
|
||||
return components[components.size()-1];
|
||||
}
|
||||
|
||||
/// Try to resolve a path to an existing file
|
||||
inline std::string resolve(const std::string &path) const {
|
||||
if (!FileStream::exists(path)) {
|
||||
for (unsigned int i=0; i<m_paths.size(); i++) {
|
||||
std::string testPath = m_paths[i] + "/" + path;
|
||||
if (FileStream::exists(testPath))
|
||||
return testPath;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/// Try to resolve all paths to an existing file
|
||||
inline std::vector<std::string> resolveAll(const std::string &path) const {
|
||||
std::vector<std::string> result;
|
||||
|
||||
if (FileStream::exists(path))
|
||||
result.push_back(path);
|
||||
|
||||
for (unsigned int i=0; i<m_paths.size(); i++) {
|
||||
std::string testPath = m_paths[i] + "/" + path;
|
||||
if (FileStream::exists(testPath))
|
||||
result.push_back(testPath);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* \brief Create a new file resolver with the default settings
|
||||
*
|
||||
* Create a new file resolver containing the current working
|
||||
* directory as the initial search path.
|
||||
*/
|
||||
FileResolver();
|
||||
|
||||
/**
|
||||
* Try to resolve a path to an existing file (returns an
|
||||
* absolute path
|
||||
* \brief Resolve a file using the stored list of search paths
|
||||
*
|
||||
* Go through the list of search paths and try to resolve the
|
||||
* supplied path with respect to each one. If everything fails,
|
||||
* the path is returned as-is.
|
||||
*/
|
||||
inline std::string resolveAbsolute(const std::string &path) const {
|
||||
return makeAbsolute(resolve(path));
|
||||
}
|
||||
fs::path resolve(const fs::path &path) const;
|
||||
|
||||
/**
|
||||
* \brief Resolve a file using the stored list of search paths
|
||||
*
|
||||
* In comparison to \ref resolve(), this funtion returns all
|
||||
* matches instead of only the first one.
|
||||
*/
|
||||
std::vector<fs::path> resolveAll(const fs::path &path) const;
|
||||
|
||||
/**
|
||||
* \brief Does the same as \ref resolve(), but returns an
|
||||
* absolute path.
|
||||
*/
|
||||
fs::path resolveAbsolute(const fs::path &path) const;
|
||||
|
||||
/// Create a clone of the file resolver
|
||||
FileResolver *clone() const;
|
||||
|
||||
/// Add a search path to the resolver
|
||||
void addPath(const fs::path &path);
|
||||
|
||||
/// Try to resolve all paths to an existing file (returns absolute paths)
|
||||
inline std::vector<std::string> resolveAllAbsolute(const std::string &path) const {
|
||||
std::vector<std::string> result;
|
||||
|
||||
if (FileStream::exists(path))
|
||||
result.push_back(makeAbsolute(path));
|
||||
|
||||
for (unsigned int i=0; i<m_paths.size(); i++) {
|
||||
std::string testPath = m_paths[i] + "/" + path;
|
||||
if (FileStream::exists(testPath))
|
||||
result.push_back(makeAbsolute(testPath));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a path for a new file. If the path is relative, it
|
||||
* is appended to the thread's current working directory
|
||||
*/
|
||||
inline std::string resolveDest(const std::string &path) const {
|
||||
if (isAbsolute(path))
|
||||
return path;
|
||||
else
|
||||
return m_currentDirectory + "/" + path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filename (e.g. last component) of an absolute
|
||||
* or relative path
|
||||
*/
|
||||
inline static std::string getFilename(const std::string &path) {
|
||||
std::vector<std::string> components = tokenize(path, "/\\");
|
||||
if (components.size() == 0)
|
||||
return "";
|
||||
return components[components.size()-1];
|
||||
}
|
||||
/// Clear all stored search paths
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Return the filename of an absolute or relative path. This
|
||||
* version also removes the file extension (everything after
|
||||
* the first period sign)
|
||||
*/
|
||||
inline static std::string getFilenameWithoutExtension(const std::string &path) {
|
||||
std::string filename = getFilename(path);
|
||||
size_t pos = filename.find('.');
|
||||
if (pos != std::string::npos)
|
||||
filename = filename.substr(0, pos);
|
||||
return filename;
|
||||
}
|
||||
|
||||
inline ~FileResolver() { }
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "FileResolver[" << endl
|
||||
<< " cwd = \"" << m_currentDirectory << "\"," << endl
|
||||
<< " paths = {" << endl;
|
||||
for (size_t i=0; i<m_paths.size(); ++i)
|
||||
oss << " \"" << m_paths[i] << "\"," << endl;
|
||||
oss << " }" << endl
|
||||
<< "]";
|
||||
return oss.str();
|
||||
}
|
||||
/// Return a human-readable string representation
|
||||
std::string toString() const;
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
inline FileResolver() { }
|
||||
|
||||
/// Check whether a given path is absolute
|
||||
bool isAbsolute(const std::string &path) const {
|
||||
#if defined(__OSX__) || defined(__LINUX__)
|
||||
return (path.length() > 0 &&
|
||||
(path[0] == '/' || path[0] == '~'));
|
||||
#else
|
||||
return (strchr(path.c_str(), ':') != NULL) ||
|
||||
(path.length() > 0 && path[0] == '\\');
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Turn a path into an absolute path
|
||||
std::string makeAbsolute(const std::string &path) const {
|
||||
if (isAbsolute(path))
|
||||
return path;
|
||||
char cwd[PATH_MAX];
|
||||
#if !defined(WIN32)
|
||||
if (getcwd(cwd, PATH_MAX) == NULL)
|
||||
#else
|
||||
if (_getcwd(cwd, PATH_MAX) == NULL)
|
||||
#endif
|
||||
Log(EError, "Cannot detect current path!");
|
||||
return std::string(cwd) + PATHSEP + path;
|
||||
}
|
||||
virtual ~FileResolver() { }
|
||||
private:
|
||||
static ThreadLocal<FileResolver> m_tls;
|
||||
std::vector<std::string> m_paths;
|
||||
std::string m_currentDirectory;
|
||||
std::vector<fs::path> m_paths;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -21,46 +21,40 @@
|
|||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/stream.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Simple Stream implementation which can be used to access files.
|
||||
/** \brief Simple \ref Stream implementation for accessing files.
|
||||
*
|
||||
* This class uses streams on posix platforms and the native
|
||||
* WIN32 API when used on windows.
|
||||
* This class uses POSIX streams on Linux and OSX and the native
|
||||
* WIN32 API when used on Windows.
|
||||
*/
|
||||
class MTS_EXPORT_CORE FileStream : public Stream {
|
||||
public:
|
||||
/// File opening modes
|
||||
enum EFileMode {
|
||||
/// rb
|
||||
EReadOnly = 0,
|
||||
/// rb+
|
||||
EReadWrite,
|
||||
/// wb
|
||||
ETruncWrite,
|
||||
/// wb+
|
||||
ETruncReadWrite,
|
||||
/// ab
|
||||
EAppendWrite,
|
||||
/// ab+
|
||||
EAppendReadWrite
|
||||
EReadOnly = 0, ///< rb
|
||||
EReadWrite, ///< rb+
|
||||
ETruncWrite, ///< wb
|
||||
ETruncReadWrite, ///< wb+
|
||||
EAppendWrite, ///< ab
|
||||
EAppendReadWrite ///< ab+
|
||||
};
|
||||
|
||||
/// Create a file stream class with no file open
|
||||
FileStream();
|
||||
|
||||
/// Create a file stream class and open a file with a given EFileMode
|
||||
FileStream(const std::string &filename, EFileMode mode = EReadOnly);
|
||||
explicit FileStream(const fs::path &path, EFileMode mode = EReadOnly);
|
||||
|
||||
/// Return the file name
|
||||
inline const std::string &getFileName() const { return m_filename; }
|
||||
|
||||
/// Check whether a file exists
|
||||
static bool exists(const std::string &filename);
|
||||
/// Return the file path
|
||||
inline const fs::path &getPath() const { return m_path; }
|
||||
|
||||
/// Open a file with a given open mode
|
||||
void open(const std::string &filename, EFileMode mode = EReadOnly);
|
||||
void open(const fs::path &filename, EFileMode mode = EReadOnly);
|
||||
|
||||
/// Close the current file
|
||||
void close();
|
||||
|
@ -99,7 +93,7 @@ protected:
|
|||
bool m_write;
|
||||
bool m_read;
|
||||
EFileMode m_mode;
|
||||
std::string m_filename;
|
||||
fs::path m_path;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CORE_FWD_H)
|
||||
#define __CORE_FWD_H
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
struct AABB;
|
||||
class Appender;
|
||||
class Bitmap;
|
||||
class BlackBodySpectrum;
|
||||
struct BSphere;
|
||||
class ConfigurableObject;
|
||||
struct CacheLineCounter;
|
||||
class Class;
|
||||
class ConditionVariable;
|
||||
class ConsoleStream;
|
||||
class DefaultFormatter;
|
||||
struct DiscretePDF;
|
||||
class FileResolver;
|
||||
class FileStream;
|
||||
class Formatter;
|
||||
struct Frame;
|
||||
class InstanceManager;
|
||||
class InterpolatedSpectrum;
|
||||
class LocalWorker;
|
||||
class Logger;
|
||||
class Matrix4x4;
|
||||
class MemoryStream;
|
||||
class Mutex;
|
||||
class NetworkedObject;
|
||||
struct Normal;
|
||||
class Object;
|
||||
class ParallelProcess;
|
||||
class Plugin;
|
||||
class PluginManager;
|
||||
class ProgressReporter;
|
||||
class Properties;
|
||||
class Random;
|
||||
struct Ray;
|
||||
struct RayDifferential;
|
||||
class RemoteProcess;
|
||||
class RemoteWorker;
|
||||
class RemoteWorkerReader;
|
||||
class Scheduler;
|
||||
class Serializable;
|
||||
class SerializableObject;
|
||||
struct SHRotation;
|
||||
class SHSampler;
|
||||
struct SHVector;
|
||||
struct SHVector4D;
|
||||
class SmoothSpectrum;
|
||||
class SocketStream;
|
||||
class SparseWavelet2D;
|
||||
class SparseWaveletOctree;
|
||||
struct Spectrum;
|
||||
class SSHStream;
|
||||
class Statistics;
|
||||
class StatsCounter;
|
||||
class Stream;
|
||||
class StreamAppender;
|
||||
class StreamBackend;
|
||||
class Thread;
|
||||
class Timer;
|
||||
struct Transform;
|
||||
struct Triangle;
|
||||
class UnbufferedAppender;
|
||||
template <typename T> struct TVector2;
|
||||
template <typename T> struct TVector3;
|
||||
template <typename T> struct TVector4;
|
||||
template <typename T> struct TPoint2;
|
||||
template <typename T> struct TPoint3;
|
||||
template <typename T> struct TPoint4;
|
||||
typedef TVector2<Float> Vector2;
|
||||
typedef TVector2<int> Vector2i;
|
||||
typedef TVector2<float> Vector2f;
|
||||
typedef TVector2<double> Vector2d;
|
||||
typedef TVector3<Float> Vector;
|
||||
typedef TVector3<Float> Vector3;
|
||||
typedef TVector3<int> Vector3i;
|
||||
typedef TVector3<float> Vector3f;
|
||||
typedef TVector3<double> Vector3d;
|
||||
typedef TVector4<Float> Vector4;
|
||||
typedef TVector4<int> Vector4i;
|
||||
typedef TVector4<float> Vector4f;
|
||||
typedef TVector4<double> Vector4d;
|
||||
typedef TPoint2<Float> Point2;
|
||||
typedef TPoint2<int> Point2i;
|
||||
typedef TPoint2<float> Point2f;
|
||||
typedef TPoint2<double> Point2d;
|
||||
typedef TPoint3<Float> Point;
|
||||
typedef TPoint3<Float> Point3;
|
||||
typedef TPoint3<int> Point3i;
|
||||
typedef TPoint3<float> Point3f;
|
||||
typedef TPoint3<double> Point3d;
|
||||
typedef TPoint4<Float> Point4;
|
||||
typedef TPoint4<int> Point4i;
|
||||
typedef TPoint4<float> Point4f;
|
||||
typedef TPoint4<double> Point4d;
|
||||
class WaitFlag;
|
||||
class Wavelet2D;
|
||||
class Wavelet3D;
|
||||
class Worker;
|
||||
class WorkProcessor;
|
||||
class WorkResult;
|
||||
class WorkUnit;
|
||||
class ZStream;
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __CORE_FWD_H */
|
|
@ -23,6 +23,14 @@
|
|||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
#if !defined(MTS_EXPORT_CORE)
|
||||
#if MTS_BUILD_MODULE == MTS_MODULE_CORE
|
||||
#define MTS_EXPORT_CORE __declspec(dllexport)
|
||||
#else
|
||||
#define MTS_EXPORT_CORE __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -33,7 +41,7 @@ extern "C" {
|
|||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
extern MTS_EXPORT_CORE char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
|
@ -47,16 +55,16 @@ extern char *optarg;
|
|||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
extern MTS_EXPORT_CORE int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
extern MTS_EXPORT_CORE int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
extern MTS_EXPORT_CORE int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* Describe the long-named options requested by the application.
|
||||
|
@ -125,17 +133,17 @@ struct option
|
|||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
|
||||
extern MTS_EXPORT_CORE int getopt (int __argc, char *const *__argv, const char *__shortopts);
|
||||
|
||||
# ifndef __need_getopt
|
||||
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
|
||||
extern MTS_EXPORT_CORE int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
extern int getopt_long_only (int __argc, char *const *__argv,
|
||||
extern MTS_EXPORT_CORE int getopt_long_only (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int __argc, char *const *__argv,
|
||||
extern MTS_EXPORT_CORE int _getopt_internal (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only);
|
|
@ -20,13 +20,11 @@
|
|||
#define __GRID_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <stdexcept>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Uniform 3D grid for storing arbitrary quantities, which can
|
||||
* be queried and updated by rasterizing rays to the grid.
|
||||
* \brief Uniform 3D grid for storing and manipulating arbitrary quantities
|
||||
*/
|
||||
template <typename ValueType> class Grid {
|
||||
public:
|
||||
|
@ -83,7 +81,7 @@ public:
|
|||
|
||||
/// Return the grid AABB
|
||||
inline const AABB &getAABB() const { return m_aabb; }
|
||||
|
||||
|
||||
/// Return the grid resolution
|
||||
inline const Vector3i &getResolution() const { return m_res; }
|
||||
|
||||
|
@ -99,7 +97,7 @@ public:
|
|||
inline const ValueType &operator()(int x, int y, int z) const {
|
||||
return m_cells[x + y*m_res.x + z*m_slab];
|
||||
}
|
||||
/// Return the underlying array
|
||||
/// Return a pointer to the underlying array
|
||||
inline ValueType *getData() const { return m_cells; }
|
||||
|
||||
/// Return a string representation
|
||||
|
@ -173,7 +171,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Rasterize a ray to the grid
|
||||
/**
|
||||
* \brief Rasterize a ray to the grid and apply the functor to
|
||||
* every traversed cell
|
||||
*/
|
||||
template <typename Functor> void rasterize(const Ray &ray, Functor &functor) {
|
||||
Float mint, maxt, t;
|
||||
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Thin wrapper around the recursive pthreads lock
|
||||
* \brief Thin wrapper around the recursive pthreads lock
|
||||
*/
|
||||
class MTS_EXPORT_CORE Mutex : public Object {
|
||||
friend class ConditionVariable;
|
||||
public:
|
||||
/// Create a new mutex object
|
||||
Mutex();
|
||||
|
||||
|
||||
/// Lock the mutex
|
||||
inline void lock() {
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
|
@ -51,15 +51,15 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* Wait flag synchronization primitive. Can be used to
|
||||
* wait for a certain flag to become true.
|
||||
* \brief Wait flag synchronization primitive. Can be used to
|
||||
* wait for a certain event to occur.
|
||||
*/
|
||||
class MTS_EXPORT_CORE WaitFlag : public Object {
|
||||
public:
|
||||
/**
|
||||
* Create a new wait flag
|
||||
* \brief Create a new wait flag
|
||||
* @param flag
|
||||
* Initial state of the flag. If set to true, <tt>wait()</tt>
|
||||
* Initial state of the flag. If set to true, \ref wait()
|
||||
* will immediately return.
|
||||
*/
|
||||
WaitFlag(bool flag = false);
|
||||
|
@ -67,16 +67,20 @@ public:
|
|||
/// Return the current flag value
|
||||
inline const bool &get() const { return m_flag; }
|
||||
|
||||
/// Set the value of the internal flag
|
||||
/// Set the value of the flag
|
||||
void set(bool value);
|
||||
|
||||
/// Wait for the flag to become true
|
||||
/// Wait for the flag to be set to true
|
||||
void wait();
|
||||
|
||||
/**
|
||||
* Similar to wait(), but also uses a time value given
|
||||
* in milliseconds. A return value of <tt>false</tt> signals
|
||||
* \brief Temporarily wait for the flag to be set to true
|
||||
*
|
||||
* Similar to \ref wait(), but also uses a time value given
|
||||
* in milliseconds. A return value of \a false signals
|
||||
* that a timeout has occurred.
|
||||
*
|
||||
* \param ms Maximum waiting time in milliseconds
|
||||
*/
|
||||
bool wait(int ms);
|
||||
|
||||
|
@ -84,27 +88,30 @@ public:
|
|||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~WaitFlag();
|
||||
protected:
|
||||
private:
|
||||
bool m_flag;
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
};
|
||||
|
||||
/**
|
||||
* Condition variable synchronization primitive. Can be used to
|
||||
* wait for an arbitrary condition to become true in a safe way.
|
||||
* \brief Condition variable synchronization primitive. Can be used to
|
||||
* wait for a condition to become true in a safe way.
|
||||
*/
|
||||
class MTS_EXPORT_CORE ConditionVariable : public Object {
|
||||
public:
|
||||
/**
|
||||
* Create a new condition variable. Also takes a mutex, which
|
||||
* is later used by wait().
|
||||
* \brief Create a new condition variable. Also takes a
|
||||
* mutex, which is later used by wait(). If none is specified,
|
||||
* a new mutex instance will be created.
|
||||
*/
|
||||
ConditionVariable(Mutex *mutex);
|
||||
ConditionVariable(Mutex *mutex = NULL);
|
||||
|
||||
/**
|
||||
* Send a signal, which wakes up at least one of the waiting
|
||||
* threads. The calling thread does not have to hold the lock,
|
||||
* \brief Send a signal, which wakes up at least one of
|
||||
* the waiting threads.
|
||||
*
|
||||
* The calling thread does not have to hold the lock,
|
||||
* but more predictable scheduling will occur if this is the
|
||||
* case.
|
||||
*/
|
||||
|
@ -113,8 +120,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Send a signal, which wakes up any waiting threads. The
|
||||
* calling thread does not have to hold the lock, but more
|
||||
* \brief Send a signal, which wakes up any waiting threads.
|
||||
*
|
||||
* The calling thread does not have to hold the lock, but more
|
||||
* predictable scheduling will occur if this is the case.
|
||||
*/
|
||||
inline void broadcast() {
|
||||
|
@ -122,7 +130,8 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Wait for a signal and release the lock in the meanwhile.
|
||||
* \brief Wait for a signal and release the lock in the meanwhile.
|
||||
*
|
||||
* Assumes that the lock specified in the constructor has
|
||||
* previously been acquired. After returning, the lock is
|
||||
* held again.
|
||||
|
@ -132,10 +141,14 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* \brief Temporarily wait for a signal and release the lock in the meanwhile.
|
||||
*
|
||||
* Similar to wait(), but also uses a time value given
|
||||
* in milliseconds. A return value of <tt>false</tt> signals
|
||||
* in milliseconds. A return value of \a false signals
|
||||
* that a timeout has occurred. The lock is held after
|
||||
* returning in either case.
|
||||
*
|
||||
* \param ms Maximum waiting time in milliseconds
|
||||
*/
|
||||
bool wait(int ms);
|
||||
|
||||
|
@ -143,7 +156,7 @@ public:
|
|||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~ConditionVariable();
|
||||
protected:
|
||||
private:
|
||||
bool m_flag;
|
||||
ref<Mutex> m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
|
|
|
@ -20,14 +20,13 @@
|
|||
#define __LOGGER_H
|
||||
|
||||
#include <mitsuba/core/formatter.h>
|
||||
#include <mitsuba/core/appender.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Logging
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/// Write a Log message to the console (to be used within subclasses of <tt>Object</tt>)
|
||||
#define Log(level, fmt, ...) Thread::getThread()->getLogger()->log(level, m_theClass, \
|
||||
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
@ -68,35 +67,39 @@ MTS_NAMESPACE_BEGIN
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
/** \brief The logger is the class responsible for the propagation of
|
||||
* debug information. It invokes a Formatter implementation to convert
|
||||
* events into a human-readable form and then sends this information to
|
||||
* every registered Appender implementation.
|
||||
/**
|
||||
* \headerfile mitsuba/core/logger.h mitsuba/mitsuba.h
|
||||
* \brief Responsible for processing log messages
|
||||
*
|
||||
* Upon receiving a log message, the Logger class invokes
|
||||
* a Formatter to convert it into a human-readable form.
|
||||
* Following that, it sends this information to every
|
||||
* registered Appender.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Logger : public Object {
|
||||
public:
|
||||
/// Construct a new logger
|
||||
/// Construct a new logger with the given minimum log level
|
||||
Logger(ELogLevel logLevel = EDebug);
|
||||
|
||||
/**
|
||||
* Process a log message
|
||||
* @param level Log level of the message
|
||||
* @param theClass Class descriptor of the message creator
|
||||
* @param fileName Source file of the message creator
|
||||
* @param lineNumber Source line number of the message creator
|
||||
* @param fmt printf-style string formatter
|
||||
* \brief Process a log message
|
||||
* \param level Log level of the message
|
||||
* \param theClass Class descriptor of the message creator
|
||||
* \param fileName Source file of the message creator
|
||||
* \param lineNumber Source line number of the message creator
|
||||
* \param fmt printf-style string formatter
|
||||
*/
|
||||
void log(ELogLevel level, const Class *theClass,
|
||||
const char *fileName, int lineNumber,
|
||||
const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Process a progress message
|
||||
* @param progress Percentage value in [0,100]
|
||||
* @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
|
||||
* \brief Process a progress message
|
||||
* \param progress Percentage value in [0,100]
|
||||
* \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
|
||||
*/
|
||||
void logProgress(Float progress, const std::string &name,
|
||||
const std::string &formatted, const std::string &eta,
|
||||
|
@ -118,10 +121,10 @@ public:
|
|||
inline size_t getAppenderCount() const { return m_appenders.size(); }
|
||||
|
||||
/// Return one of the appenders
|
||||
inline Appender *getAppender(int index) { return m_appenders[index]; }
|
||||
inline Appender *getAppender(size_t index) { return m_appenders[index]; }
|
||||
|
||||
/// Return one of the appenders
|
||||
inline const Appender *getAppender(int index) const { return m_appenders[index]; }
|
||||
inline const Appender *getAppender(size_t index) const { return m_appenders[index]; }
|
||||
|
||||
/// Set the logger's formatter implementation
|
||||
void setFormatter(Formatter *formatter);
|
||||
|
@ -142,7 +145,7 @@ public:
|
|||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~Logger();
|
||||
protected:
|
||||
private:
|
||||
ELogLevel m_logLevel;
|
||||
ref<Formatter> m_formatter;
|
||||
ref<Mutex> m_mutex;
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Simple memory buffer-based stream with automatic memory management
|
||||
* (dynamically expands as data is written to it)
|
||||
*
|
||||
* The underlying memory storage of this implementation dynamically expands
|
||||
* as data is written to the stream.
|
||||
*/
|
||||
class MTS_EXPORT_CORE MemoryStream : public Stream {
|
||||
public:
|
||||
|
|
|
@ -19,30 +19,24 @@
|
|||
#if !defined(__NETOBJECT_H)
|
||||
#define __NETOBJECT_H
|
||||
|
||||
#include <mitsuba/core/sched.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Interface of an abstract object referencing
|
||||
* globally shared resources. When it is serialized for use in a
|
||||
* parallel process executed on several machines, the object
|
||||
* is first given the opportunity to bind named resources to
|
||||
* the process, which will then be distributed to all participating
|
||||
* compute servers. Once unserialized on the remote side,
|
||||
* <tt>wakeup</tt> is called to let the object re-associate
|
||||
* with the shared 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 <tt>\ref bindUsedResources()</tt>). These will then be
|
||||
* distributed to all participating compute servers. Once unserialized on the remote side,
|
||||
* <tt>\ref wakeup()</tt> is called to let the object re-associate with the shared resources.
|
||||
*/
|
||||
class MTS_EXPORT_CORE NetworkedObject : public ConfigurableObject {
|
||||
public:
|
||||
/// Constructor
|
||||
inline NetworkedObject(const Properties &props) : ConfigurableObject(props) { }
|
||||
|
||||
/// Unserialize a configurable object
|
||||
inline NetworkedObject(Stream *stream, InstanceManager *manager)
|
||||
: ConfigurableObject(stream, manager) {
|
||||
}
|
||||
|
||||
/// Bind any used resources to the process \a proc
|
||||
virtual void bindUsedResources(ParallelProcess *proc) const;
|
||||
|
||||
/// Retrieve any required resources
|
||||
virtual void wakeup(std::map<std::string, SerializableObject *> ¶ms);
|
||||
|
||||
/// Serialize this object to a stream
|
||||
|
@ -52,6 +46,14 @@ public:
|
|||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~NetworkedObject() { }
|
||||
|
||||
/// Constructor
|
||||
inline NetworkedObject(const Properties &props) : ConfigurableObject(props) { }
|
||||
|
||||
/// Unserialize a configurable object
|
||||
inline NetworkedObject(Stream *stream, InstanceManager *manager)
|
||||
: ConfigurableObject(stream, manager) {
|
||||
}
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -23,165 +23,48 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Simple three-dimensional normal class using floating point values.
|
||||
* This class is different from the Vector class in how it is treated
|
||||
* by linear transformations.
|
||||
/**
|
||||
* \headerfile mitsuba/core/normal.h mitsuba/mitsuba.h
|
||||
* \brief Three-dimensional normal data structure
|
||||
*
|
||||
* Internally represented using floating point numbers of the chosen
|
||||
* compile-time precision. The main difference in comparison to <tt>TVector3<Float></tt>
|
||||
* is in how instances of <tt>Normal</tt> are treated by linear transformations.
|
||||
*/
|
||||
class Normal {
|
||||
public:
|
||||
Float x, y, z;
|
||||
struct Normal : public TVector3<Float> {
|
||||
/** \brief Construct a new normal without initializing it.
|
||||
*
|
||||
* This construtor is useful when the normal will either not
|
||||
* be used at all (it might be part of a larger data structure)
|
||||
* or initialized at a later point in time. Always make sure
|
||||
* that one of the two is the case! Otherwise your program will do
|
||||
* computations involving uninitialized memory, which will probably
|
||||
* lead to a difficult-to-find bug.
|
||||
*/
|
||||
Normal() { }
|
||||
|
||||
inline Normal(Float _x = 0.0f, Float _y = 0.0f, Float _z = 0.0f)
|
||||
: x(_x), y(_y), z(_z) {
|
||||
/// Initialize the vector with the specified X and Z components
|
||||
Normal(Float x, Float y, Float z) : TVector3<Float>(x, y, z) { }
|
||||
|
||||
/// Initialize all components of the the normal with the specified value
|
||||
explicit Normal(Float val) : TVector3<Float>(val) { }
|
||||
|
||||
/// Unserialize a normal from a binary data stream
|
||||
Normal(Stream *stream) {
|
||||
x = stream->readElement<Float>();
|
||||
y = stream->readElement<Float>();
|
||||
z = stream->readElement<Float>();
|
||||
}
|
||||
|
||||
explicit inline Normal(const Vector &v)
|
||||
: x(v.x), y(v.y), z(v.z) {
|
||||
}
|
||||
/// Construct a normal from a vector data structure
|
||||
Normal(const TVector3<Float> &v) : TVector3<Float>(v.x, v.y, v.z) { }
|
||||
|
||||
inline Normal(Stream *stream) {
|
||||
x = stream->readFloat();
|
||||
y = stream->readFloat();
|
||||
z = stream->readFloat();
|
||||
}
|
||||
|
||||
inline Normal operator+(const Normal &v) const {
|
||||
return Normal(x + v.x, y + v.y, z + v.z);
|
||||
}
|
||||
|
||||
inline Normal operator-(const Normal &v) const {
|
||||
return Normal(x - v.x, y - v.y, z - v.z);
|
||||
}
|
||||
|
||||
inline Normal& operator+=(const Normal &v) {
|
||||
x += v.x; y += v.y; z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Normal& operator-=(const Normal &v) {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Normal operator*(Float f) const {
|
||||
return Normal(x*f, y*f, z*f);
|
||||
}
|
||||
|
||||
inline Normal &operator*=(Float f) {
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Normal operator-() const {
|
||||
return Normal(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline Normal operator/(Float f) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Normal: Division by zero!");
|
||||
#endif
|
||||
Float r = 1.0f / f;
|
||||
return Normal(x * r, y * r, z * r);
|
||||
}
|
||||
|
||||
inline Normal &operator/=(Float f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Normal: Division by zero!");
|
||||
#endif
|
||||
Float r = 1.0f / f;
|
||||
x *= r;
|
||||
y *= r;
|
||||
z *= r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Float operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline Float &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return x==0 && y == 0 && z == 0;
|
||||
}
|
||||
|
||||
inline Float lengthSquared() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
inline Float length() const {
|
||||
return std::sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
inline bool operator==(const Normal &v) const {
|
||||
return (v.x == x && v.y == y && v.z == z);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Normal &v) const {
|
||||
return !operator==(v);
|
||||
}
|
||||
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeFloat(x);
|
||||
stream->writeFloat(y);
|
||||
stream->writeFloat(z);
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << ", " << z << "]";
|
||||
return oss.str();
|
||||
/// Assign a vector to this normal
|
||||
void operator=(const TVector3<Float> &v) {
|
||||
x = v.x; y = v.y; z = v.z;
|
||||
}
|
||||
};
|
||||
|
||||
inline Float dot(const Normal &v1, const Normal &v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
inline Float dot(const Vector &v1, const Normal &v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
inline Float dot(const Normal &v1, const Vector &v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
inline Float absDot(const Normal &v1, const Normal &v2) {
|
||||
return std::abs(dot(v1, v2));
|
||||
}
|
||||
|
||||
inline Float absDot(const Vector &v1, const Normal &v2) {
|
||||
return std::abs(dot(v1, v2));
|
||||
}
|
||||
|
||||
inline Float absDot(const Normal &v1, const Vector &v2) {
|
||||
return std::abs(dot(v1, v2));
|
||||
}
|
||||
|
||||
inline Normal normalize(const Normal &n) {
|
||||
Float length = n.length();
|
||||
#ifdef MTS_DEBUG
|
||||
if (length == 0.0f) {
|
||||
SLog(EWarn, "Zero-length normal encountered!");
|
||||
return n;
|
||||
} else {
|
||||
return n / length;
|
||||
}
|
||||
#else
|
||||
return n / length;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Vector::Vector(const Normal &n)
|
||||
: x(n.x), y(n.y), z(n.z) {
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __NORMAL_H */
|
||||
|
|
|
@ -24,42 +24,52 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Base class of all Mitsuba classes.
|
||||
/**
|
||||
* \headerfile mitsuba/core/object.h mitsuba/mitsuba.h
|
||||
* \brief Parent of all Mitsuba classes.
|
||||
*
|
||||
* Contains functions relevant to every object
|
||||
* such as reference counting, limited type
|
||||
* introspection and lifetime management.
|
||||
* Contains functions relevant to every object such as reference counting,
|
||||
* limited type introspection and lifetime management.
|
||||
*
|
||||
* @see ref, Class
|
||||
* \sa ref, Class
|
||||
*/
|
||||
class MTS_EXPORT_CORE Object {
|
||||
public:
|
||||
/// Object constructor
|
||||
/// Construct a new object
|
||||
Object();
|
||||
|
||||
/// Get the reference count
|
||||
/// Return the current reference count
|
||||
inline int getRefCount() const;
|
||||
|
||||
/** \brief Increase the reference count of the
|
||||
* object.
|
||||
* object by one.
|
||||
*/
|
||||
void incRef() const;
|
||||
|
||||
/** \brief Decrease the reference count object
|
||||
* of the object. It will automatically be de-
|
||||
* allocated once the reference count reaches
|
||||
* zero.
|
||||
/** \brief Decrease the reference count of
|
||||
* the object and possibly deallocate it.
|
||||
*
|
||||
* The object will automatically be deallocated once
|
||||
* the reference count reaches zero.
|
||||
*/
|
||||
void decRef() const;
|
||||
|
||||
/// Retrieve this object's class
|
||||
virtual const Class *getClass() const;
|
||||
|
||||
/// Convert to string
|
||||
/**
|
||||
* \brief Return a human-readable string representation
|
||||
* of the object's contents.
|
||||
*
|
||||
* This function is mainly useful for debugging purposes
|
||||
* and should ideally be implemented by all subclasses.
|
||||
* The default implementation simply returns <tt>MyObject[unknown]</tt>,
|
||||
* where <tt>MyObject</tt> is the name of the subclass.
|
||||
*/
|
||||
virtual std::string toString() const;
|
||||
protected:
|
||||
/** \brief Virtual private deconstructor.
|
||||
* (Will only be called by 'ref')
|
||||
* (Will only be called by \ref ref)
|
||||
*/
|
||||
virtual ~Object();
|
||||
private:
|
||||
|
@ -70,7 +80,7 @@ private:
|
|||
mutable pthread_mutex_t m_refLock;
|
||||
#endif
|
||||
public:
|
||||
static Class *m_theClass;
|
||||
static Class *m_theClass; ///< Pointer to the object's class descriptor
|
||||
};
|
||||
|
||||
inline int Object::getRefCount() const {
|
||||
|
|
|
@ -20,21 +20,69 @@
|
|||
#define __OCTREE_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/core/octree.h>
|
||||
#include <mitsuba/core/atomic.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
/**
|
||||
* Templated multiple-reference octree. Based on the excellent
|
||||
* implementation in PBRT. Modifications are the addition of a
|
||||
* bounding sphere query and support for multithreading.
|
||||
* \brief Implements a lock-free singly linked list.
|
||||
*/
|
||||
template <typename T> class LockFreeList {
|
||||
public:
|
||||
struct ListItem {
|
||||
T value;
|
||||
ListItem *next;
|
||||
|
||||
inline ListItem(const T &value) :
|
||||
value(value), next(NULL) { }
|
||||
};
|
||||
|
||||
inline LockFreeList() : m_head(NULL) {}
|
||||
|
||||
~LockFreeList() {
|
||||
ListItem *cur = m_head;
|
||||
while (cur) {
|
||||
ListItem *next = cur->next;
|
||||
delete cur;
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
inline const ListItem *head() const {
|
||||
return m_head;
|
||||
}
|
||||
|
||||
void append(const T &value) {
|
||||
ListItem *item = new ListItem(value);
|
||||
ListItem **cur = &m_head;
|
||||
while (!atomicCompareAndExchangePtr<ListItem>(cur, item, NULL))
|
||||
cur = &((*cur)->next);
|
||||
}
|
||||
private:
|
||||
ListItem *m_head;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generic multiple-reference octree.
|
||||
*
|
||||
* Based on the excellent implementation in PBRT. Modifications are
|
||||
* the addition of a bounding sphere query and support for multithreading.
|
||||
*/
|
||||
template <typename T> class Octree {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a new octree
|
||||
*
|
||||
* By default, the maximum tree depth is set to 16
|
||||
*/
|
||||
|
||||
inline Octree(const AABB &aabb, int maxDepth = 16)
|
||||
: m_aabb(aabb), m_maxDepth(maxDepth) {
|
||||
}
|
||||
|
||||
/// Insert an item with the specified cell coverage
|
||||
inline void insert(const T &value, const AABB &coverage) {
|
||||
insert(&m_root, m_aabb, value, coverage,
|
||||
coverage.getExtents().lengthSquared(), 0);
|
||||
|
@ -59,29 +107,34 @@ private:
|
|||
struct OctreeNode {
|
||||
public:
|
||||
OctreeNode() {
|
||||
pthread_rwlock_init(&lock, NULL);
|
||||
for (int i=0; i<8; ++i)
|
||||
children[i] = NULL;
|
||||
}
|
||||
|
||||
~OctreeNode() {
|
||||
pthread_rwlock_destroy(&lock);
|
||||
for (int i=0; i<8; ++i) {
|
||||
if (children[i])
|
||||
delete children[i];
|
||||
}
|
||||
}
|
||||
|
||||
inline void readLock() const { pthread_rwlock_rdlock(&lock); }
|
||||
inline void readUnlock() const { pthread_rwlock_unlock(&lock); }
|
||||
inline void writeLock() { pthread_rwlock_wrlock(&lock); }
|
||||
inline void writeUnlock() { pthread_rwlock_unlock(&lock); }
|
||||
|
||||
OctreeNode *children[8];
|
||||
mutable pthread_rwlock_t lock;
|
||||
std::vector<T> data;
|
||||
LockFreeList<T> data;
|
||||
};
|
||||
|
||||
/// Return the AABB for a child of the specified index
|
||||
inline AABB childBounds(int child, const AABB &nodeAABB, const Point ¢er) const {
|
||||
AABB childAABB;
|
||||
childAABB.min.x = (child & 4) ? center.x : nodeAABB.min.x;
|
||||
childAABB.max.x = (child & 4) ? nodeAABB.max.x : center.x;
|
||||
childAABB.min.y = (child & 2) ? center.y : nodeAABB.min.y;
|
||||
childAABB.max.y = (child & 2) ? nodeAABB.max.y : center.y;
|
||||
childAABB.min.z = (child & 1) ? center.z : nodeAABB.min.z;
|
||||
childAABB.max.z = (child & 1) ? nodeAABB.max.z : center.z;
|
||||
return childAABB;
|
||||
}
|
||||
|
||||
|
||||
void insert(OctreeNode *node, const AABB &nodeAABB, const T &value,
|
||||
const AABB &coverage, Float diag2, int depth) {
|
||||
/* Add the data item to the current octree node if the max. tree
|
||||
|
@ -89,51 +142,32 @@ private:
|
|||
than the current node size */
|
||||
if (depth == m_maxDepth ||
|
||||
(nodeAABB.getExtents().lengthSquared() < diag2)) {
|
||||
node->writeLock();
|
||||
node->data.push_back(value);
|
||||
node->writeUnlock();
|
||||
node->data.append(value);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise: test for overlap */
|
||||
const Point center = nodeAABB.getCenter();
|
||||
bool over[8];
|
||||
AABB childAABB;
|
||||
|
||||
over[0] = over[1] = over[2] = over[3] = (coverage.min.x <= center.x);
|
||||
over[4] = over[5] = over[6] = over[7] = (coverage.max.x > center.x);
|
||||
over[0] &= (coverage.min.y <= center.y);
|
||||
over[1] &= (coverage.min.y <= center.y);
|
||||
over[4] &= (coverage.min.y <= center.y);
|
||||
over[5] &= (coverage.min.y <= center.y);
|
||||
over[2] &= (coverage.max.y > center.y);
|
||||
over[3] &= (coverage.max.y > center.y);
|
||||
over[6] &= (coverage.max.y > center.y);
|
||||
over[7] &= (coverage.max.y > center.y);
|
||||
over[0] &= (coverage.min.z <= center.z);
|
||||
over[2] &= (coverage.min.z <= center.z);
|
||||
over[4] &= (coverage.min.z <= center.z);
|
||||
over[6] &= (coverage.min.z <= center.z);
|
||||
over[1] &= (coverage.max.z > center.z);
|
||||
over[3] &= (coverage.max.z > center.z);
|
||||
over[5] &= (coverage.max.z > center.z);
|
||||
over[7] &= (coverage.max.z > center.z);
|
||||
/* Otherwise: test for overlap */
|
||||
bool x[2] = { coverage.min.x <= center.x, coverage.max.x > center.x };
|
||||
bool y[2] = { coverage.min.y <= center.y, coverage.max.y > center.y };
|
||||
bool z[2] = { coverage.min.z <= center.z, coverage.max.z > center.z };
|
||||
bool over[8] = { x[0] & y[0] & z[0], x[0] & y[0] & z[1],
|
||||
x[0] & y[1] & z[0], x[0] & y[1] & z[1],
|
||||
x[1] & y[0] & z[0], x[1] & y[0] & z[1],
|
||||
x[1] & y[1] & z[0], x[1] & y[1] & z[1] };
|
||||
|
||||
/* Recurse */
|
||||
for (int child=0; child<8; ++child) {
|
||||
if (!over[child])
|
||||
continue;
|
||||
if (!node->children[child]) {
|
||||
node->writeLock();
|
||||
node->children[child] = new OctreeNode();
|
||||
node->writeUnlock();
|
||||
OctreeNode *newNode = new OctreeNode();
|
||||
if (!atomicCompareAndExchangePtr<OctreeNode>(&node->children[child], newNode, NULL))
|
||||
delete newNode;
|
||||
}
|
||||
childAABB.min.x = (child & 4) ? center.x : nodeAABB.min.x;
|
||||
childAABB.max.x = (child & 4) ? nodeAABB.max.x : center.x;
|
||||
childAABB.min.y = (child & 2) ? center.y : nodeAABB.min.y;
|
||||
childAABB.max.y = (child & 2) ? nodeAABB.max.y : center.y;
|
||||
childAABB.min.z = (child & 1) ? center.z : nodeAABB.min.z;
|
||||
childAABB.max.z = (child & 1) ? nodeAABB.max.z : center.z;
|
||||
const AABB childAABB(childBounds(child, nodeAABB, center));
|
||||
insert(node->children[child], childAABB,
|
||||
value, coverage, diag2, depth+1);
|
||||
}
|
||||
|
@ -144,25 +178,20 @@ private:
|
|||
const AABB &nodeAABB, const Point &p, Functor &functor) const {
|
||||
const Point center = nodeAABB.getCenter();
|
||||
|
||||
node->readLock();
|
||||
for (size_t i=0; i<node->data.size(); ++i)
|
||||
functor(node->data[i]);
|
||||
const typename LockFreeList<T>::ListItem *item = node->data.head();
|
||||
while (item) {
|
||||
functor(item->value);
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
int child = (p.x > center.x ? 4 : 0)
|
||||
+ (p.y > center.y ? 2 : 0)
|
||||
+ (p.z > center.z ? 1 : 0);
|
||||
|
||||
OctreeNode *childNode = node->children[child];
|
||||
node->readUnlock();
|
||||
|
||||
if (childNode) {
|
||||
AABB childAABB;
|
||||
childAABB.min.x = (child & 4) ? center.x : nodeAABB.min.x;
|
||||
childAABB.max.x = (child & 4) ? nodeAABB.max.x : center.x;
|
||||
childAABB.min.y = (child & 2) ? center.y : nodeAABB.min.y;
|
||||
childAABB.max.y = (child & 2) ? nodeAABB.max.y : center.y;
|
||||
childAABB.min.z = (child & 1) ? center.z : nodeAABB.min.z;
|
||||
childAABB.max.z = (child & 1) ? nodeAABB.max.z : center.z;
|
||||
const AABB childAABB(childBounds(child, nodeAABB, center));
|
||||
lookup(node->children[child], childAABB, p, functor);
|
||||
}
|
||||
}
|
||||
|
@ -172,22 +201,16 @@ private:
|
|||
Functor &functor) {
|
||||
const Point center = nodeAABB.getCenter();
|
||||
|
||||
node->readLock();
|
||||
for (size_t i=0; i<node->data.size(); ++i)
|
||||
functor(node->data[i]);
|
||||
node->readUnlock();
|
||||
const typename LockFreeList<T>::ListItem *item = node->data.head();
|
||||
while (item) {
|
||||
functor(item->value);
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
// Potential for much optimization..
|
||||
for (int child=0; child<8; ++child) {
|
||||
if (node->children[child]) {
|
||||
AABB childAABB;
|
||||
childAABB.min.x = (child & 4) ? center.x : nodeAABB.min.x;
|
||||
childAABB.max.x = (child & 4) ? nodeAABB.max.x : center.x;
|
||||
childAABB.min.y = (child & 2) ? center.y : nodeAABB.min.y;
|
||||
childAABB.max.y = (child & 2) ? nodeAABB.max.y : center.y;
|
||||
childAABB.min.z = (child & 1) ? center.z : nodeAABB.min.z;
|
||||
childAABB.max.z = (child & 1) ? nodeAABB.max.z : center.z;
|
||||
|
||||
const AABB childAABB(childBounds(child, nodeAABB, center));
|
||||
if (childAABB.overlaps(sphere))
|
||||
searchSphere(node->children[child], childAABB, sphere, functor);
|
||||
}
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Utility class, which represents a discrete probability
|
||||
* distribution function along with its cumulative distribution
|
||||
* function. Can transform uniformly distributed samples so
|
||||
* that they match the stored distribution.
|
||||
* \brief Stores a discrete probability distribution
|
||||
*
|
||||
* This class can be used to transform uniformly distributed samples
|
||||
* so that they match the stored distribution.
|
||||
*/
|
||||
class DiscretePDF {
|
||||
struct DiscretePDF {
|
||||
public:
|
||||
/// Allocate a PDF with the given number of entries
|
||||
explicit inline DiscretePDF(int nEntries = 0) : m_ready(false) {
|
||||
|
@ -41,7 +41,7 @@ public:
|
|||
m_cdf.push_back(0.0f);
|
||||
}
|
||||
|
||||
/// Return the amount of entries
|
||||
/// Return the number of entries
|
||||
inline size_t size() const {
|
||||
return m_pdf.size();
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Normalize the PDF and build the associated cumulative
|
||||
* distribution function. Returns the sum of all unnormalized
|
||||
* PDF values.
|
||||
* \brief Normalize the PDF and build the associated cumulative
|
||||
* distribution function.
|
||||
* \return Sum of all unnormalized PDF values
|
||||
*/
|
||||
inline Float build() {
|
||||
SAssert(m_pdf.size() > 0 && !m_ready);
|
||||
|
@ -87,8 +87,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Transform a uniformly distributed sample. Returns the
|
||||
* PDF entry index.
|
||||
* \brief %Transform a uniformly distributed sample
|
||||
* \param[in] sampleValue Uniform sample
|
||||
* \return Sample index
|
||||
*/
|
||||
inline int sample(Float sampleValue) const {
|
||||
std::vector<Float>::const_iterator entry =
|
||||
|
@ -98,8 +99,10 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Transform a uniformly distributed sample. Returns the
|
||||
* PDF entry index and the probability value at that index
|
||||
* \brief %Transform a uniformly distributed sample.
|
||||
* \param[in] sampleValue Uniform sample
|
||||
* \param[out] pdf Probability value of the sample
|
||||
* \return Sample index
|
||||
*/
|
||||
inline int sample(Float sampleValue, Float &pdf) const {
|
||||
int index = sample(sampleValue);
|
||||
|
@ -108,9 +111,11 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Transform a uniformly distributed sample. Returns the
|
||||
* PDF entry index. The original sample is transformed so
|
||||
* that it can be re-used.
|
||||
* \brief %Transform a uniformly distributed sample.
|
||||
*
|
||||
* The original sample is adjusted so that it can be reused.
|
||||
* \param[in,out] sampleValue Uniform sample
|
||||
* \return Sample index
|
||||
*/
|
||||
inline int sampleReuse(Float &sampleValue) const {
|
||||
int index = sample(sampleValue);
|
||||
|
@ -120,9 +125,12 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Transform a uniformly distributed sample. Returns the
|
||||
* PDF entry index and the probability value at that index.
|
||||
* The original sample is transformed so that it can be re-used.
|
||||
* \brief %Transform a uniformly distributed sample.
|
||||
*
|
||||
* The original sample is adjusted so that it can be reused.
|
||||
* \param[in,out] sampleValue Uniform sample
|
||||
* \param[out] pdf Probability value of the sample
|
||||
* \return Sample index
|
||||
*/
|
||||
inline int sampleReuse(Float &sampleValue, Float &pdf) const {
|
||||
int index = sample(sampleValue, pdf);
|
||||
|
|
|
@ -90,6 +90,8 @@
|
|||
#endif
|
||||
|
||||
#define SIZE_T_FMT "%Iu"
|
||||
#define BOOST_FILESYSTEM_NO_LIB
|
||||
#define BOOST_SYSTEM_NO_LIB
|
||||
#else
|
||||
#define MTS_EXPORT
|
||||
#define MTS_EXPORT_CORE
|
||||
|
|
|
@ -20,15 +20,18 @@
|
|||
#define __PLUGIN_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Utility;
|
||||
|
||||
/**
|
||||
* Abstract plugin class -- can represent loadable configurable objects
|
||||
* and utilities. Please see the <tt>ConfigurableObject</tt> and
|
||||
* <tt>Utility</tt> class for details
|
||||
* \brief Abstract plugin class -- represents loadable configurable objects
|
||||
* and utilities.
|
||||
*
|
||||
* Please see the <tt>\ref ConfigurableObject</tt> and
|
||||
* <tt>\ref Utility</tt> classes for details
|
||||
*/
|
||||
class MTS_EXPORT_CORE Plugin {
|
||||
typedef void *(*CreateInstanceFunc)(const Properties &props);
|
||||
|
@ -36,7 +39,7 @@ class MTS_EXPORT_CORE Plugin {
|
|||
typedef char *(*GetDescriptionFunc)();
|
||||
public:
|
||||
/// Load a plugin from the supplied path
|
||||
Plugin(const std::string &shortName, const std::string &path);
|
||||
Plugin(const std::string &shortName, const fs::path &path);
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~Plugin();
|
||||
|
@ -54,13 +57,15 @@ public:
|
|||
std::string getDescription() const;
|
||||
|
||||
/// Return the path of this plugin
|
||||
inline const std::string &getPath() const { return m_path; }
|
||||
inline const fs::path &getPath() const { return m_path; }
|
||||
|
||||
/// Return a short name of this plugin
|
||||
inline const std::string &getShortName() const { return m_shortName; }
|
||||
protected:
|
||||
/// Resolve the given symbol and return a pointer
|
||||
void *getSymbol(const std::string &sym);
|
||||
/// Check whether a certain symbol is provided by the plugin
|
||||
bool hasSymbol(const std::string &sym) const;
|
||||
private:
|
||||
#if defined(WIN32)
|
||||
HMODULE m_handle;
|
||||
|
@ -68,15 +73,18 @@ private:
|
|||
void *m_handle;
|
||||
#endif
|
||||
std::string m_shortName;
|
||||
std::string m_path;
|
||||
fs::path m_path;
|
||||
bool m_isUtility;
|
||||
GetDescriptionFunc m_getDescription;
|
||||
CreateInstanceFunc m_createInstance;
|
||||
CreateUtilityFunc m_createUtility;
|
||||
};
|
||||
|
||||
class FileResolver;
|
||||
|
||||
/**
|
||||
* \brief The plugin manager is responsible for resolving and
|
||||
* loading external plugins.
|
||||
*/
|
||||
class MTS_EXPORT_CORE PluginManager : public Object {
|
||||
public:
|
||||
/// Return the global plugin manager
|
||||
|
@ -90,7 +98,15 @@ public:
|
|||
/// Return the list of loaded plugins
|
||||
std::vector<std::string> getLoadedPlugins() const;
|
||||
|
||||
/// Instantiate an object
|
||||
/**
|
||||
* \brief Instantiate an object using a plugin
|
||||
* \param classType Expected type of the plugin. An
|
||||
* exception will be thrown if it turns out not
|
||||
* to derive from this class.
|
||||
* \param props A \ref Properties instance containing
|
||||
* all information required to find and construct
|
||||
* the plugin.
|
||||
*/
|
||||
ConfigurableObject *createObject(
|
||||
const Class *classType,
|
||||
const Properties &props
|
||||
|
|
|
@ -23,470 +23,572 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Simple three-dimensional point class using floating point values.
|
||||
* This class is different from the Vector class in how it is treated
|
||||
* by linear transformations.
|
||||
/**
|
||||
* \headerfile mitsuba/core/point.h mitsuba/mitsuba.h
|
||||
* \brief Parameterizable two-dimensional point data structure
|
||||
*/
|
||||
class Point {
|
||||
public:
|
||||
Float x, y, z;
|
||||
template <typename T> struct TPoint2 {
|
||||
T x, y;
|
||||
|
||||
inline Point(Float _x = 0.0f, Float _y = 0.0f, Float _z = 0.0f)
|
||||
: x(_x), y(_y), z(_z) {
|
||||
}
|
||||
|
||||
inline Point(Stream *stream) {
|
||||
x = stream->readFloat();
|
||||
y = stream->readFloat();
|
||||
z = stream->readFloat();
|
||||
}
|
||||
|
||||
explicit inline Point(const Vector &v)
|
||||
: x(v.x), y(v.y), z(v.z) {
|
||||
}
|
||||
|
||||
inline Point operator+(const Vector &v) const {
|
||||
return Point(x + v.x, y + v.y, z + v.z);
|
||||
}
|
||||
|
||||
inline Point operator-(const Vector &v) const {
|
||||
return Point(x - v.x, y - v.y, z - v.z);
|
||||
}
|
||||
|
||||
inline Vector operator-(const Point &p) const {
|
||||
return Vector(x - p.x, y - p.y, z - p.z);
|
||||
}
|
||||
|
||||
inline Point operator+(const Point &p) const {
|
||||
return Point(x + p.x, y + p.y, z + p.z);
|
||||
}
|
||||
|
||||
inline Point& operator+=(const Point &p) {
|
||||
x += p.x; y += p.y; z += p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point& operator+=(const Vector &v) {
|
||||
x += v.x; y += v.y; z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point& operator-=(const Vector &v) {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point operator*(Float f) const {
|
||||
return Point(x*f, y*f, z*f);
|
||||
}
|
||||
|
||||
inline Point &operator*=(Float f) {
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point operator/(Float f) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point: Division by zero!");
|
||||
/** \brief Construct a new point without initializing it.
|
||||
*
|
||||
* This construtor is useful when the point will either not
|
||||
* be used at all (it might be part of a larger data structure)
|
||||
* or initialized at a later point in time. Always make sure
|
||||
* that one of the two is the case! Otherwise your program will do
|
||||
* computations involving uninitialized memory, which will probably
|
||||
* lead to a difficult-to-find bug.
|
||||
*/
|
||||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint2() { }
|
||||
#else
|
||||
TPoint2() { x = y = std::numeric_limits<double>::quiet_NaN(); }
|
||||
#endif
|
||||
Float r = 1.0f / f;
|
||||
return Point(x * r, y * r, z * r);
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
TPoint2(T x, T y) : x(x), y(y) { }
|
||||
|
||||
/// Initialize the point with the components of another point
|
||||
template <typename T2> explicit TPoint2(const TPoint2<T2> &p)
|
||||
: x((T) p.x), y((T) p.y) { }
|
||||
|
||||
/// Initialize the point with the components of a vector data structure
|
||||
template <typename T2> explicit TPoint2(const TVector2<T2> &v)
|
||||
: x((T) v.x), y((T) v.y) { }
|
||||
|
||||
/// Initialize all components of the the point with the specified value
|
||||
explicit TPoint2(T val) : x(val), y(val) { }
|
||||
|
||||
/// Unserialize a point from a binary data stream
|
||||
explicit TPoint2(Stream *stream) {
|
||||
x = stream->readElement<T>();
|
||||
y = stream->readElement<T>();
|
||||
}
|
||||
|
||||
inline Point &operator/=(Float f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point: Division by zero!");
|
||||
#endif
|
||||
Float r = 1.0f / f;
|
||||
x *= r;
|
||||
y *= r;
|
||||
z *= r;
|
||||
/// Add a vector to a point and return the result
|
||||
TPoint2 operator+(const TVector2<T> &v) const {
|
||||
return TPoint2(x + v.x, y + v.y);
|
||||
}
|
||||
|
||||
/// Add two points and return the result (e.g. to compute a weighted position)
|
||||
TPoint2 operator+(const TPoint2 &p) const {
|
||||
return TPoint2(x + p.x, y + p.y);
|
||||
}
|
||||
|
||||
/// Add a vector to this one (e.g. to compute a weighted position)
|
||||
TPoint2& operator+=(const TVector2<T> &v) {
|
||||
x += v.x; y += v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Float operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline Float &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline bool operator==(const Point &v) const {
|
||||
return (v.x == x && v.y == y && v.z == z);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Point &v) const {
|
||||
return !operator==(v);
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return x==0 && y == 0 && z == 0;
|
||||
}
|
||||
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeFloat(x);
|
||||
stream->writeFloat(y);
|
||||
stream->writeFloat(z);
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << ", " << z << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
class Point2 {
|
||||
public:
|
||||
Float x, y;
|
||||
|
||||
inline Point2(Float _x = 0.0f, Float _y = 0.0f)
|
||||
: x(_x), y(_y) {
|
||||
}
|
||||
|
||||
inline Point2(Stream *stream) {
|
||||
x = stream->readFloat();
|
||||
y = stream->readFloat();
|
||||
}
|
||||
|
||||
inline Point2 operator*(Float f) const {
|
||||
return Point2(x*f, y*f);
|
||||
}
|
||||
|
||||
inline Point2 &operator*=(Float f) {
|
||||
x *= f;
|
||||
y *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2 operator+(const Point2 &p) const {
|
||||
return Point2(x + p.x, y + p.y);
|
||||
}
|
||||
|
||||
inline Point2 operator+(const Vector2 &p) const {
|
||||
return Point2(x + p.x, y + p.y);
|
||||
}
|
||||
|
||||
inline Point2& operator+=(const Point2 &p) {
|
||||
x += p.x; y += p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2& operator+=(const Vector2 &p) {
|
||||
/// Add a point to this one (e.g. to compute a weighted position)
|
||||
TPoint2& operator+=(const TPoint2 &p) {
|
||||
x += p.x; y += p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2 operator-(const Point2 &p) const {
|
||||
return Vector2(x - p.x, y - p.y);
|
||||
}
|
||||
|
||||
inline Point2 operator-(const Vector2 &p) const {
|
||||
return Point2(x - p.x, y - p.y);
|
||||
/// Subtract a vector from this point
|
||||
TPoint2 operator-(const TVector2<T> &v) const {
|
||||
return TPoint2(x - v.x, y - v.y);
|
||||
}
|
||||
|
||||
inline Point2& operator-=(const Point2 &p) {
|
||||
x -= p.x; y -= p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2& operator-=(const Vector2 &p) {
|
||||
x -= p.x; y -= p.y;
|
||||
return *this;
|
||||
/// Subtract two points from each other and return the difference as a vector
|
||||
TVector2<T> operator-(const TPoint2 &p) const {
|
||||
return TVector2<T>(x - p.x, y - p.y);
|
||||
}
|
||||
|
||||
inline Point2 operator/(Float f) const {
|
||||
Float r = 1.0f / f;
|
||||
return Point2(x * r, y * r);
|
||||
}
|
||||
|
||||
inline Point2 &operator/=(Float f) {
|
||||
Float r = 1.0f / f;
|
||||
x *= r;
|
||||
y *= r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Float operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline Float &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline bool operator==(const Point2 &v) const {
|
||||
return (v.x == x && v.y == y);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Point2 &v) const {
|
||||
return !operator==(v);
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return x==0 && y == 0;
|
||||
}
|
||||
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeFloat(x);
|
||||
stream->writeFloat(y);
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
class Point3i {
|
||||
public:
|
||||
int x, y, z;
|
||||
|
||||
inline Point3i(int _x = 0, int _y = 0, int _z = 0)
|
||||
: x(_x), y(_y), z(_z) {
|
||||
}
|
||||
|
||||
inline Point3i(Stream *stream) {
|
||||
x = stream->readInt();
|
||||
y = stream->readInt();
|
||||
z = stream->readInt();
|
||||
}
|
||||
|
||||
explicit inline Point3i(const Vector3i &v)
|
||||
: x(v.x), y(v.y), z(v.z) {
|
||||
}
|
||||
|
||||
inline Point3i operator+(const Vector3i &v) const {
|
||||
return Point3i(x + v.x, y + v.y, z + v.z);
|
||||
}
|
||||
|
||||
inline Point3i operator-(const Vector3i &v) const {
|
||||
return Point3i(x - v.x, y - v.y, z - v.z);
|
||||
}
|
||||
|
||||
inline Vector3i operator-(const Point3i &p) const {
|
||||
return Vector3i(x - p.x, y - p.y, z - p.z);
|
||||
}
|
||||
|
||||
inline Point3i operator+(const Point3i &p) const {
|
||||
return Point3i(x + p.x, y + p.y, z + p.z);
|
||||
}
|
||||
|
||||
inline Point3i& operator+=(const Point3i &p) {
|
||||
x += p.x; y += p.y; z += p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point3i& operator+=(const Vector3i &v) {
|
||||
x += v.x; y += v.y; z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point3i& operator-=(const Vector3i &v) {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point3i operator*(int f) const {
|
||||
return Point3i(x*f, y*f, z*f);
|
||||
}
|
||||
|
||||
inline Point3i &operator*=(int f) {
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point3i operator/(int i) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (i == 0)
|
||||
SLog(EWarn, "Point3i: Division by zero!");
|
||||
#endif
|
||||
return Point3i(x / i, y / i, z / i);
|
||||
}
|
||||
|
||||
inline Point3i &operator/=(int i) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (i == 0)
|
||||
SLog(EWarn, "Point3i: Division by zero!");
|
||||
#endif
|
||||
x /= i;
|
||||
y /= i;
|
||||
z /= i;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline int operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline int &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline bool operator==(const Point3i &v) const {
|
||||
return (v.x == x && v.y == y && v.z == z);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Point3i &v) const {
|
||||
return !operator==(v);
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return x==0 && y == 0 && z == 0;
|
||||
}
|
||||
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeInt(x);
|
||||
stream->writeInt(y);
|
||||
stream->writeInt(z);
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << ", " << z << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
class Point2i {
|
||||
public:
|
||||
int x, y;
|
||||
|
||||
inline Point2i(int _x = 0, int _y = 0)
|
||||
: x(_x), y(_y) {
|
||||
}
|
||||
|
||||
explicit inline Point2i(const Vector2i &v)
|
||||
: x(v.x), y(v.y) {
|
||||
}
|
||||
|
||||
inline Point2i(Stream *stream) {
|
||||
x = stream->readInt();
|
||||
y = stream->readInt();
|
||||
}
|
||||
|
||||
inline Point2i operator*(int i) const {
|
||||
return Point2i(x*i, y*i);
|
||||
}
|
||||
|
||||
inline Point2i &operator*=(int i) {
|
||||
x *= i;
|
||||
y *= i;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2i operator+(const Point2i &p) const {
|
||||
return Point2i(x + p.x, y + p.y);
|
||||
}
|
||||
|
||||
inline Point2i operator+(const Vector2i &v) const {
|
||||
return Point2i(x + v.x, y + v.y);
|
||||
}
|
||||
|
||||
inline Point2i& operator+=(const Point2i &p) {
|
||||
x += p.x; y += p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2i& operator+=(const Vector2i &v) {
|
||||
x += v.x; y += v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2i operator-(const Point2i &p) const {
|
||||
return Point2i(x - p.x, y - p.y);
|
||||
}
|
||||
|
||||
inline Point2i operator-(const Vector2i &v) const {
|
||||
return Point2i(x - v.x, y - v.y);
|
||||
}
|
||||
|
||||
inline Point2i& operator-=(const Point2i &p) {
|
||||
x -= p.x; y -= p.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2i& operator-=(const Vector2i &v) {
|
||||
/// Subtract a vector from this point
|
||||
TPoint2& operator-=(const TVector2<T> &v) {
|
||||
x -= v.x; y -= v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Point2i operator/(int i) const {
|
||||
return Point2i(x / i, y / i);
|
||||
/// Scale the point's coordinates by the given scalar and return the result
|
||||
TPoint2 operator*(T f) const {
|
||||
return TPoint2(x * f, y * f);
|
||||
}
|
||||
|
||||
inline Point2i &operator/=(int i) {
|
||||
x /= i;
|
||||
y /= i;
|
||||
/// Scale the point's coordinates by the given scalar
|
||||
TPoint2 &operator*=(T f) {
|
||||
x *= f; y *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int operator[](int i) const {
|
||||
/// Return a version of the point, which has been flipped along the origin
|
||||
TPoint2 operator-() const {
|
||||
return TPoint2(-x, -y);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar and return the result
|
||||
TPoint2 operator/(T f) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point2: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
return TPoint2(x * recip, y * recip);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar
|
||||
TPoint2 &operator/=(T f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point2: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
x *= recip; y *= recip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Index into the point's components
|
||||
T &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
int &operator[](int i) {
|
||||
/// Index into the point's components (const version)
|
||||
T operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
inline bool operator==(const Point2i &v) const {
|
||||
/// Return whether or not this point is identically zero
|
||||
bool isZero() const {
|
||||
return x == 0 && y == 0;
|
||||
}
|
||||
|
||||
/// Equality test
|
||||
bool operator==(const TPoint2 &v) const {
|
||||
return (v.x == x && v.y == y);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Point2i &v) const {
|
||||
return !operator==(v);
|
||||
|
||||
/// Inequality test
|
||||
bool operator!=(const TPoint2 &v) const {
|
||||
return v.x != x || v.y != y;
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return x==0 && y == 0;
|
||||
/// Serialize this point to a binary data stream
|
||||
void serialize(Stream *stream) const {
|
||||
stream->writeElement<T>(x);
|
||||
stream->writeElement<T>(y);
|
||||
}
|
||||
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeInt(x);
|
||||
stream->writeInt(y);
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
/// Return a readable string representation of this point
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
inline Vector::Vector(const Point3i &p)
|
||||
: x((Float) p.x), y((Float) p.y), z((Float) p.z) {
|
||||
template <typename T> inline TPoint2<T> operator*(T f, const TPoint2<T> &v) {
|
||||
return v*f;
|
||||
}
|
||||
|
||||
inline Vector3i::Vector3i(const Point3i &p)
|
||||
: x(p.x), y(p.y), z(p.z) {
|
||||
template <typename T> inline T distance(const TPoint2<T> &p1, const TPoint2<T> &p2) {
|
||||
return (p1-p2).length();
|
||||
}
|
||||
|
||||
inline Vector::Vector(const Point &p)
|
||||
: x(p.x), y(p.y), z(p.z) {
|
||||
template <typename T> inline T distanceSquared(const TPoint2<T> &p1, const TPoint2<T> &p2) {
|
||||
return (p1-p2).lengthSquared();
|
||||
}
|
||||
|
||||
inline Vector2::Vector2(const Point2 &p)
|
||||
: x(p.x), y(p.y) {
|
||||
template <> inline TPoint2<int> TPoint2<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point2i: Division by zero!");
|
||||
#endif
|
||||
return TPoint2(x/s, y/s);
|
||||
}
|
||||
|
||||
inline Vector2i::Vector2i(const Point2i &p)
|
||||
: x(p.x), y(p.y) {
|
||||
template <> inline TPoint2<int> &TPoint2<int>::operator/=(int s) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point2i: Division by zero!");
|
||||
#endif
|
||||
x /= s;
|
||||
y /= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Float distance(const Point &p1, const Point &p2) {
|
||||
return (p1 - p2).length();
|
||||
/**
|
||||
* \headerfile mitsuba/core/point.h mitsuba/mitsuba.h
|
||||
* \brief Parameterizable three-dimensional point data structure
|
||||
*/
|
||||
template <typename T> struct TPoint3 {
|
||||
T x, y, z;
|
||||
|
||||
/** \brief Construct a new point without initializing it.
|
||||
*
|
||||
* This construtor is useful when the point will either not
|
||||
* be used at all (it might be part of a larger data structure)
|
||||
* or initialized at a later point in time. Always make sure
|
||||
* that one of the two is the case! Otherwise your program will do
|
||||
* computations involving uninitialized memory, which will probably
|
||||
* lead to a difficult-to-find bug.
|
||||
*/
|
||||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint3() { }
|
||||
#else
|
||||
TPoint3() { x = y = z = std::numeric_limits<double>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
TPoint3(T x, T y, T z) : x(x), y(y), z(z) { }
|
||||
|
||||
/// Initialize the point with the components of another point
|
||||
template <typename T2> explicit TPoint3(const TPoint3<T2> &p)
|
||||
: x((T) p.x), y((T) p.y), z((T) p.z) { }
|
||||
|
||||
/// Initialize the point with the components of a vector data structure
|
||||
template <typename T2> explicit TPoint3(const TVector3<T2> &v)
|
||||
: x((T) v.x), y((T) v.y), z((T) v.z) { }
|
||||
|
||||
/// Initialize all components of the the point with the specified value
|
||||
explicit TPoint3(T val) : x(val), y(val), z(val) { }
|
||||
|
||||
/// Unserialize a point from a binary data stream
|
||||
explicit TPoint3(Stream *stream) {
|
||||
x = stream->readElement<T>();
|
||||
y = stream->readElement<T>();
|
||||
z = stream->readElement<T>();
|
||||
}
|
||||
|
||||
/// Add a vector to a point and return the result
|
||||
TPoint3 operator+(const TVector3<T> &v) const {
|
||||
return TPoint3(x + v.x, y + v.y, z + v.z);
|
||||
}
|
||||
|
||||
/// Add two points and return the result (e.g. to compute a weighted position)
|
||||
TPoint3 operator+(const TPoint3 &p) const {
|
||||
return TPoint3(x + p.x, y + p.y, z + p.z);
|
||||
}
|
||||
|
||||
/// Add a vector to this one (e.g. to compute a weighted position)
|
||||
TPoint3& operator+=(const TVector3<T> &v) {
|
||||
x += v.x; y += v.y; z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Add a point to this one (e.g. to compute a weighted position)
|
||||
TPoint3& operator+=(const TPoint3 &p) {
|
||||
x += p.x; y += p.y; z += p.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Subtract a vector from this point
|
||||
TPoint3 operator-(const TVector3<T> &v) const {
|
||||
return TPoint3(x - v.x, y - v.y, z - v.z);
|
||||
}
|
||||
|
||||
/// Subtract two points from each other and return the difference as a vector
|
||||
TVector3<T> operator-(const TPoint3 &p) const {
|
||||
return TVector3<T>(x - p.x, y - p.y, z - p.z);
|
||||
}
|
||||
|
||||
/// Subtract a vector from this point
|
||||
TPoint3& operator-=(const TVector3<T> &v) {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Scale the point's coordinates by the given scalar and return the result
|
||||
TPoint3 operator*(T f) const {
|
||||
return TPoint3(x * f, y * f, z * f);
|
||||
}
|
||||
|
||||
/// Scale the point's coordinates by the given scalar
|
||||
TPoint3 &operator*=(T f) {
|
||||
x *= f; y *= f; z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a version of the point, which has been flipped along the origin
|
||||
TPoint3 operator-() const {
|
||||
return TPoint3(-x, -y, -z);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar and return the result
|
||||
TPoint3 operator/(T f) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point3: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
return TPoint3(x * recip, y * recip, z * recip);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar
|
||||
TPoint3 &operator/=(T f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point3: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
x *= recip; y *= recip; z *= recip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Index into the point's components
|
||||
T &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
/// Index into the point's components (const version)
|
||||
T operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
/// Return whether or not this point is identically zero
|
||||
bool isZero() const {
|
||||
return x == 0 && y == 0 && z == 0;
|
||||
}
|
||||
|
||||
/// Equality test
|
||||
bool operator==(const TPoint3 &v) const {
|
||||
return (v.x == x && v.y == y && v.z == z);
|
||||
}
|
||||
|
||||
/// Inequality test
|
||||
bool operator!=(const TPoint3 &v) const {
|
||||
return v.x != x || v.y != y || v.z != z;
|
||||
}
|
||||
|
||||
/// Serialize this point to a binary data stream
|
||||
void serialize(Stream *stream) const {
|
||||
stream->writeElement<T>(x);
|
||||
stream->writeElement<T>(y);
|
||||
stream->writeElement<T>(z);
|
||||
}
|
||||
|
||||
/// Return a readable string representation of this point
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << ", " << z << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> inline TPoint3<T> operator*(T f, const TPoint3<T> &v) {
|
||||
return v*f;
|
||||
}
|
||||
|
||||
inline Float distanceSquared(const Point &p1, const Point &p2) {
|
||||
return (p1 - p2).lengthSquared();
|
||||
template <typename T> inline T distance(const TPoint3<T> &p1, const TPoint3<T> &p2) {
|
||||
return (p1-p2).length();
|
||||
}
|
||||
|
||||
template <typename T> inline T distanceSquared(const TPoint3<T> &p1, const TPoint3<T> &p2) {
|
||||
return (p1-p2).lengthSquared();
|
||||
}
|
||||
|
||||
template <> inline TPoint3<int> TPoint3<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point3i: Division by zero!");
|
||||
#endif
|
||||
return TPoint3(x/s, y/s, z/s);
|
||||
}
|
||||
|
||||
template <> inline TPoint3<int> &TPoint3<int>::operator/=(int s) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point3i: Division by zero!");
|
||||
#endif
|
||||
x /= s;
|
||||
y /= s;
|
||||
z /= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \headerfile mitsuba/core/point.h mitsuba/mitsuba.h
|
||||
* \brief Parameterizable four-dimensional point data structure
|
||||
*/
|
||||
template <typename T> struct TPoint4 {
|
||||
T x, y, z, w;
|
||||
|
||||
/** \brief Construct a new point without initializing it.
|
||||
*
|
||||
* This construtor is useful when the point will either not
|
||||
* be used at all (it might be part of a larger data structure)
|
||||
* or initialized at a later point in time. Always make sure
|
||||
* that one of the two is the case! Otherwise your program will do
|
||||
* computations involving uninitialized memory, which will probably
|
||||
* lead to a difficult-to-find bug.
|
||||
*/
|
||||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint4() { }
|
||||
#else
|
||||
TPoint4() { x = y = z = w = std::numeric_limits<double>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
TPoint4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) { }
|
||||
|
||||
/// Initialize the point with the components of another point
|
||||
template <typename T2> explicit TPoint4(const TPoint4<T2> &p)
|
||||
: x((T) p.x), y((T) p.y), z((T) p.z), w((T) p.w) { }
|
||||
|
||||
/// Initialize the point with the components of a vector data structure
|
||||
template <typename T2> explicit TPoint4(const TVector4<T2> &v)
|
||||
: x((T) v.x), y((T) v.y), z((T) v.z), w((T) v.w) { }
|
||||
|
||||
/// Initialize all components of the the point with the specified value
|
||||
explicit TPoint4(T val) : x(val), y(val), z(val), w(val) { }
|
||||
|
||||
/// Unserialize a point from a binary data stream
|
||||
explicit TPoint4(Stream *stream) {
|
||||
x = stream->readElement<T>();
|
||||
y = stream->readElement<T>();
|
||||
z = stream->readElement<T>();
|
||||
w = stream->readElement<T>();
|
||||
}
|
||||
|
||||
/// Add a vector to a point and return the result
|
||||
TPoint4 operator+(const TVector4<T> &v) const {
|
||||
return TPoint4(x + v.x, y + v.y, z + v.z, w + v.w);
|
||||
}
|
||||
|
||||
/// Add two points and return the result (e.g. to compute a weighted position)
|
||||
TPoint4 operator+(const TPoint4 &p) const {
|
||||
return TPoint4(x + p.x, y + p.y, z + p.z, w + p.w);
|
||||
}
|
||||
|
||||
/// Add a vector to this one (e.g. to compute a weighted position)
|
||||
TPoint4& operator+=(const TVector4<T> &v) {
|
||||
x += v.x; y += v.y; z += v.z; w += v.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Add a point to this one (e.g. to compute a weighted position)
|
||||
TPoint4& operator+=(const TPoint4 &p) {
|
||||
x += p.x; y += p.y; z += p.z; w += p.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Subtract a vector from this point
|
||||
TPoint4 operator-(const TVector4<T> &v) const {
|
||||
return TPoint4(x - v.x, y - v.y, z - v.z, w - v.w);
|
||||
}
|
||||
|
||||
/// Subtract two points from each other and return the difference as a vector
|
||||
TVector4<T> operator-(const TPoint4 &p) const {
|
||||
return TVector4<T>(x - p.x, y - p.y, z - p.z, w - p.w);
|
||||
}
|
||||
|
||||
/// Subtract a vector from this point
|
||||
TPoint4& operator-=(const TVector4<T> &v) {
|
||||
x -= v.x; y -= v.y; z -= v.z; w -= v.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Scale the point's coordinates by the given scalar and return the result
|
||||
TPoint4 operator*(T f) const {
|
||||
return TPoint4(x * f, y * f, z * f, w * f);
|
||||
}
|
||||
|
||||
/// Scale the point's coordinates by the given scalar
|
||||
TPoint4 &operator*=(T f) {
|
||||
x *= f; y *= f; z *= f; w *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a version of the point, which has been flipped along the origin
|
||||
TPoint4 operator-() const {
|
||||
return TPoint4(-x, -y, -z, -w);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar and return the result
|
||||
TPoint4 operator/(T f) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point4: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
return TPoint4(x * recip, y * recip, z * recip, w * recip);
|
||||
}
|
||||
|
||||
/// Divide the point's coordinates by the given scalar
|
||||
TPoint4 &operator/=(T f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0)
|
||||
SLog(EWarn, "Point4: Division by zero!");
|
||||
#endif
|
||||
T recip = (T) 1 / f;
|
||||
x *= recip; y *= recip; z *= recip; w *= recip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Index into the point's components
|
||||
T &operator[](int i) {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
/// Index into the point's components (const version)
|
||||
T operator[](int i) const {
|
||||
return (&x)[i];
|
||||
}
|
||||
|
||||
/// Return whether or not this point is identically zero
|
||||
bool isZero() const {
|
||||
return x == 0 && y == 0 && z == 0 && w == 0;
|
||||
}
|
||||
|
||||
/// Equality test
|
||||
bool operator==(const TPoint4 &v) const {
|
||||
return (v.x == x && v.y == y && v.z == z && v.w == w);
|
||||
}
|
||||
|
||||
/// Inequality test
|
||||
bool operator!=(const TPoint4 &v) const {
|
||||
return v.x != x || v.y != y || v.z != z || v.w != w;
|
||||
}
|
||||
|
||||
/// Serialize this point to a binary data stream
|
||||
void serialize(Stream *stream) const {
|
||||
stream->writeElement<T>(x);
|
||||
stream->writeElement<T>(y);
|
||||
stream->writeElement<T>(z);
|
||||
stream->writeElement<T>(w);
|
||||
}
|
||||
|
||||
/// Return a readable string representation of this point
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "[" << x << ", " << y << ", " << z << ", " << w << "]";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> inline TPoint4<T> operator*(T f, const TPoint4<T> &v) {
|
||||
return v*f;
|
||||
}
|
||||
|
||||
template <typename T> inline T distance(const TPoint4<T> &p1, const TPoint4<T> &p2) {
|
||||
return (p1-p2).length();
|
||||
}
|
||||
|
||||
template <typename T> inline T distanceSquared(const TPoint4<T> &p1, const TPoint4<T> &p2) {
|
||||
return (p1-p2).lengthSquared();
|
||||
}
|
||||
|
||||
template <> inline TPoint4<int> TPoint4<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point4i: Division by zero!");
|
||||
#endif
|
||||
return TPoint4(x/s, y/s, z/s, w/s);
|
||||
}
|
||||
|
||||
template <> inline TPoint4<int> &TPoint4<int>::operator/=(int s) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
SLog(EWarn, "Point4i: Division by zero!");
|
||||
#endif
|
||||
|
||||
x /= s;
|
||||
y /= s;
|
||||
z /= s;
|
||||
w /= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
#if !defined(__PROPERTIES_H)
|
||||
#define __PROPERTIES_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/transform.h>
|
||||
#include <mitsuba/core/spectrum.h>
|
||||
#include <map>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Associative map for values of various types. Used to
|
||||
* construct sub-classes of <tt>ConfigurableObject</tt>
|
||||
* construct subclasses of <tt>ConfigurableObject</tt>.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Properties {
|
||||
public:
|
||||
|
@ -135,6 +134,7 @@ public:
|
|||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
private:
|
||||
/// \cond
|
||||
struct Element {
|
||||
PropertyType type;
|
||||
union {
|
||||
|
@ -150,6 +150,7 @@ private:
|
|||
std::string v_string;
|
||||
mutable bool queried;
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
std::map<std::string, Element> m_elements;
|
||||
std::string m_pluginName, m_id;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define __RANDOM_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <algorithm>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
|
||||
/*
|
||||
A C-program for MT19937-64 (2004/9/29 version).
|
||||
|
@ -86,12 +86,17 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
/**
|
||||
* \brief %Random number generator based on Mersenne Twister
|
||||
* by Takuji Nishimura and Makoto Matsumoto.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Random : public SerializableObject {
|
||||
public:
|
||||
/**
|
||||
* Construct a new seeded random generator. Uses the default
|
||||
* seed on Windows and '/dev/urandom' on OSX and Linux.
|
||||
* \brief Construct a new seeded random generator.
|
||||
*
|
||||
* Uses the default seed on Windows and '/dev/urandom'
|
||||
* on OSX and Linux.
|
||||
*/
|
||||
Random();
|
||||
|
||||
|
@ -123,8 +128,10 @@ public:
|
|||
Float nextFloat();
|
||||
|
||||
/**
|
||||
* Draw a uniformly distributed permutation and permute the given STL container
|
||||
* (see Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2)
|
||||
* \brief Draw a uniformly distributed permutation and permute the
|
||||
* given STL container.
|
||||
*
|
||||
* See Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2.
|
||||
*/
|
||||
template <typename Iterator> void shuffle(Iterator it1, Iterator it2) {
|
||||
for (Iterator it = it2 - 1; it > it1; --it)
|
||||
|
|
|
@ -19,24 +19,18 @@
|
|||
#if !defined(__RAY_H)
|
||||
#define __RAY_H
|
||||
|
||||
#include <mitsuba/core/point.h>
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Simple three-dimensional ray class with
|
||||
minimum / maximum extent information */
|
||||
class Ray {
|
||||
public:
|
||||
/// Ray origin
|
||||
Point o;
|
||||
/// Minimum range for intersection tests
|
||||
Float mint;
|
||||
/// Ray direction
|
||||
Vector d;
|
||||
/// Maximum range for intersection tests
|
||||
Float maxt;
|
||||
/// Ray direction reciprocal
|
||||
Vector dRcp;
|
||||
struct Ray {
|
||||
Point o; ///< Ray origin
|
||||
Float mint; ///< Minimum range for intersection tests
|
||||
Vector d; ///< Ray direction
|
||||
Float maxt; ///< Maximum range for intersection tests
|
||||
Vector dRcp; ///< Componentwise reciprocals of the ray direction
|
||||
|
||||
/// Construct a new ray
|
||||
inline Ray() : mint(Epsilon), maxt(std::numeric_limits<Float>::infinity()) {
|
||||
|
@ -108,10 +102,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** \brief Ray differential -- enhances the basic ray class with
|
||||
/** \brief %Ray differential -- enhances the basic ray class with
|
||||
information about the rays of adjacent pixels on the view plane */
|
||||
class RayDifferential : public Ray {
|
||||
public:
|
||||
struct RayDifferential : public Ray {
|
||||
bool hasDifferentials;
|
||||
Ray rx, ry;
|
||||
|
||||
|
@ -126,16 +119,36 @@ public:
|
|||
inline explicit RayDifferential(const Ray &ray)
|
||||
: Ray(ray), hasDifferentials(false) {
|
||||
}
|
||||
|
||||
|
||||
inline RayDifferential(const RayDifferential &ray)
|
||||
: Ray(ray), hasDifferentials(ray.hasDifferentials), rx(ray.rx), ry(ray.ry) {
|
||||
}
|
||||
|
||||
void scaleDifferential(Float amount) {
|
||||
rx.setOrigin(o + (rx.o - o) * amount);
|
||||
ry.setOrigin(o + (ry.o - o) * amount);
|
||||
rx.setDirection(d + (rx.d - d) * amount);
|
||||
ry.setDirection(d + (ry.d - d) * amount);
|
||||
}
|
||||
|
||||
inline void operator=(const RayDifferential &ray) {
|
||||
o = ray.o;
|
||||
mint = ray.mint;
|
||||
d = ray.d;
|
||||
maxt = ray.maxt;
|
||||
dRcp = ray.dRcp;
|
||||
hasDifferentials = ray.hasDifferentials;
|
||||
rx = ray.rx;
|
||||
ry = ray.ry;
|
||||
}
|
||||
|
||||
inline void operator=(const Ray &ray) {
|
||||
setOrigin(ray.o);
|
||||
setDirection(ray.d);
|
||||
o = ray.o;
|
||||
mint = ray.mint;
|
||||
d = ray.d;
|
||||
maxt = ray.maxt;
|
||||
dRcp = ray.dRcp;
|
||||
hasDifferentials = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -172,7 +185,7 @@ struct RayInterval4 {
|
|||
mint = SSEConstants::eps;
|
||||
maxt = SSEConstants::p_inf;
|
||||
}
|
||||
|
||||
|
||||
inline RayInterval4(const Ray *rays) {
|
||||
for (int i=0; i<4; i++) {
|
||||
mint.f[i] = rays[i].mint;
|
||||
|
|
|
@ -21,8 +21,16 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief A simple wrapper class which takes care of
|
||||
* referencing and unreferencing objects
|
||||
/**
|
||||
* \headerfile mitsuba/core/ref.h mitsuba/mitsuba.h
|
||||
* \brief Reference counting helper
|
||||
*
|
||||
* The \a ref refeference template is a simple wrapper to store a
|
||||
* pointer to an object. It takes care of increasing and decreasing
|
||||
* the reference count of the object. When the last reference goes
|
||||
* out of scope, the associated object will be deallocated.
|
||||
*
|
||||
* \author Wenzel Jakob
|
||||
*/
|
||||
template <typename T> class ref {
|
||||
public:
|
||||
|
@ -30,13 +38,13 @@ public:
|
|||
ref() : m_ptr(NULL) { }
|
||||
|
||||
/// Construct a reference from a pointer
|
||||
ref(T *ptr) : m_ptr(ptr) { if (m_ptr) m_ptr->incRef(); }
|
||||
|
||||
ref(T *ptr) : m_ptr(ptr) { if (m_ptr) ((Object *) m_ptr)->incRef(); }
|
||||
|
||||
/// Copy-constructor
|
||||
ref(const ref &pRef) : m_ptr(pRef.m_ptr) { if (m_ptr) m_ptr->incRef(); }
|
||||
ref(const ref &pRef) : m_ptr(pRef.m_ptr) { if (m_ptr) ((Object *) m_ptr)->incRef(); }
|
||||
|
||||
/// Destroy this reference
|
||||
~ref() { if (m_ptr) m_ptr->decRef(); }
|
||||
~ref() { if (m_ptr) ((Object *) m_ptr)->decRef(); }
|
||||
|
||||
/// Overwrite this reference with another reference
|
||||
inline ref& operator= (const ref& pref) {
|
||||
|
@ -45,9 +53,9 @@ public:
|
|||
T* tmp = m_ptr;
|
||||
m_ptr = pref.m_ptr;
|
||||
if (m_ptr)
|
||||
m_ptr->incRef();
|
||||
((Object *) m_ptr)->incRef();
|
||||
if (tmp)
|
||||
tmp->decRef();
|
||||
((Object *) tmp)->decRef();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -58,9 +66,9 @@ public:
|
|||
T* tmp = m_ptr;
|
||||
m_ptr = ptr;
|
||||
if (m_ptr)
|
||||
m_ptr->incRef();
|
||||
((Object *) m_ptr)->incRef();
|
||||
if (tmp)
|
||||
tmp->decRef();
|
||||
((Object *) tmp)->decRef();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#if !defined(__SCHED_H)
|
||||
#define __SCHED_H
|
||||
|
||||
#include <mitsuba/core/mstream.h>
|
||||
#include <mitsuba/core/serialization.h>
|
||||
#include <mitsuba/core/lock.h>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
|
||||
|
@ -31,7 +32,7 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Abstract work unit. Represents a small amount of information
|
||||
* \brief Abstract work unit -- represents a small amount of information
|
||||
* that encodes part of a larger processing task.
|
||||
*/
|
||||
class MTS_EXPORT_CORE WorkUnit : public Object {
|
||||
|
@ -55,8 +56,8 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Abstract work result. Represents the information that encodes
|
||||
* the result of a processed <tt>WorkUnit</tt> instance.
|
||||
* \brief Abstract work result -- represents the result of a
|
||||
* processed <tt>\ref WorkUnit</tt> instance.
|
||||
*/
|
||||
class MTS_EXPORT_CORE WorkResult : public Object {
|
||||
public:
|
||||
|
@ -76,30 +77,28 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Abstract work processor. Takes work units and turns them into
|
||||
* <tt>WorkResult</tt> instances. The class is serializable so that
|
||||
* it can be sent over the network if required. It is possible to
|
||||
* keep local state in <tt>WorkProcessor</tt> instances (e.g. scratch
|
||||
* space for computations), though anything not returned in the form
|
||||
* of <tt>WorkResult</tt>s will eventually be lost. Each worker
|
||||
* (both locally and remotely) has its own <tt>WorkProcessor</tt>,
|
||||
* and therefore no form of locking is required.
|
||||
* \brief Abstract work processor -- takes work units and turns them into
|
||||
* <tt>WorkResult</tt> instances.
|
||||
*
|
||||
* The class is serializable so that it can be sent over the network if
|
||||
* required. It is possible to keep local state in <tt>WorkProcessor</tt>
|
||||
* instances (e.g. scratch space for computations), though anything not
|
||||
* returned in the form of <tt>WorkResult</tt>s will eventually be lost.
|
||||
* Each worker (both locally and remotely) has its own <tt>WorkProcessor</tt>,
|
||||
* and therefore no form of locking is required within instances of this class.
|
||||
*/
|
||||
class MTS_EXPORT_CORE WorkProcessor : public SerializableObject {
|
||||
friend class Scheduler;
|
||||
public:
|
||||
/**
|
||||
* Create a work unit of the proper type and size.
|
||||
*/
|
||||
/// Create a work unit of the proper type and size.
|
||||
virtual ref<WorkUnit> createWorkUnit() const = 0;
|
||||
|
||||
/**
|
||||
* Create a work result of the proper type and size
|
||||
*/
|
||||
/// Create a work result of the proper type and size
|
||||
virtual ref<WorkResult> createWorkResult() const = 0;
|
||||
|
||||
/**
|
||||
* Create a copy of this work processor instance.
|
||||
* \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.
|
||||
|
@ -107,22 +106,23 @@ public:
|
|||
virtual ref<WorkProcessor> clone() const = 0;
|
||||
|
||||
/**
|
||||
* Called once before processing starts. This is useful for allocating
|
||||
* scratch space or resolving references to resource objects. Lengthy
|
||||
* computations should be performed in process() instead of here, since
|
||||
* this this method will be called while the central scheduler lock
|
||||
* is held. A thrown exception will lead to the termination of the parallel
|
||||
* process.
|
||||
* \brief Called once before processing starts.
|
||||
*
|
||||
* This is useful for allocating scratch space or resolving references
|
||||
* to resource objects. Lengthy computations should be performed in
|
||||
* process() instead of here, since this this method will be called
|
||||
* while the central scheduler lock is held. A thrown exception will
|
||||
* lead to the termination of the parallel process.
|
||||
*/
|
||||
virtual void prepare() = 0;
|
||||
|
||||
/**
|
||||
* Process a work unit and store the computed results. The <tt>active</tt>
|
||||
* parameter can be used to signal a premature stop of the execution flow.
|
||||
* In this case, the work result is allowed to be undefined (it will
|
||||
* simply be ignored).
|
||||
* A thrown exception will lead to the termination of the parallel
|
||||
* process.
|
||||
* \brief Process a work unit and store the computed results.
|
||||
*
|
||||
* The <tt>active</tt> parameter can be used to signal a premature
|
||||
* stop of the execution flow. In this case, the work result is allowed
|
||||
* to be undefined (it will simply be ignored). A thrown exception will
|
||||
* lead to the termination of the parallel process.
|
||||
*/
|
||||
virtual void process(const WorkUnit *workUnit, WorkResult *workResult,
|
||||
const bool &stop) = 0;
|
||||
|
@ -137,9 +137,10 @@ protected:
|
|||
: SerializableObject(stream, manager) { }
|
||||
|
||||
/**
|
||||
* Look up a named resource, which has been bound to the associated
|
||||
* parallel process. Throws an exception if the resource is not
|
||||
* known / bound.
|
||||
* \brief Look up a named resource, which has been bound to
|
||||
* the associated parallel process.
|
||||
*
|
||||
* Throws an exception if the resource is not known / bound.
|
||||
*/
|
||||
SerializableObject *getResource(const std::string &name);
|
||||
protected:
|
||||
|
@ -147,114 +148,143 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* 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 accepting their results.
|
||||
* The module that performs the actual computation is an instance of
|
||||
* <tt>WorkProcessor</tt>, which is also specified here.
|
||||
* \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
|
||||
* accepting their results. The module that performs the actual computation
|
||||
* is an instance of <tt>WorkProcessor</tt>, which is also specified here.
|
||||
* Finally, the this class references `resources', which denote
|
||||
* chunks of globally shared read-only data required during execution.
|
||||
*/
|
||||
class MTS_EXPORT_CORE ParallelProcess : public Object {
|
||||
friend class Scheduler;
|
||||
public:
|
||||
/// Binding from local resource names to global resource IDs
|
||||
typedef std::map<std::string, int> ResourceBindings;
|
||||
|
||||
/// Return codes used by generateWork() and getReturnStatus()
|
||||
enum EStatus {
|
||||
EUnknown,
|
||||
EPause,
|
||||
ESuccess,
|
||||
EFailure
|
||||
EUnknown, ///< Unknown return status
|
||||
EPause, ///< Temporarily, no work units can be created
|
||||
ESuccess, ///< The process finished / a piece of work was generated
|
||||
EFailure ///< The process failed / no more work is available
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a piece of work. Takes a pre-allocated <tt>WorkUnit</tt>
|
||||
* instance of the appropriate sub-type and size (as specified by
|
||||
* <tt>ParallelProcess::getWorkUnitName</tt>) 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 (EFailure) or temporarily
|
||||
* paused (EPause). When EPause was used, resubmission via
|
||||
* <tt>Scheduler::schedule()</tt> 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 <tt>worker</tt>
|
||||
* 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 thrown exception
|
||||
* will lead to the termination of the parallel process.
|
||||
* \brief Generate a piece of work.
|
||||
*
|
||||
* Takes a pre-allocated <tt>\ref WorkUnit</tt> instance of
|
||||
* the appropriate sub-type and size (as specified by
|
||||
* <tt>\ref ParallelProcess::getWorkUnitName()</tt>) 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 <tt>\ref Scheduler::schedule()</tt> 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 <tt>worker</tt> 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
|
||||
* thrown exception will lead to the termination of the
|
||||
* parallel process.
|
||||
*
|
||||
* \param unit Work unit data structure to be filled
|
||||
* \param worker ID of the worker executing this function
|
||||
*/
|
||||
virtual EStatus generateWork(WorkUnit *unit, int worker) = 0;
|
||||
|
||||
/**
|
||||
* Called whenever a work unit has been completed. Note
|
||||
* that this may be executed by different threads and
|
||||
* likely out of order (some sort of locking will
|
||||
* generally be required when modifying data structures).
|
||||
* \brief Called whenever a work unit has been completed.
|
||||
*
|
||||
* Note that this function may concurrently be executed by
|
||||
* multiple threads. Also, processing of work results will
|
||||
* generally be out of order with respect to the creation
|
||||
* in \ref generateWork().
|
||||
*
|
||||
* When a work unit is only partially completed due to
|
||||
* a call to <tt>Scheduler::cancel</tt>, the second
|
||||
* parameter is set to true.
|
||||
* A thrown exception will lead to the termination of
|
||||
* the parallel process.
|
||||
*
|
||||
* \param result Work result to be processed
|
||||
* \param cancelled Was the associated work unit not fully completed
|
||||
*/
|
||||
virtual void processResult(const WorkResult *result,
|
||||
bool cancelled) = 0;
|
||||
|
||||
/**
|
||||
* Called when the parallel process is canceled
|
||||
* by Scheduler::cancel(). The default implementation
|
||||
* does nothing.
|
||||
* \brief Called when the parallel process is canceled by
|
||||
* \ref Scheduler::cancel().
|
||||
*
|
||||
* The default implementation does nothing.
|
||||
*/
|
||||
virtual void handleCancellation();
|
||||
|
||||
/**
|
||||
* After a process has finished excecution, its return
|
||||
* status can be queried through this method.
|
||||
* Returns one of <tt>Success, Failure or Unknown</tt>
|
||||
* (EUnknown means that the process is either still running
|
||||
* \brief Query the return status of a process after its
|
||||
* execution has finished.
|
||||
*
|
||||
* Returns one of <tt>\ref Success, \ref Failure or \ref Unknown</tt>
|
||||
* (\ref EUnknown means that the process is either still running
|
||||
* or has never been scheduled).
|
||||
*/
|
||||
inline EStatus getReturnStatus() const { return m_returnStatus; }
|
||||
|
||||
/**
|
||||
* Create an instance of the algorithm responsible
|
||||
* \brief Create an instance of the algorithm responsible
|
||||
* for executing the work units of this parallel process.
|
||||
*/
|
||||
virtual ref<WorkProcessor> createWorkProcessor() const = 0;
|
||||
|
||||
/**
|
||||
* Bind a resource to this parallel process. Takes a resource
|
||||
* ID as given by the scheduler and associates it with a name.
|
||||
* This name can later be used by the work processor to access
|
||||
* the resource data.
|
||||
* \brief Bind a resource to this parallel process.
|
||||
*
|
||||
* Takes a resource ID as given by the scheduler and associates it
|
||||
* with a name. This name can later be used by the work processor
|
||||
* to access the resource data.
|
||||
*
|
||||
* \param name Process-specific name of the resource
|
||||
* \param id Resource ID as returned by \ref Scheduler::registerResource()
|
||||
* \sa WorkProcessor::getResource
|
||||
*/
|
||||
virtual void bindResource(const std::string &name, int id);
|
||||
|
||||
/**
|
||||
* Is this process local, i.e. not distributed to remote
|
||||
* processing nodes? The default implementation returs false.
|
||||
* \brief Is this process strictly local?
|
||||
*
|
||||
* If a process is marked as local, it shouldn't be distributed
|
||||
* to remote processing nodes? The default implementation
|
||||
* returns false.
|
||||
*/
|
||||
virtual bool isLocal() const;
|
||||
|
||||
/**
|
||||
* Return the log level for events associated with this process.
|
||||
* \brief Return the log level for events associated with this process.
|
||||
*
|
||||
* By default, this is set to EDebug
|
||||
*/
|
||||
inline ELogLevel getLogLevel() const { return m_logLevel; }
|
||||
|
||||
/**
|
||||
* Return a list of the bound resources
|
||||
* \brief Return a list of all bound resources
|
||||
*/
|
||||
inline const ResourceBindings &getResourceBindings() const { return m_bindings; }
|
||||
|
||||
/**
|
||||
* Return a list of plugins required by this parallel process.
|
||||
* The default implementation just returns all plugins that are
|
||||
* loaded in the current application image.
|
||||
* \brief Return a list of plugins required by this parallel process.
|
||||
*
|
||||
* This is required so that remote machines can load the plugins before
|
||||
* they accept work from this process. The default implementation just
|
||||
* returns all plugins that are loaded in the current application.
|
||||
*/
|
||||
virtual std::vector<std::string> getRequiredPlugins();
|
||||
|
||||
|
@ -274,35 +304,40 @@ protected:
|
|||
class Worker;
|
||||
|
||||
/**
|
||||
* Centralized task scheduler implementation. Accepts parallelizable
|
||||
* jobs and distributes their computational load both locally and remotely.
|
||||
* This is done by associating different types of <tt>Worker</tt>s 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.
|
||||
* \brief Centralized task scheduler implementation.
|
||||
*
|
||||
* Accepts parallelizable jobs and distributes their computational load
|
||||
* both locally and remotely. This is done by associating different types
|
||||
* of <tt>\ref Worker</tt>s 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.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Scheduler : public Object {
|
||||
friend class Worker;
|
||||
public:
|
||||
/**
|
||||
* Schedule a parallelizable process for execution. If the
|
||||
* scheduler is currently running and idle, its execution
|
||||
* will begin immediately. Returns false if the process
|
||||
* is already scheduled and has not yet terminated.
|
||||
* \brief Schedule a parallelizable process for execution.
|
||||
*
|
||||
* If the scheduler is currently running and idle, its execution
|
||||
* will begin immediately. Returns \a false if the process
|
||||
* is already scheduled and has not yet terminated and \a true
|
||||
* in any other case.
|
||||
*/
|
||||
bool schedule(ParallelProcess *process);
|
||||
|
||||
/**
|
||||
* Block until the process has successfully been completed
|
||||
* or canceled prematurely. Returns false if the process
|
||||
* does not exist or has already finished by the time
|
||||
* <tt>wait()</tt> is invoked.
|
||||
* \brief Block until the process has successfully been completed
|
||||
* or canceled prematurely.
|
||||
*
|
||||
* Returns false if the process does not exist or has already
|
||||
* finished by the time <tt>\ref wait()</tt> is invoked.
|
||||
*/
|
||||
bool wait(const ParallelProcess *process);
|
||||
|
||||
/**
|
||||
* Cancel the execution of a parallelizable process. Upon
|
||||
* return, no more work from this process is running.
|
||||
* \brief Cancel the execution of a parallelizable process.
|
||||
*
|
||||
* Upon return, no more work from this process is running.
|
||||
* Returns false if the process does not exist (anymore).
|
||||
*/
|
||||
inline bool cancel(ParallelProcess *proc) {
|
||||
|
@ -310,41 +345,49 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Register a serializable resource with the scheduler. This should be
|
||||
* thought of as a constant state that is shared amongst all processing
|
||||
* nodes. Resources can be reused by subsequent parallel processes, and
|
||||
* consequently do not have to be re-transmitted over the network. Returns
|
||||
* a resource ID, which can be used to reference the associated data.
|
||||
* \brief Register a serializable resource with the scheduler.
|
||||
*
|
||||
* A resource should be thought of as a constant state that is shared
|
||||
* amongst all processing nodes. Resources can be reused by
|
||||
* subsequent parallel processes, and consequently do not have to be
|
||||
* re-transmitted over the network. Returns a resource ID, which can be
|
||||
* used to reference the associated data.
|
||||
*/
|
||||
int registerResource(SerializableObject *resource);
|
||||
|
||||
/**
|
||||
* Register a 'manifold' resource with the scheduler. 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.
|
||||
* <tt>resources</tt> must be a vector whose length is equal
|
||||
* to <tt>getCoreCount()</tt>.
|
||||
* \brief Register a \a manifold resource with the scheduler.
|
||||
*
|
||||
* \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. <tt>resources</tt> must be a vector whose
|
||||
* length is equal to <tt>\ref getCoreCount()</tt>.
|
||||
*/
|
||||
int registerManifoldResource(std::vector<SerializableObject *> &resources);
|
||||
|
||||
/**
|
||||
* Increase the reference count of a previously registered resource.
|
||||
* \brief Increase the reference count of a previously registered resource.
|
||||
*
|
||||
* The resource must be unregistered an additional time after calling
|
||||
* this function.
|
||||
*
|
||||
* \sa unregisterResource
|
||||
*/
|
||||
void retainResource(int resourceID);
|
||||
|
||||
/**
|
||||
* Unregister a resource from the scheduler (takes the previously
|
||||
* created ID). Note that the resource's won't be removed
|
||||
* until all processes using it have terminated)
|
||||
* \brief Unregister a resource from the scheduler
|
||||
*
|
||||
* Note that the resource's won't be removed until all processes using
|
||||
* it have terminated)
|
||||
*/
|
||||
void unregisterResource(int id);
|
||||
|
||||
/**
|
||||
* Return the ID of a registered resource. Throws an exception
|
||||
* if the resource cannot be found.
|
||||
* \brief Return the ID of a registered resource
|
||||
*
|
||||
* Throws an exception if the resource cannot be found.
|
||||
*/
|
||||
int getResourceID(const SerializableObject *resource) const;
|
||||
|
||||
|
@ -364,15 +407,15 @@ public:
|
|||
void start();
|
||||
|
||||
/**
|
||||
* Puase the distribution of work units and shut down all running workers.
|
||||
* Any currently scheduled work units are still completed. Processing can
|
||||
* be resumed via <tt>start()</tt>.
|
||||
* \brief Pause the distribution of work units and shut down all
|
||||
* running workers.
|
||||
*
|
||||
* Any currently scheduled work units are still completed.
|
||||
* Processing can be resumed via <tt>\ref start()</tt>.
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Cancel all running processes and free memory used by resources
|
||||
*/
|
||||
|
||||
/// Cancel all running processes and free memory used by resources
|
||||
void stop();
|
||||
|
||||
/// Return the total number of cores exposed through this scheduler
|
||||
|
@ -401,6 +444,8 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
public:
|
||||
// Public, but shouldn't be part of the documentation
|
||||
/// \cond
|
||||
struct ProcessRecord {
|
||||
/* Unique ID value assigned to this process */
|
||||
int id;
|
||||
|
@ -476,6 +521,8 @@ public:
|
|||
/// The scheduler is shutting down
|
||||
EStop
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
/// Look up a resource by ID & core index
|
||||
SerializableObject *getResource(int id, int coreIndex = -1);
|
||||
|
||||
|
@ -483,13 +530,14 @@ public:
|
|||
const MemoryStream *getResourceStream(int id);
|
||||
|
||||
/**
|
||||
* Test whether a resource is marked as manifold,
|
||||
* i.e. different for every core
|
||||
* \brief Test whether a resource is marked as manifold,
|
||||
* i.e. different for every core.
|
||||
*/
|
||||
bool isManifoldResource(int id) const;
|
||||
protected:
|
||||
/// Protected constructor
|
||||
Scheduler();
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~Scheduler();
|
||||
|
||||
|
@ -519,7 +567,7 @@ protected:
|
|||
signalProcessTermination(item.proc, item.rec);
|
||||
m_mutex->unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cancel the execution of a parallelizable process. Upon
|
||||
* return, no more work from this process is running. When
|
||||
|
@ -583,7 +631,7 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* Base class of all worker implementations
|
||||
* \brief Base class of all worker implementations
|
||||
*/
|
||||
class MTS_EXPORT_CORE Worker : public Thread {
|
||||
friend class Scheduler;
|
||||
|
@ -609,20 +657,22 @@ protected:
|
|||
int workerIndex, int coreOffset);
|
||||
|
||||
/**
|
||||
* Called to inform a worker that a resource is no longer in use. The
|
||||
* remote worker uses this to notify the machine on the other end that
|
||||
* \brief Called to inform a worker that a resource is no longer in use.
|
||||
*
|
||||
* The remote worker uses this to notify the machine on the other end that
|
||||
* the memory used by this resource can now be released.
|
||||
*/
|
||||
virtual void signalResourceExpiration(int id) = 0;
|
||||
|
||||
/**
|
||||
* Called to inform a worker that a process has been cancelled
|
||||
* \brief Called to inform a worker that a process has been cancelled
|
||||
*
|
||||
* Guaranteed to be called while the Scheduler's main lock is held.
|
||||
*/
|
||||
virtual void signalProcessCancellation(int id) = 0;
|
||||
|
||||
/**
|
||||
* Called to inform a worker that a process has successfully been
|
||||
* \brief Called to inform a worker that a process has successfully been
|
||||
* completed and any associated resources can be freed.
|
||||
*/
|
||||
virtual void signalProcessTermination(int id) = 0;
|
||||
|
@ -663,7 +713,7 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Local worker thread. Acquires work from the scheduler and executes
|
||||
* \brief Acquires work from the scheduler and executes
|
||||
* it locally.
|
||||
*/
|
||||
class MTS_EXPORT_CORE LocalWorker : public Worker {
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
|
||||
#include <mitsuba/core/sched.h>
|
||||
|
||||
/* How many work units should be sent to a remote worker
|
||||
/** How many work units should be sent to a remote worker
|
||||
at a time? This is a multiple of the worker's core count */
|
||||
#define BACKLOG_FACTOR 3
|
||||
|
||||
/* Once the back log factor drops below this value (also a
|
||||
/** Once the back log factor drops below this value (also a
|
||||
multiple of the core size), the stream processor will
|
||||
continue sending batches of work units */
|
||||
#define CONTINUE_FACTOR 2
|
||||
|
@ -34,16 +34,18 @@ MTS_NAMESPACE_BEGIN
|
|||
|
||||
class RemoteWorkerReader;
|
||||
class StreamBackend;
|
||||
class FileResolver;
|
||||
|
||||
/**
|
||||
* Remote worker thread. Acquires work from the scheduler and forwards
|
||||
* it to a processing node reachable over some form of stream (usually
|
||||
* a <tt>SocketStream</tt>).
|
||||
* \brief Acquires work from the scheduler and forwards
|
||||
* it to a processing node reachable through a \ref Stream.
|
||||
*/
|
||||
class MTS_EXPORT_CORE RemoteWorker : public Worker {
|
||||
friend class RemoteWorkerReader;
|
||||
public:
|
||||
/**
|
||||
* \brief Construct a new remote worker with the given name and
|
||||
* communication stream
|
||||
*/
|
||||
RemoteWorker(const std::string &name, Stream *stream);
|
||||
|
||||
/// Return the name of the node on the other side
|
||||
|
@ -85,8 +87,9 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Remote worker helper thread - constantly waits for finished
|
||||
* work units sent by the processing node.
|
||||
* \brief Communication helper thread required by \ref RemoteWorker.
|
||||
*
|
||||
* Constantly waits for finished work units sent by the processing node.
|
||||
*/
|
||||
class MTS_EXPORT_CORE RemoteWorkerReader : public Thread {
|
||||
friend class RemoteWorker;
|
||||
|
@ -111,11 +114,19 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* 'Fake' parallel process used to insert work units from a
|
||||
* \brief Parallel process facade used to insert work units from a
|
||||
* remote scheduler into the local one.
|
||||
*/
|
||||
class MTS_EXPORT_CORE RemoteProcess : public ParallelProcess {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a new remote process
|
||||
*
|
||||
* \param id Identification number for this process
|
||||
* \param logLevel Log level for events associated with this process
|
||||
* \param backend The responsible server-side communication backend
|
||||
* \param proc Work processor instance for use with this process
|
||||
*/
|
||||
RemoteProcess(int id, ELogLevel logLevel,
|
||||
StreamBackend *backend, WorkProcessor *proc);
|
||||
|
||||
|
@ -126,6 +137,7 @@ public:
|
|||
ref<WorkProcessor> createWorkProcessor() const;
|
||||
void handleCancellation();
|
||||
|
||||
/// Get an empty work unit from the process (or create one)
|
||||
inline WorkUnit *getEmptyWorkUnit() {
|
||||
ref<WorkUnit> wu;
|
||||
m_mutex->lock();
|
||||
|
@ -140,12 +152,14 @@ public:
|
|||
return wu;
|
||||
}
|
||||
|
||||
/// Make a full work unit available to the process
|
||||
inline void putFullWorkUnit(WorkUnit *wu) {
|
||||
m_mutex->lock();
|
||||
m_full.push_back(wu);
|
||||
m_mutex->unlock();
|
||||
}
|
||||
|
||||
/// Mark the process as finished
|
||||
inline void setDone() {
|
||||
m_mutex->lock();
|
||||
m_done = true;
|
||||
|
@ -167,9 +181,10 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* Stream backend - attaches to the end of a stream, accepts work units
|
||||
* and forwards them to the local scheduler. Can be used to create
|
||||
* remote processing nodes.
|
||||
* \brief Network processing communication backend
|
||||
*
|
||||
* Attaches to the end of a stream, accepts work units and forwards
|
||||
* them to the local scheduler. Can be used to create network processing nodes.
|
||||
*/
|
||||
class MTS_EXPORT_CORE StreamBackend : public Thread {
|
||||
friend class RemoteProcess;
|
||||
|
@ -193,7 +208,7 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* Create a new stream backend
|
||||
* \brief Create a new stream backend
|
||||
*
|
||||
* @param name
|
||||
* Name of the created thread
|
||||
|
@ -224,7 +239,6 @@ private:
|
|||
std::map<int, RemoteProcess *> m_processes;
|
||||
std::map<int, int> m_resources;
|
||||
ref<Mutex> m_sendMutex;
|
||||
ref<FileResolver> m_resolver;
|
||||
bool m_detach;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Serializable interface
|
||||
/** \brief Abstract interface implemented by all serializable classes
|
||||
*/
|
||||
class MTS_EXPORT_CORE Serializable {
|
||||
public:
|
||||
|
@ -34,43 +34,49 @@ protected:
|
|||
virtual ~Serializable() { }
|
||||
};
|
||||
|
||||
/** \brief Base class of all reference-counted objects with serialization support.
|
||||
/** \brief Base class of all reference-counted objects with serialization support
|
||||
*
|
||||
* To support unserialization from a stream, the implementation should use one of the
|
||||
* RTTI macros "MTS_IMPLEMENT_CLASS_*S".
|
||||
* RTTI macros \ref MTS_IMPLEMENT_CLASS_S or \ref MTS_IMPLEMENT_CLASS_IS.
|
||||
*/
|
||||
class MTS_EXPORT_CORE SerializableObject : public Object, public Serializable {
|
||||
public:
|
||||
inline SerializableObject() { }
|
||||
|
||||
/// Unserialize a serializable object
|
||||
SerializableObject(Stream *stream, InstanceManager *manager);
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// Construct a serializable object
|
||||
inline SerializableObject() { }
|
||||
|
||||
/// Virtual deconstructor
|
||||
virtual ~SerializableObject() { }
|
||||
};
|
||||
|
||||
/** \brief The instance manager coordinates the serialization/
|
||||
* unserialization process when link structures are encountered
|
||||
* in which an object is referenced by multiple other objects
|
||||
* within the same data stream. Cyclic dependencies can also
|
||||
* be handled.
|
||||
/** \brief Coordinates the serialization and unserialization of object graphs
|
||||
*
|
||||
* When serializaing a complicated object graph to a binary data stream,
|
||||
* the instance manager annotates the data stream to avoid serializing
|
||||
* objects twice or becoming stuck in a cyclic dependency. This allows
|
||||
* arbitrary connected graphs to be serialized.
|
||||
*
|
||||
* Similarly when unserializing a stream, it ensures that the resulting
|
||||
* object graph has the same structure.
|
||||
*/
|
||||
class MTS_EXPORT_CORE InstanceManager : public Object {
|
||||
friend class SerializableObject;
|
||||
public:
|
||||
/** \brief Construct a new instance manager */
|
||||
/// \brief Construct a new instance manager
|
||||
InstanceManager();
|
||||
|
||||
/// Retrieve/load an instance by ID
|
||||
/// Retrieve an instance from the given stream
|
||||
SerializableObject *getInstance(Stream *stream);
|
||||
|
||||
/// Store/skip an instance returning its ID
|
||||
/// Store an instance to the given stream
|
||||
void serialize(Stream *stream, const SerializableObject *inst);
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
private:
|
||||
/// Virtual destructor
|
||||
virtual ~InstanceManager();
|
||||
|
||||
|
|
|
@ -32,10 +32,13 @@ namespace ublas = boost::numeric::ublas;
|
|||
|
||||
struct SHVector;
|
||||
|
||||
/* Stores the diagonal blocks of a spherical harmonic rotation matrix */
|
||||
/**
|
||||
* \brief Stores the diagonal blocks of a spherical harmonic rotation matrix
|
||||
*/
|
||||
struct MTS_EXPORT_CORE SHRotation {
|
||||
std::vector<ublas::matrix<Float> > blocks;
|
||||
|
||||
/// Construct a new rotation storage for the given number of bands
|
||||
inline SHRotation(int bands) : blocks(bands) {
|
||||
for (int i=0; i<bands; ++i) {
|
||||
int dim = 2*i+1;
|
||||
|
@ -44,26 +47,31 @@ struct MTS_EXPORT_CORE SHRotation {
|
|||
}
|
||||
|
||||
/**
|
||||
* Transform a coefficient vector and store the result into
|
||||
* the given target vector. The source and target must have
|
||||
* the same number of bands.
|
||||
* \brief Transform a coefficient vector and store the result into
|
||||
* the given target vector.
|
||||
*
|
||||
* The source and target must have the same number of bands.
|
||||
*/
|
||||
void operator()(const SHVector &source, SHVector &target) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores a truncated real spherical harmonics representation of
|
||||
* an L2-integrable function. Also provides some other useful
|
||||
* functionality, such as evaluation, projection and rotation.
|
||||
* \brief Stores a truncated real spherical harmonics representation of
|
||||
* an L2-integrable function.
|
||||
*
|
||||
* Also provides some other useful functionality, such as evaluation,
|
||||
* projection and rotation.
|
||||
*
|
||||
* The Mathematica equivalent of the basis functions implemented here is:
|
||||
*
|
||||
* <pre>
|
||||
* 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}
|
||||
* }]
|
||||
* </pre>
|
||||
*/
|
||||
struct MTS_EXPORT_CORE SHVector {
|
||||
public:
|
||||
|
@ -169,18 +177,20 @@ public:
|
|||
/// Evaluate for a direction given in spherical coordinates
|
||||
Float eval(Float theta, Float phi) const;
|
||||
|
||||
/// Evaluate for a direction given in cartesian coordinates
|
||||
/// Evaluate for a direction given in Cartesian coordinates
|
||||
Float eval(const Vector &v) const;
|
||||
|
||||
/**
|
||||
* Evaluate for a direction given in spherical coordinates.
|
||||
* \brief Evaluate for a direction given in spherical coordinates.
|
||||
*
|
||||
* This function is much faster but only works for azimuthally
|
||||
* invariant functions
|
||||
*/
|
||||
Float evalAzimuthallyInvariant(Float theta, Float phi) const;
|
||||
|
||||
/**
|
||||
* Evaluate for a direction given in cartesian coordinates.
|
||||
* \brief Evaluate for a direction given in cartesian coordinates.
|
||||
*
|
||||
* This function is much faster but only works for azimuthally
|
||||
* invariant functions
|
||||
*/
|
||||
|
@ -194,7 +204,7 @@ public:
|
|||
|
||||
/// Dot product
|
||||
inline friend Float dot(const SHVector &v1, const SHVector &v2) {
|
||||
const int size = std::min(v1.m_coeffs.size(), v2.m_coeffs.size());
|
||||
const size_t size = std::min(v1.m_coeffs.size(), v2.m_coeffs.size());
|
||||
return std::inner_product(
|
||||
v1.m_coeffs.begin(), v1.m_coeffs.begin() + size,
|
||||
v2.m_coeffs.begin(), Float()
|
||||
|
@ -214,8 +224,10 @@ public:
|
|||
void offset(Float value);
|
||||
|
||||
/**
|
||||
* Convolve the SH representation with the supplied kernel,
|
||||
* which must be rotationally symmetric around the Z-axis.
|
||||
* \brief Convolve the SH representation with the supplied kernel.
|
||||
*
|
||||
* Based on the Funk-Hecke theorem -- the kernel must be rotationally
|
||||
* symmetric around the Z-axis.
|
||||
*/
|
||||
void convolve(const SHVector &kernel);
|
||||
|
||||
|
@ -303,7 +315,7 @@ public:
|
|||
return error/denom;
|
||||
}
|
||||
|
||||
/* Evaluate an associated Legendre polynomial using the usual recurrence formulae */
|
||||
/// Evaluate an associated Legendre polynomial using the usual recurrence formulae
|
||||
static Float legendre(int l, int m, Float x);
|
||||
|
||||
/// Return a normalization coefficient
|
||||
|
@ -315,8 +327,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Recursively computes rotation matrices for each band of SH coefficients. Based on
|
||||
* 'Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion'
|
||||
* \brief Recursively computes rotation matrices for each band of SH coefficients.
|
||||
*
|
||||
* Based on 'Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion'
|
||||
* by Ivanic and Ruedenberg. The implemented tables follow the notation in
|
||||
* 'Spherical Harmonic Lighting: The Gritty Details' by Robin Green.
|
||||
*/
|
||||
|
@ -340,22 +353,23 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* Implementation of 'Importance Sampling Spherical Harmonics'
|
||||
* \brief Implementation of 'Importance Sampling Spherical Harmonics'
|
||||
* by W. Jarsz, N. Carr and H. W. Jensen (EUROGRAPHICS 2009)
|
||||
*/
|
||||
class MTS_EXPORT_CORE SHSampler : public Object {
|
||||
public:
|
||||
/**
|
||||
* Create a spherical harmonics sampler object for the
|
||||
* specified amount of SH coefficient bands. The 'depth'
|
||||
* parameter specifies the number of recursive sample
|
||||
* warping steps.
|
||||
* \brief Precompute a spherical harmonics sampler object
|
||||
*
|
||||
* \param bands Number of SH coefficient bands to support
|
||||
* \param depth Number of recursive sample warping steps.
|
||||
*/
|
||||
SHSampler(int bands, int depth);
|
||||
|
||||
/**
|
||||
* Warp a uniform sample in [0,1]^2 to one that is
|
||||
* \brief Warp a uniform sample in [0,1]^2 to one that is
|
||||
* approximately proportional to the specified function.
|
||||
*
|
||||
* The resulting sample will have spherical coordinates
|
||||
* [0,pi]x[0,2pi] and its actual PDF (which might be
|
||||
* slightly different from the function evaluated at the
|
||||
|
@ -370,7 +384,7 @@ public:
|
|||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~SHSampler();
|
||||
|
||||
|
||||
/* Index into the assoc. legendre polynomial table */
|
||||
inline int I(int l, int m) const { return l*(l+1)/2 + m; }
|
||||
|
||||
|
@ -381,11 +395,11 @@ protected:
|
|||
return -m_phiMap[depth][phiBlock][P(m)] * m_legendreMap[depth][zBlock][I(l, std::abs(m))];
|
||||
}
|
||||
|
||||
/* Recursively compute assoc. legendre & phi integrals */
|
||||
/// Recursively compute assoc. legendre & phi integrals
|
||||
Float *legendreIntegrals(Float a, Float b);
|
||||
Float *phiIntegrals(Float a, Float b);
|
||||
|
||||
/* Integrate a SH expansion over the specified mip-map region */
|
||||
/// Integrate a SH expansion over the specified mip-map region
|
||||
Float integrate(int depth, int zBlock, int phiBlock, const SHVector &f) const;
|
||||
protected:
|
||||
int m_bands;
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Stores a 4D function f(wi, wo) (such as a BRDF or phase function)
|
||||
* using a 2D table of spherical harmonics expansions. Discretizaiton
|
||||
* occurs in the 'wi' space. Later lookups interpolate amongst
|
||||
* the 4 adjacent samples
|
||||
* \brief Stores a 4D function f(wi, wo) (such as a BRDF or phase function)
|
||||
* using a 2D table of spherical harmonics expansions.
|
||||
*
|
||||
* Discretizaiton occurs in the 'wi' space. Lookups interpolate amongst
|
||||
* the 4 adjacent samples.
|
||||
*/
|
||||
struct SHVector4D {
|
||||
public:
|
||||
|
|
|
@ -30,49 +30,53 @@ MTS_NAMESPACE_BEGIN
|
|||
|
||||
/**
|
||||
* \brief Abstract smooth spectral power distribution data type,
|
||||
* which supports sampling at arbitrary wavelengths
|
||||
* which supports evaluation at arbitrary wavelengths
|
||||
*/
|
||||
class MTS_EXPORT_CORE SmoothSpectrum {
|
||||
public:
|
||||
/**
|
||||
* Return the value of the spectral power distribution
|
||||
* for the given wavelength.
|
||||
* Evaluate the value of the spectral power distribution
|
||||
* at the given wavelength.
|
||||
*/
|
||||
virtual Float sample(Float lambda) const = 0;
|
||||
virtual Float eval(Float lambda) const = 0;
|
||||
|
||||
virtual ~SmoothSpectrum() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* This class uses Plank's black body law to compute the
|
||||
* spectral power distribution of a black body with the
|
||||
* given temperature.
|
||||
* \brief Spectral power distribution based on Planck's black body law
|
||||
*
|
||||
* Computes the spectral power distribution of a black body of the
|
||||
* specified temperature.
|
||||
*/
|
||||
class MTS_EXPORT_CORE BlackBodySpectrum : public SmoothSpectrum {
|
||||
public:
|
||||
/**
|
||||
* Construct a new black body spectrum given the emitter's
|
||||
* temperature in kelvin.
|
||||
* \brief Construct a new black body spectrum given the emitter's
|
||||
* temperature in Kelvin.
|
||||
*/
|
||||
inline BlackBodySpectrum(Float temperature) {
|
||||
m_temperature = temperature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the spectral power distribution
|
||||
* for the given wavelength.
|
||||
virtual ~BlackBodySpectrum() { }
|
||||
|
||||
/** \brief Return the value of the spectral power distribution
|
||||
* at the given wavelength.
|
||||
*/
|
||||
virtual Float sample(Float lambda) const;
|
||||
virtual Float eval(Float lambda) const;
|
||||
private:
|
||||
Float m_temperature;
|
||||
};
|
||||
|
||||
/**
|
||||
* Linearly interpolated spectral power distribution
|
||||
* \brief Linearly interpolated spectral power distribution
|
||||
*/
|
||||
class MTS_EXPORT_CORE InterpolatedSpectrum : public SmoothSpectrum {
|
||||
public:
|
||||
/**
|
||||
* Construct a new black body spectrum given the emitter's
|
||||
* temperature in kelvin.
|
||||
* \brief Create a new interpolated spectrum with space
|
||||
* for the specified number of samples
|
||||
*/
|
||||
inline InterpolatedSpectrum(size_t size = 0) {
|
||||
m_wavelength.reserve(size);
|
||||
|
@ -80,49 +84,56 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Append an entry to the spectral power distribution. Entries
|
||||
* must be added in order of increasing wavelength
|
||||
* \brief Append an entry to the spectral power distribution.
|
||||
*
|
||||
* Entries must be added in order of increasing wavelength
|
||||
*/
|
||||
void appendSample(Float lambda, Float value);
|
||||
|
||||
/**
|
||||
* Return the value of the spectral power distribution
|
||||
* for the given wavelength.
|
||||
* \brief Return the value of the spectral power distribution
|
||||
* at the given wavelength.
|
||||
*/
|
||||
virtual Float sample(Float lambda) const;
|
||||
virtual Float eval(Float lambda) const;
|
||||
|
||||
virtual ~InterpolatedSpectrum() { }
|
||||
private:
|
||||
std::vector<Float> m_wavelength, m_value;
|
||||
};
|
||||
|
||||
/** \brief Spectral power distribution data type
|
||||
* using a fixed number of wavelength samples. When
|
||||
* SPECTRUM_SAMPLES is set to 3, the class falls back
|
||||
* to linear RGB.
|
||||
/** \brief Discrete spectral power distribution
|
||||
* based on a (usually small) number of wavelength samples.
|
||||
*
|
||||
* When SPECTRUM_SAMPLES is set to 3 (the default), this class
|
||||
* falls back to linear RGB as its internal representation.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Spectrum {
|
||||
struct MTS_EXPORT_CORE Spectrum {
|
||||
public:
|
||||
/// Set all samples to the given value
|
||||
inline Spectrum(Float v = 0.0f) {
|
||||
/// Create a new spectral power distribution, but don't initialize the contents
|
||||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
inline Spectrum() { }
|
||||
#else
|
||||
inline Spectrum() {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] = std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// Create a new spectral power distribution with all samples set to the given value
|
||||
explicit inline Spectrum(Float v) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] = v;
|
||||
}
|
||||
|
||||
/// Initialize with spectral values from a smooth spectrum
|
||||
Spectrum(const SmoothSpectrum *smooth);
|
||||
|
||||
/// Convert from RGBE
|
||||
inline Spectrum(const uint8_t rgbe[4]) {
|
||||
fromRGBE(rgbe);
|
||||
}
|
||||
|
||||
/// Copy a spectrum
|
||||
inline Spectrum(Float spd[SPECTRUM_SAMPLES]) {
|
||||
/// Copy a spectral power distribution
|
||||
explicit inline Spectrum(Float spd[SPECTRUM_SAMPLES]) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] = spd[i];
|
||||
}
|
||||
|
||||
/// Unserialize a spectrum
|
||||
inline Spectrum(Stream *stream) {
|
||||
/// Unserialize a spectral power distribution from a binary data stream
|
||||
explicit inline Spectrum(Stream *stream) {
|
||||
stream->readFloatArray(s, SPECTRUM_SAMPLES);
|
||||
}
|
||||
|
||||
|
@ -134,7 +145,7 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
/// Add two spectral power distributions
|
||||
/// Add a spectral power distribution to this instance
|
||||
inline Spectrum& operator+=(const Spectrum &spd) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] += spd.s[i];
|
||||
|
@ -149,14 +160,14 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
/// Subtract a spectral power distribution
|
||||
/// Subtract a spectral power distribution from this instance
|
||||
inline Spectrum& operator-=(const Spectrum &spd) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] -= spd.s[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Multiplication with a scalar
|
||||
/// Multiply by a scalar
|
||||
inline Spectrum operator*(Float f) const {
|
||||
Spectrum value = *this;
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
|
@ -164,19 +175,19 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
/// Multiplication with a scalar
|
||||
/// Multiply by a scalar
|
||||
inline friend Spectrum operator*(Float f, Spectrum &spd) {
|
||||
return spd * f;
|
||||
}
|
||||
|
||||
/// Multiplication with a scalar
|
||||
/// Multiply by a scalar
|
||||
inline Spectrum& operator*=(Float f) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Multiplication with another spectrum
|
||||
/// Perform a component-wise multiplication by another spectrum
|
||||
inline Spectrum operator*(const Spectrum &spd) const {
|
||||
Spectrum value = *this;
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
|
@ -184,21 +195,29 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
/// Multiplication with another spectrum
|
||||
/// Perform a component-wise multiplication by another spectrum
|
||||
inline Spectrum& operator*=(const Spectrum &spd) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] *= spd.s[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Component-wise division by another spectrum
|
||||
/// Perform a component-wise division by another spectrum
|
||||
inline Spectrum& operator/=(const Spectrum &spd) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] /= spd.s[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Perform a component-wise division by another spectrum
|
||||
inline Spectrum operator/(Spectrum spd) const {
|
||||
Spectrum value = *this;
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
value.s[i] /= spd.s[i];
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Division by a scalar
|
||||
/// Divide by a scalar
|
||||
inline Spectrum operator/(Float f) const {
|
||||
Spectrum value = *this;
|
||||
#ifdef MTS_DEBUG
|
||||
|
@ -213,15 +232,7 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
/// Component-wise division by another spectrum
|
||||
inline Spectrum operator/(Spectrum spd) const {
|
||||
Spectrum value = *this;
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
value.s[i] /= spd.s[i];
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Component-wise comparison against another spectrum
|
||||
/// Equality test
|
||||
inline bool operator==(Spectrum spd) const {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++) {
|
||||
if (s[i] != spd.s[i])
|
||||
|
@ -230,17 +241,17 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Component-wise comparison against another spectrum
|
||||
/// Inequality test
|
||||
inline bool operator!=(Spectrum spd) const {
|
||||
return !operator==(spd);
|
||||
}
|
||||
|
||||
/// Division by a scalar
|
||||
/// Divide by a scalar
|
||||
inline friend Spectrum operator/(Float f, Spectrum &spd) {
|
||||
return spd / f;
|
||||
}
|
||||
|
||||
/// Division by a scalar
|
||||
/// Divide by a scalar
|
||||
inline Spectrum& operator/=(Float f) {
|
||||
#ifdef MTS_DEBUG
|
||||
if (f == 0) {
|
||||
|
@ -262,7 +273,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Returns whether the spectrum only contains valid non-negative samples
|
||||
/// Returns whether the spectrum only contains valid (non-NaN, nonnegative) samples
|
||||
inline bool isValid() const {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
if (ubi_isnan(s[i]) || s[i] < 0.0f)
|
||||
|
@ -270,7 +281,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Multiply-accumulate operation
|
||||
/// Multiply-accumulate operation, adds \a weight * \a spd
|
||||
inline void addWeighted(Float weight, const Spectrum &spd) {
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; i++)
|
||||
s[i] += weight * spd.s[i];
|
||||
|
@ -352,10 +363,10 @@ public:
|
|||
bool isBlack() const;
|
||||
|
||||
/**
|
||||
* Sample the SPD at an arbitrary wavelength
|
||||
* \brief Evaluate the SPD at an arbitrary wavelength
|
||||
* (uses interpolation)
|
||||
*/
|
||||
Float sample(Float lambda) const;
|
||||
Float eval(Float lambda) const;
|
||||
|
||||
/// Return the luminance in candelas.
|
||||
#if SPECTRUM_SAMPLES == 3
|
||||
|
@ -400,14 +411,15 @@ public:
|
|||
/// Convert from sRGB
|
||||
void fromSRGB(Float r, Float g, Float b);
|
||||
|
||||
/** Linear RGBE conversion based on Bruce Walter's and Greg Ward's code
|
||||
-> http://www.graphics.cornell.edu/online/formats/rgbe/rgbe.c */
|
||||
/// Linear RGBE conversion based on Bruce Walter's and Greg Ward's code
|
||||
void fromRGBE(const uint8_t rgbe[4]);
|
||||
|
||||
/** Linear RGBE conversion based on Bruce Walter's and Greg Ward's code
|
||||
-> http://www.graphics.cornell.edu/online/formats/rgbe/rgbe.c */
|
||||
/// Linear RGBE conversion based on Bruce Walter's and Greg Ward's code
|
||||
void toRGBE(uint8_t rgbe[4]) const;
|
||||
|
||||
/// Initialize with spectral values from a smooth spectrum representation
|
||||
void fromSmoothSpectrum(const SmoothSpectrum *smooth);
|
||||
|
||||
/// Serialize this spectrum to a stream
|
||||
inline void serialize(Stream *stream) const {
|
||||
stream->writeFloatArray(s, SPECTRUM_SAMPLES);
|
||||
|
@ -434,12 +446,16 @@ protected:
|
|||
/// Configured wavelengths in nanometers
|
||||
static Float m_wavelengths[SPECTRUM_SAMPLES];
|
||||
|
||||
/// Normalization factors for XYZ<->RGB conversion
|
||||
/// Normalization factor for XYZ<->RGB conversion
|
||||
static Float m_normalization;
|
||||
|
||||
/// Inverse of \ref m_normalization
|
||||
static Float m_invNormalization;
|
||||
|
||||
/* CIE 1931 XYZ color matching functions from
|
||||
http://www.cvrl.org/database/data/cmfs/ciexyz31_1.txt */
|
||||
/**
|
||||
* @{ \name CIE 1931 XYZ color matching functions.
|
||||
* From http://www.cvrl.org/database/data/cmfs/ciexyz31_1.txt
|
||||
*/
|
||||
static const int CIE_start = 360;
|
||||
static const int CIE_end = 830;
|
||||
static const int CIE_count = CIE_end - CIE_start + 1;
|
||||
|
@ -447,6 +463,7 @@ protected:
|
|||
static const Float CIE_X[CIE_count];
|
||||
static const Float CIE_Y[CIE_count];
|
||||
static const Float CIE_Z[CIE_count];
|
||||
/// @}
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -94,7 +94,10 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/* SSE 4-vector and handy aliases */
|
||||
/**
|
||||
* \headerfile mitsuba/core/sse.h mitsuba/mitsuba.h
|
||||
* \brief SSE 4-vector and useful aliases
|
||||
*/
|
||||
union SSEVector {
|
||||
__m128 ps;
|
||||
__m128i pi;
|
||||
|
@ -124,7 +127,10 @@ union SSEVector {
|
|||
}
|
||||
};
|
||||
|
||||
/** Some useful constant values for use with SSE */
|
||||
/**
|
||||
* \brief Some useful constant values for use with SSE
|
||||
* \headerfile mitsuba/core/sse.h mitsuba/mitsuba.h
|
||||
*/
|
||||
class MTS_EXPORT_CORE SSEConstants {
|
||||
public:
|
||||
/// (0, 0, 0, 0)
|
||||
|
@ -192,6 +198,10 @@ __declspec(naked) static FINLINE unsigned __int64 __cdecl rdtsc(void) {
|
|||
ret
|
||||
}
|
||||
}
|
||||
#else
|
||||
static FINLINE __int64 rdtsc(void) {
|
||||
return __rdtsc();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,12 +24,13 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
/** \brief SSH stream implementation - remotely runs a program
|
||||
* and exposes its stdin/stdout streams through an instance of
|
||||
* <tt>Stream</tt>. To make this work, passwordless authentication
|
||||
* must be enabled (for example by using public key authentication
|
||||
* in addition to a running ssh-agent which stores the decrypted
|
||||
* private key).
|
||||
/** \brief Stream implementation based on an encrypted SSH tunnel
|
||||
*
|
||||
* This class remotely starts a program and exposes its stdin/stdout
|
||||
* streams through an instance of <tt>\ref Stream</tt>. To make all
|
||||
* of this work, passwordless authentication must be enabled (for
|
||||
* example by using public key authentication in addition to a
|
||||
* running ssh-agent, which stores the decrypted private key).
|
||||
*
|
||||
* On Windows, things are implemented a bit differently: Instead
|
||||
* of OpenSSH, plink.exe (from PUTTY) is used and must be available
|
||||
|
@ -46,6 +47,12 @@ public:
|
|||
* the maximum amount of time that can be spent before failing to
|
||||
* create the initial connection. This feature is unsupported
|
||||
* (and ignored) on Windows.
|
||||
*
|
||||
* \param userName Username to use for the authentication
|
||||
* \param hostName Destination host name
|
||||
* \param cmdLine Command (with arguments) to be executed on the remote side
|
||||
* \param port Destination port
|
||||
* \param timeout Maximum time to use for the connection attempt (in seconds)
|
||||
*/
|
||||
SSHStream(const std::string &userName,
|
||||
const std::string &hostName,
|
||||
|
@ -87,7 +94,7 @@ protected:
|
|||
* the socket if it is still open
|
||||
*/
|
||||
virtual ~SSHStream();
|
||||
protected:
|
||||
private:
|
||||
std::string m_userName, m_hostName;
|
||||
int m_port, m_timeout;
|
||||
size_t m_received, m_sent;
|
||||
|
|
|
@ -30,25 +30,34 @@ MTS_NAMESPACE_BEGIN
|
|||
/// Size of the console-based progress message
|
||||
#define PROGRESS_MSG_SIZE 56
|
||||
|
||||
/// Specifies the number of internal counters associated with each statistics counter
|
||||
/// Needed for SMP/ccNUMA systems where different processors might be
|
||||
/// contending for a cache line containing a counter. The solution used here
|
||||
/// tries to ensure that every processor has its own local counter.
|
||||
/**
|
||||
* Specifies the number of internal counters associated with each
|
||||
* statistics counter. Needed for SMP/ccNUMA systems where different
|
||||
* processors might be contending for a cache line containing a counter.
|
||||
* The solution used here tries to ensure that every processor has
|
||||
* its own local counter.
|
||||
*/
|
||||
|
||||
#define NUM_COUNTERS 128 // Must be a power of 2
|
||||
#define NUM_COUNTERS_MASK (NUM_COUNTERS-1)
|
||||
|
||||
/* Determines the multiples (e.g. 1000, 1024) and units */
|
||||
/// Determines the multiples (e.g. 1000, 1024) and units
|
||||
enum EStatsType {
|
||||
ENumberValue,
|
||||
EByteCount,
|
||||
EPercentage
|
||||
ENumberValue = 0, ///< Simple unitless number, e.g. # of rays
|
||||
EByteCount, ///< Number of read/written/transferred bytes
|
||||
EPercentage ///< Percentage with respect to a base counter
|
||||
};
|
||||
|
||||
struct CacheLineCounter { // Counter in 128 bytes - avoid false sharing
|
||||
/**
|
||||
* \brief Counter data structure, which is suitable for ccNUMA/SMP machines
|
||||
*
|
||||
* This counter takes up at least one cache line
|
||||
* to reduce false sharing.
|
||||
*/
|
||||
struct CacheLineCounter {
|
||||
#if (defined(WIN32) && !defined(WIN64)) || (defined(__POWERPC__) && !defined(_LP64))
|
||||
// WIN32 & Darwin (PPC/32) doesn't support atomic 64 bit increment operations
|
||||
// -> restrict counters to 32bit
|
||||
// -> restrict counters to 32bit :(
|
||||
uint32_t value;
|
||||
uint32_t unused2;
|
||||
#else
|
||||
|
@ -58,12 +67,27 @@ struct CacheLineCounter { // Counter in 128 bytes - avoid false sharing
|
|||
};
|
||||
|
||||
/** \brief General-purpose statistics counter
|
||||
*
|
||||
* This class implements a simple counter, which can be used to track various
|
||||
* quantities within Mitsuba. At various points during the execution, it is
|
||||
* possible to then call \ref Statistics::printStats() to get a human-readable
|
||||
* report of their values.
|
||||
*/
|
||||
class MTS_EXPORT_CORE StatsCounter {
|
||||
public:
|
||||
/// Create a new statistics counter and associate it with a category:name pair
|
||||
/**
|
||||
* \brief Create a new statistics counter
|
||||
*
|
||||
* \param category Category of the counter when shown in the statistics summary
|
||||
* \param name Name of the counter when shown in the statistics summary
|
||||
* \param type Characterization of the quantity that will be measured
|
||||
* \param initial Initial value of the counter
|
||||
* \param base Initial value of the base counter (only for <tt>type == EPercentage</tt>)
|
||||
*/
|
||||
StatsCounter(const std::string &category, const std::string &name,
|
||||
EStatsType type = ENumberValue, uint64_t initial = 0L, uint64_t base = 0L);
|
||||
|
||||
/// Free all storage used by the counter
|
||||
~StatsCounter();
|
||||
|
||||
/// Increment the counter value by one
|
||||
|
@ -91,7 +115,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
/// Increment the counter amount by the specified amount
|
||||
/// Increment the counter by the specified amount
|
||||
#ifdef MTS_NO_STATISTICS
|
||||
inline void operator+=(size_t amount) { }
|
||||
#elif defined(WIN64)
|
||||
|
@ -108,7 +132,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
/// Increment the base amount by the specified amount (only for use with EPercentage)
|
||||
/// Increment the base counter by the specified amount (only for use with EPercentage)
|
||||
#ifdef MTS_NO_STATISTICS
|
||||
inline void incrementBase(size_t amount = 1) { }
|
||||
#elif defined(WIN64)
|
||||
|
@ -158,8 +182,6 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
/// Set the reference number (only used with the EPercentage counter type)
|
||||
|
||||
/// Sorting by name (for the statistics)
|
||||
bool operator<(const StatsCounter &v) const;
|
||||
private:
|
||||
|
@ -200,7 +222,7 @@ public:
|
|||
|
||||
/// Check whether progress bars are enabled
|
||||
static inline bool isEnabled() { return m_enabled; }
|
||||
protected:
|
||||
private:
|
||||
/// Convert a time value to a human-readable format
|
||||
void printTime(Float time, std::ostream &os) const;
|
||||
private:
|
||||
|
@ -247,7 +269,7 @@ protected:
|
|||
Statistics();
|
||||
/// Virtual destructor
|
||||
virtual ~Statistics() { }
|
||||
|
||||
private:
|
||||
struct compareCategory {
|
||||
bool operator()(const StatsCounter *c1, const StatsCounter *c2) {
|
||||
if (c1->getCategory() == c2->getCategory())
|
||||
|
@ -255,7 +277,7 @@ protected:
|
|||
return c1->getCategory() < c2->getCategory();
|
||||
}
|
||||
};
|
||||
private:
|
||||
|
||||
static ref<Statistics> m_instance;
|
||||
std::vector<const StatsCounter *> m_counters;
|
||||
std::vector<std::pair<std::string, std::string> > m_plugins;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#ifndef __MITSUBA_STL_H
|
||||
#define __MITSUBA_STL_H
|
||||
|
||||
|
||||
/* Include some SGI STL extensions, which might be missing */
|
||||
#ifdef __GNUC__
|
||||
#include <ext/functional>
|
||||
|
@ -26,7 +26,10 @@ using __gnu_cxx::select2nd;
|
|||
using __gnu_cxx::compose1;
|
||||
#else
|
||||
#include <functional>
|
||||
|
||||
namespace std {
|
||||
/// \cond
|
||||
// (Don't include in the documentation)
|
||||
template <class _Pair> struct _Select1st : public unary_function<_Pair, typename _Pair::first_type> {
|
||||
const typename _Pair::first_type& operator()(const _Pair& __x) const {
|
||||
return __x.first;
|
||||
|
@ -56,10 +59,9 @@ namespace std {
|
|||
template <class _Operation1, class _Operation2> inline unary_compose<_Operation1,_Operation2> compose1(const _Operation1& __fn1, const _Operation2& __fn2) {
|
||||
return unary_compose<_Operation1,_Operation2>(__fn1, __fn2);
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#define snprintf _snprintf
|
||||
|
@ -93,62 +95,69 @@ using std::compose1;
|
|||
MTS_NAMESPACE_BEGIN
|
||||
extern MTS_EXPORT_CORE void * __restrict allocAligned(size_t size);
|
||||
extern MTS_EXPORT_CORE void freeAligned(void *ptr);
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
namespace std {
|
||||
template <typename T> class aligned_allocator {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
/**
|
||||
* \brief Aligned memory allocator for use with SSE2-based code
|
||||
* \headerfile mitsuba/core/stl.h mitsuba/mitsuba.h
|
||||
*
|
||||
* Basic implementaiton, which forwards all calls to \ref allocAligned.
|
||||
*/
|
||||
template <typename T> class aligned_allocator {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind {
|
||||
typedef aligned_allocator<U> other;
|
||||
};
|
||||
|
||||
pointer address (reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
const_pointer address (const_reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
aligned_allocator() throw() { }
|
||||
|
||||
aligned_allocator(const aligned_allocator&) throw() { }
|
||||
|
||||
template <class U> aligned_allocator (const aligned_allocator<U>&) throw() { }
|
||||
|
||||
~aligned_allocator() throw() { }
|
||||
|
||||
size_type max_size () const throw() {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
||||
T* __restrict allocate (size_type num, const_pointer *hint = 0) {
|
||||
return (T *) mitsuba::allocAligned(num*sizeof(T));
|
||||
}
|
||||
|
||||
void construct (pointer p, const T& value) {
|
||||
*p=value;
|
||||
}
|
||||
|
||||
void destroy (pointer p) {
|
||||
p->~T();
|
||||
};
|
||||
|
||||
void deallocate (pointer p, size_type num) {
|
||||
freeAligned(p);
|
||||
}
|
||||
/// \cond
|
||||
template <class U> struct rebind {
|
||||
typedef aligned_allocator<U> other;
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
pointer address (reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
const_pointer address (const_reference value) const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
aligned_allocator() throw() { }
|
||||
|
||||
aligned_allocator(const aligned_allocator&) throw() { }
|
||||
|
||||
template <class U> aligned_allocator (const aligned_allocator<U>&) throw() { }
|
||||
|
||||
~aligned_allocator() throw() { }
|
||||
|
||||
size_type max_size () const throw() {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
||||
T* __restrict allocate (size_type num, const_pointer *hint = 0) {
|
||||
return (T *) mitsuba::allocAligned(num*sizeof(T));
|
||||
}
|
||||
|
||||
void construct (pointer p, const T& value) {
|
||||
*p=value;
|
||||
}
|
||||
|
||||
void destroy (pointer p) {
|
||||
p->~T();
|
||||
};
|
||||
|
||||
void deallocate (pointer p, size_type num) {
|
||||
freeAligned(p);
|
||||
}
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#if defined(WIN32)
|
||||
inline bool ubi_isnan(float f) {
|
||||
int classification = ::_fpclass(f);
|
||||
|
@ -159,6 +168,10 @@ inline bool ubi_isnan(double f) {
|
|||
int classification = ::_fpclass(f);
|
||||
return classification == _FPCLASS_QNAN || classification == _FPCLASS_SNAN;
|
||||
}
|
||||
extern "C" {
|
||||
extern MTS_EXPORT_CORE float nextafterf(float x, float y);
|
||||
};
|
||||
|
||||
#else
|
||||
inline bool ubi_isnan(float f) {
|
||||
return std::fpclassify(f) == FP_NAN;
|
||||
|
|
|
@ -23,34 +23,55 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Abstract seekable stream class which defines
|
||||
* all functions to be implemented by stream subclasses,
|
||||
* such as <tt>FileStream</tt>, <tt>MemoryStream</tt>,
|
||||
* <tt>SocketStream</tt>, <tt>ConsoleStream</tt> or
|
||||
* <tt>SSHStream</tt>.
|
||||
/** \brief Abstract seekable stream class
|
||||
*
|
||||
* Also supports platform-independent reads and writes
|
||||
* (automatic endianness conversion).
|
||||
* Specifies all functions to be implemented by stream
|
||||
* subclasses and provides various convenience functions
|
||||
* based on them.
|
||||
*
|
||||
* All read<b>X</b>() and write<b>X</b>() methods support transparent
|
||||
* endianness conversion based on the endianness of the underlying
|
||||
* system and the value passed to \ref setByteOrder().
|
||||
*
|
||||
* \sa FileStream, MemoryStream, SocketStream,
|
||||
* ConsoleStream, SSHStream, ZStream
|
||||
*/
|
||||
class MTS_EXPORT_CORE Stream : public Object {
|
||||
public:
|
||||
/// Defines the byte order to use in this Stream
|
||||
enum EByteOrder {
|
||||
/// PowerPC, SPARC, Motorola 68K
|
||||
EBigEndian = 0,
|
||||
/// x86
|
||||
ELittleEndian = 1,
|
||||
/// Network byte order
|
||||
ENetworkByteOrder = EBigEndian
|
||||
EBigEndian = 0, ///< PowerPC, SPARC, Motorola 68K
|
||||
ELittleEndian = 1, ///< x86, x86_64
|
||||
ENetworkByteOrder = EBigEndian ///< Network byte order (an alias for big endian)
|
||||
};
|
||||
|
||||
/// Create a new stream
|
||||
/**
|
||||
* \brief Create a new stream.
|
||||
*
|
||||
* By default, it assumes the byte order of the
|
||||
* underlying system, i.e. no endianness conversion
|
||||
* is performed.
|
||||
*/
|
||||
Stream();
|
||||
|
||||
/// Set the stream byte order
|
||||
void setByteOrder(EByteOrder byteOrder);
|
||||
|
||||
/// Read data from the stream
|
||||
/// Return the byte order of this stream
|
||||
inline EByteOrder getByteOrder() const { return m_byteOrder; }
|
||||
|
||||
/// Return the byte order of the underlying machine
|
||||
inline EByteOrder getHostByteOrder() { return m_hostByteOrder; }
|
||||
|
||||
/// Return a string representation
|
||||
virtual std::string toString() const;
|
||||
|
||||
/// @{ \name Abstract methods to be implemented by subclasses
|
||||
|
||||
/// Read a specified amount of data from the stream
|
||||
virtual void read(void *ptr, size_t size) = 0;
|
||||
|
||||
/// Write data into the stream
|
||||
/// Write a specified amount of data into the stream
|
||||
virtual void write(const void *ptr, size_t size) = 0;
|
||||
|
||||
/// Seek to a position inside the stream
|
||||
|
@ -62,7 +83,7 @@ public:
|
|||
/// Get the current position inside the stream
|
||||
virtual size_t getPos() const = 0;
|
||||
|
||||
/// Return the current size of the stream
|
||||
/// Return the size of the stream
|
||||
virtual size_t getSize() const = 0;
|
||||
|
||||
/// Flush the stream's buffers
|
||||
|
@ -74,6 +95,10 @@ public:
|
|||
/// Can we read from the stream?
|
||||
virtual bool canRead() const = 0;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @{ \name Convenience functions
|
||||
|
||||
/// Skip the given number of bytes
|
||||
void skip(size_t amount);
|
||||
|
||||
|
@ -123,32 +148,32 @@ public:
|
|||
inline void writeBool(bool value) { writeUChar(value); }
|
||||
|
||||
/// Write a single-precision floating point number (32 bit) to the stream
|
||||
void writeSingle(float pFloat);
|
||||
void writeSingle(float value);
|
||||
|
||||
/// Write a single-precision floating point array (32 bit) to the stream
|
||||
void writeSingleArray(const float *pFloat, size_t size);
|
||||
void writeSingleArray(const float *data, size_t size);
|
||||
|
||||
/// Write a double-precision floating point number (64 bit) to the stream
|
||||
void writeDouble(double pDouble);
|
||||
void writeDouble(double value);
|
||||
|
||||
/// Write a double-precision floating point array (64 bit) to the stream
|
||||
void writeDoubleArray(const double *pDouble, size_t size);
|
||||
void writeDoubleArray(const double *data, size_t size);
|
||||
|
||||
/// Write a floating point number (configured precision) to the stream
|
||||
inline void writeFloat(Float pFloat) {
|
||||
inline void writeFloat(Float value) {
|
||||
#ifdef SINGLE_PRECISION
|
||||
writeSingle(pFloat);
|
||||
writeSingle(value);
|
||||
#else
|
||||
writeDouble(pFloat);
|
||||
writeDouble(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Write an array of floating point values (configured precision) to the stream
|
||||
inline void writeFloatArray(const Float *pFloat, size_t size) {
|
||||
inline void writeFloatArray(const Float *data, size_t size) {
|
||||
#ifdef SINGLE_PRECISION
|
||||
writeSingleArray(pFloat, size);
|
||||
writeSingleArray(data, size);
|
||||
#else
|
||||
writeDoubleArray(pFloat, size);
|
||||
writeDoubleArray(data, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -204,13 +229,13 @@ public:
|
|||
float readSingle();
|
||||
|
||||
/// Read a double-precision floating point array (64 bit) from the stream
|
||||
void readSingleArray(float *pDouble, size_t size);
|
||||
void readSingleArray(float *data, size_t size);
|
||||
|
||||
/// Read a double-precision floating point number (64 bit) from the stream
|
||||
double readDouble();
|
||||
|
||||
/// Read a double-precision floating point array (64 bit) from the stream
|
||||
void readDoubleArray(double *pDouble, size_t size);
|
||||
void readDoubleArray(double *data, size_t size);
|
||||
|
||||
/// Write a floating point number (configured precision) to the stream
|
||||
inline Float readFloat() {
|
||||
|
@ -222,33 +247,30 @@ public:
|
|||
}
|
||||
|
||||
/// Write an array of floating point values (configured precision) to the stream
|
||||
inline void readFloatArray(Float *pFloat, size_t size) {
|
||||
inline void readFloatArray(Float *data, size_t size) {
|
||||
#ifdef SINGLE_PRECISION
|
||||
readSingleArray(pFloat, size);
|
||||
readSingleArray(data, size);
|
||||
#else
|
||||
readDoubleArray(pFloat, size);
|
||||
readDoubleArray(data, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy content from this stream into another stream
|
||||
* @param numBytes
|
||||
* \brief Copy content from this stream into another stream
|
||||
* \param stream Destination stream
|
||||
* \param numBytes
|
||||
* The number of bytes to copy. When -1 is specified,
|
||||
* copying proceeds until the end of the source stream.
|
||||
*/
|
||||
void copyTo(Stream *stream, int64_t numBytes = -1);
|
||||
|
||||
/// Return a string representation
|
||||
virtual std::string toString() const;
|
||||
/// Read an element from the stream (uses partial template specialization)
|
||||
template <typename T> T readElement();
|
||||
|
||||
/// Set the stream byte order
|
||||
void setByteOrder(EByteOrder byteOrder);
|
||||
/// Write an element to the stream (uses partial template specialization)
|
||||
template <typename T> void writeElement(T value);
|
||||
|
||||
/// Return the stream byte order
|
||||
inline EByteOrder getByteOrder() const { return m_byteOrder; }
|
||||
|
||||
/// Return the host byte order
|
||||
inline EByteOrder getHostByteOrder() { return m_hostByteOrder; }
|
||||
/// @}
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
|
@ -259,6 +281,43 @@ private:
|
|||
EByteOrder m_byteOrder;
|
||||
};
|
||||
|
||||
|
||||
template <typename T> inline T Stream::readElement() {
|
||||
Log(EError, "Stream::readElement<T>: not implemented!");
|
||||
}
|
||||
|
||||
template <typename T> inline void Stream::writeElement(T value) {
|
||||
Log(EError, "Stream::writeElement<T>: not implemented!");
|
||||
}
|
||||
|
||||
/// \cond
|
||||
template <> inline float Stream::readElement() { return readSingle(); }
|
||||
template <> inline double Stream::readElement() { return readDouble(); }
|
||||
template <> inline char Stream::readElement() { return readChar(); }
|
||||
template <> inline unsigned char Stream::readElement() { return readUChar(); }
|
||||
template <> inline bool Stream::readElement() { return readBool(); }
|
||||
template <> inline int16_t Stream::readElement() { return readShort(); }
|
||||
template <> inline uint16_t Stream::readElement() { return readUShort(); }
|
||||
template <> inline int32_t Stream::readElement() { return readInt(); }
|
||||
template <> inline uint32_t Stream::readElement() { return readUInt(); }
|
||||
template <> inline int64_t Stream::readElement() { return readLong(); }
|
||||
template <> inline uint64_t Stream::readElement() { return readULong(); }
|
||||
template <> inline std::string Stream::readElement() { return readString(); }
|
||||
|
||||
template <> inline void Stream::writeElement(float val) { return writeSingle(val); }
|
||||
template <> inline void Stream::writeElement(double val) { return writeDouble(val); }
|
||||
template <> inline void Stream::writeElement(char val) { return writeChar(val); }
|
||||
template <> inline void Stream::writeElement(unsigned char val) { return writeUChar(val); }
|
||||
template <> inline void Stream::writeElement(bool val) { return writeBool(val); }
|
||||
template <> inline void Stream::writeElement(int16_t val) { return writeShort(val); }
|
||||
template <> inline void Stream::writeElement(uint16_t val) { return writeUShort(val); }
|
||||
template <> inline void Stream::writeElement(int32_t val) { return writeInt(val); }
|
||||
template <> inline void Stream::writeElement(uint32_t val) { return writeUInt(val); }
|
||||
template <> inline void Stream::writeElement(int64_t val) { return writeLong(val); }
|
||||
template <> inline void Stream::writeElement(uint64_t val) { return writeULong(val); }
|
||||
template <> inline void Stream::writeElement(const std::string &val) { return writeString(val); }
|
||||
/// \endcond
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __STREAM_H */
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \headerfile mitsuba/core/thread.h mitsuba/mitsuba.h
|
||||
* \brief Cross-platform thread implementation
|
||||
*/
|
||||
class MTS_EXPORT_CORE Thread : public Object {
|
||||
public:
|
||||
/// Available thread priorities
|
||||
/// Possible priority values for \ref Thread::setPriority()
|
||||
enum EThreadPriority {
|
||||
EIdlePriority = 0,
|
||||
ELowestPriority,
|
||||
|
@ -36,17 +40,32 @@ public:
|
|||
ERealtimePriority
|
||||
};
|
||||
|
||||
/// Create a new thread object
|
||||
/**
|
||||
* \brief Create a new thread object
|
||||
* \param name An identifying name of this thread
|
||||
* (will be shown in debug messages)
|
||||
* \param stackSize Initial stack size of the thread
|
||||
* (0 = default)
|
||||
*/
|
||||
Thread(const std::string &name,
|
||||
unsigned int stackSize = 0);
|
||||
|
||||
/// Set the thread priority
|
||||
void setPriority(EThreadPriority priority);
|
||||
/**
|
||||
* \brief Set the thread priority
|
||||
*
|
||||
* This does not always work -- for instance, Linux
|
||||
* requires root privileges for this operation.
|
||||
*
|
||||
* \return \a true upon success.
|
||||
*/
|
||||
bool setPriority(EThreadPriority priority);
|
||||
|
||||
/**
|
||||
* Set the critical flag. When an thread marked critical crashes
|
||||
* from an uncaught exception, the whole process is terminated
|
||||
* (default: false).
|
||||
* \brief Specify whether or not this thread is critical
|
||||
*
|
||||
* When an thread marked critical crashes from an uncaught
|
||||
* exception, the whole process is brought down.
|
||||
* The default is \a false.
|
||||
*/
|
||||
inline void setCritical(bool critical) { m_critical = critical; }
|
||||
|
||||
|
@ -59,7 +78,7 @@ public:
|
|||
/// Return the thread's stack size
|
||||
inline int getStackSize() const { return m_stackSize; }
|
||||
|
||||
/// Return the thread's ID
|
||||
/// Return the thread ID
|
||||
#if defined(__OSX__)
|
||||
inline static int getID() { return getThread()->m_id; }
|
||||
#elif defined(WIN32)
|
||||
|
@ -68,24 +87,30 @@ public:
|
|||
inline static int getID() { return m_id; }
|
||||
#endif
|
||||
|
||||
/// Return the thread's name
|
||||
/// Return the name of this thread
|
||||
inline const std::string &getName() const { return m_name; }
|
||||
|
||||
/// Set the thread's name
|
||||
/// Set the name of this thread
|
||||
inline void setName(const std::string &name) { m_name = name; }
|
||||
|
||||
/// Return the parent thread
|
||||
inline Thread *getParent() { return m_parent; }
|
||||
|
||||
/// Return the parent thread
|
||||
/// Return the parent thread (const version)
|
||||
inline const Thread *getParent() const { return m_parent.get(); }
|
||||
|
||||
/// Set the thread's logger
|
||||
/// Set the logger instance used to process log messages from this thread
|
||||
inline void setLogger(Logger *logger) { m_logger = logger; }
|
||||
|
||||
/// Return the thread's logger
|
||||
/// Return the thread's logger instance
|
||||
inline Logger *getLogger() { return m_logger; }
|
||||
|
||||
/// Set the thread's file resolver
|
||||
inline void setFileResolver(FileResolver *fresolver) { m_fresolver = fresolver; }
|
||||
|
||||
/// Return the thread's file resolver
|
||||
inline FileResolver *getFileResolver() { return m_fresolver; }
|
||||
|
||||
/// Return the current thread
|
||||
inline static Thread *getThread() {
|
||||
return m_self->get();
|
||||
|
@ -98,9 +123,11 @@ public:
|
|||
void start();
|
||||
|
||||
/**
|
||||
* Detach the thread - after this, <tt>join()</tt>
|
||||
* cannot be used anymore. Releases resources,
|
||||
* would otherwise be held until a call to <tt>join().</tt>
|
||||
* \brief Detach the thread and release resources
|
||||
*
|
||||
* After a call to this function, \ref join()
|
||||
* cannot be used anymore. This releases resources, which
|
||||
* would otherwise be held until a call to \ref join().
|
||||
*/
|
||||
void detach();
|
||||
|
||||
|
@ -141,6 +168,7 @@ protected:
|
|||
private:
|
||||
ref<Thread> m_parent;
|
||||
ref<Logger> m_logger;
|
||||
ref<FileResolver> m_fresolver;
|
||||
ref<Mutex> m_joinMutex;
|
||||
std::string m_name;
|
||||
unsigned int m_stackSize;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#if !defined(__TIMER_H)
|
||||
#define __TIMER_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
|
|
@ -20,21 +20,41 @@
|
|||
#define __TLS_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/**
|
||||
* Thin wrapper around posix thread local storage
|
||||
* \headerfile mitsuba/core/tls.h mitsuba/mitsuba.h
|
||||
* \brief Thin wrapper around posix thread local storage.
|
||||
* Stores references to Object instances.
|
||||
*
|
||||
* This class implements a simple reference-counting thread-local
|
||||
* pointer storage.
|
||||
* \sa PrimitiveThreadLocal
|
||||
*/
|
||||
template <typename T> class ThreadLocal {
|
||||
public:
|
||||
/// Create a new (empty) thread-local reference
|
||||
inline ThreadLocal() {
|
||||
pthread_key_create(&m_key, ThreadLocal::deletePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroy the thread-local reference
|
||||
*
|
||||
* Beware: all threads that ever used this TLS (other than
|
||||
* the caller of the destructor) must either either died or
|
||||
* called \ref cleanup() prior to the destructor invocation --
|
||||
* otherwise, the reference counts will be incorrect and
|
||||
* memory leaks will ensue..
|
||||
*/
|
||||
inline ~ThreadLocal() {
|
||||
cleanup();
|
||||
pthread_key_delete(m_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Make the thread-local reference point to the given
|
||||
* instance and update the reference counts
|
||||
*/
|
||||
inline void set(T *value) {
|
||||
T *previous = get();
|
||||
if (previous != NULL)
|
||||
|
@ -44,41 +64,60 @@ public:
|
|||
pthread_setspecific(m_key, value);
|
||||
}
|
||||
|
||||
/// Return the currently stored reference
|
||||
inline T *get() {
|
||||
return static_cast<T *>(pthread_getspecific(m_key));
|
||||
}
|
||||
protected:
|
||||
|
||||
/// Return the currently stored reference (const version)
|
||||
inline const T *get() const {
|
||||
return static_cast<const T *>(pthread_getspecific(m_key));
|
||||
}
|
||||
|
||||
/// Set the reference to <tt>NULL</tt> and update the reference counts.
|
||||
void cleanup() {
|
||||
set(NULL);
|
||||
}
|
||||
private:
|
||||
static void deletePtr(void *ptr) {
|
||||
static_cast<T *>(ptr)->decRef();
|
||||
}
|
||||
protected:
|
||||
|
||||
pthread_key_t m_key;
|
||||
};
|
||||
|
||||
/**
|
||||
* As above, but meant for stack-allocated objects
|
||||
* \headerfile mitsuba/core/tls.h mitsuba/mitsuba.h
|
||||
* \brief Thin wrapper around posix thread local storage.
|
||||
* Stores heap-allocated data other than Object instances.
|
||||
* \sa ThreadLocal
|
||||
*/
|
||||
template <typename T> class PrimitiveThreadLocal {
|
||||
public:
|
||||
/// Create a new thread local storage object
|
||||
inline PrimitiveThreadLocal() {
|
||||
pthread_key_create(&m_key, PrimitiveThreadLocal::deletePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroy the thread local storage object
|
||||
*
|
||||
* Beware: all threads that ever used this TLS (other than
|
||||
* the caller) must either either died or called cleanup()
|
||||
* before this destructor is called -- otherwise memory leaks
|
||||
* will ensue.
|
||||
* the caller of the destructor) must either either died or
|
||||
* called \ref cleanup() prior to the destructor invocation --
|
||||
* otherwise, memory leaks will ensue..
|
||||
*/
|
||||
inline ~PrimitiveThreadLocal() {
|
||||
cleanup();
|
||||
pthread_key_delete(m_key);
|
||||
}
|
||||
|
||||
/// Update the data associated with the current thread
|
||||
inline void set(T &value) {
|
||||
get() = value;
|
||||
}
|
||||
|
||||
/// Return a reference to the data associated with the current thread
|
||||
inline T &get() {
|
||||
T *value = static_cast<T *>(pthread_getspecific(m_key));
|
||||
if (value == NULL) {
|
||||
|
@ -89,6 +128,10 @@ public:
|
|||
return *value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the data associated with the
|
||||
* current thread (const version)
|
||||
*/
|
||||
inline const T &get() const {
|
||||
T *value = static_cast<T *>(pthread_getspecific(m_key));
|
||||
if (value == NULL) {
|
||||
|
@ -99,19 +142,19 @@ public:
|
|||
return *value;
|
||||
}
|
||||
|
||||
/// Delete the data record associated with the current thread
|
||||
void cleanup() {
|
||||
T *value = static_cast<T *>(pthread_getspecific(m_key));
|
||||
if (value != NULL)
|
||||
delete value;
|
||||
pthread_setspecific(m_key, NULL);
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
static void deletePtr(void *ptr) {
|
||||
delete static_cast<T *>(ptr);
|
||||
}
|
||||
protected:
|
||||
|
||||
pthread_key_t m_key;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __TLS_H */
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#if !defined(__TRANSFORM_H)
|
||||
#define __TRANSFORM_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/ray.h>
|
||||
#include <mitsuba/core/normal.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -33,6 +33,9 @@ public:
|
|||
/// Initialize with the identity matrix
|
||||
Matrix4x4();
|
||||
|
||||
/// Initialize the matrix with constant entries
|
||||
Matrix4x4(Float value);
|
||||
|
||||
/// Unserialize a matrix from a stream
|
||||
Matrix4x4(Stream *stream);
|
||||
|
||||
|
@ -76,13 +79,10 @@ protected:
|
|||
virtual ~Matrix4x4() { }
|
||||
};
|
||||
|
||||
struct Frame;
|
||||
|
||||
/**
|
||||
* \brief Transform class encapsulating a linear affine
|
||||
* transformation (using homogenous coordinates) and its inverse
|
||||
* \brief Encapsulates a 4x4 linear transformation and its inverse
|
||||
*/
|
||||
class MTS_EXPORT_CORE Transform {
|
||||
struct MTS_EXPORT_CORE Transform {
|
||||
public:
|
||||
/// Create an identity transformation
|
||||
Transform();
|
||||
|
@ -231,6 +231,31 @@ public:
|
|||
dest.z = m_invTransform->m[0][2] * v.x + m_invTransform->m[1][2] * v.y
|
||||
+ m_invTransform->m[2][2] * v.z;
|
||||
}
|
||||
|
||||
/// 4D matrix-vector multiplication
|
||||
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;
|
||||
Float y = m_transform->m[1][0] * v.x + m_transform->m[1][1] * v.y
|
||||
+ m_transform->m[1][2] * v.z + m_transform->m[1][3] * v.w;
|
||||
Float z = m_transform->m[2][0] * v.x + m_transform->m[2][1] * v.y
|
||||
+ m_transform->m[2][2] * v.z + m_transform->m[2][3] * v.w;
|
||||
Float w = m_transform->m[3][0] * v.x + m_transform->m[3][1] * v.y
|
||||
+ m_transform->m[3][2] * v.z + m_transform->m[3][3] * v.w;
|
||||
return Vector4(x,y,z,w);
|
||||
}
|
||||
|
||||
/// 4D matrix-vector multiplication
|
||||
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;
|
||||
dest.y = m_transform->m[1][0] * v.x + m_transform->m[1][1] * v.y
|
||||
+ m_transform->m[1][2] * v.z + m_transform->m[1][3] * v.w;
|
||||
dest.z = m_transform->m[2][0] * v.x + m_transform->m[2][1] * v.y
|
||||
+ m_transform->m[2][2] * v.z + m_transform->m[2][3] * v.w;
|
||||
dest.w = m_transform->m[3][0] * v.x + m_transform->m[3][1] * v.y
|
||||
+ m_transform->m[3][2] * v.z + m_transform->m[3][3] * v.w;
|
||||
}
|
||||
|
||||
/// Transform a ray. Assumes that there is no scaling
|
||||
inline void operator()(const Ray &a, Ray &b) const {
|
||||
|
@ -264,47 +289,47 @@ public:
|
|||
|
||||
/** \brief Create a perspective transformation.
|
||||
* (Maps [near, far] to [0, 1])
|
||||
* @param fov Field of view in degrees
|
||||
* @param clipNear Near clipping plane
|
||||
* @param clipFar Far clipping plane
|
||||
* \param fov Field of view in degrees
|
||||
* \param clipNear Near clipping plane
|
||||
* \param clipFar Far clipping plane
|
||||
*/
|
||||
static Transform perspective(Float fov, Float clipNear, Float clipFar);
|
||||
|
||||
/** \brief Create a perspective transformation for OpenGL.
|
||||
* (Maps [near, far] to [-1, 1])
|
||||
* @param fov Field of view in degrees
|
||||
* @param clipNear Near clipping plane distance
|
||||
* @param clipFar Far clipping plane distance
|
||||
* \param fov Field of view in degrees
|
||||
* \param clipNear Near clipping plane distance
|
||||
* \param clipFar Far clipping plane distance
|
||||
*/
|
||||
static Transform glPerspective(Float fov, Float clipNear, Float clipFar);
|
||||
|
||||
/** \brief Create a perspective transformation for OpenGL.
|
||||
* @param left Left clipping plane coordinate
|
||||
* @param right Right clipping plane coordinate
|
||||
* @param top Top clipping plane coordinate
|
||||
* @param bottom Bottom clipping plane coordinate
|
||||
* @param clipNear Near clipping plane distance
|
||||
* @param clipFar Far clipping plane distance
|
||||
* \param left Left clipping plane coordinate
|
||||
* \param right Right clipping plane coordinate
|
||||
* \param top Top clipping plane coordinate
|
||||
* \param bottom Bottom clipping plane coordinate
|
||||
* \param nearVal Near clipping plane distance
|
||||
* \param farVal Far clipping plane distance
|
||||
*/
|
||||
static Transform glFrustum(Float left, Float right, Float bottom, Float top, Float nearVal, Float farVal);
|
||||
|
||||
/** \brief Create an orthographic transformation, which maps Z to [0,1]
|
||||
* and leaves the X and Y coordinates untouched.
|
||||
* @param clipNear Near clipping plane
|
||||
* @param clipFar Far clipping plane
|
||||
* \param clipNear Near clipping plane
|
||||
* \param clipFar Far clipping plane
|
||||
*/
|
||||
static Transform orthographic(Float clipNear, Float clipFar);
|
||||
|
||||
/** \brief Create an orthographic transformation for OpenGL
|
||||
* @param clipNear Near clipping plane
|
||||
* @param clipFar Far clipping plane
|
||||
* \param clipNear Near clipping plane
|
||||
* \param clipFar Far clipping plane
|
||||
*/
|
||||
static Transform glOrthographic(Float clipNear, Float clipFar);
|
||||
|
||||
/** \brief Create a look-at camera transformation
|
||||
* @param p Camera position
|
||||
* @param t Target vector
|
||||
* @param u Up vector
|
||||
* \param p Camera position
|
||||
* \param t Target vector
|
||||
* \param u Up vector
|
||||
*/
|
||||
static Transform lookAt(const Point &p, const Point &t, const Vector &u);
|
||||
|
||||
|
|
|
@ -24,67 +24,94 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Mesh vertex data structure. Stores 3D coordinates,
|
||||
* vertex normals, UV coordinates and a tangent frame
|
||||
*/
|
||||
struct Vertex {
|
||||
Point v;
|
||||
Normal n;
|
||||
Point2 uv;
|
||||
Vector dpdu, dpdv;
|
||||
|
||||
inline bool operator==(const Vertex &vert) const {
|
||||
return (v == vert.v && n == vert.n && uv == vert.uv
|
||||
&& dpdu == vert.dpdu && dpdv == vert.dpdv);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Vertex &vert) const {
|
||||
return !operator==(vert);
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Triangle class including a collection of routines
|
||||
* for analysis and transformation. Triangles are stored as
|
||||
* indices into a vertex array
|
||||
/**
|
||||
* \brief Simple triangle class including a collection of routines
|
||||
* for analysis and transformation.
|
||||
*
|
||||
* Triangles are stored as indices into a vertex array
|
||||
*/
|
||||
struct MTS_EXPORT_CORE Triangle {
|
||||
/* Indices into a vertex buffer */
|
||||
unsigned int idx[3];
|
||||
/// Indices into a vertex buffer
|
||||
uint32_t idx[3];
|
||||
|
||||
/// Construct an axis-aligned box, which contains the triangle
|
||||
AABB getAABB(const Vertex *buffer) const;
|
||||
inline AABB getAABB(const Point *positions) const {
|
||||
AABB result(positions[idx[0]]);
|
||||
result.expandBy(positions[idx[1]]);
|
||||
result.expandBy(positions[idx[2]]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis-aligned bounding box of a triangle after it has
|
||||
* clipped to the extends of another, given AABB. This function uses the
|
||||
* Sutherland-Hodgman algorithm to calculate the convex polygon, which
|
||||
* is created when applying all 6 AABB splitting planes to the triangle.
|
||||
* Afterwards, the AABB of the newly created convex polygon is returned.
|
||||
* This function is an important component for efficiently creating
|
||||
* 'Perfect Split' KD-trees. For more detail, see
|
||||
* "On building fast kd-Trees for Ray Tracing, and on doing
|
||||
* \brief Returns the axis-aligned bounding box of a triangle after it has
|
||||
* clipped to the extends of another, given AABB.
|
||||
*
|
||||
* This function uses the Sutherland-Hodgman algorithm to calculate the
|
||||
* convex polygon, which is created when applying all 6 AABB splitting
|
||||
* planes to the triangle. Afterwards, the AABB of the newly created
|
||||
* convex polygon is returned. This function is an important component
|
||||
* for efficiently creating 'Perfect Split' KD-trees. For more detail,
|
||||
* see "On building fast kd-Trees for Ray Tracing, and on doing
|
||||
* that in O(N log N)" by Ingo Wald and Vlastimil Havran
|
||||
*/
|
||||
AABB getClippedAABB(const Vertex *buffer, const AABB &aabb) const;
|
||||
AABB getClippedAABB(const Point *positions, const AABB &aabb) const;
|
||||
|
||||
/// Uniformly sample a point on the triangle and return its normal
|
||||
Point sample(const Point *positions, const Normal *normals,
|
||||
Normal &n, const Point2 &seed) const;
|
||||
|
||||
/// Calculate the surface area of this triangle
|
||||
Float surfaceArea(const Point *positions) const;
|
||||
|
||||
/** \brief Ray-triangle intersection test
|
||||
*
|
||||
* Uses the algorithm presented by Moeller and Trumbore at
|
||||
* http://www.acm.org/jgt/papers/MollerTrumbore97/code.html
|
||||
* Returns true if an intersection has been detected
|
||||
* On success, pT contains the distance from the ray origin to the
|
||||
* intersection point and pUV contains the intersection point in
|
||||
* On success, \a t contains the distance from the ray origin to the
|
||||
* intersection point, and \a u and \a v contain the intersection point in
|
||||
* the local triangle coordinate system
|
||||
*/
|
||||
bool rayIntersect(const Vertex *buffer, const Ray &ray, Float &u,
|
||||
Float &v, Float &t) const;
|
||||
FINLINE bool rayIntersect(const Point *positions, const Ray &ray, Float &u,
|
||||
Float &v, Float &t) const {
|
||||
const Point &v0 = positions[idx[0]];
|
||||
const Point &v1 = positions[idx[1]];
|
||||
const Point &v2 = positions[idx[2]];
|
||||
|
||||
/// Uniformly sample a point on the triangle and return its normal
|
||||
Point sample(const Vertex *buffer, Normal &n, const Point2 &seed) const;
|
||||
/* find vectors for two edges sharing v[0] */
|
||||
Vector edge1 = v1 - v0, edge2 = v2 - v0;
|
||||
|
||||
/// Calculate the surface area of this triangle
|
||||
Float surfaceArea(const Vertex *buffer) const;
|
||||
/* begin calculating determinant - also used to calculate U parameter */
|
||||
Vector pvec = cross(ray.d, edge2);
|
||||
|
||||
/* if determinant is near zero, ray lies in plane of triangle */
|
||||
Float det = dot(edge1, pvec);
|
||||
|
||||
if (det > -1e-8f && det < 1e-8f)
|
||||
return false;
|
||||
Float inv_det = 1.0f / det;
|
||||
|
||||
/* calculate distance from v[0] to ray origin */
|
||||
Vector tvec = ray.o - v0;
|
||||
|
||||
/* calculate U parameter and test bounds */
|
||||
u = dot(tvec, pvec) * inv_det;
|
||||
if (u < 0.0 || u > 1.0)
|
||||
return false;
|
||||
|
||||
/* prepare to test V parameter */
|
||||
Vector qvec = cross(tvec, edge1);
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
v = dot(ray.d, qvec) * inv_det;
|
||||
if (v < 0.0 || u + v > 1.0)
|
||||
return false;
|
||||
|
||||
/* ray intersects triangle -> compute t */
|
||||
t = dot(edge2, qvec) * inv_det;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
#if !defined(__UTIL_H)
|
||||
#define __UTIL_H
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Random;
|
||||
// -----------------------------------------------------------------------
|
||||
// Miscellaneous
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -45,21 +46,9 @@ extern MTS_EXPORT_CORE std::string indent(const std::string &string, int amount=
|
|||
/// Convert a time difference (in ms) to a string representation
|
||||
extern MTS_EXPORT_CORE std::string timeToString(Float time);
|
||||
|
||||
/// Convert a string to lower case
|
||||
extern MTS_EXPORT_CORE std::string toLowerCase(const std::string &string);
|
||||
|
||||
/// Convert a string to upper case
|
||||
extern MTS_EXPORT_CORE std::string toUpperCase(const std::string &string);
|
||||
|
||||
/// Trim spaces (' ', '\n', '\r', '\t') from the ends of a string
|
||||
/// Trim spaces (' ', '\\n', '\\r', '\\t') from the ends of a string
|
||||
extern MTS_EXPORT_CORE std::string trim(const std::string& str);
|
||||
|
||||
/// Determines whether a string starts with the string given as second parameter
|
||||
extern MTS_EXPORT_CORE bool startsWith(const std::string& str, const std::string& start);
|
||||
|
||||
/// Determines whether a string ends with the string given as second parameter
|
||||
extern MTS_EXPORT_CORE bool endsWith(const std::string& str, const std::string& end);
|
||||
|
||||
/// Allocate an aligned region of memory
|
||||
extern MTS_EXPORT_CORE void * __restrict allocAligned(size_t size);
|
||||
|
||||
|
@ -123,21 +112,23 @@ extern MTS_EXPORT_CORE bool solveLinearSystem2x2(const Float a[2][2], const Floa
|
|||
extern MTS_EXPORT_CORE void coordinateSystem(const Vector &a, Vector &b, Vector &c);
|
||||
|
||||
/**
|
||||
* \brief Generate optionally jittered, stratified 1D samples
|
||||
* @param dest A pointer to a floating point array with at least
|
||||
* \brief Generate (optionally jittered) stratified 1D samples
|
||||
* \param random Source of random numbers
|
||||
* \param dest A pointer to a floating point array with at least
|
||||
* count entries
|
||||
* @param count The interval [0, 1] is split into count strata
|
||||
* @param jitter Randomly jitter the samples?
|
||||
* \param count The interval [0, 1] is split into count strata
|
||||
* \param jitter Randomly jitter the samples?
|
||||
*/
|
||||
extern MTS_EXPORT_CORE void stratifiedSample1D(Random *random, Float *dest,
|
||||
int count, bool jitter);
|
||||
|
||||
/**
|
||||
* \brief Generate optionally jittered, stratified 2D samples
|
||||
* @param dest A pointer to a floating point array
|
||||
* @param countX The X axis interval [0, 1] is split into countX strata
|
||||
* @param countY The Y axis interval [0, 1] is split into countY strata
|
||||
* @param jitter Randomly jitter the samples?
|
||||
* \brief Generate (optionally jittered) stratified 2D samples
|
||||
* \param random Source of random numbers
|
||||
* \param dest A pointer to a floating point array
|
||||
* \param countX The X axis interval [0, 1] is split into countX strata
|
||||
* \param countY The Y axis interval [0, 1] is split into countY strata
|
||||
* \param jitter Randomly jitter the samples?
|
||||
*/
|
||||
extern MTS_EXPORT_CORE void stratifiedSample2D(Random *random, Point2 *dest,
|
||||
int countX, int countY, bool jitter);
|
||||
|
@ -175,12 +166,12 @@ extern MTS_EXPORT_CORE Point2 squareToTriangle(const Point2 &sample);
|
|||
|
||||
/// Convert radians to degrees
|
||||
inline Float radToDeg(Float rad) {
|
||||
return 180.0f*rad/M_PI;
|
||||
return 180.0f * rad / M_PI;
|
||||
}
|
||||
|
||||
/// Convert degrees to radians
|
||||
inline Float degToRad(Float deg) {
|
||||
return deg*M_PI/180.0f;
|
||||
return deg * M_PI / 180.0f;
|
||||
}
|
||||
|
||||
/// Simple floating point clamping function
|
||||
|
@ -205,13 +196,13 @@ inline int clamp(int value, int min, int max) {
|
|||
* Calculates the unpolarized fresnel reflection coefficient for a
|
||||
* dielectric material
|
||||
*
|
||||
* @param cosTheta1
|
||||
* \param cosTheta1
|
||||
* Cosine of the angle between the normal and the incident ray
|
||||
* @param cosTheta2
|
||||
* \param cosTheta2
|
||||
* Cosine of the angle between the normal and the transmitted ray
|
||||
* @param etaExt
|
||||
* \param etaExt
|
||||
* Refraction coefficient outside of the material
|
||||
* @param etaInt
|
||||
* \param etaInt
|
||||
* Refraction coefficient inside the material
|
||||
*/
|
||||
extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosTheta1, Float cosTheta2,
|
||||
|
@ -221,11 +212,11 @@ extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosTheta1, Float cosTheta2,
|
|||
* Calculates the unpolarized fresnel reflection coefficient for a
|
||||
* dielectric material. Handles incidence from either sides.
|
||||
*
|
||||
* @param cosTheta1
|
||||
* \param cosTheta1
|
||||
* Cosine of the angle between the normal and the incident ray
|
||||
* @param etaExt
|
||||
* \param etaExt
|
||||
* Refraction coefficient outside of the material
|
||||
* @param etaInt
|
||||
* \param etaInt
|
||||
* Refraction coefficient inside the material
|
||||
*/
|
||||
extern MTS_EXPORT_CORE Float fresnel(Float cosTheta1, Float etaExt, Float etaInt);
|
||||
|
@ -234,11 +225,11 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosTheta1, Float etaExt, Float etaInt
|
|||
* Calculates the unpolarized fresnel reflection coefficient on
|
||||
* an interface to a conductor.
|
||||
*
|
||||
* @param cosTheta
|
||||
* \param cosTheta
|
||||
* Cosine of the angle between the normal and the incident ray
|
||||
* @param eta
|
||||
* \param eta
|
||||
* Relative refractive index (per wavelength)
|
||||
* @param k
|
||||
* \param k
|
||||
* Absorption coefficient (per wavelength)
|
||||
*/
|
||||
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosTheta, const Spectrum &eta, const Spectrum &k);
|
||||
|
@ -259,9 +250,44 @@ extern MTS_EXPORT_CORE Float radicalInverse(int b, int i);
|
|||
*/
|
||||
extern MTS_EXPORT_CORE Float radicalInverseIncremental(int b, Float x);
|
||||
|
||||
/* Rational approximation to the inverse normal cumulative distribution function */
|
||||
/**
|
||||
* Rational approximation to the inverse normal
|
||||
* cumulative distribution function
|
||||
* Source: http://home.online.no/~pjacklam/notes/invnorm/impl/sprouse/ltqnorm.c
|
||||
* \author Peter J. Acklam
|
||||
*/
|
||||
extern MTS_EXPORT_CORE double normalQuantile(double p);
|
||||
|
||||
/// Cast between types, which have an identical binary representation.
|
||||
template<typename T, typename U> inline T union_cast(const U &val) {
|
||||
BOOST_STATIC_ASSERT(sizeof(T) == sizeof(U));
|
||||
|
||||
union {
|
||||
U u;
|
||||
T t;
|
||||
} caster = {val};
|
||||
|
||||
return caster.t;
|
||||
}
|
||||
|
||||
/// Return a string representation of a list of objects
|
||||
template<class T> std::string listToString(const std::vector<T> &vec) {
|
||||
std::ostringstream oss;
|
||||
oss << "{" << endl;
|
||||
for (size_t i=0; i<vec.size(); ++i) {
|
||||
oss << " " << indent(vec[i]->toString());
|
||||
if (i != vec.size()-1)
|
||||
oss << "," << endl;
|
||||
else
|
||||
oss << endl;
|
||||
}
|
||||
oss << "}";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/// Turn a memory size into a human-readable string
|
||||
extern MTS_EXPORT std::string memString(size_t size);
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@
|
|||
#define __WAVELET_H
|
||||
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/serialization.h>
|
||||
|
||||
//#define USE_GOOGLE_SPARSE_HASHMAP 1
|
||||
//#define USE_GOOGLE_DENSE_HASHMAP 1
|
||||
|
@ -37,19 +38,18 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class SparseWavelet2D;
|
||||
class SparseWaveletOctree;
|
||||
|
||||
/**
|
||||
* Non-standard 2D Haar wavelet transformation. Based on
|
||||
* "Wavelets for computer graphics: A primer, part 1" by
|
||||
* \brief Performs non-standard 2D Haar wavelet transformations.
|
||||
*
|
||||
* Based on "Wavelets for computer graphics: A primer, part 1" by
|
||||
* Eric J. Stollnitz, Tony D. DeRose, and David H. Salesin
|
||||
* (IEEE Computer Graphics and Applications, May 1995)
|
||||
*/
|
||||
class MTS_EXPORT_CORE Wavelet2D : public Object {
|
||||
public:
|
||||
/**
|
||||
* Create a wavelet representation from a given bitmap.
|
||||
* \brief Create a wavelet representation from a given bitmap.
|
||||
*
|
||||
* Only one color channel is supported for this encoding, so
|
||||
* the desired channel must be selected using the `colorChannel'
|
||||
* parameter.
|
||||
|
@ -60,7 +60,8 @@ public:
|
|||
Wavelet2D(const SparseWavelet2D *sw);
|
||||
|
||||
/**
|
||||
* Turn the wavelet representation back into an image.
|
||||
* \brief Turn the wavelet representation back into an image.
|
||||
*
|
||||
* Optionally, scale+offset factors can be supplied to
|
||||
* map the bitmap to a desired brightness
|
||||
*/
|
||||
|
@ -70,7 +71,7 @@ public:
|
|||
void discard(Float fraction);
|
||||
|
||||
/**
|
||||
* Discard components such that the relative L^2-error is below the
|
||||
* \brief Discard components such that the relative L^2-error is below the
|
||||
* given bound. Returns the achieved compression ratio.
|
||||
*/
|
||||
Float compress(Float maxError);
|
||||
|
@ -101,6 +102,7 @@ protected:
|
|||
/// Virtual destructor
|
||||
virtual ~Wavelet2D();
|
||||
protected:
|
||||
/// \cond
|
||||
struct coeff_t {
|
||||
inline coeff_t() { }
|
||||
inline coeff_t(size_t index, float value)
|
||||
|
@ -112,15 +114,16 @@ protected:
|
|||
size_t index;
|
||||
float value;
|
||||
};
|
||||
/// \endcond
|
||||
protected:
|
||||
float *m_data;
|
||||
float *m_temp;
|
||||
Vector2 m_range;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the non-standard 3D wavelet transform using Haar basis functions.
|
||||
* \brief Implements the non-standard 3D wavelet transform using
|
||||
* Haar basis functions.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Wavelet3D : public Object {
|
||||
public:
|
||||
|
@ -132,7 +135,7 @@ public:
|
|||
Wavelet3D(const float *data, size_t resolution);
|
||||
|
||||
/**
|
||||
* Turn the wavelet representation back into a dense format
|
||||
* \brief Turn the wavelet representation back into a dense format
|
||||
*/
|
||||
void decode(float *target);
|
||||
|
||||
|
@ -140,7 +143,7 @@ public:
|
|||
void discard(Float fraction);
|
||||
|
||||
/**
|
||||
* Discard components such that the relative L^2-error is below the
|
||||
* \brief Discard components such that the relative L^2-error is below the
|
||||
* given bound. Returns the achieved compression ratio.
|
||||
*/
|
||||
Float compress(Float maxRelError);
|
||||
|
@ -169,6 +172,7 @@ protected:
|
|||
/// Virtual destructor
|
||||
virtual ~Wavelet3D();
|
||||
protected:
|
||||
/// \cond
|
||||
struct coeff_t {
|
||||
inline coeff_t() { }
|
||||
inline coeff_t(size_t index, float value)
|
||||
|
@ -182,18 +186,19 @@ protected:
|
|||
size_t index;
|
||||
float value;
|
||||
};
|
||||
/// \endcond
|
||||
protected:
|
||||
float *m_data;
|
||||
float *m_temp;
|
||||
Vector2 m_range;
|
||||
size_t m_size, m_slab;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sparse 2D wavelet representation using the Haar basis
|
||||
* \brief Sparse 2D wavelet representation using the Haar basis
|
||||
*/
|
||||
class MTS_EXPORT_CORE SparseWavelet2D : public SerializableObject {
|
||||
public:
|
||||
/// 2D wavelet coefficient index for \ref SparseWavelet2D
|
||||
struct Key {
|
||||
uint16_t empty;
|
||||
uint8_t level; // level in the hierarchy
|
||||
|
@ -298,8 +303,9 @@ public:
|
|||
Float getPixel(const Point2i &pt) const;
|
||||
|
||||
/**
|
||||
* Compute a line integral in 2D wavelet space. Coordinates are
|
||||
* expected as pixel coordinates in [0,0]-[size,size],
|
||||
* \brief Compute a line integral in 2D wavelet space.
|
||||
*
|
||||
* Coordinates are expected as pixel coordinates in [0,0]-[size,size],
|
||||
* but are allowed to be fractional
|
||||
*/
|
||||
Float lineIntegral(Point2 start, Point2 end) const;
|
||||
|
@ -325,7 +331,8 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Sparse 3D wavelet representation using the Haar basis and an octree structure
|
||||
* \brief Sparse 3D wavelet representation using the Haar basis and an
|
||||
* octree structure
|
||||
*/
|
||||
class MTS_EXPORT_CORE SparseWaveletOctree : public Object {
|
||||
public:
|
||||
|
@ -350,6 +357,9 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~SparseWaveletOctree() { }
|
||||
private:
|
||||
struct Node {
|
||||
inline Node(float value) : value(value) {
|
||||
for (int i=0; i<8; ++i)
|
||||
|
@ -363,9 +373,6 @@ protected:
|
|||
Float lineIntegral(int32_t idx,
|
||||
Float tx0, Float ty0, Float tz0,
|
||||
Float tx1, Float ty1, Float tz1, uint8_t a) const;
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~SparseWaveletOctree() { }
|
||||
private:
|
||||
Node *m_root;
|
||||
std::vector<Node> m_nodes;
|
||||
|
|
|
@ -58,6 +58,7 @@ protected:
|
|||
GLuint64 m_indexAddr;
|
||||
GLuint m_vertexSize;
|
||||
GLuint m_indexSize;
|
||||
int m_stride;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -68,6 +68,21 @@ public:
|
|||
/// Set a Vector4 parameter
|
||||
void setParameter(int id, const Vector4 &value);
|
||||
|
||||
/// Set a Point parameter
|
||||
void setParameter(int id, const Point &value);
|
||||
|
||||
/// Set a Point3i parameter
|
||||
void setParameter(int id, const Point3i &value);
|
||||
|
||||
/// Set a Point2 parameter
|
||||
void setParameter(int id, const Point2 &value);
|
||||
|
||||
/// Set a Point2i parameter
|
||||
void setParameter(int id, const Point2i &value);
|
||||
|
||||
/// Set a Point4 parameter
|
||||
void setParameter(int id, const Point4 &value);
|
||||
|
||||
/// Set a Transform parameter
|
||||
void setParameter(int id, const Transform &value);
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
#define MTS_GL_MAX_QUEUED_TRIS 500000
|
||||
|
||||
class MTS_EXPORT_HW GLRenderer : public Renderer {
|
||||
public:
|
||||
/// Construct a new OpenGL rendering interface
|
||||
|
@ -126,6 +128,12 @@ protected:
|
|||
virtual ~GLRenderer();
|
||||
protected:
|
||||
bool m_transmitOnlyPositions;
|
||||
bool m_normalsEnabled;
|
||||
bool m_texcoordsEnabled;
|
||||
bool m_tangentsEnabled;
|
||||
bool m_colorsEnabled;
|
||||
size_t m_queuedTriangles;
|
||||
int m_stride;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
GPUGeometry(const TriMesh *mesh);
|
||||
|
||||
/// Return the name of this geometry object
|
||||
inline const std::string &getName() { return m_mesh->getName(); }
|
||||
inline std::string getName() const { return m_mesh->getName(); }
|
||||
|
||||
/// Upload the geometry object
|
||||
virtual void init() = 0;
|
||||
|
|
|
@ -98,13 +98,43 @@ public:
|
|||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
|
||||
/// Set a Vector4 parameter by name
|
||||
inline void setParameter(const std::string &name, const Vector4 &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Point parameter by name
|
||||
inline void setParameter(const std::string &name, const Point &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Point3i parameter by name
|
||||
inline void setParameter(const std::string &name, const Point3i &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Point2 parameter by name
|
||||
inline void setParameter(const std::string &name, const Point2 &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Point2i parameter by name
|
||||
inline void setParameter(const std::string &name, const Point2i &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Point4 parameter by name
|
||||
inline void setParameter(const std::string &name, const Point4 &value,
|
||||
bool failIfMissing = true) {
|
||||
setParameter(getParameterID(name, failIfMissing), value);
|
||||
}
|
||||
|
||||
/// Set a Transform parameter by name
|
||||
inline void setParameter(const std::string &name, const Transform &value,
|
||||
bool failIfMissing = true) {
|
||||
|
@ -145,6 +175,21 @@ public:
|
|||
/// Set a Vector4 parameter
|
||||
virtual void setParameter(int id, const Vector4 &value) = 0;
|
||||
|
||||
/// Set a Point parameter
|
||||
virtual void setParameter(int id, const Point &value) = 0;
|
||||
|
||||
/// Set a Point3i parameter
|
||||
virtual void setParameter(int id, const Point3i &value) = 0;
|
||||
|
||||
/// Set a Point2 parameter
|
||||
virtual void setParameter(int id, const Point2 &value) = 0;
|
||||
|
||||
/// Set a Point2i parameter
|
||||
virtual void setParameter(int id, const Point2i &value) = 0;
|
||||
|
||||
/// Set a Point4 parameter
|
||||
virtual void setParameter(int id, const Point4 &value) = 0;
|
||||
|
||||
/// Set a Transform parameter
|
||||
virtual void setParameter(int id, const Transform &value) = 0;
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ public:
|
|||
const Bitmap *getBitmap(unsigned int slot = EDefaultPosition) const;
|
||||
|
||||
/// Return the number of stored bitmaps
|
||||
inline int getBitmapCount() const { return m_bitmaps.size(); }
|
||||
inline int getBitmapCount() const { return (int) m_bitmaps.size(); }
|
||||
|
||||
/// Upload the texture
|
||||
virtual void init() = 0;
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
/// Prepare for rendering a material with BSDF 'bsdf' illuminated by VPL 'vpl'.
|
||||
void configure(const VPL &vpl, const BSDF *bsdf,
|
||||
const Luminaire *luminaire, const Point &camPos);
|
||||
const Luminaire *luminaire, const Point &camPos, bool faceNormals);
|
||||
|
||||
/// Draw the background if there is an environment luminaire
|
||||
void drawBackground(const Transform &clipToWorld, const Point &camPos);
|
||||
|
@ -171,7 +171,7 @@ private:
|
|||
|
||||
struct VPLProgramConfiguration {
|
||||
VPLDependencyNode vpl, bsdf, luminaire;
|
||||
bool hasLuminaire;
|
||||
bool hasLuminaire, faceNormals;
|
||||
int param_shadowMap, param_vplPos, param_camPos, param_vplPower;
|
||||
int param_vplN, param_vplS, param_vplT, param_vplWi, param_vplUV;
|
||||
int param_nearClip, param_invClipRange, param_minDist;
|
||||
|
@ -179,8 +179,8 @@ private:
|
|||
|
||||
inline VPLProgramConfiguration() { }
|
||||
|
||||
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire)
|
||||
: vpl(vpl), bsdf(bsdf), luminaire(luminaire) {
|
||||
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire, bool faceNormals)
|
||||
: vpl(vpl), bsdf(bsdf), luminaire(luminaire), faceNormals(faceNormals) {
|
||||
hasLuminaire = (luminaire != NULL);
|
||||
}
|
||||
|
||||
|
@ -224,6 +224,8 @@ private:
|
|||
oss << ", luminaire=";
|
||||
luminaire.toString(oss);
|
||||
}
|
||||
if (faceNormals)
|
||||
oss << ", faceNormals";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,28 +31,44 @@
|
|||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
|
||||
/// Current release of Mitsuba
|
||||
#define MTS_VERSION "0.1.3"
|
||||
|
||||
/// Year of this release
|
||||
#define MTS_YEAR "2010"
|
||||
|
||||
/// Default port of <tt>mtssrv</tt>
|
||||
#define MTS_DEFAULT_PORT 7554
|
||||
|
||||
#if defined(__LINUX__)
|
||||
/// Default resource directory for packaged releases on Linux
|
||||
#define MTS_RESOURCE_DIR "/usr/share/mitsuba"
|
||||
#endif
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
#include <mitsuba/core/stl.h>
|
||||
#include <mitsuba/core/ref.h>
|
||||
#include <mitsuba/core/object.h>
|
||||
#include <mitsuba/core/sse.h>
|
||||
/**
|
||||
* Include a basic subset of the core classes
|
||||
*/
|
||||
#include <mitsuba/core/constants.h>
|
||||
#include <mitsuba/core/fwd.h>
|
||||
#include <mitsuba/render/fwd.h>
|
||||
#include <mitsuba/core/stl.h>
|
||||
#include <mitsuba/core/object.h>
|
||||
#include <mitsuba/core/ref.h>
|
||||
#include <mitsuba/core/sse.h>
|
||||
#include <mitsuba/core/tls.h>
|
||||
#include <mitsuba/core/lock.h>
|
||||
#include <mitsuba/core/logger.h>
|
||||
#include <mitsuba/core/thread.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/core/vector.h>
|
||||
#include <mitsuba/core/point.h>
|
||||
#include <mitsuba/core/normal.h>
|
||||
#include <mitsuba/core/spectrum.h>
|
||||
#include <mitsuba/core/util.h>
|
||||
|
||||
#endif /* __MITSUBA_H */
|
||||
|
|
|
@ -19,12 +19,105 @@
|
|||
#if !defined(__BSDF_H)
|
||||
#define __BSDF_H
|
||||
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/core/frame.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/render/shader.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Abstract BxDF base-class, which supports reflection and
|
||||
/**
|
||||
* Specifies the transported quantity when sampling / evaluating a BSDF
|
||||
*/
|
||||
enum ETransportQuantity {
|
||||
ERadiance = 1,
|
||||
EImportance = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Data structure, which contains all information required to
|
||||
* sample or query a BSDF.
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER BSDFQueryRecord {
|
||||
public:
|
||||
/**
|
||||
* Given a surface interaction and an incident direction
|
||||
* construct a query record which can be used to sample
|
||||
* an outgoing direction.
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
inline BSDFQueryRecord(RadianceQueryRecord &rRec,
|
||||
const Intersection &its, Point2 sample);
|
||||
|
||||
/**
|
||||
* Given a surface interaction and an incident direction,
|
||||
* construct a query record which can be used to sample
|
||||
* an outgoing direction.
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
inline BSDFQueryRecord(const Intersection &its, Point2 sample);
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
inline BSDFQueryRecord(RadianceQueryRecord &rRec,
|
||||
const Intersection &its, const Vector &wo);
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
inline BSDFQueryRecord(const Intersection &its, const Vector &wo);
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
*/
|
||||
inline BSDFQueryRecord(const Intersection &its, const Vector &wi,
|
||||
const Vector &wo);
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/* Pointer to the associated radiance query record (or NULL) */
|
||||
RadianceQueryRecord *rRec;
|
||||
|
||||
/* Surface interaction */
|
||||
const Intersection &its;
|
||||
|
||||
/* Incident direction */
|
||||
Vector wi;
|
||||
|
||||
/* Outgoing/sampled direction */
|
||||
Vector wo;
|
||||
|
||||
/* Random sample used to generate the new direction */
|
||||
Point2 sample;
|
||||
|
||||
/* Transported quantity (radiance or importance) -- required for
|
||||
non-reciprocal BSDFs such as transmission through a dielectric
|
||||
material */
|
||||
ETransportQuantity quantity;
|
||||
|
||||
/* Bit mask containing the component types, which may be sampled.
|
||||
After sampling has been performed, the component type is stored
|
||||
inside 'sampledType'. */
|
||||
unsigned int typeMask, sampledType;
|
||||
|
||||
/* To sample a specific BSDF component, this entry must be non-negative.
|
||||
After sampling has been performed, the component index is stored
|
||||
inside 'sampledComponent' */
|
||||
int component, sampledComponent;
|
||||
};
|
||||
|
||||
/** \brief Abstract BSDF base-class, which supports reflection and
|
||||
* transmission using a common interface for sampling and evaluation.
|
||||
* A BSDF can consist of several components, which can optionally be
|
||||
* independently sampled and/or evaluated.
|
||||
|
@ -35,13 +128,14 @@ public:
|
|||
* BSDF classification types, can be combined using binary OR.
|
||||
*/
|
||||
enum EBSDFType {
|
||||
EUnknown = 0x00,
|
||||
EDiffuseReflection = 0x01, /* Perfect diffuse reflection */
|
||||
EDiffuseTransmission = 0x02, /* Perfect diffuse transmission */
|
||||
EDeltaReflection = 0x04, /* Reflection using a delta function */
|
||||
EDeltaTransmission = 0x08, /* Transmission using a delta function */
|
||||
EGlossyReflection = 0x10, /* Glossy reflection */
|
||||
EGlossyTransmission = 0x20 /* Glossy transmission */
|
||||
EUnknown = 0x0000,
|
||||
EDiffuseReflection = 0x0001, /* Perfect diffuse reflection */
|
||||
EDiffuseTransmission = 0x0002, /* Perfect diffuse transmission */
|
||||
EDeltaReflection = 0x0004, /* Reflection using a delta function */
|
||||
EDeltaTransmission = 0x0008, /* Transmission using a delta function */
|
||||
EGlossyReflection = 0x0010, /* Glossy reflection */
|
||||
EGlossyTransmission = 0x0020, /* Glossy transmission */
|
||||
EAnisotropicMaterial = 0x1000 /* Reflection is not invariant to rotation */
|
||||
};
|
||||
|
||||
/// Type combinations
|
||||
|
@ -55,17 +149,17 @@ public:
|
|||
EAll = EDiffuse | EDelta | EGlossy
|
||||
};
|
||||
|
||||
/// Return the number of components of this BxDF
|
||||
/// Return the number of components of this BSDF
|
||||
inline int getComponentCount() const {
|
||||
return m_componentCount;
|
||||
}
|
||||
|
||||
/// Return an (OR-ed) integer listing this BxDF's components
|
||||
/// Return an (OR-ed) integer listing this BSDF's components
|
||||
inline unsigned int getType() const {
|
||||
return m_combinedType;
|
||||
}
|
||||
|
||||
/// Returns the BxDF type for a specific component
|
||||
/// Returns the BSDF type for a specific component
|
||||
inline unsigned int getType(int component) const {
|
||||
return m_type[component];
|
||||
}
|
||||
|
@ -75,7 +169,7 @@ public:
|
|||
return (type & m_combinedType) != 0;
|
||||
}
|
||||
|
||||
/// Return whether this BxDF makes use of ray differentials
|
||||
/// Return whether this BSDF makes use of ray differentials
|
||||
inline bool usesRayDifferentials() const {
|
||||
return m_usesRayDifferentials;
|
||||
}
|
||||
|
@ -84,14 +178,14 @@ public:
|
|||
virtual Spectrum getDiffuseReflectance(const Intersection &its) const = 0;
|
||||
|
||||
/**
|
||||
* Sample the BxDF and divide by the probability of the sample. If a
|
||||
* Sample the BSDF and divide by the probability of the sample. If a
|
||||
* component mask or a specific component index is given, the sample
|
||||
* is drawn from the matching component. Depending on the transport type
|
||||
* the BSDF or its adjoint version is used.
|
||||
* @return The BSDF value divided by the sample probability
|
||||
*/
|
||||
virtual Spectrum sample(BSDFQueryRecord &bRec) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method - similar to sample(), but also multiplies
|
||||
* by the cosine factor of the sampled direction.
|
||||
|
@ -99,11 +193,13 @@ public:
|
|||
*/
|
||||
inline Spectrum sampleCos(BSDFQueryRecord &bRec) const {
|
||||
Spectrum bsdfVal = sample(bRec);
|
||||
if (bsdfVal.isBlack())
|
||||
return bsdfVal; // bRec.wo is undefined, play safe
|
||||
return bsdfVal * std::abs(Frame::cosTheta(bRec.wo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample the BxDF and explicitly provided the probability density
|
||||
* Sample the BSDF and explicitly provided the probability density
|
||||
* of the sampled direction. If a component mask or a specific
|
||||
* component index is given, the sample is drawn from the matching
|
||||
* component. Depending on the transport type the BSDF or its adjoint
|
||||
|
@ -119,14 +215,16 @@ public:
|
|||
*/
|
||||
inline Spectrum sampleCos(BSDFQueryRecord &bRec, Float &pdf) const {
|
||||
Spectrum bsdfVal(sample(bRec, pdf));
|
||||
if (bsdfVal.isBlack())
|
||||
return bsdfVal; // bRec.wo is undefined, play safe
|
||||
return bsdfVal * std::abs(Frame::cosTheta(bRec.wo));
|
||||
}
|
||||
|
||||
/// Evaluate the BxDF f(wi, wo) or its adjoint version f^{*}(wi, wo)
|
||||
/// Evaluate the BSDF f(wi, wo) or its adjoint version f^{*}(wi, wo)
|
||||
virtual Spectrum f(const BSDFQueryRecord &bRec) const = 0;
|
||||
|
||||
/**
|
||||
* Evaluate the BxDF f(wi, wo) or its adjoint version f^{*}(wi, wo).
|
||||
* Evaluate the BSDF f(wi, wo) or its adjoint version f^{*}(wi, wo).
|
||||
* Also multiplies by the cosine factor of the sampled direction.
|
||||
*/
|
||||
inline Spectrum fCos(const BSDFQueryRecord &bRec) const {
|
||||
|
@ -172,6 +270,8 @@ protected:
|
|||
std::string m_name;
|
||||
};
|
||||
|
||||
extern void operator<<(const ETransportQuantity &quantity, std::ostream &os);
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_H */
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CONST_TEXTURE_H)
|
||||
#define __CONST_TEXTURE_H
|
||||
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class MTS_EXPORT_RENDER ConstantTexture : public Texture {
|
||||
public:
|
||||
inline ConstantTexture(const Spectrum &value)
|
||||
: Texture(Properties()), m_value(value) {
|
||||
}
|
||||
|
||||
ConstantTexture(Stream *stream, InstanceManager *manager);
|
||||
|
||||
inline Spectrum getValue(const Intersection &its) const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline Spectrum getAverage() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline Spectrum getMaximum() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "ConstantTexture[value=" << m_value.toString() << "]";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
inline bool usesRayDifferentials() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Shader *createShader(Renderer *renderer) const;
|
||||
|
||||
void serialize(Stream *stream, InstanceManager *manager) const;
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
Spectrum m_value;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __CONST_TEXTURE_H */
|
|
@ -21,11 +21,12 @@
|
|||
|
||||
#include <mitsuba/render/sampler.h>
|
||||
#include <mitsuba/render/renderproc_wr.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Bitmap;
|
||||
|
||||
/** \brief Abstract Film base class - used to store samples
|
||||
* generated by the Integrator.
|
||||
*/
|
||||
|
@ -55,7 +56,7 @@ public:
|
|||
virtual void toBitmap(Bitmap *bitmap) const = 0;
|
||||
|
||||
/// Develop the film and write the result to the specified filename
|
||||
virtual void develop(const std::string &fileName) = 0;
|
||||
virtual void develop(const fs::path &fileName) = 0;
|
||||
|
||||
/// Ignoring the crop window, return the resolution of the underlying sensor
|
||||
inline const Vector2i &getSize() const { return m_size; }
|
||||
|
@ -89,7 +90,7 @@ public:
|
|||
virtual void serialize(Stream *stream, InstanceManager *manager) const;
|
||||
|
||||
/// Does the destination already exist?
|
||||
virtual bool destinationExists(const std::string &baseName) const = 0;
|
||||
virtual bool destinationExists(const fs::path &baseName) const = 0;
|
||||
|
||||
/// Return the properties of this film
|
||||
inline const Properties &getProperties() const { return m_properties; }
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__RENDER_FWD_H)
|
||||
#define __RENDER_FWD_H
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class BlockedImageProcess;
|
||||
class BlockedRenderProcess;
|
||||
class BlockListener;
|
||||
class BSDF;
|
||||
struct BSDFQueryRecord;
|
||||
class Camera;
|
||||
class ConstantTexture;
|
||||
struct EmissionRecord;
|
||||
class Film;
|
||||
class GatherPhotonProcess;
|
||||
class HemisphereSampler;
|
||||
class HWResource;
|
||||
class ImageBlock;
|
||||
class Integrator;
|
||||
struct Intersection;
|
||||
class IrradianceCache;
|
||||
template <typename Derived> class GenericKDTree;
|
||||
class KDTree;
|
||||
class LocalWorker;
|
||||
class Luminaire;
|
||||
struct LuminaireSamplingRecord;
|
||||
class Medium;
|
||||
struct MediumSamplingRecord;
|
||||
class MIPMap;
|
||||
class MonteCarloIntegrator;
|
||||
class ParticleProcess;
|
||||
class ParticleTracer;
|
||||
class PhaseFunction;
|
||||
class PhotonMap;
|
||||
class PreviewWorker;
|
||||
class ProjectiveCamera;
|
||||
struct RadianceQueryRecord;
|
||||
class Random;
|
||||
class RangeWorkUnit;
|
||||
class ReconstructionFilter;
|
||||
class RectangularWorkUnit;
|
||||
class RenderJob;
|
||||
class RenderListener;
|
||||
class RenderQueue;
|
||||
class SampleIntegrator;
|
||||
class Sampler;
|
||||
class Scene;
|
||||
class SceneHandler;
|
||||
class Shader;
|
||||
class Shape;
|
||||
struct ShapeSamplingRecord;
|
||||
class SparseMipmap3D;
|
||||
class Spiral;
|
||||
class Subsurface;
|
||||
class TabulatedFilter;
|
||||
class Texture;
|
||||
struct TriAccel;
|
||||
struct TriAccel4;
|
||||
class TriMesh;
|
||||
class Utility;
|
||||
class VolumeDataSource;
|
||||
struct VPL;
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __RENDER_FWD_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -19,16 +19,12 @@
|
|||
#if !defined(__INTEGRATOR_H)
|
||||
#define __INTEGRATOR_H
|
||||
|
||||
#include <mitsuba/render/sampler.h>
|
||||
#include <mitsuba/core/netobject.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/render/shape.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
class Camera;
|
||||
class RenderQueue;
|
||||
class RenderJob;
|
||||
|
||||
/**
|
||||
* Abstract integrator base-class. Does not make any assumptions on
|
||||
* how radiance is computed.
|
||||
|
@ -45,7 +41,7 @@ public:
|
|||
* which have been made available to all local and remote workers.
|
||||
* The default implementation simply returns.
|
||||
*/
|
||||
virtual void preprocess(const Scene *scene, RenderQueue *queue,
|
||||
virtual bool preprocess(const Scene *scene, RenderQueue *queue,
|
||||
const RenderJob *job, int sceneResID, int cameraResID,
|
||||
int samplerResID);
|
||||
|
||||
|
@ -110,6 +106,170 @@ protected:
|
|||
Properties m_properties;
|
||||
};
|
||||
|
||||
struct MTS_EXPORT_RENDER RadianceQueryRecord {
|
||||
public:
|
||||
/**
|
||||
* List of suported query types. These can be combined by a binary OR.
|
||||
*/
|
||||
enum ERadianceQuery {
|
||||
/* Emitted radiance from a luminaire intersected by the ray */
|
||||
EEmittedRadiance = 0x0001,
|
||||
|
||||
/* Emitted radiance from a subsurface integrator */
|
||||
ESubsurfaceRadiance = 0x0002,
|
||||
|
||||
/* Direct (surface) radiance */
|
||||
EDirectRadiance = 0x0004,
|
||||
|
||||
/* Indirect (surface) radiance, where the last bounce did not go
|
||||
through a Dirac delta BSDF */
|
||||
EIndirectRadiance = 0x0008,
|
||||
|
||||
/* Indirect (surface) radiance, where the last bounce went
|
||||
through a Dirac delta BSDF */
|
||||
ECausticRadiance = 0x0010,
|
||||
|
||||
/* In-scattered radiance due to volumetric scattering (direct) */
|
||||
EInscatteredDirectRadiance = 0x0020,
|
||||
|
||||
/* In-scattered radiance due to volumetric scattering (indirect) */
|
||||
EInscatteredIndirectRadiance = 0x0040,
|
||||
|
||||
/* Distance to the next surface intersection */
|
||||
EDistance = 0x0080,
|
||||
|
||||
/* Opacity value: 1 when a surface was hit, 0 when the ray leads
|
||||
into empty space. When there is a participating medium,
|
||||
this can also take on fractional values. */
|
||||
EOpacity = 0x0100,
|
||||
|
||||
/* A ray intersection may need to be performed. This can be set to
|
||||
zero if the caller has already provided the intersection */
|
||||
EIntersection = 0x0200,
|
||||
|
||||
/* Radiance from volumes */
|
||||
EVolumeRadiance = EInscatteredDirectRadiance | EInscatteredIndirectRadiance,
|
||||
|
||||
/* Radiance query without emitted radiance, ray intersection required */
|
||||
ERadianceNoEmission = ESubsurfaceRadiance | EDirectRadiance | EIndirectRadiance
|
||||
| ECausticRadiance | EInscatteredDirectRadiance | EInscatteredIndirectRadiance | EIntersection,
|
||||
|
||||
/* Default radiance query, ray intersection required */
|
||||
ERadiance = ERadianceNoEmission | EEmittedRadiance,
|
||||
|
||||
/* Radiance + opacity */
|
||||
ECameraRay = ERadiance | EOpacity
|
||||
};
|
||||
|
||||
/// Construct an invalid radiance query record
|
||||
inline RadianceQueryRecord()
|
||||
: type(0), scene(NULL), sampler(NULL),
|
||||
depth(0), alpha(0), dist(-1), wavelength(-1), extra(0) {
|
||||
}
|
||||
|
||||
/// Construct a radiance query record for the given scene and sampler
|
||||
inline RadianceQueryRecord(const Scene *scene, Sampler *sampler)
|
||||
: type(0), scene(scene), sampler(sampler),
|
||||
depth(0), alpha(0), dist(-1), wavelength(-1), extra(0) {
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
inline RadianceQueryRecord(const RadianceQueryRecord &rRec)
|
||||
: type(rRec.type), scene(rRec.scene), sampler(rRec.sampler),
|
||||
depth(rRec.depth), alpha(rRec.alpha), dist(rRec.dist),
|
||||
wavelength(rRec.wavelength), extra(rRec.extra) {
|
||||
}
|
||||
|
||||
/// Begin a new query of the given type
|
||||
inline void newQuery(int _type) {
|
||||
type = _type;
|
||||
depth = 1;
|
||||
wavelength = -1;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
/// Initialize the query record for a recursive query
|
||||
inline void recursiveQuery(const RadianceQueryRecord &parent, int _type) {
|
||||
type = _type;
|
||||
scene = parent.scene;
|
||||
sampler = parent.sampler;
|
||||
depth = parent.depth+1;
|
||||
wavelength = parent.wavelength;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a ray intersection. This
|
||||
* does several things at once - if the intersection has
|
||||
* already been provided, the function returns.
|
||||
* Otherwise, it
|
||||
* - performs the ray intersection
|
||||
* - computes the attenuation due to participating media
|
||||
* and stores it in <tt>attenuation</tt>.
|
||||
* - sets the alpha value (if <tt>EAlpha</tt> is set in <tt>type</tt>)
|
||||
* - sets the distance value (if <tt>EDistance</tt> is set in <tt>type</tt>)
|
||||
* - clears the <tt>EIntersection</tt> flag in <tt>type</tt>
|
||||
* Returns true if there is a valid intersection.
|
||||
*/
|
||||
inline bool rayIntersect(const RayDifferential &ray);
|
||||
|
||||
/// Retrieve a 2D sample
|
||||
inline Point2 nextSample2D();
|
||||
|
||||
/// Retrieve a 1D sample
|
||||
inline Float nextSample1D();
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
// An asterisk (*) marks entries, which may be overwritten
|
||||
// by the callee.
|
||||
|
||||
/// Query type (*)
|
||||
int type;
|
||||
|
||||
/// Pointer to the associated scene
|
||||
const Scene *scene;
|
||||
|
||||
/// Sample generator
|
||||
Sampler *sampler;
|
||||
|
||||
/// Current depth value (# of light bounces) (*)
|
||||
int depth;
|
||||
|
||||
/// Surface interaction data structure (*)
|
||||
Intersection its;
|
||||
|
||||
/// Attenuation along the current ray (*)
|
||||
Spectrum attenuation;
|
||||
|
||||
/// Opacity value of the associated pixel (*)
|
||||
Float alpha;
|
||||
|
||||
/**
|
||||
* Ray distance to the first surface interaction
|
||||
* (if requested by the query type EDistance) (*)
|
||||
*/
|
||||
Float dist;
|
||||
|
||||
/**
|
||||
* In some cases, the integrator may be forced to restrict
|
||||
* radiance computations to one wavelength (e.g. when intersecting
|
||||
* a dielectric material with dispersion or while path
|
||||
* tracing through a highly scattering medium with a non-constant
|
||||
* scattering coefficient). This attribute is used to store the
|
||||
* chosen wavelength. (*)
|
||||
*/
|
||||
int wavelength;
|
||||
|
||||
/**
|
||||
* Internal flag, which can be used to pass additional information
|
||||
* amonst recursive calls inside an integrator. The use
|
||||
* is dependent on the particular integrator implementation. (*)
|
||||
*/
|
||||
int extra;
|
||||
};
|
||||
|
||||
/** \brief Abstract base class, which describes integrators
|
||||
* capable of computing samples of the scene's radiance function.
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef Spectrum TranslationalGradient[3];
|
|||
*
|
||||
* @author Wenzel Jakob
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER HemisphereSampler : public Object {
|
||||
class MTS_EXPORT_RENDER HemisphereSampler : public Object {
|
||||
public:
|
||||
struct SampleEntry {
|
||||
Vector d;
|
||||
|
|
|
@ -19,413 +19,200 @@
|
|||
#if !defined(__KD_TREE_H)
|
||||
#define __KD_TREE_H
|
||||
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/render/shape.h>
|
||||
#include <mitsuba/render/gkdtree.h>
|
||||
#include <mitsuba/render/triaccel.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
|
||||
/**
|
||||
* First, some default configuration definitions:
|
||||
*
|
||||
* If SSE is available, use the quad-packed TriAccel4 intersection method.
|
||||
* Otherwise, fall back to the scalar TriAccel implementation. To use the
|
||||
* scalar Moeller-Trumbore intersection algorithm (slower), remove this
|
||||
* whole following block:
|
||||
*/
|
||||
#ifdef MTS_SSE
|
||||
#define MTS_USE_TRIACCEL4 1
|
||||
#define MTS_USE_TRIACCEL 1
|
||||
#else
|
||||
#define MTS_USE_TRIACCEL 1
|
||||
#include <mitsuba/render/triaccel.h>
|
||||
#endif
|
||||
|
||||
#if defined(MTS_KD_CONSERVE_MEMORY)
|
||||
#if defined(MTS_HAS_COHERENT_RT)
|
||||
/* Coherent ray tracing needs the plain TriAccel data stucture.
|
||||
Note that both TriAccel and TriAccel4 can be pre-computed
|
||||
at the same time in order to have a performance gain with
|
||||
both coherent and non-coherent methods (at the cost of higher
|
||||
memory usage) */
|
||||
#define MTS_USE_TRIACCEL 1
|
||||
#if !defined(MTS_SSE)
|
||||
#error Coherent ray tracing requires SSE
|
||||
#error MTS_KD_CONSERVE_MEMORY & MTS_HAS_COHERENT_RT are incompatible
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(MTS_USE_TRIACCEL4) && !defined(MTS_USE_TRIACCEL)
|
||||
/* Switch to Moeller-Trumbore if neither TriAccel4 nor TriAccel is selected */
|
||||
#define MTS_USE_MT 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Pre-defined max. stack size for the ray traversal algorithm
|
||||
*/
|
||||
#define MTS_KD_MAXDEPTH 35
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* SAH KD-tree acceleration data structure for fast ray-triangle intersections.
|
||||
* Implements the construction algorithm for 'perfect split' trees as outlined
|
||||
* in the paper "On Bulding fast kd-Trees for Ray Tracing, and on doing that in
|
||||
* O(N log N)" by Ingo Wald and Vlastimil Havran. Non-triangle shapes are also
|
||||
* supported, but most optimizations here target large triangle meshes.
|
||||
* \brief SAH KD-tree acceleration data structure for fast ray-triangle
|
||||
* intersections.
|
||||
*
|
||||
* This class offers a choice of several different triangle intersection algorithms:
|
||||
* Implements the construction algorithm for 'perfect split' trees as outlined
|
||||
* in the paper "On Bulding fast kd-Trees for Ray Tracing, and on doing that in
|
||||
* O(N log N)" by Ingo Wald and Vlastimil Havran. Non-triangle shapes are
|
||||
* supported, but most optimizations here target large triangle meshes.
|
||||
* For more details regarding the construction algorithm, please refer to
|
||||
* the class \ref GenericKDTree.
|
||||
*
|
||||
* This class offers a choice of two different triangle intersection algorithms:
|
||||
* By default, intersections are computed using the "TriAccel" projection with
|
||||
* pre-computation method from Ingo Wald's PhD thesis "Realtime Ray Tracing
|
||||
* and Interactive Global Illumination". When SSE is available on the target system,
|
||||
* leaf triangles are stored in an explicit, packed format so that up to four
|
||||
* intersections can be performed simultaneously. While about 15% faster, this also
|
||||
* tends to duplicate a lot of geometry, which results in high memory usage.
|
||||
* Therefore, this behavior can optionally be turned off with a #define. The third
|
||||
* choice is the Moeller-Trumbore intersection test, which requires the least amount
|
||||
* of memory, but is also the slowest.
|
||||
* and Interactive Global Illumination". This adds an overhead of 48 bytes per
|
||||
* triangle.
|
||||
*
|
||||
* When SSE is enabled, packets of 4 rays can efficiently be traced to make
|
||||
* use of any ray coherence. This requires "TriAccel" or "TriAccel4" to be
|
||||
* enabled.
|
||||
* When compiled with MTS_KD_CONSERVE_MEMORY, the Moeller-Trumbore intersection
|
||||
* test is used instead, which doesn't need any extra storage. However, it also
|
||||
* tends to be quite a bit slower.
|
||||
*
|
||||
* During the kd-tree construction, this class uses a technique named
|
||||
* "primitive clipping" to significantly improve the quality of the resulting
|
||||
* trees. However, the involved Sutherland-Hodgman iterations are expensive
|
||||
* and can lead to long construction times. The setClip method can be used
|
||||
* to deactivate primitive clipping at the cost of slower intersections.
|
||||
*
|
||||
* Finally, this class also uses an optimized ray traversal algorithm
|
||||
* (TA^B_{rec}), which is explained in Vlastimil Havran's PhD thesis
|
||||
* "Heuristic Ray Shooting Algorithms".
|
||||
*
|
||||
* @author Wenzel Jakob
|
||||
* \sa GenericKDTree
|
||||
*/
|
||||
class MTS_EXPORT_RENDER KDTree : public Object {
|
||||
class MTS_EXPORT_RENDER KDTree : public GenericKDTree<KDTree> {
|
||||
friend class GenericKDTree<KDTree>;
|
||||
public:
|
||||
/// Construct a new kd-tree in an unbuilt state
|
||||
/// Create an empty kd-tree
|
||||
KDTree();
|
||||
|
||||
/// Add geometry to the kd-tree
|
||||
/// Add a shape to the kd-tree
|
||||
void addShape(const Shape *shape);
|
||||
|
||||
|
||||
/// Return the list of stored shapes
|
||||
inline const std::vector<const Shape *> &getShapes() const { return m_shapes; }
|
||||
|
||||
/// Set the relative cost of an intersection operation
|
||||
inline void setIntersectionCost(Float pCost) { m_intersectionCost = pCost; }
|
||||
/**
|
||||
* \brief Return an axis-aligned bounding box containing all primitives
|
||||
*/
|
||||
inline const AABB &getAABB() const { return m_aabb; }
|
||||
|
||||
/// Return the relative cost of an intersection operation
|
||||
inline Float getIntersectionCost() const { return m_intersectionCost; }
|
||||
|
||||
/// Set the relative cost of a traversal operation
|
||||
inline void setTraversalCost(Float pCost) { m_traversalCost = pCost; }
|
||||
|
||||
/// Return the relative cost of a traversal operation
|
||||
inline Float getTraversalCost() const { return m_traversalCost; }
|
||||
|
||||
/// Set a bonus factor for cutting away empty space
|
||||
inline void setEmptyBonus(Float pCost) { m_emptyBonus = pCost; }
|
||||
|
||||
/// Return the bonus factor for cutting away empty space
|
||||
inline Float getEmptyBonus() const { return m_emptyBonus; }
|
||||
|
||||
/// Set the min. number of primitives, which will never be split.
|
||||
inline void setStopPrims(int pCost) { m_stopPrims = pCost; }
|
||||
|
||||
/// Return the min. number of primitives, which will never be split.
|
||||
inline int getStopPrims() const { return m_stopPrims; }
|
||||
|
||||
/// Enable or disable primitive clipping
|
||||
inline void setClip(bool pClip) { m_clip = pClip; }
|
||||
|
||||
/// Return whether primitive clipping is enabled
|
||||
inline bool getClip() const { return m_clip; }
|
||||
|
||||
/// Has the kd-tree been built?
|
||||
inline bool isBuilt() const { return m_built; }
|
||||
|
||||
/// Return the axis-aligned bounding box containing all primitives
|
||||
inline const AABB &getAABB() const { return m_rootBounds; }
|
||||
|
||||
/// Return the bounding sphere containing all primitives
|
||||
inline const BSphere &getBSphere() const { return m_bsphere; }
|
||||
|
||||
/// Build the kd-tree
|
||||
/// Build the kd-tree (needs to be called before tracing any rays)
|
||||
void build();
|
||||
|
||||
/**
|
||||
* Intersect a ray with the stored triangle meshes and only
|
||||
* check for intersections. This is the fastest intersection test.
|
||||
*/
|
||||
bool rayIntersect(const Ray &ray) const;
|
||||
|
||||
/**
|
||||
* Intersect a ray with the stored triangle meshes and return
|
||||
* a detailed intersection information record
|
||||
* \brief Intersect a ray against all primitives stored in the kd-tree
|
||||
*/
|
||||
bool rayIntersect(const Ray &ray, Intersection &its) const;
|
||||
|
||||
/**
|
||||
* Intersect four rays with the stored triangle meshes while making
|
||||
* use of ray coherence to do this very efficiently. If the coherent
|
||||
* ray tracing #define is missing, this function simply does four
|
||||
* separate mono-ray traversals.
|
||||
* \brief Test a ray for intersection against all primitives stored in the kd-tree
|
||||
*/
|
||||
void rayIntersectPacket(const Ray *rays, Intersection *its) const;
|
||||
bool rayIntersect(const Ray &ray) const;
|
||||
|
||||
#if defined(MTS_HAS_COHERENT_RT)
|
||||
/**
|
||||
* Intersect four rays with the stored triangle meshes while making
|
||||
* \brief Intersect four rays with the stored triangle meshes while making
|
||||
* use of ray coherence to do this very efficiently. Requires SSE.
|
||||
*/
|
||||
void rayIntersectPacket(const RayPacket4 &packet,
|
||||
const RayInterval4 &interval, Intersection4 &its) const;
|
||||
const RayInterval4 &interval, Intersection4 &its, void *temp) const;
|
||||
|
||||
/**
|
||||
* Fallback for incoherent rays
|
||||
* \brief Fallback for incoherent rays
|
||||
* \sa rayIntesectPacket
|
||||
*/
|
||||
void rayIntersectPacketIncoherent(const RayPacket4 &packet,
|
||||
const RayInterval4 &interval, Intersection4 &its) const;
|
||||
const RayInterval4 &interval, Intersection4 &its, void *temp) const;
|
||||
#endif
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// Virtual destructor
|
||||
virtual ~KDTree();
|
||||
/**
|
||||
* \brief Return the shape index corresponding to a primitive index
|
||||
* seen by the generic kd-tree implementation. When this is a triangle
|
||||
* mesh, the \a idx parameter is updated to the triangle index within
|
||||
* the mesh.
|
||||
*/
|
||||
index_type findShape(index_type &idx) const {
|
||||
std::vector<index_type>::const_iterator it = std::lower_bound(
|
||||
m_shapeMap.begin(), m_shapeMap.end(), idx+1) - 1;
|
||||
idx -= *it;
|
||||
return (index_type) (it - m_shapeMap.begin());
|
||||
}
|
||||
|
||||
/// KD-tree node in 8 bytes
|
||||
struct KDNode {
|
||||
union {
|
||||
/* Inner node */
|
||||
struct {
|
||||
/* Bit layout:
|
||||
31 : False (inner node)
|
||||
30-3 : Offset to the right child
|
||||
3-0 : Split axis
|
||||
*/
|
||||
uint32_t combined;
|
||||
|
||||
/// Split plane coordinate
|
||||
float split;
|
||||
} inner;
|
||||
|
||||
/* Leaf node */
|
||||
struct {
|
||||
/* Bit layout:
|
||||
31 : True (leaf node)
|
||||
30-0 : Offset to the node's triangle list
|
||||
*/
|
||||
uint32_t combined;
|
||||
|
||||
/// End offset of the triangle list
|
||||
uint32_t end;
|
||||
} leaf;
|
||||
};
|
||||
|
||||
enum EMask {
|
||||
ETypeMask = 1 << 31,
|
||||
ELeafOffsetMask = ~ETypeMask,
|
||||
EInnerAxisMask = 3,
|
||||
EInnerOffsetMask = ~EInnerAxisMask
|
||||
};
|
||||
|
||||
inline void setLeaf(unsigned int offset, unsigned int numPrims) {
|
||||
leaf.combined = ETypeMask | offset;
|
||||
leaf.end = offset + numPrims;
|
||||
/// Return the axis-aligned bounding box of a certain primitive
|
||||
FINLINE AABB getAABB(index_type idx) const {
|
||||
index_type shapeIdx = findShape(idx);
|
||||
const Shape *shape = m_shapes[shapeIdx];
|
||||
if (m_triangleFlag[shapeIdx]) {
|
||||
const TriMesh *mesh = static_cast<const TriMesh *>(shape);
|
||||
return mesh->getTriangles()[idx].getAABB(mesh->getVertexPositions());
|
||||
} else {
|
||||
return shape->getAABB();
|
||||
}
|
||||
}
|
||||
|
||||
inline void setInner(int axis, unsigned int offset, Float split) {
|
||||
inner.combined = axis | (offset << 2);
|
||||
inner.split = (float) split;
|
||||
/// Return the AABB of a primitive when clipped to another AABB
|
||||
FINLINE AABB getClippedAABB(index_type idx, const AABB &aabb) const {
|
||||
index_type shapeIdx = findShape(idx);
|
||||
const Shape *shape = m_shapes[shapeIdx];
|
||||
if (m_triangleFlag[shapeIdx]) {
|
||||
const TriMesh *mesh = static_cast<const TriMesh *>(shape);
|
||||
return mesh->getTriangles()[idx].getClippedAABB(mesh->getVertexPositions(), aabb);
|
||||
} else {
|
||||
return shape->getClippedAABB(aabb);
|
||||
}
|
||||
}
|
||||
|
||||
FINLINE bool isLeaf() const {
|
||||
return leaf.combined & ETypeMask;
|
||||
}
|
||||
|
||||
FINLINE uint32_t getPrimStart() const {
|
||||
return leaf.combined & ELeafOffsetMask;
|
||||
}
|
||||
|
||||
FINLINE uint32_t getPrimEnd() const {
|
||||
return leaf.end;
|
||||
}
|
||||
|
||||
FINLINE const KDNode * __restrict getLeft() const {
|
||||
return this +
|
||||
((inner.combined & EInnerOffsetMask) >> 2);
|
||||
}
|
||||
|
||||
FINLINE const KDNode * __restrict getOtherChild() const {
|
||||
return (const KDNode *) ((ptrdiff_t) this ^ (ptrdiff_t) 8);
|
||||
}
|
||||
|
||||
FINLINE const KDNode * __restrict getRight() const {
|
||||
return getLeft() + 1;
|
||||
}
|
||||
|
||||
inline float getSplit() const {
|
||||
return inner.split;
|
||||
}
|
||||
|
||||
inline int getAxis() const {
|
||||
return inner.combined & EInnerAxisMask;
|
||||
}
|
||||
FINLINE size_type getPrimitiveCount() const {
|
||||
return m_shapeMap[m_shapeMap.size()-1];
|
||||
}
|
||||
|
||||
/// Temporarily holds some intersection information
|
||||
struct IntersectionCache {
|
||||
size_type shapeIndex;
|
||||
size_type primIndex;
|
||||
Float u, v;
|
||||
};
|
||||
|
||||
/// Primitive classification during tree-construction
|
||||
enum EClassificationResult {
|
||||
EBothSides = 1,
|
||||
ELeftSide = 2,
|
||||
ERightSide = 3,
|
||||
EBothSidesProcessed = 4
|
||||
};
|
||||
/**
|
||||
* Check whether a primitive is intersected by the given ray. Some
|
||||
* temporary space is supplied to store data that can later
|
||||
* be used to create a detailed intersection record.
|
||||
*/
|
||||
FINLINE EIntersectionResult intersect(const Ray &ray, index_type idx, Float mint,
|
||||
Float maxt, Float &t, void *temp) const {
|
||||
IntersectionCache *cache =
|
||||
static_cast<IntersectionCache *>(temp);
|
||||
|
||||
#if defined(MTS_USE_TRIACCEL)
|
||||
typedef TriAccel KDTriangle;
|
||||
#if defined(MTS_KD_CONSERVE_MEMORY)
|
||||
index_type shapeIdx = findShape(idx);
|
||||
if (EXPECT_TAKEN(m_triangleFlag[shapeIdx])) {
|
||||
const TriMesh *mesh =
|
||||
static_cast<const TriMesh *>(m_shapes[shapeIdx]);
|
||||
const Triangle &tri = mesh->getTriangles()[idx];
|
||||
Float tempU, tempV, tempT;
|
||||
if (tri.rayIntersect(mesh->getVertexPositions(), ray,
|
||||
tempU, tempV, tempT)) {
|
||||
if (tempT < mint || tempT > maxt)
|
||||
return ENo;
|
||||
t = tempT;
|
||||
cache->shapeIndex = shapeIdx;
|
||||
cache->primIndex = primIdx;
|
||||
cache->u = tempU;
|
||||
cache->v = tempV;
|
||||
return EYes;
|
||||
}
|
||||
} else {
|
||||
const Shape *shape = m_shapes[shapeIndex];
|
||||
if (shape->rayIntersect(ray, mint, maxt, t,
|
||||
reinterpret_cast<uint8_t*>(temp) + 8)) {
|
||||
cache->shapeIndex = shapeIdx;
|
||||
cache->primIndex = KNoTriangleFlag;
|
||||
return EYes;
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct KDTriangle {
|
||||
uint32_t k;
|
||||
uint32_t index;
|
||||
uint32_t shapeIndex;
|
||||
};
|
||||
const TriAccel &ta = m_triAccel[idx];
|
||||
if (EXPECT_TAKEN(m_triAccel[idx].k != KNoTriangleFlag)) {
|
||||
Float tempU, tempV, tempT;
|
||||
if (ta.rayIntersect(ray, mint, maxt, tempU, tempV, tempT)) {
|
||||
t = tempT;
|
||||
cache->shapeIndex = ta.shapeIndex;
|
||||
cache->primIndex = ta.primIndex;
|
||||
cache->u = tempU;
|
||||
cache->v = tempV;
|
||||
return EYes;
|
||||
}
|
||||
} else {
|
||||
uint32_t shapeIndex = ta.shapeIndex;
|
||||
const Shape *shape = m_shapes[shapeIndex];
|
||||
if (shape->rayIntersect(ray, mint, maxt, t,
|
||||
reinterpret_cast<uint8_t*>(temp) + 8)) {
|
||||
cache->shapeIndex = shapeIndex;
|
||||
cache->primIndex = KNoTriangleFlag;
|
||||
return EYes;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// AABB edge event data structure
|
||||
struct EdgeEvent {
|
||||
/// Possible event types
|
||||
enum EEventType {
|
||||
EEdgeEnd = 0,
|
||||
EEdgePlanar = 1,
|
||||
EEdgeStart = 2
|
||||
};
|
||||
|
||||
/// Dummy constructor
|
||||
inline EdgeEvent() { }
|
||||
|
||||
/// Create a new edge event
|
||||
inline EdgeEvent(uint8_t type, Float t, int index)
|
||||
: t(t), index(index), type(type) {
|
||||
}
|
||||
|
||||
/* Plane position */
|
||||
Float t;
|
||||
/* Triangle index */
|
||||
int index;
|
||||
/* Event type: end/planar/start */
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
typedef std::vector<EdgeEvent> EdgeEventVec;
|
||||
typedef EdgeEventVec EdgeEventVec3[3];
|
||||
|
||||
/// Edge event comparison functor
|
||||
struct EdgeEventSorter : public std::binary_function<EdgeEvent, EdgeEvent, bool> {
|
||||
inline bool operator()(const EdgeEvent &a, const EdgeEvent &b) const {
|
||||
if (a.t != b.t)
|
||||
return a.t < b.t;
|
||||
return a.type < b.type;
|
||||
}
|
||||
};
|
||||
|
||||
/// Score for a split candidate
|
||||
struct Score {
|
||||
enum EPlanarSide {
|
||||
EPlanarLeft = 0,
|
||||
EPlanarRight = 1
|
||||
};
|
||||
|
||||
/// Create an upper bound score
|
||||
inline Score() : score(std::numeric_limits<Float>::infinity()) {
|
||||
}
|
||||
|
||||
/// Create a new store record
|
||||
inline Score(Float score, Float t, int nLeft, int nRight,
|
||||
uint8_t axis, uint8_t planarSide) : score(score), t(t),
|
||||
nLeft(nLeft), nRight(nRight), axis(axis), planarSide(planarSide) {
|
||||
}
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "Score[value=" << score << ", t=" << t
|
||||
<< ", axis=" << (int) axis << ", planarSide="
|
||||
<< (planarSide == EPlanarLeft ? "left" : "right")
|
||||
<< ", nLeft=" << nLeft << ", nRight=" << nRight
|
||||
<< "]";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/// Numerical score value
|
||||
Float score;
|
||||
/// Split position
|
||||
Float t;
|
||||
/// Primitive counts on the left and right side
|
||||
int nLeft, nRight;
|
||||
/// Split axis
|
||||
uint8_t axis;
|
||||
/// Should planar prims be placed left or right?
|
||||
uint8_t planarSide;
|
||||
/// Score comparison operator
|
||||
inline bool operator<(const Score &b) const {
|
||||
return score < b.score;
|
||||
}
|
||||
};
|
||||
|
||||
/// Surface area heuristic (SAH) cost function
|
||||
inline Float SAH(Float prLeft, Float prRight, int numLeft, int numRight) {
|
||||
Float cost = m_traversalCost + m_intersectionCost
|
||||
* (prLeft * numLeft + prRight * numRight);
|
||||
|
||||
/* Favor splits, which cut off empty regions of space */
|
||||
if (numLeft == 0 || numRight == 0)
|
||||
cost *= m_emptyBonus;
|
||||
return cost;
|
||||
return ENo;
|
||||
}
|
||||
|
||||
/// Surface area heuristic
|
||||
inline Score SAH(int axis, Float invArea, AABB aabb, Float t, int numLeft,
|
||||
int numRight, int numPlanar) {
|
||||
/* Generate the left+right node bounding boxes */
|
||||
AABB leftBounds = aabb, rightBounds = aabb;
|
||||
leftBounds.max[axis] = t; rightBounds.min[axis] = t;
|
||||
|
||||
if (std::abs(aabb.min[axis]-t) < Epsilon ||
|
||||
std::abs(aabb.max[axis]-t) < Epsilon) {
|
||||
/* Do not allow tiny splits */
|
||||
return Score(std::numeric_limits<Float>::infinity(),
|
||||
t, numLeft, numRight+numPlanar, axis, Score::EPlanarRight);
|
||||
}
|
||||
|
||||
/* Determinate approximate intersection probabilities
|
||||
for uniformly distributed rays */
|
||||
Float prLeft = leftBounds.getSurfaceArea() * invArea,
|
||||
prRight = rightBounds.getSurfaceArea() * invArea;
|
||||
|
||||
/* Two costs are calculated depending on whether planar
|
||||
primitives are put on the left or right side */
|
||||
Float costPlanarLeft = SAH(prLeft, prRight,
|
||||
numLeft + numPlanar, numRight);
|
||||
Float costPlanarRight = SAH(prLeft, prRight,
|
||||
numLeft, numRight + numPlanar);
|
||||
|
||||
if (costPlanarLeft < costPlanarRight)
|
||||
return Score(costPlanarLeft, t, numLeft+numPlanar, numRight,
|
||||
axis, Score::EPlanarLeft);
|
||||
else
|
||||
return Score(costPlanarRight, t, numLeft, numRight+numPlanar,
|
||||
axis, Score::EPlanarRight);
|
||||
}
|
||||
|
||||
/// Ray traversal stack entry for incoherent ray tracing
|
||||
struct KDStackEntry {
|
||||
/* Pointer to the far child */
|
||||
const KDNode * __restrict node;
|
||||
/* Distance traveled along the ray (entry or exit) */
|
||||
Float t;
|
||||
/* Previous stack item */
|
||||
uint32_t prev;
|
||||
/* Associated point */
|
||||
Point pb;
|
||||
};
|
||||
|
||||
#if defined(MTS_HAS_COHERENT_RT)
|
||||
/// Ray traversal stack entry for uncoherent ray tracing
|
||||
struct CoherentKDStackEntry {
|
||||
|
@ -436,78 +223,15 @@ protected:
|
|||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Intersection method from Vlastimil Havran's
|
||||
* PhD thesis (algorithm TA^B_{rec})
|
||||
*/
|
||||
bool rayIntersect(const Ray &ray, Intersection &its, Float mint, Float maxt,
|
||||
bool shadowRay, unsigned int &shapeIndex, unsigned int &primIndex) const;
|
||||
|
||||
/// Recursive tree-building algorithm
|
||||
void buildTree(int nodeIndex, int depth, int badRefines,
|
||||
int numPrims, const AABB &aabb, EdgeEventVec3 &allEvents);
|
||||
|
||||
/// Create a leaf kd-tree node
|
||||
void createLeaf(int nodeIndex, int depth, int numPrims,
|
||||
EdgeEventVec3 &allEvents);
|
||||
|
||||
/**
|
||||
* Fallback for incoherent rays
|
||||
*/
|
||||
inline void rayIntersectPacketIncoherent(const Ray *rays, Intersection *its) const {
|
||||
for (int i=0; i<4; i++) {
|
||||
if (!rayIntersect(rays[i], its[i]))
|
||||
its[i].t = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
/* Has the kd-tree been built yet? */
|
||||
bool m_built;
|
||||
/* Axis-aligned bounding box of the root node */
|
||||
AABB m_rootBounds;
|
||||
/* Bounding sphere of the root node */
|
||||
BSphere m_bsphere;
|
||||
/* Pointers to all contained shapes */
|
||||
/// Virtual destructor
|
||||
virtual ~KDTree();
|
||||
private:
|
||||
std::vector<const Shape *> m_shapes;
|
||||
/// Storage for kd-tree nodes
|
||||
std::vector<KDNode, std::aligned_allocator<KDNode> > m_nodes;
|
||||
#if defined(MTS_USE_TRIACCEL4)
|
||||
/// Explicitly store per-leaf quad-packed triangles
|
||||
TriAccel4 *m_packedTriangles;
|
||||
std::vector<TriAccel4> m_tempPackedTriangles;
|
||||
unsigned int m_packedTriangleCount;
|
||||
std::vector<bool> m_triangleFlag;
|
||||
std::vector<index_type> m_shapeMap;
|
||||
#if !defined(MTS_KD_CONSERVE_MEMORY)
|
||||
TriAccel *m_triAccel;
|
||||
#endif
|
||||
#if defined(MTS_USE_TRIACCEL) || defined(MTS_USE_MT)
|
||||
/// Storage for triangle redirection indices
|
||||
std::vector<unsigned int> m_indices;
|
||||
#endif
|
||||
/// Total number of triangles/non-triangles in the tree
|
||||
unsigned int m_triangleCount, m_nonTriangleCount, m_primitiveCount;
|
||||
/// Geometry storage
|
||||
KDTriangle* m_triangles;
|
||||
/// Cost values for the surface are heuristic
|
||||
Float m_traversalCost, m_intersectionCost, m_emptyBonus;
|
||||
/// Ad-hoc depth cutoff value when building the tree
|
||||
int m_maxDepth;
|
||||
/// Allowed number of bad refines before creating a leaf
|
||||
int m_maxBadRefines;
|
||||
/// Minimal number of primitives per node
|
||||
int m_stopPrims;
|
||||
/// Use primitive clipping?
|
||||
bool m_clip;
|
||||
/// Storage for edge events
|
||||
EdgeEventVec3 m_events, *m_rightEvents;
|
||||
/// Short-term storage for edge events completely located left or right
|
||||
EdgeEventVec m_eventsL, m_eventsR;
|
||||
/// Short-term storage for edge events from by prims overlapping the split
|
||||
EdgeEventVec m_sEventsL, m_sEventsR;
|
||||
/// Statistics
|
||||
int m_leafNodes, m_innerNodes;
|
||||
int m_minLeafPrims, m_maxLeafPrims;
|
||||
int m_totalLeafDepth, m_actualMaxDepth;
|
||||
int m_leafPrims, m_clippedAway;
|
||||
int m_badRefines, m_bucketCount;
|
||||
int m_failures, *m_triBuckets;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -19,12 +19,98 @@
|
|||
#if !defined(__LUMINAIRE_H)
|
||||
#define __LUMINAIRE_H
|
||||
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/render/shape.h>
|
||||
#include <mitsuba/render/shader.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
/**
|
||||
* Data structure used to record information associated with
|
||||
* sampled shadow rays
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER LuminaireSamplingRecord {
|
||||
public:
|
||||
/// Create an invalid record
|
||||
inline LuminaireSamplingRecord() : luminaire(NULL) { }
|
||||
|
||||
/**
|
||||
* When a ray strikes a luminaire that is part of the scene,
|
||||
* the associated intersection record can be converted into
|
||||
* a luminaire sampling record in order to query the luminaire
|
||||
* for emitted radiance. (defined in records.inl)
|
||||
*/
|
||||
LuminaireSamplingRecord(const Intersection &its, const Vector &direction);
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Associated luminaire
|
||||
const Luminaire *luminaire;
|
||||
|
||||
/// Data record of the associated shape sample
|
||||
ShapeSamplingRecord sRec;
|
||||
|
||||
/// Direction vector pointing away from the light source
|
||||
Vector d;
|
||||
|
||||
/// Probability density of the sampled point on the luminaire
|
||||
Float pdf;
|
||||
|
||||
/**
|
||||
* Emitted radiance at 'p' into direction 'd' divided by the associated
|
||||
* probability. Already contains the geometric term and optionally
|
||||
* attenuation when generated via Scene::sampleLuminaireAttenuated.
|
||||
*/
|
||||
Spectrum Le;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data structure used to record information associated with
|
||||
* luminaire emission sampling
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER EmissionRecord {
|
||||
public:
|
||||
enum ESamplingType {
|
||||
ENormal,
|
||||
EPreview
|
||||
};
|
||||
|
||||
/// Construct a luminaire sampling record that can be used to query a luminaire
|
||||
inline EmissionRecord(const Luminaire *luminaire,
|
||||
const ShapeSamplingRecord &sRec, const Vector &d)
|
||||
: luminaire(luminaire), type(ENormal), sRec(sRec), d(d) { }
|
||||
|
||||
inline EmissionRecord() : luminaire(NULL), type(ENormal) { }
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Associated luminaire
|
||||
const Luminaire *luminaire;
|
||||
|
||||
ESamplingType type;
|
||||
|
||||
/// Data record of the associated shape sample
|
||||
ShapeSamplingRecord sRec;
|
||||
|
||||
/// Direction vector pointing away from the light source
|
||||
Vector d;
|
||||
|
||||
/**
|
||||
* Radiant emittance at the sampled point. When this
|
||||
* record was populated using Scene::sampleEmission(), 'P'
|
||||
* has already been multiplied by the directional
|
||||
* scattering distribution and divided by the associated
|
||||
* sampling densities.
|
||||
*/
|
||||
Spectrum P;
|
||||
|
||||
/// Area probability density
|
||||
Float pdfArea;
|
||||
|
||||
/// Directional probability density (wrt. projected solid angles)
|
||||
Float pdfDir;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract implementation of a luminaire. Supports emission and
|
||||
|
|
|
@ -21,16 +21,63 @@
|
|||
|
||||
#include <mitsuba/core/netobject.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/render/records.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
/**
|
||||
* Data record associated with the sampling procedure responsible for
|
||||
* choosing a point on the in-scattering line integral (while solving
|
||||
* the radiative transfer equation using Monte Carlo methods).
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER MediumSamplingRecord {
|
||||
public:
|
||||
inline MediumSamplingRecord() : medium(NULL) { }
|
||||
|
||||
class Scene;
|
||||
class Sampler;
|
||||
class RenderQueue;
|
||||
class RenderJob;
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/* Traveled distance */
|
||||
Float t;
|
||||
|
||||
/** \brief Abstract phase function
|
||||
/* Interaction point */
|
||||
Point p;
|
||||
|
||||
/* Local particle orientation */
|
||||
Vector orientation;
|
||||
|
||||
/* Reference to the associated medium */
|
||||
const Medium *medium;
|
||||
|
||||
/* Specifies the attenuation along the segment [mint, t].
|
||||
When sampling a distance fails, this contains the
|
||||
attenuation along the whole ray.
|
||||
*/
|
||||
Spectrum attenuation;
|
||||
|
||||
/* The medium's absorption coefficient at that point */
|
||||
Spectrum sigmaA;
|
||||
|
||||
/* The medium's scattering coefficient at that point */
|
||||
Spectrum sigmaS;
|
||||
|
||||
/**
|
||||
* Can contain two things:
|
||||
* If a medium interaction occurred, this records the probability
|
||||
* of having sampled the point p. Otherwise, it contains the
|
||||
* probability of moving through the medium without an interaction.
|
||||
*/
|
||||
Float pdf;
|
||||
|
||||
/// Max. albedo over all spectral samples
|
||||
Float albedo;
|
||||
|
||||
/// Multiple importance sampling weight
|
||||
Float miWeight;
|
||||
};
|
||||
|
||||
/** \brief Abstract phase function.
|
||||
*
|
||||
* The convention used here is that the incident and exitant
|
||||
* direction arguments point away from the scattering event (similar to BSDFs).
|
||||
*/
|
||||
class MTS_EXPORT_RENDER PhaseFunction : public ConfigurableObject {
|
||||
public:
|
||||
|
@ -39,7 +86,7 @@ public:
|
|||
EDelta
|
||||
};
|
||||
|
||||
/// Evaluate the phase function for a pair of directions (wi, wo)
|
||||
/// Evaluate the phase function for an outward-pointing pair of directions (wi, wo)
|
||||
virtual Spectrum f(const MediumSamplingRecord &mRec, const Vector &wi, const Vector &wo) const = 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#if !defined(__MIPMAP_H)
|
||||
#define __MIPMAP_H
|
||||
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/render/shape.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -66,6 +66,14 @@ public:
|
|||
|
||||
/// Return a pointer to internal image representation at full resolution
|
||||
inline const Spectrum *getImageData() const { return m_pyramid[0]; }
|
||||
|
||||
/// Return a pointer to internal image representation at the specified resolution
|
||||
inline const Spectrum *getImageData(int level) const { return m_pyramid[level]; }
|
||||
|
||||
/// Return the resolution of the specified level
|
||||
inline const Vector2i getLevelResolution(int level) const {
|
||||
return Vector2i(m_levelWidth[level], m_levelHeight[level]);
|
||||
}
|
||||
|
||||
/// Get the component-wise maximum at the zero level
|
||||
Spectrum getMaximum() const;
|
||||
|
@ -78,10 +86,12 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// \cond
|
||||
struct ResampleWeight {
|
||||
int firstTexel;
|
||||
Float weight[4];
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
/// Calculate weights for up-sampling a texture
|
||||
ResampleWeight *resampleWeights(int oldRes, int newRes) const;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define __MIPMAP3D_H
|
||||
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -82,6 +83,7 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
/// \cond
|
||||
struct QueryContext {
|
||||
uint8_t a; // ray directionality flag
|
||||
Float maxt;
|
||||
|
@ -99,6 +101,7 @@ protected:
|
|||
int32_t child[8];
|
||||
float value;
|
||||
};
|
||||
/// \endcond
|
||||
|
||||
uint32_t build(int level, const Point3i &p, float **pyramid,
|
||||
std::vector<bool> *bitPyramid);
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#if !defined(__PHOTONMAP_H)
|
||||
#define __PHOTONMAP_H
|
||||
|
||||
#include <mitsuba/core/serialization.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/render/records.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -112,7 +112,7 @@ public:
|
|||
Spectrum estimateIrradiance(
|
||||
const Point &p, const Normal &n,
|
||||
Float searchRadius,
|
||||
unsigned int maxPhotons) const;
|
||||
size_t maxPhotons) const;
|
||||
|
||||
/**
|
||||
* Using the photon map, estimate the irradiance on a surface (filtered
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
Spectrum estimateIrradianceFiltered(
|
||||
const Point &p, const Normal &n,
|
||||
Float searchRadius,
|
||||
unsigned int maxPhotons) const;
|
||||
size_t maxPhotons) const;
|
||||
|
||||
/**
|
||||
* Using the photon map and a surface intersection, estimate the
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
Spectrum estimateRadianceFiltered(
|
||||
const Intersection &its,
|
||||
Float searchRadius,
|
||||
unsigned int maxPhotons) const;
|
||||
size_t maxPhotons) const;
|
||||
|
||||
/**
|
||||
* Compute scattered contributions from all photons within
|
||||
|
@ -156,7 +156,7 @@ public:
|
|||
* to the 'maxDepth' parameter. This function is meant to be
|
||||
* used with progressive photon mapping.
|
||||
*/
|
||||
int estimateRadianceRaw(const Intersection &its,
|
||||
size_t estimateRadianceRaw(const Intersection &its,
|
||||
Float searchRadius, Spectrum &result, int maxDepth) const;
|
||||
|
||||
/**
|
||||
|
@ -176,7 +176,7 @@ public:
|
|||
const MediumSamplingRecord &mRec,
|
||||
const Ray &ray,
|
||||
Float searchRadius,
|
||||
unsigned int maxPhotons,
|
||||
size_t maxPhotons,
|
||||
const Medium *medium) const;
|
||||
|
||||
/// Determine if the photon map is completely filled
|
||||
|
@ -195,7 +195,7 @@ public:
|
|||
}
|
||||
|
||||
/// Return the position of a photon in the photon map (for debugging)
|
||||
inline Point getPhotonPosition(int i) const {
|
||||
inline Point getPhotonPosition(size_t i) const {
|
||||
return m_photons[i].getPosition();
|
||||
}
|
||||
|
||||
|
@ -313,7 +313,9 @@ public:
|
|||
#if defined(DOUBLE_PRECISION) || SPECTRUM_SAMPLES > 3
|
||||
return power;
|
||||
#else
|
||||
return Spectrum(power);
|
||||
Spectrum result;
|
||||
result.fromRGBE(power);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -358,6 +360,7 @@ protected:
|
|||
typedef std::vector<photon_ptr>::iterator photon_iterator;
|
||||
typedef std::pair<float, const_photon_ptr> search_result;
|
||||
|
||||
/// \cond
|
||||
/* Photon position comparison functor (< comparison). */
|
||||
struct comparePhotonLess : public std::unary_function<photon_ptr, bool> {
|
||||
public:
|
||||
|
@ -397,6 +400,8 @@ protected:
|
|||
return a.first <= b.first;
|
||||
}
|
||||
};
|
||||
|
||||
/// \endcond
|
||||
protected:
|
||||
/* ===================================================================== */
|
||||
/* Protected subroutines */
|
||||
|
@ -423,8 +428,8 @@ protected:
|
|||
* @return
|
||||
* The number of results
|
||||
*/
|
||||
unsigned int nnSearch(const Point &p, Float &searchRadiusSquared,
|
||||
unsigned int maxSize, search_result *results) const;
|
||||
size_t nnSearch(const Point &p, Float &searchRadiusSquared,
|
||||
size_t maxSize, search_result *results) const;
|
||||
|
||||
/**
|
||||
* Partition a list of photons so that there is an ordering between
|
||||
|
@ -466,17 +471,16 @@ protected:
|
|||
inline size_t rightChild(size_t index) const { return 2*index + 1; }
|
||||
inline bool isInnerNode(size_t index) const { return index <= m_lastInnerNode; }
|
||||
inline bool hasRightChild(size_t index) const { return index <= m_lastRChildNode; }
|
||||
protected:
|
||||
private:
|
||||
/* ===================================================================== */
|
||||
/* Protected attributes */
|
||||
/* ===================================================================== */
|
||||
|
||||
struct ThreadContext {
|
||||
AABB aabb;
|
||||
int photonOffset;
|
||||
int photonCount;
|
||||
int maxPhotons;
|
||||
uint8_t unused[128]; // Avoid false sharing
|
||||
size_t photonOffset;
|
||||
size_t photonCount;
|
||||
size_t maxPhotons;
|
||||
uint8_t unused[128-sizeof(AABB)-sizeof(size_t)*3]; // Avoid false sharing
|
||||
};
|
||||
|
||||
/* Precomputed lookup tables */
|
||||
|
|
|
@ -1,556 +0,0 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__RECORDS_H)
|
||||
#define __RECORDS_H
|
||||
|
||||
#include <mitsuba/core/frame.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Shape;
|
||||
class Luminaire;
|
||||
class Medium;
|
||||
class Scene;
|
||||
class Sampler;
|
||||
class BSDF;
|
||||
|
||||
/**
|
||||
* Specifies the transported quantity when sampling a BSDF
|
||||
*/
|
||||
enum ETransportQuantity {
|
||||
ERadiance = 1,
|
||||
EImportance = 2
|
||||
};
|
||||
|
||||
/** \brief Container for all information related to
|
||||
* a surface intersection
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER Intersection {
|
||||
public:
|
||||
inline Intersection() : t(std::numeric_limits<Float>::infinity()), shape(NULL) {
|
||||
}
|
||||
|
||||
/* Convert a vector expressed inside the shading frame into world
|
||||
coordinates */
|
||||
inline Vector toWorld(const Vector &v) const {
|
||||
return shFrame.toWorld(v);
|
||||
}
|
||||
|
||||
/* Convert a vector expressed inside world coordinates frame into
|
||||
shading frame coordinates */
|
||||
inline Vector toLocal(const Vector &v) const {
|
||||
return shFrame.toLocal(v);
|
||||
}
|
||||
|
||||
/// Is the current intersection valid?
|
||||
inline bool isValid() const {
|
||||
return t != std::numeric_limits<Float>::infinity();
|
||||
}
|
||||
|
||||
/// Is the intersected shape also a luminaire?
|
||||
inline bool isLuminaire() const;
|
||||
|
||||
/// Does the intersected shape have a subsurface integrator?
|
||||
inline bool hasSubsurface() const;
|
||||
|
||||
/**
|
||||
* Returns the BSDF of the intersected shape. The
|
||||
* parameter ray must match the one used to create
|
||||
* the intersection record. Computes texture coordinate
|
||||
* partials if this is required by the BSDF.
|
||||
* Should only be called if there is a valid
|
||||
* intersection!
|
||||
*/
|
||||
inline const BSDF *getBSDF(const RayDifferential &ray);
|
||||
|
||||
/**
|
||||
* Returns radiance emitted into direction d.
|
||||
* Should only be called if the intersected
|
||||
* shape is indeed a luminaire!
|
||||
*/
|
||||
inline Spectrum Le(const Vector &d) const;
|
||||
|
||||
/**
|
||||
* Returns radiance from a subsurface integrator
|
||||
* emitted into direction d.
|
||||
* Should only be called if the intersected
|
||||
* shape does indeed have a subsurface integrator!
|
||||
*/
|
||||
inline Spectrum LoSub(const Scene *scene, const Vector &d) const;
|
||||
|
||||
/// Computes texture coordinate partials
|
||||
void computePartials(const RayDifferential &ray);
|
||||
|
||||
/* Return a string representation */
|
||||
std::string toString() const;
|
||||
public:
|
||||
/* Incident direction in the local frame */
|
||||
Vector wi;
|
||||
|
||||
/* Distance traveled along the ray */
|
||||
Float t;
|
||||
|
||||
/* Intersection point in 3D coordinates */
|
||||
Point p;
|
||||
|
||||
/* Geometry frame */
|
||||
Frame geoFrame;
|
||||
|
||||
/* Shading frame */
|
||||
Frame shFrame;
|
||||
|
||||
/* UV surface coordinates */
|
||||
Point2 uv;
|
||||
|
||||
/* Position partials wrt. to changes in texture-space */
|
||||
Vector dpdu, dpdv;
|
||||
|
||||
/* Texture coordinate mapping partials wrt. changes in screen-space */
|
||||
Float dudx, dudy, dvdx, dvdy;
|
||||
|
||||
/* Affected shape */
|
||||
const Shape *shape;
|
||||
|
||||
/* Have texture coordinate partials been computed */
|
||||
bool hasUVPartials;
|
||||
};
|
||||
|
||||
struct MTS_EXPORT_RENDER ShapeSamplingRecord {
|
||||
public:
|
||||
inline ShapeSamplingRecord() { }
|
||||
|
||||
inline ShapeSamplingRecord(const Point &p, const Normal &n)
|
||||
: p(p), n(n) { }
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Sampled surface position
|
||||
Point p;
|
||||
|
||||
/// Sampled surface normal
|
||||
Normal n;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data structure used to record information associated with
|
||||
* sampled shadow rays
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER LuminaireSamplingRecord {
|
||||
public:
|
||||
/// Create an invalid record
|
||||
inline LuminaireSamplingRecord() : luminaire(NULL) { }
|
||||
|
||||
/**
|
||||
* When a ray strikes a luminaire that is part of the scene,
|
||||
* the associated intersection record can be converted into
|
||||
* a luminaire sampling record in order to query the luminaire
|
||||
* for emitted radiance. (defined in shape.h)
|
||||
*/
|
||||
inline LuminaireSamplingRecord(const Intersection &its, const Vector &direction);
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Associated luminaire
|
||||
const Luminaire *luminaire;
|
||||
|
||||
/// Data record of the associated shape sample
|
||||
ShapeSamplingRecord sRec;
|
||||
|
||||
/// Direction vector pointing away from the light source
|
||||
Vector d;
|
||||
|
||||
/// Probability density of the sampled point on the luminaire
|
||||
Float pdf;
|
||||
|
||||
/**
|
||||
* Emitted radiance at 'p' into direction 'd' divided by the associated
|
||||
* probability. Already contains the geometric term and optionally
|
||||
* attenuation when generated via Scene::sampleLuminaireAttenuated.
|
||||
*/
|
||||
Spectrum Le;
|
||||
};
|
||||
|
||||
struct MTS_EXPORT_RENDER EmissionRecord {
|
||||
public:
|
||||
enum ESamplingType {
|
||||
ENormal,
|
||||
EPreview
|
||||
};
|
||||
|
||||
/// Construct a luminaire sampling record that can be used to query a luminaire
|
||||
inline EmissionRecord(const Luminaire *luminaire,
|
||||
const ShapeSamplingRecord &sRec, const Vector &d)
|
||||
: luminaire(luminaire), type(ENormal), sRec(sRec), d(d) { }
|
||||
|
||||
inline EmissionRecord() : luminaire(NULL), type(ENormal) { }
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Associated luminaire
|
||||
const Luminaire *luminaire;
|
||||
|
||||
ESamplingType type;
|
||||
|
||||
/// Data record of the associated shape sample
|
||||
ShapeSamplingRecord sRec;
|
||||
|
||||
/// Direction vector pointing away from the light source
|
||||
Vector d;
|
||||
|
||||
/**
|
||||
* Radiant emittance at the sampled point. When this
|
||||
* record was populated using Scene::sampleEmission(), 'P'
|
||||
* has already been multiplied by the directional
|
||||
* scattering distribution and divided by the associated
|
||||
* sampling densities.
|
||||
*/
|
||||
Spectrum P;
|
||||
|
||||
/// Area probability density
|
||||
Float pdfArea;
|
||||
|
||||
/// Directional probability density (wrt. projected solid angles)
|
||||
Float pdfDir;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data record associated with the sampling procedure responsible for
|
||||
* choosing a point on the in-scattering line integral (while solving
|
||||
* the radiative transfer equation using Monte Carlo methods).
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER MediumSamplingRecord {
|
||||
public:
|
||||
inline MediumSamplingRecord() : medium(NULL) { }
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/* Traveled distance */
|
||||
Float t;
|
||||
|
||||
/* Interaction point */
|
||||
Point p;
|
||||
|
||||
/* Local particle orientation */
|
||||
Vector orientation;
|
||||
|
||||
/* Reference to the associated medium */
|
||||
const Medium *medium;
|
||||
|
||||
/* Specifies the attenuation along the segment [mint, t].
|
||||
When sampling a distance fails, this contains the
|
||||
attenuation along the whole ray.
|
||||
*/
|
||||
Spectrum attenuation;
|
||||
|
||||
/* The medium's absorption coefficient at that point */
|
||||
Spectrum sigmaA;
|
||||
|
||||
/* The medium's scattering coefficient at that point */
|
||||
Spectrum sigmaS;
|
||||
|
||||
/**
|
||||
* Can contain two things:
|
||||
* If a medium interaction occurred, this records the probability
|
||||
* of having sampled the point p. Otherwise, it contains the
|
||||
* probability of moving through the medium without an interaction.
|
||||
*/
|
||||
Float pdf;
|
||||
|
||||
/// Max. albedo over all spectral samples
|
||||
Float albedo;
|
||||
|
||||
/// Multiple importance sampling weight
|
||||
Float miWeight;
|
||||
};
|
||||
|
||||
struct MTS_EXPORT_RENDER RadianceQueryRecord {
|
||||
public:
|
||||
/**
|
||||
* List of suported query types. These can be combined by a binary OR.
|
||||
*/
|
||||
enum ERadianceQuery {
|
||||
/* Emitted radiance from a luminaire intersected by the ray */
|
||||
EEmittedRadiance = 0x0001,
|
||||
|
||||
/* Emitted radiance from a subsurface integrator */
|
||||
ESubsurfaceRadiance = 0x0002,
|
||||
|
||||
/* Direct (surface) radiance */
|
||||
EDirectRadiance = 0x0004,
|
||||
|
||||
/* Indirect (surface) radiance, where the last bounce did not go
|
||||
through a Dirac delta BSDF */
|
||||
EIndirectRadiance = 0x0008,
|
||||
|
||||
/* Indirect (surface) radiance, where the last bounce went
|
||||
through a Dirac delta BSDF */
|
||||
ECausticRadiance = 0x0010,
|
||||
|
||||
/* In-scattered radiance due to volumetric scattering (direct) */
|
||||
EInscatteredDirectRadiance = 0x0020,
|
||||
|
||||
/* In-scattered radiance due to volumetric scattering (indirect) */
|
||||
EInscatteredIndirectRadiance = 0x0040,
|
||||
|
||||
/* Distance to the next surface intersection */
|
||||
EDistance = 0x0080,
|
||||
|
||||
/* Opacity value: 1 when a surface was hit, 0 when the ray leads
|
||||
into empty space. When there is a participating medium,
|
||||
this can also take on fractional values. */
|
||||
EOpacity = 0x0100,
|
||||
|
||||
/* A ray intersection may need to be performed. This can be set to
|
||||
zero if the caller has already provided the intersection */
|
||||
EIntersection = 0x0200,
|
||||
|
||||
/* Radiance from volumes */
|
||||
EVolumeRadiance = EInscatteredDirectRadiance | EInscatteredIndirectRadiance,
|
||||
|
||||
/* Radiance query without emitted radiance, ray intersection required */
|
||||
ERadianceNoEmission = ESubsurfaceRadiance | EDirectRadiance | EIndirectRadiance
|
||||
| ECausticRadiance | EInscatteredDirectRadiance | EInscatteredIndirectRadiance | EIntersection,
|
||||
|
||||
/* Default radiance query, ray intersection required */
|
||||
ERadiance = ERadianceNoEmission | EEmittedRadiance,
|
||||
|
||||
/* Radiance + opacity */
|
||||
ECameraRay = ERadiance | EOpacity
|
||||
};
|
||||
|
||||
/// Construct an invalid radiance query record
|
||||
inline RadianceQueryRecord()
|
||||
: type(0), scene(NULL), sampler(NULL),
|
||||
depth(0), alpha(0), dist(-1), wavelength(-1), extra(0) {
|
||||
}
|
||||
|
||||
/// Construct a radiance query record for the given scene and sampler
|
||||
inline RadianceQueryRecord(const Scene *scene, Sampler *sampler)
|
||||
: type(0), scene(scene), sampler(sampler),
|
||||
depth(0), alpha(0), dist(-1), wavelength(-1), extra(0) {
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
inline RadianceQueryRecord(const RadianceQueryRecord &rRec)
|
||||
: type(rRec.type), scene(rRec.scene), sampler(rRec.sampler),
|
||||
depth(rRec.depth), alpha(rRec.alpha), dist(rRec.dist),
|
||||
wavelength(rRec.wavelength), extra(rRec.extra) {
|
||||
}
|
||||
|
||||
/// Begin a new query of the given type
|
||||
inline void newQuery(int _type) {
|
||||
type = _type;
|
||||
depth = 1;
|
||||
wavelength = -1;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
/// Initialize the query record for a recursive query
|
||||
inline void recursiveQuery(const RadianceQueryRecord &parent, int _type) {
|
||||
type = _type;
|
||||
scene = parent.scene;
|
||||
sampler = parent.sampler;
|
||||
depth = parent.depth+1;
|
||||
wavelength = parent.wavelength;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a ray intersection (in records.inl). This
|
||||
* does several things at once - if the intersection has
|
||||
* already been provided, the function returns.
|
||||
* Otherwise, it
|
||||
* - performs the ray intersection
|
||||
* - computes the attenuation due to participating media
|
||||
* and stores it in <tt>attenuation</tt>.
|
||||
* - sets the alpha value (if <tt>EAlpha</tt> is set in <tt>type</tt>)
|
||||
* - sets the distance value (if <tt>EDistance</tt> is set in <tt>type</tt>)
|
||||
* - clears the <tt>EIntersection</tt> flag in <tt>type</tt>
|
||||
* Returns true if there is a valid intersection.
|
||||
*/
|
||||
inline bool rayIntersect(const RayDifferential &ray);
|
||||
|
||||
/// Retrieve a 2D sample
|
||||
inline Point2 nextSample2D();
|
||||
|
||||
/// Retrieve a 1D sample
|
||||
inline Float nextSample1D();
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
// An asterisk (*) marks entries, which may be overwritten
|
||||
// by the callee.
|
||||
|
||||
/// Query type (*)
|
||||
int type;
|
||||
|
||||
/// Pointer to the associated scene
|
||||
const Scene *scene;
|
||||
|
||||
/// Sample generator
|
||||
Sampler *sampler;
|
||||
|
||||
/// Current depth value (# of light bounces) (*)
|
||||
int depth;
|
||||
|
||||
/// Surface interaction data structure (*)
|
||||
Intersection its;
|
||||
|
||||
/// Attenuation along the current ray (*)
|
||||
Spectrum attenuation;
|
||||
|
||||
/// Opacity value of the associated pixel (*)
|
||||
Float alpha;
|
||||
|
||||
/**
|
||||
* Ray distance to the first surface interaction
|
||||
* (if requested by the query type EDistance) (*)
|
||||
*/
|
||||
Float dist;
|
||||
|
||||
/**
|
||||
* In some cases, the integrator may be forced to restrict
|
||||
* radiance computations to one wavelength (e.g. when intersecting
|
||||
* a dielectric material with dispersion or while path
|
||||
* tracing through a highly scattering medium with a non-constant
|
||||
* scattering coefficient). This attribute is used to store the
|
||||
* chosen wavelength. (*)
|
||||
*/
|
||||
int wavelength;
|
||||
|
||||
/**
|
||||
* Internal flag, which can be used to pass additional information
|
||||
* amonst recursive calls inside an integrator. The use
|
||||
* is dependent on the particular integrator implementation. (*)
|
||||
*/
|
||||
int extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data structure, which contains all information required to
|
||||
* sample or query a BSDF.
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER BSDFQueryRecord {
|
||||
public:
|
||||
/**
|
||||
* Given a surface interaction and an incident direction
|
||||
* construct a query record which can be used to sample
|
||||
* an outgoing direction.
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
explicit inline BSDFQueryRecord(RadianceQueryRecord &rRec, const Intersection &its, Point2 sample)
|
||||
: rRec(&rRec), its(its), wi(its.wi), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a surface interaction and an incident direction,
|
||||
* construct a query record which can be used to sample
|
||||
* an outgoing direction.
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
explicit inline BSDFQueryRecord(const Intersection &its, Point2 sample)
|
||||
: rRec(NULL), its(its), wi(its.wi), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
explicit inline BSDFQueryRecord(RadianceQueryRecord &rRec,
|
||||
const Intersection &its, const Vector &wo)
|
||||
: rRec(&rRec), its(its), wi(its.wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
* For convenience, this function uses the local incident direction
|
||||
* vector contained in the supplied intersection record.
|
||||
*/
|
||||
explicit inline BSDFQueryRecord(const Intersection &its, const Vector &wo)
|
||||
: rRec(NULL), its(its), wi(its.wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a surface interaction an an incident/exitant direction
|
||||
* pair (wi, wo), create a BSDF query record to evaluate f(wi, wo).
|
||||
*/
|
||||
explicit inline BSDFQueryRecord(const Intersection &its, const Vector &wi, const Vector &wo)
|
||||
: rRec(NULL), its(its), wi(wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline BSDFQueryRecord(const BSDFQueryRecord &r) :
|
||||
rRec(r.rRec), its(r.its), wi(r.wi), wo(r.wo), sample(r.sample), quantity(r.quantity),
|
||||
typeMask(r.typeMask), sampledType(r.sampledType), component(r.component),
|
||||
sampledComponent(r.sampledComponent) {
|
||||
}
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/* Pointer to the associated radiance query record (or NULL) */
|
||||
RadianceQueryRecord *rRec;
|
||||
|
||||
/* Surface interaction */
|
||||
const Intersection &its;
|
||||
|
||||
/* Incident direction */
|
||||
Vector wi;
|
||||
|
||||
/* Outgoing/sampled direction */
|
||||
Vector wo;
|
||||
|
||||
/* Random sample used to generate the new direction */
|
||||
Point2 sample;
|
||||
|
||||
/* Transported quantity (radiance or importance) -- required for
|
||||
non-reciprocal BSDFs such as transmission through a dielectric
|
||||
material */
|
||||
ETransportQuantity quantity;
|
||||
|
||||
/* Bit mask containing the component types, which may be sampled.
|
||||
After sampling has been performed, the component type is stored
|
||||
inside 'sampledType'. */
|
||||
unsigned int typeMask, sampledType;
|
||||
|
||||
/* To sample a specific BSDF component, this entry must be non-negative.
|
||||
After sampling has been performed, the component index is stored
|
||||
inside 'sampledComponent' */
|
||||
int component, sampledComponent;
|
||||
};
|
||||
|
||||
extern void operator<<(const ETransportQuantity &quantity, std::ostream &os);
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __RECORDS_H */
|
|
@ -2,6 +2,33 @@
|
|||
#define __RECORDS_INLINE_H
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
inline BSDFQueryRecord::BSDFQueryRecord(RadianceQueryRecord &rRec,
|
||||
const Intersection &its, Point2 sample): rRec(&rRec),
|
||||
its(its), wi(its.wi), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline BSDFQueryRecord::BSDFQueryRecord(const Intersection &its, Point2 sample)
|
||||
: rRec(NULL), its(its), wi(its.wi), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline BSDFQueryRecord::BSDFQueryRecord(RadianceQueryRecord &rRec,
|
||||
const Intersection &its, const Vector &wo)
|
||||
: rRec(&rRec), its(its), wi(its.wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline BSDFQueryRecord::BSDFQueryRecord(const Intersection &its, const Vector &wo)
|
||||
: rRec(NULL), its(its), wi(its.wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline BSDFQueryRecord::BSDFQueryRecord(const Intersection &its, const Vector &wi, const Vector &wo)
|
||||
: rRec(NULL), its(its), wi(wi), wo(wo), sample(sample), quantity(ERadiance),
|
||||
typeMask(0xFFFFFFFF), sampledType(0), component(-1), sampledComponent(-1) {
|
||||
}
|
||||
|
||||
inline bool Intersection::hasSubsurface() const {
|
||||
return shape->hasSubsurface();
|
||||
|
|
|
@ -62,7 +62,6 @@ private:
|
|||
ref<Scene> m_scene;
|
||||
ref<RenderQueue> m_queue;
|
||||
ref<TestSupervisor> m_testSupervisor;
|
||||
ref<FileResolver> m_fileResolver;
|
||||
int m_sceneResID, m_samplerResID, m_cameraResID;
|
||||
bool m_ownsSceneResource;
|
||||
bool m_ownsCameraResource;
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class RenderJob;
|
||||
|
||||
/**
|
||||
* Parallel process for rendering with sampling-based integrators. Splits
|
||||
* an image into square pixel regions, which can be processed independently.
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class RenderJob;
|
||||
|
||||
/**
|
||||
* Abstract render listener - can be used to react to
|
||||
* progress messages (e.g. in a GUI)
|
||||
|
@ -60,7 +58,7 @@ public:
|
|||
RenderQueue();
|
||||
|
||||
/// Return the current number of jobs in the queue
|
||||
inline int getJobCount() const { return m_jobs.size(); }
|
||||
inline size_t getJobCount() const { return m_jobs.size(); }
|
||||
|
||||
/// Add a render job to the queue
|
||||
void addJob(RenderJob *thr);
|
||||
|
@ -96,7 +94,7 @@ public:
|
|||
private:
|
||||
/// Virtual destructor
|
||||
virtual ~RenderQueue();
|
||||
protected:
|
||||
private:
|
||||
struct JobRecord {
|
||||
/* Only starting time for now */
|
||||
unsigned int startTime;
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#if !defined(__RFILTER_H)
|
||||
#define __RFILTER_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/random.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
|
@ -19,11 +19,17 @@
|
|||
#if !defined(__SCENE_H)
|
||||
#define __SCENE_H
|
||||
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/render/camera.h>
|
||||
#include <mitsuba/core/netobject.h>
|
||||
#include <mitsuba/core/pdf.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/render/kdtree.h>
|
||||
#include <mitsuba/render/camera.h>
|
||||
#include <mitsuba/render/luminaire.h>
|
||||
#include <mitsuba/render/integrator.h>
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/subsurface.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/medium.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
@ -80,7 +86,7 @@ public:
|
|||
* which have been made available to all local and remote workers.
|
||||
* Returns true upon successful completion.
|
||||
*/
|
||||
void preprocess(RenderQueue *queue, const RenderJob *job,
|
||||
bool preprocess(RenderQueue *queue, const RenderJob *job,
|
||||
int sceneResID, int cameraResID, int samplerResID);
|
||||
|
||||
/**
|
||||
|
@ -366,13 +372,13 @@ public:
|
|||
inline const std::vector<ConfigurableObject *> &getReferencedObjects() const { return m_objects; }
|
||||
|
||||
/// Return the name of the file containing the original description of this scene
|
||||
inline const std::string getSourceFile() const { return m_sourceFile; }
|
||||
inline const fs::path getSourceFile() const { return m_sourceFile; }
|
||||
/// Set the name of the file containing the original description of this scene
|
||||
void setSourceFile(const std::string &name) { m_sourceFile = name; }
|
||||
void setSourceFile(const fs::path &name) { m_sourceFile = name; }
|
||||
/// Return the render output filename
|
||||
inline const std::string getDestinationFile() const { return m_destinationFile; }
|
||||
inline const fs::path getDestinationFile() const { return m_destinationFile; }
|
||||
/// Set the render output filename
|
||||
void setDestinationFile(const std::string &name) { m_destinationFile = name; }
|
||||
void setDestinationFile(const fs::path &name) { m_destinationFile = name; }
|
||||
/// Does the destination file already exist?
|
||||
inline bool destinationExists() const { return m_camera->getFilm()->destinationExists(m_destinationFile); }
|
||||
|
||||
|
@ -410,8 +416,8 @@ private:
|
|||
std::vector<Subsurface *> m_ssIntegrators;
|
||||
std::vector<ConfigurableObject *> m_objects;
|
||||
std::vector<NetworkedObject *> m_netObjects;
|
||||
std::string m_sourceFile;
|
||||
std::string m_destinationFile;
|
||||
fs::path m_sourceFile;
|
||||
fs::path m_destinationFile;
|
||||
DiscretePDF m_luminairePDF;
|
||||
AABB m_aabb;
|
||||
BSphere m_bsphere;
|
||||
|
|
|
@ -36,6 +36,8 @@ class GPUProgram;
|
|||
class MTS_EXPORT_RENDER HWResource {
|
||||
public:
|
||||
virtual Shader *createShader(Renderer *renderer) const;
|
||||
|
||||
virtual ~HWResource() { }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,8 +36,10 @@ MTS_NAMESPACE_BEGIN
|
|||
*/
|
||||
class MTS_EXPORT_RENDER SceneHandler : public HandlerBase {
|
||||
public:
|
||||
SceneHandler();
|
||||
SceneHandler(const std::map<std::string, std::string> ¶ms,
|
||||
typedef std::map<std::string, ConfigurableObject *> NamedObjectMap;
|
||||
typedef std::map<std::string, std::string> ParameterMap;
|
||||
|
||||
SceneHandler(const ParameterMap ¶ms, NamedObjectMap *objects = NULL,
|
||||
bool isIncludedFile = false);
|
||||
virtual ~SceneHandler();
|
||||
|
||||
|
@ -56,6 +58,13 @@ public:
|
|||
inline const Scene *getScene() const { return m_scene.get(); }
|
||||
inline Scene *getScene() { return m_scene; }
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implementation of the SAX ErrorHandler interface
|
||||
// -----------------------------------------------------------------------
|
||||
void warning(const SAXParseException& exc);
|
||||
void error(const SAXParseException& exc);
|
||||
void fatalError(const SAXParseException& exc);
|
||||
protected:
|
||||
inline std::string transcode(const XMLCh * const xmlName) const {
|
||||
char *value = XMLString::transcode(xmlName);
|
||||
std::string result(value);
|
||||
|
@ -63,12 +72,8 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implementation of the SAX ErrorHandler interface
|
||||
// -----------------------------------------------------------------------
|
||||
void warning(const SAXParseException& exc);
|
||||
void error(const SAXParseException& exc);
|
||||
void fatalError(const SAXParseException& exc);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
struct ParseContext {
|
||||
inline ParseContext(ParseContext *_parent)
|
||||
|
@ -82,8 +87,8 @@ private:
|
|||
};
|
||||
|
||||
ref<Scene> m_scene;
|
||||
std::map<std::string, ConfigurableObject *> m_objects;
|
||||
std::map<std::string, std::string> m_params;
|
||||
ParameterMap m_params;
|
||||
NamedObjectMap *m_namedObjects;
|
||||
PluginManager *m_pluginManager;
|
||||
std::stack<ParseContext> m_context;
|
||||
Transform m_transform;
|
||||
|
|
|
@ -19,16 +19,132 @@
|
|||
#if !defined(__SHAPE_H)
|
||||
#define __SHAPE_H
|
||||
|
||||
#include <mitsuba/core/bsphere.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/core/transform.h>
|
||||
#include <mitsuba/core/frame.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/core/serialization.h>
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/luminaire.h>
|
||||
#include <mitsuba/render/subsurface.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Data record, which holds sampling-related information
|
||||
* for a shape.
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER ShapeSamplingRecord {
|
||||
public:
|
||||
/// Create a sampling record (does no initialization!)
|
||||
inline ShapeSamplingRecord() { }
|
||||
|
||||
/// Create a sampling record with the specified position and normal
|
||||
inline ShapeSamplingRecord(const Point &p, const Normal &n)
|
||||
: p(p), n(n) { }
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Sampled surface position
|
||||
Point p;
|
||||
|
||||
/// Sampled surface normal
|
||||
Normal n;
|
||||
};
|
||||
|
||||
/** \brief Container for all information related to
|
||||
* a surface intersection
|
||||
*/
|
||||
struct MTS_EXPORT_RENDER Intersection {
|
||||
public:
|
||||
inline Intersection() :
|
||||
t(std::numeric_limits<Float>::infinity()),
|
||||
shape(NULL) { }
|
||||
|
||||
/* Convert a vector expressed inside the shading frame into world
|
||||
coordinates */
|
||||
inline Vector toWorld(const Vector &v) const {
|
||||
return shFrame.toWorld(v);
|
||||
}
|
||||
|
||||
/* Convert a vector expressed inside world coordinates frame into
|
||||
shading frame coordinates */
|
||||
inline Vector toLocal(const Vector &v) const {
|
||||
return shFrame.toLocal(v);
|
||||
}
|
||||
|
||||
/// Is the current intersection valid?
|
||||
inline bool isValid() const {
|
||||
return t != std::numeric_limits<Float>::infinity();
|
||||
}
|
||||
|
||||
/// Is the intersected shape also a luminaire?
|
||||
inline bool isLuminaire() const;
|
||||
|
||||
/// Does the intersected shape have a subsurface integrator?
|
||||
inline bool hasSubsurface() const;
|
||||
|
||||
/**
|
||||
* Returns the BSDF of the intersected shape. The
|
||||
* parameter ray must match the one used to create
|
||||
* the intersection record. Computes texture coordinate
|
||||
* partials if this is required by the BSDF.
|
||||
* Should only be called if there is a valid
|
||||
* intersection!
|
||||
*/
|
||||
inline const BSDF *getBSDF(const RayDifferential &ray);
|
||||
|
||||
/**
|
||||
* Returns radiance emitted into direction d.
|
||||
* Should only be called if the intersected
|
||||
* shape is indeed a luminaire!
|
||||
*/
|
||||
inline Spectrum Le(const Vector &d) const;
|
||||
|
||||
/**
|
||||
* Returns radiance from a subsurface integrator
|
||||
* emitted into direction d.
|
||||
* Should only be called if the intersected
|
||||
* shape does indeed have a subsurface integrator!
|
||||
*/
|
||||
inline Spectrum LoSub(const Scene *scene, const Vector &d) const;
|
||||
|
||||
/// Computes texture coordinate partials
|
||||
void computePartials(const RayDifferential &ray);
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
public:
|
||||
/// Distance traveled along the ray
|
||||
Float t;
|
||||
|
||||
/* Intersection point in 3D coordinates */
|
||||
Point p;
|
||||
|
||||
/// Geometry frame
|
||||
Frame geoFrame;
|
||||
|
||||
/// Shading frame
|
||||
Frame shFrame;
|
||||
|
||||
/// UV surface coordinates
|
||||
Point2 uv;
|
||||
|
||||
/// Position partials wrt. the texture space parameterization
|
||||
Vector dpdu, dpdv;
|
||||
|
||||
/// Texture coordinate mapping partials wrt. changes in screen-space
|
||||
Float dudx, dudy, dvdx, dvdy;
|
||||
|
||||
/// Interpolated vertex color
|
||||
Spectrum color;
|
||||
|
||||
/// Incident direction in the local frame
|
||||
Vector wi;
|
||||
|
||||
/// Affected shape
|
||||
const Shape *shape;
|
||||
|
||||
/// Have texture coordinate partials been computed
|
||||
bool hasUVPartials;
|
||||
};
|
||||
|
||||
/** \brief Abstract base class of all shapes
|
||||
*/
|
||||
class MTS_EXPORT_RENDER Shape : public ConfigurableObject {
|
||||
|
@ -36,43 +152,59 @@ public:
|
|||
/// Is this a compound shape consisting of several sub-objects?
|
||||
virtual bool isCompound() const;
|
||||
|
||||
/// Return a sub-element of a compound shape
|
||||
/**
|
||||
* \brief Return a sub-element of a compound shape.
|
||||
*
|
||||
* When expanding shapes, the scene will repeatedly call this
|
||||
* function with increasing indices. Returning \a NULL indicates
|
||||
* that no more elements are available.
|
||||
*/
|
||||
virtual Shape *getElement(int i);
|
||||
|
||||
/// Does this shape support primitive clipping?
|
||||
virtual bool isClippable() const;
|
||||
/// Return the shape's surface area
|
||||
virtual Float getSurfaceArea() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the minimal axis-aligned bounding box of this shape
|
||||
* after it has clipped to the extends of another AABB.
|
||||
* This is extremely useful to construct better kd-trees.
|
||||
*/
|
||||
virtual AABB getClippedAABB(const AABB &aabb) const;
|
||||
|
||||
/// Fast ray intersection test (only calculates the intersection distance)
|
||||
virtual bool rayIntersect(const Ray &ray, Float start, Float end, Float &t) const;
|
||||
|
||||
/// More detailed ray intersection test, which stores local geometry information in 'its'
|
||||
virtual bool rayIntersect(const Ray &ray, Intersection &its) const;
|
||||
|
||||
#if defined(MTS_SSE)
|
||||
/// Perform 4 simultaneous intersection tests using SSE
|
||||
virtual __m128 rayIntersectPacket(const RayPacket4 &packet, const
|
||||
__m128 mint, __m128 maxt, __m128 inactive, Intersection4 &its) const;
|
||||
#endif
|
||||
|
||||
/// Return a bounding sphere containing the shape
|
||||
inline const BSphere &getBSphere() const { return m_bsphere; }
|
||||
|
||||
/// Return a bounding box containing the shape
|
||||
inline const AABB &getAABB() const { return m_aabb; }
|
||||
virtual AABB getAABB() const = 0;
|
||||
|
||||
/**
|
||||
* Sample a point on the shape - should be uniform
|
||||
* wrt. surface area. Returns the associated probability
|
||||
* density
|
||||
* \brief Returns the minimal axis-aligned bounding box
|
||||
* of this shape when clipped to another bounding box.
|
||||
*
|
||||
* This is extremely important to construct decent kd-trees.
|
||||
* The default implementation just takes the bounding box
|
||||
* returned by \ref getAABB() and clips it to \a box.
|
||||
*/
|
||||
virtual Float sampleArea(ShapeSamplingRecord &sRec, const Point2 &sample) const;
|
||||
virtual AABB getClippedAABB(const AABB &box) const;
|
||||
|
||||
/**
|
||||
* \brief Fast ray intersection test
|
||||
*
|
||||
* Check whether the shape is intersected by the given ray. Some
|
||||
* temporary space (\ref MTS_KD_INTERSECTION_TEMP-4 bytes) is,
|
||||
* supplied which can be used to cache information about the
|
||||
* intersection. The function \ref fillIntersectionRecord()
|
||||
* can later use this information to fill in a detailed
|
||||
* intersection record.
|
||||
*/
|
||||
virtual bool rayIntersect(const Ray &ray, Float mint,
|
||||
Float maxt, Float &t, void *temp) const;
|
||||
|
||||
/**
|
||||
* \brief Given that an intersection has been found, create a
|
||||
* detailed intersection record
|
||||
*/
|
||||
virtual void fillIntersectionRecord(const Ray &ray, Float t,
|
||||
const void *temp, Intersection &its) const;
|
||||
|
||||
/**
|
||||
* \brief Sample a point on the shape
|
||||
*
|
||||
* Should be uniform wrt. surface area. Returns the
|
||||
* associated probability density
|
||||
*/
|
||||
virtual Float sampleArea(ShapeSamplingRecord &sRec,
|
||||
const Point2 &sample) const;
|
||||
|
||||
/**
|
||||
* Return the probability density of sampling the
|
||||
|
@ -81,20 +213,22 @@ public:
|
|||
virtual Float pdfArea(const ShapeSamplingRecord &sRec) const;
|
||||
|
||||
/**
|
||||
* Sample a point on the shape - should be uniform
|
||||
* wrt. solid angle. Returns the associated probability
|
||||
* density
|
||||
* \brief Sample a point on the shape and return the associated
|
||||
* probability wrt. solid angle.
|
||||
*
|
||||
* Should ideally be uniform wrt. solid angle as seen
|
||||
* from \a x. The default implementation, just uses
|
||||
* \ref sampleArea, which can lead to lots of noise.
|
||||
*/
|
||||
virtual Float sampleSolidAngle(ShapeSamplingRecord &sRec, const Point &from, const Point2 &sample) const;
|
||||
virtual Float sampleSolidAngle(ShapeSamplingRecord &sRec,
|
||||
const Point &x, const Point2 &sample) const;
|
||||
|
||||
/**
|
||||
* Return the probability density of sampling the
|
||||
* given point using sampleSolidAngle()
|
||||
* \brief Return the probability density of sampling the given
|
||||
* point using \ref sampleSolidAngle().
|
||||
*/
|
||||
virtual Float pdfSolidAngle(const ShapeSamplingRecord &sRec, const Point &from) const;
|
||||
|
||||
/// Return the shape's surface area
|
||||
inline Float getSurfaceArea() const { return m_surfaceArea; }
|
||||
virtual Float pdfSolidAngle(const ShapeSamplingRecord &sRec,
|
||||
const Point &x) const;
|
||||
|
||||
/// Return the shape's BSDF
|
||||
inline const BSDF *getBSDF() const { return m_bsdf.get(); }
|
||||
|
@ -102,7 +236,7 @@ public:
|
|||
inline BSDF *getBSDF() { return m_bsdf.get(); }
|
||||
|
||||
/// Return the name of this shape
|
||||
inline const std::string &getName() const { return m_name; }
|
||||
virtual std::string getName() const;
|
||||
|
||||
/// Does this shape have a sub-surface integrator?
|
||||
inline bool hasSubsurface() const { return m_subsurface.get() != NULL; }
|
||||
|
@ -137,16 +271,13 @@ protected:
|
|||
/// Virtual destructor
|
||||
virtual ~Shape();
|
||||
protected:
|
||||
Transform m_worldToObject, m_objectToWorld;
|
||||
std::string m_name;
|
||||
AABB m_aabb;
|
||||
ref<BSDF> m_bsdf;
|
||||
ref<Subsurface> m_subsurface;
|
||||
ref<Luminaire> m_luminaire;
|
||||
Float m_surfaceArea, m_invSurfaceArea;
|
||||
BSphere m_bsphere;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __SHAPE_H */
|
||||
|
||||
|
||||
|
|
|
@ -19,15 +19,10 @@
|
|||
#if !defined(__SUBSURFACE_H)
|
||||
#define __SUBSURFACE_H
|
||||
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/core/netobject.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
class RenderQueue;
|
||||
class RenderJob;
|
||||
|
||||
/**
|
||||
* Abstract subsurface integrator -- can be attached to an arbitrary
|
||||
* shape to compute exitant radiance due to internal scattering.
|
||||
|
@ -39,9 +34,12 @@ public:
|
|||
* resource IDs of the associated scene, camera and sample generator,
|
||||
* which have been made available to all local and remote workers.
|
||||
*/
|
||||
virtual void preprocess(const Scene *scene, RenderQueue *queue, const RenderJob *job,
|
||||
virtual bool preprocess(const Scene *scene, RenderQueue *queue, const RenderJob *job,
|
||||
int sceneResID, int cameraResID, int samplerResID) = 0;
|
||||
|
||||
/// Cancel any running pre-process tasks
|
||||
virtual void cancel() = 0;
|
||||
|
||||
/// Return the list of shapes associated with this subsurface integrator
|
||||
inline const std::vector<Shape *> getShapes() const { return m_shapes; }
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ MTS_NAMESPACE_BEGIN
|
|||
/**
|
||||
* When a testcase is being compiled, define the following preprocessor macros for convenience
|
||||
*/
|
||||
#define assertEquals(expected, actual) assertEqualsImpl(expected, actual, Epsilon, __FILE__, __LINE__)
|
||||
#define assertEquals(expected, actual) assertEqualsImpl(expected, actual, 0, __FILE__, __LINE__)
|
||||
#define assertEqualsEpsilon(expected, actual, epsilon) assertEqualsImpl(expected, actual, epsilon, __FILE__, __LINE__)
|
||||
#define assertTrue(expr) assertTrueImpl(expr, #expr, __FILE__, __LINE__)
|
||||
#define assertFalse(expr) assertFalseImpl(expr, #expr, __FILE__, __LINE__)
|
||||
|
@ -122,7 +122,7 @@ protected:
|
|||
private:
|
||||
struct TestResult {
|
||||
bool success;
|
||||
std::string input, output;
|
||||
fs::path input, output;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue