cleanup phase is done -- merging into the default branch
commit
ebc7c814dd
53
.hgignore
53
.hgignore
|
@ -1,46 +1,63 @@
|
|||
^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
|
||||
|
||||
# SCons-related
|
||||
^\.sconf_temp/.*$
|
||||
^.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).
|
23
SConstruct
23
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,16 @@ 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('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,7 +273,8 @@ 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();
|
||||
|
@ -307,13 +314,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":
|
||||
|
@ -480,6 +487,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'])
|
||||
|
@ -703,7 +711,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']
|
||||
|
|
|
@ -13,5 +13,6 @@ XERCESLIB = ['xerces-c']
|
|||
GLLIB = ['GL', 'GLEWmx', 'Xxf86vm']
|
||||
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
|
||||
|
|
|
@ -12,7 +12,6 @@ Mitsuba makes heavy use of the following amazing libraries and tools:
|
|||
\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 ccvt (Capacity-Constrained Voronoi Tessellations) by Michael Balzer, Thomas Schlömer and Oliver Deussen
|
||||
\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}
|
||||
|
|
|
@ -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>
|
||||
*/
|
||||
|
|
@ -23,25 +23,35 @@
|
|||
|
||||
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 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 +71,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 +106,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 +143,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 +160,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 +170,41 @@ 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;
|
||||
}
|
||||
/**
|
||||
* \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;
|
||||
|
||||
/// Expands the bounding box to contain another vector
|
||||
/// 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 +250,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 {
|
||||
|
|
|
@ -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) { \
|
||||
|
|
|
@ -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,19 +57,19 @@ 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; }
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
|
|
|
@ -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,116 @@
|
|||
/*
|
||||
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 TVector3<Float> Vector;
|
||||
typedef TVector3<Float> Vector3;
|
||||
typedef TVector3<int> Vector3i;
|
||||
typedef TVector4<Float> Vector4;
|
||||
typedef TVector4<int> Vector4i;
|
||||
typedef TPoint2<Float> Point2;
|
||||
typedef TPoint2<int> Point2i;
|
||||
typedef TPoint3<Float> Point;
|
||||
typedef TPoint3<Float> Point3;
|
||||
typedef TPoint3<int> Point3i;
|
||||
typedef TPoint4<Float> Point4;
|
||||
typedef TPoint4<int> Point4i;
|
||||
struct Vertex;
|
||||
class WaitFlag;
|
||||
class Wavelet2D;
|
||||
class Wavelet3D;
|
||||
class Worker;
|
||||
class WorkProcessor;
|
||||
class WorkResult;
|
||||
class WorkUnit;
|
||||
class ZStream;
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __CORE_FWD_H */
|
|
@ -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,29 @@ 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().
|
||||
*/
|
||||
ConditionVariable(Mutex *mutex);
|
||||
|
||||
/**
|
||||
* 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 +119,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 +129,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 +140,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 +155,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,
|
||||
|
@ -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 {
|
||||
|
|
|
@ -25,16 +25,24 @@
|
|||
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 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);
|
||||
|
|
|
@ -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,7 +57,7 @@ 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; }
|
||||
|
@ -68,15 +71,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 +96,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
|
||||
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
|
||||
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
|
||||
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,29 @@ 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) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -76,13 +76,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();
|
||||
|
@ -264,47 +261,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);
|
||||
|
||||
|
|
|
@ -25,17 +25,18 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Mesh vertex data structure. Stores 3D coordinates,
|
||||
* vertex normals, UV coordinates and a tangent frame
|
||||
* \brief 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;
|
||||
Point p; ///< %Position
|
||||
Normal n; ///< %Normal
|
||||
Point2 uv; ///< %Texture coordinates
|
||||
Vector dpdu; ///< Partial derivative of the position with respect to \a u.
|
||||
Vector dpdv; ///< Partial derivative of the position with respect to \a v.
|
||||
|
||||
inline bool operator==(const Vertex &vert) const {
|
||||
return (v == vert.v && n == vert.n && uv == vert.uv
|
||||
return (p == vert.p && n == vert.n && uv == vert.uv
|
||||
&& dpdu == vert.dpdu && dpdv == vert.dpdv);
|
||||
}
|
||||
|
||||
|
@ -44,26 +45,29 @@ struct Vertex {
|
|||
}
|
||||
};
|
||||
|
||||
/** \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 */
|
||||
/// Indices into a vertex buffer
|
||||
unsigned int idx[3];
|
||||
|
||||
/// Construct an axis-aligned box, which contains the triangle
|
||||
AABB getAABB(const Vertex *buffer) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
@ -73,8 +77,8 @@ struct MTS_EXPORT_CORE Triangle {
|
|||
* 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,
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class Random;
|
||||
// -----------------------------------------------------------------------
|
||||
// Miscellaneous
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -45,21 +44,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 +110,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 +164,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 +194,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 +210,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 +223,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,7 +248,12 @@ 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);
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,11 +19,104 @@
|
|||
#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
|
||||
|
||||
/**
|
||||
* 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 BxDF 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
|
||||
|
@ -99,6 +192,8 @@ 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));
|
||||
}
|
||||
|
||||
|
@ -119,6 +214,8 @@ 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));
|
||||
}
|
||||
|
||||
|
@ -172,6 +269,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,83 @@
|
|||
/*
|
||||
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;
|
||||
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 */
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
#if !defined(__KD_TREE_H)
|
||||
#define __KD_TREE_H
|
||||
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/render/triaccel.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/render/shape.h>
|
||||
|
||||
/**
|
||||
* First, some default configuration definitions:
|
||||
|
@ -36,7 +34,6 @@
|
|||
#define MTS_USE_TRIACCEL 1
|
||||
#else
|
||||
#define MTS_USE_TRIACCEL 1
|
||||
#include <mitsuba/render/triaccel.h>
|
||||
#endif
|
||||
|
||||
#if defined(MTS_HAS_COHERENT_RT)
|
||||
|
@ -56,6 +53,8 @@
|
|||
#define MTS_USE_MT 1
|
||||
#endif
|
||||
|
||||
#include <mitsuba/render/triaccel.h>
|
||||
|
||||
/**
|
||||
* Pre-defined max. stack size for the ray traversal algorithm
|
||||
*/
|
||||
|
@ -190,6 +189,8 @@ protected:
|
|||
/// Virtual destructor
|
||||
virtual ~KDTree();
|
||||
|
||||
/// \cond
|
||||
|
||||
/// KD-tree node in 8 bytes
|
||||
struct KDNode {
|
||||
union {
|
||||
|
@ -435,6 +436,7 @@ protected:
|
|||
const KDNode * __restrict node;
|
||||
};
|
||||
#endif
|
||||
/// \endcond
|
||||
|
||||
/**
|
||||
* Intersection method from Vlastimil Havran's
|
||||
|
@ -470,7 +472,7 @@ protected:
|
|||
/* Pointers to all contained shapes */
|
||||
std::vector<const Shape *> m_shapes;
|
||||
/// Storage for kd-tree nodes
|
||||
std::vector<KDNode, std::aligned_allocator<KDNode> > m_nodes;
|
||||
std::vector<KDNode, aligned_allocator<KDNode> > m_nodes;
|
||||
#if defined(MTS_USE_TRIACCEL4)
|
||||
/// Explicitly store per-leaf quad-packed triangles
|
||||
TriAccel4 *m_packedTriangles;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -466,11 +471,10 @@ 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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -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() { }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,16 +19,128 @@
|
|||
#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:
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/** \brief Abstract base class of all shapes
|
||||
*/
|
||||
class MTS_EXPORT_RENDER Shape : public ConfigurableObject {
|
||||
|
@ -82,16 +194,15 @@ public:
|
|||
|
||||
/**
|
||||
* Sample a point on the shape - should be uniform
|
||||
* wrt. solid angle. Returns the associated probability
|
||||
* wrt. solid angle as seen from \a x. Returns the associated probability
|
||||
* density
|
||||
*/
|
||||
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()
|
||||
* Return the probability density of sampling the given point using sampleSolidAngle()
|
||||
*/
|
||||
virtual Float pdfSolidAngle(const ShapeSamplingRecord &sRec, const Point &from) const;
|
||||
virtual Float pdfSolidAngle(const ShapeSamplingRecord &sRec, const Point &x) const;
|
||||
|
||||
/// Return the shape's surface area
|
||||
inline Float getSurfaceArea() const { return m_surfaceArea; }
|
||||
|
@ -150,3 +261,5 @@ protected:
|
|||
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; }
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ protected:
|
|||
private:
|
||||
struct TestResult {
|
||||
bool success;
|
||||
std::string input, output;
|
||||
fs::path input, output;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#if !defined(__TEXTURE_H)
|
||||
#define __TEXTURE_H
|
||||
|
||||
#include <mitsuba/render/records.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/render/shader.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
@ -40,45 +40,6 @@ protected:
|
|||
virtual ~Texture();
|
||||
};
|
||||
|
||||
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 /* __TEXTURE_H */
|
||||
|
|
|
@ -83,7 +83,7 @@ inline int TriAccel::load(const Point &A, const Point &B, const Point &C) {
|
|||
/* Pre-compute intersection calculation constants */
|
||||
n_u = N[u] / n_k;
|
||||
n_v = N[v] / n_k;
|
||||
n_d = dot(A, N) / n_k;
|
||||
n_d = dot(Vector(A), N) / n_k;
|
||||
b_nu = b[u] / denom;
|
||||
b_nv = -b[v] / denom;
|
||||
a_u = A[u];
|
||||
|
|
|
@ -171,7 +171,7 @@ inline int TriAccel4::load(const Point *A, const Point *B, const Point *C,
|
|||
constants */
|
||||
nu[i] = N[u] / n_k;
|
||||
nv[i] = N[v] / n_k;
|
||||
nd[i] = dot(A[i], N) / n_k;
|
||||
nd[i] = dot(Vector(A[i]), N) / n_k;
|
||||
bnu[i] = b[u] / denom;
|
||||
bnv[i] = -b[v] / denom;
|
||||
au[i] = A[i][u];
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#if !defined(__VOLUME_H)
|
||||
#define __VOLUME_H
|
||||
|
||||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/cobject.h>
|
||||
#include <mitsuba/core/aabb.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/hw/renderer.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -17,15 +17,26 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/hw/renderer.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/*!
|
||||
The Lambertian material represents a one-sided ideal diffuse material
|
||||
with the specified amount of reflectance. Optionally, a texture map may
|
||||
be applied. If no extra information is provided, the material will revert to
|
||||
the default of uniform 50% reflectance.
|
||||
|
||||
/**
|
||||
* Simple one-sided Lambertian (i.e. perfectly diffuse) material
|
||||
*/
|
||||
Seen from the back side, this material will appear completely black.
|
||||
|
||||
\verbatim
|
||||
<bsdf type="lambertian">
|
||||
<srgb name="reflectance" value="#a4da85"/>
|
||||
</bsdf>
|
||||
\endverbatim
|
||||
*/
|
||||
class Lambertian : public BSDF {
|
||||
public:
|
||||
Lambertian(const Properties &props)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/hw/renderer.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/hw/gpuprogram.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/hw/gpuprogram.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -327,7 +327,8 @@ public:
|
|||
Frame mFrame(sampleBeckmannD(bRec.sample));
|
||||
|
||||
/* Perfect specular reflection along the microsurface normal */
|
||||
refract(mFrame.toLocal(bRec.wi), bRec.wo, bRec.quantity);
|
||||
if (refract(mFrame.toLocal(bRec.wi), bRec.wo, bRec.quantity) == 0)
|
||||
return Spectrum(0.0f);
|
||||
bRec.wo = mFrame.toWorld(bRec.wo);
|
||||
|
||||
bRec.sampledComponent = 1;
|
||||
|
@ -335,7 +336,7 @@ public:
|
|||
|
||||
if (Frame::cosTheta(bRec.wi)*Frame::cosTheta(bRec.wo) >= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
|
||||
return f(bRec) / pdf(bRec);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/bsdf.h>
|
||||
#include <mitsuba/render/texture.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include <mitsuba/hw/gpuprogram.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
|
|
@ -16,20 +16,16 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define BOOST_FILESYSTEM_NO_LIB
|
||||
#define BOOST_SYSTEM_NO_LIB
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/core/fstream.h>
|
||||
#include <dae.h>
|
||||
#include <dom/domCOLLADA.h>
|
||||
#include <dom/domProfile_COMMON.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <fstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(__OSX__)
|
||||
#include <OpenGL/glu.h>
|
||||
|
@ -48,7 +44,7 @@ enum ESourceType {
|
|||
EVertexColors = 3,
|
||||
ELast
|
||||
};
|
||||
|
||||
|
||||
struct Vec4 {
|
||||
Float x, y, z, w;
|
||||
|
||||
|
@ -85,6 +81,7 @@ struct VertexData {
|
|||
std::vector<Vec4 *> data;
|
||||
std::vector<int> typeToOffset;
|
||||
std::vector<int> typeToOffsetInStream;
|
||||
std::vector<size_t> typeToCount;
|
||||
|
||||
VertexData() : glPos(NULL) {
|
||||
}
|
||||
|
@ -116,9 +113,12 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
for (size_t i=0; i<result->nSources; ++i)
|
||||
result->data[i] = NULL;
|
||||
result->typeToOffset.resize(ELast);
|
||||
result->typeToCount.resize(ELast);
|
||||
result->typeToOffsetInStream.resize(ELast);
|
||||
for (int i=0; i<ELast; ++i)
|
||||
for (int i=0; i<ELast; ++i) {
|
||||
result->typeToOffset[i] = result->typeToOffsetInStream[i] = -1;
|
||||
result->typeToCount[i] = 0;
|
||||
}
|
||||
int vertInputIndex = 0;
|
||||
|
||||
for (size_t i=0; i<inputs.getCount(); ++i) {
|
||||
|
@ -151,14 +151,14 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
domAccessor *accessor = techniqueCommon->getAccessor();
|
||||
if (!accessor)
|
||||
SLog(EError, "Data source does not have a <accessor> tag!");
|
||||
int nParams = (int) accessor->getParam_array().getCount(),
|
||||
stride = (int) accessor->getStride(),
|
||||
size = (int) accessor->getCount();
|
||||
unsigned int nParams = (unsigned int) accessor->getParam_array().getCount(),
|
||||
stride = (unsigned int) accessor->getStride();
|
||||
size_t size = (size_t) accessor->getCount();
|
||||
SAssert(nParams <= 4);
|
||||
|
||||
Vec4 *target = new Vec4[size];
|
||||
for (int j=0; j<size; ++j)
|
||||
for (int k=0; k<nParams; ++k)
|
||||
for (size_t j=0; j<size; ++j)
|
||||
for (unsigned int k=0; k<nParams; ++k)
|
||||
target[j][k] = (Float) floatArray[j*stride+k];
|
||||
|
||||
result->data[offset] = target;
|
||||
|
@ -167,9 +167,10 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
SAssert(accessor->getStride() == 3);
|
||||
SAssert(result->typeToOffset[EPosition] == -1);
|
||||
result->typeToOffset[EPosition] = offset;
|
||||
result->typeToCount[EPosition] = size;
|
||||
result->typeToOffsetInStream[EPosition] = offsetInStream;
|
||||
result->glPos = new GLdouble[3*size];
|
||||
for (int k=0; k<3*size; ++k)
|
||||
for (size_t k=0; k<3*size; ++k)
|
||||
result->glPos[k] = floatArray[k];
|
||||
} else if (semantic == "NORMAL") {
|
||||
SAssert(accessor->getStride() == 3);
|
||||
|
@ -177,12 +178,14 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
result->hasNormals = true;
|
||||
result->typeToOffset[ENormal] = offset;
|
||||
result->typeToOffsetInStream[ENormal] = offsetInStream;
|
||||
result->typeToCount[ENormal] = size;
|
||||
} else if (semantic == "TEXCOORD") {
|
||||
SAssert(accessor->getStride() == 2 || accessor->getStride() == 3);
|
||||
if (result->typeToOffset[EUV] == -1) {
|
||||
result->hasUVs = true;
|
||||
result->typeToOffset[EUV] = offset;
|
||||
result->typeToOffsetInStream[EUV] = offsetInStream;
|
||||
result->typeToCount[EUV] = size;
|
||||
} else {
|
||||
SLog(EWarn, "Found multiple sets of texture coordinates - ignoring!");
|
||||
}
|
||||
|
@ -191,6 +194,7 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
"(Lighting/shading -> Batch Bake in Maya)");
|
||||
result->typeToOffset[EVertexColors] = offset;
|
||||
result->typeToOffsetInStream[EVertexColors] = offsetInStream;
|
||||
result->typeToCount[EVertexColors] = size;
|
||||
} else {
|
||||
SLog(EError, "Encountered an unknown source semantic: %s", semantic.c_str());
|
||||
}
|
||||
|
@ -204,12 +208,12 @@ VertexData *fetchVertexData(Transform transform, std::ostream &os,
|
|||
struct vertex_key_order : public
|
||||
std::binary_function<Vertex, Vertex, bool> {
|
||||
static int compare(const Vertex &v1, const Vertex &v2) {
|
||||
if (v1.v.x < v2.v.x) return -1;
|
||||
else if (v1.v.x > v2.v.x) return 1;
|
||||
if (v1.v.y < v2.v.y) return -1;
|
||||
else if (v1.v.y > v2.v.y) return 1;
|
||||
if (v1.v.z < v2.v.z) return -1;
|
||||
else if (v1.v.z > v2.v.z) return 1;
|
||||
if (v1.p.x < v2.p.x) return -1;
|
||||
else if (v1.p.x > v2.p.x) return 1;
|
||||
if (v1.p.y < v2.p.y) return -1;
|
||||
else if (v1.p.y > v2.p.y) return 1;
|
||||
if (v1.p.z < v2.p.z) return -1;
|
||||
else if (v1.p.z > v2.p.z) return 1;
|
||||
if (v1.n.x < v2.n.x) return -1;
|
||||
else if (v1.n.x > v2.n.x) return 1;
|
||||
if (v1.n.y < v2.n.y) return -1;
|
||||
|
@ -264,7 +268,7 @@ struct triangle_key_order : public std::binary_function<SimpleTriangle, SimpleTr
|
|||
typedef std::map<SimpleTriangle, bool, triangle_key_order> TriangleMap;
|
||||
|
||||
void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::string matID, Transform transform,
|
||||
std::ostream &os, VertexData *vData, TriangleMap &triMap, const std::string &meshesDirectory) {
|
||||
std::ostream &os, VertexData *vData, TriangleMap &triMap, const fs::path &meshesDirectory) {
|
||||
std::vector<Vertex> vertexBuffer;
|
||||
std::vector<Triangle> triangles;
|
||||
std::map<Vertex, int, vertex_key_order> vertexMap;
|
||||
|
@ -278,16 +282,24 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
for (size_t i=0; i<tess_data.size(); i+=tess_nSources) {
|
||||
Vertex vertex;
|
||||
domUint posRef = tess_data[i+vData->typeToOffsetInStream[EPosition]];
|
||||
vertex.v = vData->data[vData->typeToOffset[EPosition]][posRef].toPoint();
|
||||
vertex.p = vData->data[vData->typeToOffset[EPosition]][posRef].toPoint();
|
||||
vertex.dpdu = vertex.dpdv = Vector(0.0f);
|
||||
|
||||
if (vData->typeToOffset[ENormal] != -1) {
|
||||
domUint normalRef = tess_data[i+vData->typeToOffsetInStream[ENormal]];
|
||||
vertex.n = vData->data[vData->typeToOffset[ENormal]][normalRef].toNormal();
|
||||
} else {
|
||||
vertex.n = Normal(0.0f);
|
||||
}
|
||||
|
||||
if (vData->typeToOffset[EUV] != -1) {
|
||||
domUint uvRef = tess_data[i+vData->typeToOffsetInStream[EUV]];
|
||||
vertex.uv = vData->data[vData->typeToOffset[EUV]][uvRef].toPoint2();
|
||||
#if 1
|
||||
vertex.uv.y = 1-vertex.uv.y; // Invert the V coordinate
|
||||
#endif
|
||||
} else {
|
||||
vertex.uv = Point2(0.0f);
|
||||
}
|
||||
|
||||
int key = -1;
|
||||
|
@ -299,11 +311,12 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
vertexMap[vertex] = (int) key;
|
||||
vertexBuffer.push_back(vertex);
|
||||
}
|
||||
|
||||
triangle.idx[triangleIdx++] = key;
|
||||
if (triangleIdx == 3) {
|
||||
Point p0 = vertexBuffer[triangle.idx[0]].v,
|
||||
p1 = vertexBuffer[triangle.idx[1]].v,
|
||||
p2 = vertexBuffer[triangle.idx[2]].v;
|
||||
Point p0 = vertexBuffer[triangle.idx[0]].p,
|
||||
p1 = vertexBuffer[triangle.idx[1]].p,
|
||||
p2 = vertexBuffer[triangle.idx[2]].p;
|
||||
if (triMap.find(SimpleTriangle(p0, p1, p2)) != triMap.end() ||
|
||||
triMap.find(SimpleTriangle(p2, p0, p1)) != triMap.end() ||
|
||||
triMap.find(SimpleTriangle(p1, p2, p0)) != triMap.end() ||
|
||||
|
@ -324,7 +337,8 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
|
||||
if (duplicates > 0) {
|
||||
if (triangles.size() == 0) {
|
||||
SLog(EWarn, "%s: Only contains duplicates of already-existing geometry. Ignoring.");
|
||||
SLog(EWarn, "\"%s/%s\": Only contains duplicates (%i triangles) of already-existing geometry. Ignoring.",
|
||||
prefixName.c_str(), id.c_str(), duplicates);
|
||||
os << "\t<!-- Ignored shape \"" << prefixName << "/"
|
||||
<< id << "\" (mat=\"" << matID << "\"), since it only contains duplicate geometry. -->" << endl << endl;
|
||||
return;
|
||||
|
@ -334,8 +348,8 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
}
|
||||
|
||||
SAssert(triangleIdx == 0);
|
||||
SLog(EInfo, "%s: Converted " SIZE_T_FMT " triangles, " SIZE_T_FMT
|
||||
" vertices (merged " SIZE_T_FMT " vertices).", id.c_str(),
|
||||
SLog(EInfo, "\"%s/%s\": Converted " SIZE_T_FMT " triangles, " SIZE_T_FMT
|
||||
" vertices (merged " SIZE_T_FMT " vertices).", prefixName.c_str(), id.c_str(),
|
||||
triangles.size(), vertexBuffer.size(), numMerged);
|
||||
|
||||
ref<TriMesh> mesh = new TriMesh(triangles.size(), vertexBuffer.size());
|
||||
|
@ -344,7 +358,7 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
mesh->calculateTangentSpaceBasis(vData->typeToOffset[ENormal]!=-1, vData->typeToOffset[EUV]!=-1);
|
||||
|
||||
std::string filename = id + std::string(".serialized");
|
||||
ref<FileStream> stream = new FileStream(meshesDirectory + filename, FileStream::ETruncReadWrite);
|
||||
ref<FileStream> stream = new FileStream(meshesDirectory / filename, FileStream::ETruncReadWrite);
|
||||
stream->setByteOrder(Stream::ENetworkByteOrder);
|
||||
mesh->serialize(stream);
|
||||
stream->close();
|
||||
|
@ -368,7 +382,7 @@ void writeGeometry(std::string prefixName, std::string id, int geomIndex, std::s
|
|||
}
|
||||
|
||||
void loadGeometry(std::string prefixName, Transform transform, std::ostream &os, domGeometry &geom,
|
||||
StringMap &matLookupTable, const std::string &meshesDir) {
|
||||
StringMap &matLookupTable, const fs::path &meshesDir) {
|
||||
std::string identifier;
|
||||
if (geom.getId() != NULL) {
|
||||
identifier = geom.getId();
|
||||
|
@ -425,14 +439,35 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
|
|||
for (size_t j=0; j<indexArray.getCount(); ++j) {
|
||||
domListOfUInts &indices = indexArray[j]->getValue();
|
||||
domUint *temp = new domUint[indices.getCount()];
|
||||
for (size_t l = 0; l<indices.getCount(); ++l)
|
||||
bool invalid = false;
|
||||
|
||||
for (int m=0; m<ELast; ++m) {
|
||||
int offset = data->typeToOffsetInStream[m];
|
||||
if (offset == -1)
|
||||
continue;
|
||||
size_t count = data->typeToCount[m];
|
||||
for (size_t l = 0; l < indices.getCount(); l+=data->nSources) {
|
||||
domUint idx = indices.get(l+offset);
|
||||
if (idx >= count) {
|
||||
SLog(EWarn, "Encountered the invalid polygon index %i "
|
||||
"(must be in [0, " SIZE_T_FMT "]) -- ignoring polygon!", (domInt) idx, count-1);
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
continue;
|
||||
|
||||
for (size_t l = 0; l<indices.getCount(); ++l)
|
||||
temp[l] = indices.get(l);
|
||||
|
||||
gluTessBeginPolygon(tess, NULL);
|
||||
gluTessBeginContour(tess);
|
||||
|
||||
for (size_t k=0; k<indices.getCount(); k+=data->nSources)
|
||||
gluTessVertex(tess, &data->glPos[temp[k+posOffset]*3], (GLvoid *) (k+temp));
|
||||
gluTessVertex(tess, &data->glPos[3*temp[k+posOffset]], (GLvoid *) (temp+k));
|
||||
|
||||
gluTessEndContour(tess);
|
||||
gluTessEndPolygon(tess);
|
||||
|
@ -463,8 +498,29 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
|
|||
|
||||
for (size_t j=0; j<vcount.getCount(); ++j) {
|
||||
size_t vertexCount = (size_t) vcount.get(j);
|
||||
|
||||
domUint *temp = new domUint[vertexCount * data->nSources];
|
||||
|
||||
bool invalid = false;
|
||||
|
||||
for (int m=0; m<ELast; ++m) {
|
||||
int offset = data->typeToOffsetInStream[m];
|
||||
if (offset == -1)
|
||||
continue;
|
||||
size_t count = data->typeToCount[m];
|
||||
for (size_t l = 0; l < vertexCount; ++l) {
|
||||
domUint idx = indexArray.get(l*data->nSources+offset);
|
||||
if (idx >= count) {
|
||||
SLog(EWarn, "Encountered the invalid polygon index %i "
|
||||
"(must be in [0, " SIZE_T_FMT "]) -- ignoring polygon!", (domInt) idx, count-1);
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
continue;
|
||||
|
||||
for (size_t l = 0; l<vertexCount * data->nSources; ++l)
|
||||
temp[l] = indexArray.get(indexOffset++);
|
||||
|
||||
|
@ -491,7 +547,7 @@ void loadGeometry(std::string prefixName, Transform transform, std::ostream &os,
|
|||
}
|
||||
}
|
||||
|
||||
void loadMaterialParam(GeometryConverter *cvt, std::ostream &os, const std::string &name, StringMap &idToTexture,
|
||||
void loadMaterialParam(GeometryConverter *cvt, std::ostream &os, const fs::path &name, StringMap &idToTexture,
|
||||
domCommon_color_or_texture_type *value, bool handleRefs) {
|
||||
if (!value)
|
||||
return;
|
||||
|
@ -517,7 +573,7 @@ void loadMaterialParam(GeometryConverter *cvt, std::ostream &os, const std::stri
|
|||
}
|
||||
}
|
||||
|
||||
void loadMaterialParam(GeometryConverter *cvt, std::ostream &os, const std::string &name, StringMap &,
|
||||
void loadMaterialParam(GeometryConverter *cvt, std::ostream &os, const fs::path &name, StringMap &,
|
||||
domCommon_float_or_param_type *value, bool handleRef) {
|
||||
if (!value)
|
||||
return;
|
||||
|
@ -622,18 +678,11 @@ void loadMaterial(GeometryConverter *cvt, std::ostream &os, domMaterial &mat, St
|
|||
os << "\t</bsdf>" << endl << endl;
|
||||
}
|
||||
} else if (lambert) {
|
||||
domCommon_float_or_param_type* transparency = lambert->getTransparency();
|
||||
domCommon_float_or_param_type::domFloat *transparencyValue =
|
||||
transparency ? transparency->getFloat() : NULL;
|
||||
if (transparencyValue && transparencyValue->getValue() > 0.5) {
|
||||
os << "\t<bsdf id=\"" << identifier << "\" type=\"dielectric\"/>" << endl << endl;
|
||||
} else {
|
||||
domCommon_color_or_texture_type* diffuse = lambert->getDiffuse();
|
||||
os << "\t<bsdf id=\"" << identifier << "\" type=\"lambertian\">" << endl;
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
}
|
||||
domCommon_color_or_texture_type* diffuse = lambert->getDiffuse();
|
||||
os << "\t<bsdf id=\"" << identifier << "\" type=\"lambertian\">" << endl;
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
} else if (blinn) {
|
||||
SLog(EWarn, "\"%s\": Encountered a \"blinn\" COLLADA material, which is currently "
|
||||
"unsupported in Mitsuba -- replacing it using a Phong material.", identifier.c_str());
|
||||
|
@ -702,7 +751,7 @@ void loadLight(Transform transform, std::ostream &os, domLight &light) {
|
|||
transform = transform * Transform::scale(Vector(1, 1, -1));
|
||||
|
||||
Point pos = transform(Point(0, 0, 0));
|
||||
Vector target = transform(Point(0, 0, 1));
|
||||
Point target = transform(Point(0, 0, 1));
|
||||
|
||||
Float intensity = 1;
|
||||
const domTechnique_Array &techniques = light.getTechnique_array();
|
||||
|
@ -783,7 +832,7 @@ void loadLight(Transform transform, std::ostream &os, domLight &light) {
|
|||
SLog(EWarn, "Encountered an unknown light type!");
|
||||
}
|
||||
|
||||
void loadImage(GeometryConverter *cvt, std::ostream &os, const std::string &textureDir,
|
||||
void loadImage(GeometryConverter *cvt, std::ostream &os, const fs::path &textureDir,
|
||||
domImage &image, StringMap &idToTexture, StringMap &fileToId) {
|
||||
std::string identifier;
|
||||
if (image.getId() != NULL) {
|
||||
|
@ -808,27 +857,27 @@ void loadImage(GeometryConverter *cvt, std::ostream &os, const std::string &text
|
|||
idToTexture[identifier] = identifier;
|
||||
fileToId[filename] = identifier;
|
||||
|
||||
boost::filesystem::path path = boost::filesystem::path(filename, boost::filesystem::native);
|
||||
std::string targetPath = textureDir + path.leaf();
|
||||
fs::path path = fs::path(filename);
|
||||
fs::path targetPath = textureDir / path.leaf();
|
||||
fs::path resolved = filename;
|
||||
|
||||
if (endsWith(filename, ".rgb"))
|
||||
std::string extension = boost::to_lower_copy(fs::extension(path));
|
||||
if (extension == ".rgb")
|
||||
SLog(EWarn, "Maya RGB images must be converted to PNG, EXR or JPEG! The 'imgcvt' "
|
||||
"utility found in the Maya binary directory can be used to do this.");
|
||||
|
||||
if (!FileStream::exists(targetPath)) {
|
||||
ref<FileResolver> fRes = FileResolver::getInstance();
|
||||
std::string resolved = fRes->resolve(path.leaf());
|
||||
if (!FileStream::exists(filename)) {
|
||||
if (!FileStream::exists(resolved)) {
|
||||
SLog(EWarn, "Found neither \"%s\" nor \"%s\"!", filename.c_str(), resolved.c_str());
|
||||
filename = cvt->locateResource(filename);
|
||||
if (filename == "")
|
||||
if (!fs::exists(targetPath)) {
|
||||
ref<FileResolver> fRes = Thread::getThread()->getFileResolver();
|
||||
if (!fs::exists(resolved)) {
|
||||
resolved = fRes->resolve(path.leaf());
|
||||
if (!fs::exists(resolved)) {
|
||||
SLog(EWarn, "Found neither \"%s\" nor \"%s\"!", filename.c_str(), resolved.file_string().c_str());
|
||||
resolved = cvt->locateResource(path.leaf());
|
||||
if (resolved.empty())
|
||||
SLog(EError, "Unable to locate a resource -- aborting conversion.");
|
||||
} else {
|
||||
filename = resolved;
|
||||
}
|
||||
}
|
||||
ref<FileStream> input = new FileStream(filename, FileStream::EReadOnly);
|
||||
ref<FileStream> input = new FileStream(resolved, FileStream::EReadOnly);
|
||||
ref<FileStream> output = new FileStream(targetPath, FileStream::ETruncReadWrite);
|
||||
input->copyTo(output);
|
||||
input->close();
|
||||
|
@ -945,7 +994,7 @@ void loadCamera(GeometryConverter *cvt, Transform transform, std::ostream &os, d
|
|||
}
|
||||
|
||||
void loadNode(GeometryConverter *cvt, Transform transform, std::ostream &os,
|
||||
domNode &node, std::string prefixName, const std::string &meshesDir) {
|
||||
domNode &node, std::string prefixName, const fs::path &meshesDir) {
|
||||
std::string identifier;
|
||||
if (node.getId() != NULL) {
|
||||
identifier = node.getId();
|
||||
|
@ -964,13 +1013,21 @@ void loadNode(GeometryConverter *cvt, Transform transform, std::ostream &os,
|
|||
for (size_t i=0; i<children.getCount(); ++i) {
|
||||
daeElement *element = children.get(i);
|
||||
if (element->typeID() == domRotate::ID()) {
|
||||
/* Skip rotations labeled as "post-rotationY". Maya exports these with some cameras,
|
||||
which introduces an incorrect 90 degree rotation unless ignored */
|
||||
/* Skip rotations labeled as "post-rotationY". Maya and 3ds max export these with some
|
||||
cameras, which introduces an incorrect 90 degree rotation unless ignored */
|
||||
if (element->hasAttribute("sid") && element->getAttribute("sid") == "post-rotationY")
|
||||
continue;
|
||||
daeTArray<double> value = daeSafeCast<domRotate>(element)->getValue();
|
||||
transform = transform *
|
||||
Transform::rotate(Vector((Float) value.get(0), (Float) value.get(1), (Float) value.get(2)), (Float) value.get(3));
|
||||
Vector axis((Float) value.get(0), (Float) value.get(1), (Float) value.get(2));
|
||||
Float angle = (Float) value.get(3);
|
||||
if (angle != 0) {
|
||||
if (axis.isZero()) {
|
||||
SLog(EWarn, "Encountered a rotation around a zero vector -- ignoring!");
|
||||
} else {
|
||||
transform = transform *
|
||||
Transform::rotate(axis, (Float) value.get(3));
|
||||
}
|
||||
}
|
||||
} else if (element->typeID() == domTranslate::ID()) {
|
||||
daeTArray<double> value = daeSafeCast<domTranslate>(element)->getValue();
|
||||
transform = transform *
|
||||
|
@ -1080,7 +1137,7 @@ GLvoid __stdcall tessVertex(void *data) {
|
|||
|
||||
GLvoid __stdcall tessCombine(GLdouble coords[3], void *vertex_data[4],
|
||||
GLfloat weight[4], void **outData) {
|
||||
SLog(EWarn, "Detected a self-intersecting polygon!");
|
||||
SLog(EWarn, "Detected a degenerate or self-intersecting polygon!");
|
||||
}
|
||||
|
||||
GLvoid __stdcall tessEnd() {
|
||||
|
@ -1093,23 +1150,17 @@ GLvoid __stdcall tessError(GLenum error) {
|
|||
GLvoid __stdcall tessEdgeFlag(GLboolean) {
|
||||
}
|
||||
|
||||
void GeometryConverter::convertCollada(const std::string &inputFile,
|
||||
void GeometryConverter::convertCollada(const fs::path &inputFile,
|
||||
std::ostream &os,
|
||||
const std::string &textureDirectory,
|
||||
const std::string &meshesDirectory) {
|
||||
#if defined(__LINUX__)
|
||||
std::string path = std::string("file://") +
|
||||
FileResolver::getInstance()->resolveAbsolute(inputFile);
|
||||
#else
|
||||
std::string path = inputFile;
|
||||
#endif
|
||||
|
||||
const fs::path &textureDirectory,
|
||||
const fs::path &meshesDirectory) {
|
||||
DAE *dae = new DAE();
|
||||
SLog(EInfo, "Loading \"%s\" ..", path.c_str());
|
||||
if (dae->load(path.c_str()) != DAE_OK)
|
||||
SLog(EError, "Could not load \"%s\"!", path.c_str());
|
||||
SLog(EInfo, "Loading \"%s\" ..", inputFile.leaf().c_str());
|
||||
if (dae->load(inputFile.file_string().c_str()) != DAE_OK)
|
||||
SLog(EError, "Could not load \"%s\"!",
|
||||
inputFile.file_string().c_str());
|
||||
|
||||
domCOLLADA *document = dae->getDom(path.c_str());
|
||||
domCOLLADA *document = dae->getDom(inputFile.file_string().c_str());
|
||||
domVisual_scene *visualScene = daeSafeCast<domVisual_scene>
|
||||
(document->getDescendant("visual_scene"));
|
||||
if (!visualScene)
|
||||
|
|
|
@ -29,12 +29,10 @@
|
|||
#include <xercesc/framework/Wrapper4InputSource.hpp>
|
||||
#include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||
#include <xercesc/util/XMLUni.hpp>
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
#include <fstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <set>
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
@ -46,18 +44,15 @@ public:
|
|||
inline ImporterDOMErrorHandler() { }
|
||||
|
||||
bool handleError(const DOMError& domError) {
|
||||
ELogLevel logLevel;
|
||||
|
||||
if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING)
|
||||
logLevel = EWarn;
|
||||
else
|
||||
logLevel = EError;
|
||||
|
||||
SLog(logLevel, "%s (line %i, char %i): %s",
|
||||
SLog(EWarn, "%s (line %i, char %i): %s",
|
||||
XMLString::transcode(domError.getLocation()->getURI()),
|
||||
domError.getLocation()->getLineNumber(),
|
||||
domError.getLocation()->getColumnNumber(),
|
||||
XMLString::transcode(domError.getMessage()));
|
||||
|
||||
if (domError.getSeverity() != DOMError::DOM_SEVERITY_WARNING)
|
||||
SLog(EError, "Encountered a critical DOM error -- giving up!");
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -129,62 +124,45 @@ bool cleanupPass(DOMNode *node, const std::set<std::string> &removals) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void GeometryConverter::convert(const std::string &inputFile,
|
||||
const std::string &outputDirectory,
|
||||
const std::string &sceneName,
|
||||
const std::string &adjustmentFile) {
|
||||
void GeometryConverter::convert(const fs::path &inputFile,
|
||||
const fs::path &outputDirectory,
|
||||
const fs::path &sceneName,
|
||||
const fs::path &adjustmentFile) {
|
||||
|
||||
std::string textureDirectory = "textures";
|
||||
std::string meshesDirectory = "meshes";
|
||||
std::string outputFile = sceneName;
|
||||
fs::path textureDirectory = "textures";
|
||||
fs::path meshesDirectory = "meshes";
|
||||
fs::path outputFile = sceneName;
|
||||
|
||||
SLog(EInfo, "Creating directories ..");
|
||||
#if !defined(WIN32)
|
||||
if (outputDirectory != "") {
|
||||
textureDirectory = outputDirectory + "/textures";
|
||||
meshesDirectory = outputDirectory + "/meshes";
|
||||
outputFile = outputDirectory + std::string("/") + sceneName;
|
||||
if (!outputDirectory.empty()) {
|
||||
textureDirectory = outputDirectory / "textures";
|
||||
meshesDirectory = outputDirectory / "meshes";
|
||||
outputFile = outputDirectory / sceneName;
|
||||
}
|
||||
|
||||
int status = mkdir(textureDirectory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
if (status != 0 && errno != EEXIST)
|
||||
SLog(EError, "Could not create the directory \"%s\"", textureDirectory.c_str());
|
||||
status = mkdir(meshesDirectory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
if (status != 0 && errno != EEXIST)
|
||||
SLog(EError, "Could not create the directory \"%s\"", meshesDirectory.c_str());
|
||||
|
||||
textureDirectory += "/";
|
||||
meshesDirectory += "/";
|
||||
#else
|
||||
if (outputDirectory != "") {
|
||||
textureDirectory = outputDirectory + "\\textures";
|
||||
meshesDirectory = outputDirectory + "\\meshes";
|
||||
outputFile = outputDirectory + std::string("\\") + sceneName;
|
||||
if (!fs::exists(textureDirectory)) {
|
||||
SLog(EInfo, "Creating directory \"%s\" ..", textureDirectory.file_string().c_str());
|
||||
fs::create_directory(textureDirectory);
|
||||
}
|
||||
|
||||
int status = CreateDirectory(textureDirectory.c_str(), NULL);
|
||||
if (status == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
SLog(EError, "Could not create the directory \"%s\"", textureDirectory.c_str());
|
||||
status = CreateDirectory(meshesDirectory.c_str(), NULL);
|
||||
if (status == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
SLog(EError, "Could not create the directory \"%s\"", meshesDirectory.c_str());
|
||||
|
||||
textureDirectory += "\\";
|
||||
meshesDirectory += "\\";
|
||||
#endif
|
||||
if (!fs::exists(meshesDirectory)) {
|
||||
SLog(EInfo, "Creating directory \"%s\" ..", meshesDirectory.file_string().c_str());
|
||||
fs::create_directory(meshesDirectory);
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
SLog(EInfo, "Beginning conversion ..");
|
||||
if (endsWith(toLowerCase(inputFile), ".dae") || endsWith(toLowerCase(inputFile), ".zae")) {
|
||||
|
||||
std::string extension = boost::to_lower_copy(fs::extension(inputFile));
|
||||
|
||||
if (extension == ".dae" || extension == ".zae") {
|
||||
convertCollada(inputFile, os, textureDirectory, meshesDirectory);
|
||||
} else if (endsWith(toLowerCase(inputFile), ".obj")) {
|
||||
} else if (extension == ".obj") {
|
||||
convertOBJ(inputFile, os, textureDirectory, meshesDirectory);
|
||||
} else {
|
||||
SLog(EError, "Unknown input format (must end in either .DAE, .ZAE or .OBJ)");
|
||||
}
|
||||
|
||||
if (adjustmentFile != "") {
|
||||
if (!adjustmentFile.empty()) {
|
||||
SLog(EInfo, "Applying adjustments ..");
|
||||
static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
|
||||
DOMImplementationLS *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
|
||||
|
@ -199,8 +177,10 @@ void GeometryConverter::convert(const std::string &inputFile,
|
|||
xmlString.length(), "bufID", false);
|
||||
Wrapper4InputSource *wrapper = new Wrapper4InputSource(memBufIS, false);
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = parser->parse(wrapper);
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *adj = parser->parseURI(adjustmentFile.c_str());
|
||||
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *adj = parser->parseURI(adjustmentFile.file_string().c_str());
|
||||
if (adj == NULL)
|
||||
SLog(EError, "Could not parse adjustments file!");
|
||||
|
||||
std::set<std::string> removals, emptyList;
|
||||
cleanupPass(adj, emptyList);
|
||||
findRemovals(adj, removals);
|
||||
|
@ -241,7 +221,7 @@ void GeometryConverter::convert(const std::string &inputFile,
|
|||
DOMLSOutput *output = impl->createLSOutput();
|
||||
serConf->setParameter(XMLUni::fgDOMErrorHandler, &errorHandler);
|
||||
serConf->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
|
||||
XMLFormatTarget *target = new LocalFileFormatTarget(outputFile.c_str());
|
||||
XMLFormatTarget *target = new LocalFileFormatTarget(outputFile.file_string().c_str());
|
||||
output->setByteStream(target);
|
||||
serializer->write(doc, output);
|
||||
delete output;
|
||||
|
@ -251,9 +231,9 @@ void GeometryConverter::convert(const std::string &inputFile,
|
|||
delete serializer;
|
||||
parser->release();
|
||||
} else {
|
||||
std::ofstream ofile(outputFile.c_str());
|
||||
fs::ofstream ofile(outputFile);
|
||||
if (ofile.fail())
|
||||
SLog(EError, "Could not write to \"%s\"!", outputFile.c_str());
|
||||
SLog(EError, "Could not write to \"%s\"!", outputFile.file_string().c_str());
|
||||
ofile << os.str();
|
||||
ofile.close();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
#include <mitsuba/mitsuba.h>
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
|
||||
using namespace mitsuba;
|
||||
|
||||
|
@ -12,29 +30,29 @@ public:
|
|||
m_fov = -1;
|
||||
}
|
||||
|
||||
void convert(const std::string &inputFile,
|
||||
const std::string &outputDirectory,
|
||||
const std::string &sceneName,
|
||||
const std::string &adjustmentFile);
|
||||
void convert(const fs::path &inputFile,
|
||||
const fs::path &outputDirectory,
|
||||
const fs::path &sceneName,
|
||||
const fs::path &adjustmentFile);
|
||||
|
||||
virtual std::string locateResource(const std::string &resource) = 0;
|
||||
virtual fs::path locateResource(const fs::path &resource) = 0;
|
||||
|
||||
inline void setSRGB(bool srgb) { m_srgb = srgb; }
|
||||
inline void setMapSmallerSide(bool mapSmallerSide) { m_mapSmallerSide = mapSmallerSide; }
|
||||
inline void setResolution(int xres, int yres) { m_xres = xres; m_yres = yres; }
|
||||
inline void setSamplesPerPixel(int samplesPerPixel) { m_samplesPerPixel = samplesPerPixel; }
|
||||
inline void setFov(Float fov) { m_fov = fov; }
|
||||
inline const std::string &getFilename() const { return m_filename; }
|
||||
inline const fs::path &getFilename() const { return m_filename; }
|
||||
private:
|
||||
void convertCollada(const std::string &inputFile, std::ostream &os,
|
||||
const std::string &textureDirectory,
|
||||
const std::string &meshesDirectory);
|
||||
void convertOBJ(const std::string &inputFile, std::ostream &os,
|
||||
const std::string &textureDirectory,
|
||||
const std::string &meshesDirectory);
|
||||
void convertCollada(const fs::path &inputFile, std::ostream &os,
|
||||
const fs::path &textureDirectory,
|
||||
const fs::path &meshesDirectory);
|
||||
void convertOBJ(const fs::path &inputFile, std::ostream &os,
|
||||
const fs::path &textureDirectory,
|
||||
const fs::path &meshesDirectory);
|
||||
public:
|
||||
bool m_srgb, m_mapSmallerSide;
|
||||
int m_xres, m_yres, m_samplesPerPixel;
|
||||
Float m_fov;
|
||||
std::string m_filename;
|
||||
fs::path m_filename;
|
||||
};
|
||||
|
|
|
@ -1,21 +1,3 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mitsuba COLLADA 1.4 and Wavefront OBJ -> XML converter
|
||||
*
|
||||
|
@ -51,8 +33,8 @@
|
|||
#include <xercesc/dom/DOMException.hpp>
|
||||
#include "converter.h"
|
||||
#include <mitsuba/hw/glrenderer.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/core/plugin.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#if defined(WIN32)
|
||||
#include "../mitsuba/getopt.h"
|
||||
#endif
|
||||
|
@ -64,8 +46,8 @@ public:
|
|||
inline ConsoleGeometryConverter() {
|
||||
}
|
||||
|
||||
std::string locateResource(const std::string &resource) {
|
||||
return "";
|
||||
fs::path locateResource(const fs::path &resource) {
|
||||
return fs::path();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -90,7 +72,7 @@ int colladaMain(int argc, char **argv) {
|
|||
int xres = -1, yres = -1;
|
||||
int samplesPerPixel = 8;
|
||||
Float fov = -1;
|
||||
FileResolver *resolver = FileResolver::getInstance();
|
||||
FileResolver *fileResolver = Thread::getThread()->getFileResolver();
|
||||
ELogLevel logLevel = EInfo;
|
||||
|
||||
optind = 1;
|
||||
|
@ -100,7 +82,7 @@ int colladaMain(int argc, char **argv) {
|
|||
case 'a': {
|
||||
std::vector<std::string> paths = tokenize(optarg, ";");
|
||||
for (unsigned int i=0; i<paths.size(); ++i)
|
||||
resolver->addPath(paths[i]);
|
||||
fileResolver->addPath(paths[i]);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
|
@ -118,7 +100,7 @@ int colladaMain(int argc, char **argv) {
|
|||
logLevel = EDebug;
|
||||
break;
|
||||
case 'f':
|
||||
fov = strtod(optarg, &end_ptr);
|
||||
fov = (Float) strtod(optarg, &end_ptr);
|
||||
if (*end_ptr != '\0')
|
||||
SLog(EError, "Invalid field of view value!");
|
||||
break;
|
||||
|
@ -190,26 +172,13 @@ int ubi_main(int argc, char **argv) {
|
|||
|
||||
Thread::getThread()->getLogger()->setLogLevel(EInfo);
|
||||
|
||||
FileResolver *resolver = FileResolver::getInstance();
|
||||
#if defined(WIN32)
|
||||
char lpFilename[1024];
|
||||
if (GetModuleFileNameA(NULL,
|
||||
lpFilename, sizeof(lpFilename))) {
|
||||
resolver->addPathFromFile(lpFilename);
|
||||
} else {
|
||||
SLog(EWarn, "Could not determine the executable path");
|
||||
}
|
||||
#elif defined(__LINUX__)
|
||||
char exePath[PATH_MAX];
|
||||
if (getcwd(exePath, PATH_MAX)) {
|
||||
resolver->addPathFromFile(exePath);
|
||||
} else {
|
||||
SLog(EWarn, "Could not determine the executable path");
|
||||
}
|
||||
resolver->addPath("/usr/share/mitsuba");
|
||||
#else
|
||||
FileResolver *fileResolver = Thread::getThread()->getFileResolver();
|
||||
|
||||
#if defined(__LINUX__)
|
||||
fileResolver->addPath(MTS_RESOURCE_DIR);
|
||||
#elif defined(__OSX__)
|
||||
MTS_AUTORELEASE_BEGIN()
|
||||
resolver->addPath(__ubi_bundlepath());
|
||||
fileResolver->addPath(__ubi_bundlepath());
|
||||
MTS_AUTORELEASE_END()
|
||||
#endif
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue