metadata
Wenzel Jakob 2013-09-04 16:54:14 +02:00
commit e459cdc015
287 changed files with 7973 additions and 3468 deletions

View File

@ -6,3 +6,6 @@ e3c0182ba64b77319ce84c9e2a8581649e68273d v0.2.1
cb6e89af8012fac22cc0f3c5ad247c98c701bdda v0.3.0
ee26517b27207353b0c8a7d357bcb4977b5d93fb v0.4.0
7db07694ea00eb1655f7a1adcc3ae880e8e116f9 v0.4.1
13a39b11aceee517c19d2e2cec2e6b875546062c v0.4.2
f1b73d39617071297167cc7ce96f3892f21105fc v0.4.3
bd6ddacdf7955e51d9b80be639c282d4974e6f56 v0.4.4

View File

@ -35,31 +35,26 @@ endif()
# Load the required modules
include (MitsubaUtil)
include (MtsGetVersionInfo)
include (CheckCXXSourceCompiles)
include (CMakeDependentOption)
# Read version (MTS_VERSION) from include/mitsuba/core/version.h
file(STRINGS "include/mitsuba/core/version.h" MITSUBA_H REGEX "^#define MTS_VERSION \"[^\"]*\"$")
string(REGEX REPLACE "^.*MTS_VERSION \"([0-9]+).*$" "\\1" MTS_VERSION_MAJOR "${MITSUBA_H}")
string(REGEX REPLACE "^.*MTS_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" MTS_VERSION_MINOR "${MITSUBA_H}")
string(REGEX REPLACE "^.*MTS_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" MTS_VERSION_PATCH "${MITSUBA_H}")
set(MTS_VERSION "${MTS_VERSION_MAJOR}.${MTS_VERSION_MINOR}.${MTS_VERSION_PATCH}")
set(MITSUBA_H)
if("${MTS_VERSION_MAJOR}" MATCHES "[0-9]+" AND
"${MTS_VERSION_MINOR}" MATCHES "[0-9]+" AND
"${MTS_VERSION_PATCH}" MATCHES "[0-9]+")
message(STATUS "mitsuba ${MTS_VERSION}")
# Read the version information
MTS_GET_VERSION_INFO()
if (MTS_HAS_VALID_REV)
message(STATUS "mitsuba ${MTS_VERSION}-hg${MTS_REV_ID} (${MTS_DATE})")
else()
message(FATAL_ERROR "The mitsuba version could not be determined!")
message(STATUS "mitsuba ${MTS_VERSION} (${MTS_DATE})")
endif()
# Setup the build options
include (MitsubaBuildOptions)
# Find the external libraries and setup the paths
include (MitsubaExternal)
# Setup the build options, include paths and compile definitions
include (MitsubaBuildOptions)
# Main mitsuba include directory
include_directories("include")
# ===== Prerequisite resources =====
@ -92,8 +87,13 @@ endif()
# Additional files to add to main executables
if(APPLE)
set(MTS_DARWIN_STUB "${CMAKE_CURRENT_SOURCE_DIR}/src/mitsuba/darwin_stub.mm")
set(MTS_WINDOWS_STUB "")
elseif(WIN32)
set(MTS_DARWIN_STUB "")
set(MTS_WINDOWS_STUB "${CMAKE_CURRENT_SOURCE_DIR}/data/windows/wmain_stub.cpp")
else()
set(MTS_DARWIN_STUB "")
set(MTS_WINDOWS_STUB "")
endif()

View File

@ -6,9 +6,10 @@ import os
resources = []
plugins = []
stubs = []
winstubs = []
Export('SCons', 'sys', 'os', 'glob', 'resources',
'plugins', 'stubs')
'plugins', 'stubs', 'winstubs')
# Configure the build framework
env = SConscript('build/SConscript.configure')
@ -18,6 +19,9 @@ Export('env')
if sys.platform == 'win32':
# Set an application icon on Windows
resources += [ env.RES('data/windows/mitsuba_res.rc') ]
# Convert the command line args from UTF-8 to UTF-16
winstubs += [ env.SharedObject('#data/windows/wmain_stub.cpp') ]
Export('winstubs')
def build(scriptFile, exports = [], duplicate = 0):
dirname = '/'.join(os.path.dirname(scriptFile).split('/')[1:])

View File

@ -285,7 +285,7 @@ if needsBuildDependencies:
print '\nThe dependency directory and your Mitsuba codebase have different version'
print 'numbers! Your copy of Mitsuba has version %s, whereas the dependencies ' % MTS_VERSION
print 'have version %s. Please bring them into sync, either by running\n' % depVersion
print '$ hg update -r v%s\n' % depVersion
print '$ hg update -r v%s\n' % depVersion
print 'in the Mitsuba directory, or by running\n'
print '$ cd dependencies'
print '$ hg pull'
@ -353,7 +353,7 @@ def configure_for_objective_cpp(env):
env.RemoveFlags(['-fstrict-aliasing', '-ftree-vectorize',
'-std=c\+\+0x'])
# Remove Intel compiler-specific optimization flags
env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div',
env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div',
'-fp-model', 'fast=.*', '-wd.*', '-openmp'])
env['CCFLAGS'] += ['-fno-strict-aliasing']
# Enforce GCC usage (Intel compiler doesn't handle Objective C/C++)
@ -374,7 +374,7 @@ env.__class__.ConfigureForObjectiveCPP = configure_for_objective_cpp
env.__class__.RelaxCompilerSettings = relax_compiler_settings
if hasCollada:
env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]] )
env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]])
env.SConsignFile()

View File

@ -20,11 +20,11 @@ GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11']
GLFLAGS = ['-DGLEW_MX']
BOOSTLIB = ['boost_system', 'boost_filesystem', 'boost_thread']
COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4']
COLLADALIB = ['collada14dom']
COLLADALIB = ['collada14dom', 'xml2']
# The following assumes that the Mitsuba bindings should be built for the
# "default" Python version. It is also possible to build bindings for multiple
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# PYTHON27LIB, PYTHON27LIBDIR and PYTHON32INCLUDE, PYTHON32LIB, PYTHON32LIBDIR
pyver = os.popen("python --version 2>&1 | grep -oE '([[:digit:]].[[:digit:]])'").read().strip().replace('.', '')

View File

@ -20,11 +20,11 @@ GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11']
GLFLAGS = ['-DGLEW_MX']
BOOSTLIB = ['boost_system', 'boost_filesystem', 'boost_thread']
COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4']
COLLADALIB = ['collada14dom']
COLLADALIB = ['collada14dom', 'xml2']
# The following assumes that the Mitsuba bindings should be built for the
# "default" Python version. It is also possible to build bindings for multiple
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# PYTHON27LIB, PYTHON27LIBDIR and PYTHON32INCLUDE, PYTHON32LIB, PYTHON32LIBDIR
pyver = os.popen("python --version 2>&1 | grep -oE '([[:digit:]].[[:digit:]])'").read().strip().replace('.', '')

View File

@ -20,11 +20,11 @@ GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11']
GLFLAGS = ['-DGLEW_MX']
BOOSTLIB = ['boost_system', 'boost_filesystem', 'boost_thread']
COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4']
COLLADALIB = ['collada14dom']
COLLADALIB = ['collada14dom', 'xml2']
# The following assumes that the Mitsuba bindings should be built for the
# "default" Python version. It is also possible to build bindings for multiple
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# PYTHON27LIB, PYTHON27LIBDIR and PYTHON32INCLUDE, PYTHON32LIB, PYTHON32LIBDIR
pyver = os.popen("python --version 2>&1 | grep -oE '([[:digit:]].[[:digit:]])'").read().strip().replace('.', '')

View File

@ -6,7 +6,7 @@ CCFLAGS = ['-arch', 'x86_64', '-mmacosx-version-min=10.7', '-march=nocona
LINKFLAGS = ['-framework', 'OpenGL', '-framework', 'Cocoa', '-arch', 'x86_64', '-mmacosx-version-min=10.7', '-Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk', '-Wl,-headerpad,128']
BASEINCLUDE = ['#include', '#dependencies/include']
BASELIBDIR = ['#dependencies/lib']
BASELIB = ['m', 'pthread', 'gomp', 'Half']
BASELIB = ['m', 'pthread', 'Half']
OEXRINCLUDE = ['#dependencies/include/OpenEXR']
OEXRLIB = ['IlmImf', 'Imath', 'Iex', 'z']
PNGLIB = ['png']

View File

@ -125,13 +125,15 @@
</ClInclude>
<ClInclude Include="..\src\samplers\sobolseq.h">
</ClInclude>
<ClInclude Include="..\src\libhw\veramono14_dsc.h">
<ClInclude Include="..\src\libhw\data\veramono14_dsc.h">
</ClInclude>
<ClInclude Include="..\src\libhw\vera14_dsc.h">
<ClInclude Include="..\src\libhw\data\vera14_dsc.h">
</ClInclude>
<ClInclude Include="..\src\libhw\veramono14_png.h">
<ClInclude Include="..\src\libhw\data\shaders.h">
</ClInclude>
<ClInclude Include="..\src\libhw\vera14_png.h">
<ClInclude Include="..\src\libhw\data\veramono14_png.h">
</ClInclude>
<ClInclude Include="..\src\libhw\data\vera14_png.h">
</ClInclude>
<ClInclude Include="..\src\medium\materials.h">
</ClInclude>
@ -203,6 +205,8 @@
</ClInclude>
<ClInclude Include="..\src\films\banner.h">
</ClInclude>
<ClInclude Include="..\src\films\annotations.h">
</ClInclude>
<ClInclude Include="..\src\shapes\shapegroup.h">
</ClInclude>
<ClInclude Include="..\src\shapes\hair.h">
@ -287,14 +291,14 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\volume.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\sahkdtree4.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\integrator.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\subsurface.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\texture.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\track.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\triaccel_sse.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\bsdf.h">
@ -385,6 +389,8 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\matrix.inl">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\math.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\ssemath.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\normal.h">
@ -409,6 +415,8 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\statistics.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\spline.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\thread.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\aabb_sse.h">
@ -431,6 +439,8 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\brent.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\track.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\chisquare.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\sched_remote.h">
@ -455,8 +465,6 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\class.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\stl.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\warp.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\util.h">
@ -511,6 +519,8 @@
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\gpugeometry.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\shadow.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\glrenderer.h">
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\glxdevice.h">
@ -629,8 +639,6 @@
</ClCompile>
<ClCompile Include="..\src\librender\photonmap.cpp">
</ClCompile>
<ClCompile Include="..\src\librender\track.cpp">
</ClCompile>
<ClCompile Include="..\src\librender\renderjob.cpp">
</ClCompile>
<ClCompile Include="..\src\librender\intersection.cpp">
@ -757,6 +765,8 @@
</ClCompile>
<ClCompile Include="..\src\libhw\vpl.cpp">
</ClCompile>
<ClCompile Include="..\src\libhw\shadow.cpp">
</ClCompile>
<ClCompile Include="..\src\libhw\basicshader.cpp">
</ClCompile>
<ClCompile Include="..\src\mitsuba\mitsuba.cpp">
@ -805,6 +815,10 @@
</ClCompile>
<ClCompile Include="..\src\libcore\logger.cpp">
</ClCompile>
<ClCompile Include="..\src\libcore\spline.cpp">
</ClCompile>
<ClCompile Include="..\src\libcore\track.cpp">
</ClCompile>
<ClCompile Include="..\src\libcore\formatter.cpp">
</ClCompile>
<ClCompile Include="..\src\libcore\bitmap.cpp">
@ -937,6 +951,8 @@
</ClCompile>
<ClCompile Include="..\src\mtsgui\main.cpp">
</ClCompile>
<ClCompile Include="..\src\mtsgui\test_simdtonemap.cpp">
</ClCompile>
<ClCompile Include="..\src\mtsgui\programsettingsdlg.cpp">
</ClCompile>
<ClCompile Include="..\src\mtsgui\symlinks_auth.cpp">
@ -1001,12 +1017,8 @@
</ClCompile>
<ClCompile Include="..\src\utils\addimages.cpp">
</ClCompile>
<ClCompile Include="..\src\utils\ttest.cpp">
</ClCompile>
<ClCompile Include="..\src\utils\kdbench.cpp">
</ClCompile>
<ClCompile Include="..\src\utils\uflakefit.cpp">
</ClCompile>
<ClCompile Include="..\src\utils\joinrgb.cpp">
</ClCompile>
<ClCompile Include="..\src\utils\cylclip.cpp">
@ -1021,6 +1033,8 @@
</ClCompile>
<ClCompile Include="..\src\shapes\ply\ply_parser.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\cube.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\serialized.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\obj.cpp">
@ -1033,9 +1047,9 @@
</ClCompile>
<ClCompile Include="..\src\shapes\hair.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\ply.cpp">
<ClCompile Include="..\src\shapes\deformable.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\animatedinstance.cpp">
<ClCompile Include="..\src\shapes\ply.cpp">
</ClCompile>
<ClCompile Include="..\src\shapes\cylinder.cpp">
</ClCompile>

View File

@ -9,136 +9,136 @@
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Source Files\converter">
<UniqueIdentifier>{b54fb131-7e86-4e08-bba2-828939a038ff}</UniqueIdentifier>
<UniqueIdentifier>{81dd9e3e-7bca-44a1-a313-76fb5af5ab0c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\bsdfs">
<UniqueIdentifier>{62e70ba9-1509-4ecb-9c06-8de3ef48cd47}</UniqueIdentifier>
<UniqueIdentifier>{7112f301-f6d5-4351-ae06-4a29910a3766}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\librender">
<UniqueIdentifier>{81da027f-f282-46cb-a88d-abc84969dbf8}</UniqueIdentifier>
<UniqueIdentifier>{15522c16-64b9-487e-b9fe-dea0094cb5c1}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\samplers">
<UniqueIdentifier>{8364b08a-50e5-471b-bfaa-4e45915df101}</UniqueIdentifier>
<UniqueIdentifier>{4df10a81-6f13-45ae-9a39-ce009db3a659}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\sensors">
<UniqueIdentifier>{bb52270c-4a49-423b-ad02-4a7c042295c2}</UniqueIdentifier>
<UniqueIdentifier>{0c722d61-5189-477d-b242-2fa2ad26c83c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\libhw">
<UniqueIdentifier>{c4330c75-0353-41ab-a809-1471f359aec6}</UniqueIdentifier>
<UniqueIdentifier>{d849b48a-b61d-4540-81ab-f5228fd6fa93}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\libhw\data">
<UniqueIdentifier>{32a38ee8-b255-4e23-8efc-9491fc27c645}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\mitsuba">
<UniqueIdentifier>{0f1ec875-44fb-46b2-9116-26d659410d97}</UniqueIdentifier>
<UniqueIdentifier>{9f6ef52b-2504-4722-a200-7aaa9603088a}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\libcore">
<UniqueIdentifier>{ab910bc2-a0a5-4f02-8232-396937071149}</UniqueIdentifier>
<UniqueIdentifier>{6c49af9f-8cac-477f-825b-ccb368e313c6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\tests">
<UniqueIdentifier>{dff3f942-f016-4bad-aa2c-63c444401a94}</UniqueIdentifier>
<UniqueIdentifier>{182aef81-5fdf-4eb1-a7d3-5b1d7d5de2b5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\medium">
<UniqueIdentifier>{855b0594-d28c-486a-b081-72991219654e}</UniqueIdentifier>
<UniqueIdentifier>{81241aff-695b-4556-bf46-e9d3ac4aa7fb}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\emitters">
<UniqueIdentifier>{08449c4a-89f1-4b5b-a756-2bd2f03bf566}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\emitters\sky">
<UniqueIdentifier>{8437086b-afc9-48b6-a358-53d4df044974}</UniqueIdentifier>
<UniqueIdentifier>{f4218b48-d878-435b-915a-8da9727666b1}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\emitters\sunsky">
<UniqueIdentifier>{d9802d62-8614-401a-afa6-941271c63386}</UniqueIdentifier>
<UniqueIdentifier>{e6e1a06f-b795-4a12-9b0c-0c730e0b2ac6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\subsurface">
<UniqueIdentifier>{65e0e20a-2809-4352-8c81-69a0a3824fa9}</UniqueIdentifier>
<UniqueIdentifier>{231a82e9-6b4b-4a95-995c-8abd0b6149b3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\rfilters">
<UniqueIdentifier>{8ea19f58-a2c0-4a30-bc79-817da2f1a1ed}</UniqueIdentifier>
<UniqueIdentifier>{4c70e19a-a935-4b0f-88e3-10683b03f66c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\volume">
<UniqueIdentifier>{753c9d80-ceb0-4932-8097-5c7cac92e091}</UniqueIdentifier>
<UniqueIdentifier>{4a433329-84ca-4a8b-938e-4d06c21ec6ff}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\mtsgui">
<UniqueIdentifier>{b4290489-566b-4576-847b-392b4c45f1f1}</UniqueIdentifier>
<UniqueIdentifier>{4414bb60-269f-4934-9dc9-58bbed35bc1d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\mtsgui\pch">
<UniqueIdentifier>{ad07dceb-214e-42e1-933d-c8ceeecd1389}</UniqueIdentifier>
<UniqueIdentifier>{4bc23857-f9a2-453d-bc64-8c9ebc5aff42}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\mtsgui\resources">
<UniqueIdentifier>{3ee94c12-30fb-4f65-8781-f7b5e8a95db2}</UniqueIdentifier>
<UniqueIdentifier>{a9318f22-caaa-40af-b8fc-9b8051ec0859}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\mtsgui\shaders">
<UniqueIdentifier>{813aba46-5b9d-4290-9a31-18e77952929e}</UniqueIdentifier>
<UniqueIdentifier>{fba5da81-e3f2-4fbe-98d7-807aaa2c2cf3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\phase">
<UniqueIdentifier>{55bcc3cd-7f6b-4bb6-b22e-b731ed0451fb}</UniqueIdentifier>
<UniqueIdentifier>{abd6883d-375b-4d85-bb93-12952995332d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\utils">
<UniqueIdentifier>{6ebccae2-fbfd-4a3f-9bfc-7e9dbd2b6d74}</UniqueIdentifier>
<UniqueIdentifier>{4c9fdf84-d6a6-47f8-8d58-c01ed8351fa0}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\films">
<UniqueIdentifier>{a339ab19-2bed-4d03-afdc-d73223648b72}</UniqueIdentifier>
<UniqueIdentifier>{366f9975-2268-4124-81b9-87e7c2c03b1e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\shapes">
<UniqueIdentifier>{87b01999-0b73-481b-b8fa-b66f594f65be}</UniqueIdentifier>
<UniqueIdentifier>{8d2d02ea-1957-4256-8046-f525d13e7ba5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\shapes\ply">
<UniqueIdentifier>{5870cf94-fb1b-44c0-90f2-32c3c8cbf6b7}</UniqueIdentifier>
<UniqueIdentifier>{8438e074-8733-4689-95ba-86145dd9fd9d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators">
<UniqueIdentifier>{90263b28-e65b-4d41-92cb-a0d1dac22564}</UniqueIdentifier>
<UniqueIdentifier>{9d35d85d-280c-49ef-869a-ffaa0602f9f5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\vpl">
<UniqueIdentifier>{453d13c1-1847-4a18-8f2e-028913b4ec43}</UniqueIdentifier>
<UniqueIdentifier>{6df94c72-e89d-451e-ad6b-160ea0313077}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\misc">
<UniqueIdentifier>{e4baad7e-ee3c-4085-961f-2851c0ed2b8f}</UniqueIdentifier>
<UniqueIdentifier>{7bec8429-3bb9-4dfd-8008-a10c675a9818}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\direct">
<UniqueIdentifier>{a7ab51c2-5596-458f-b5f0-1129dc3dbbf5}</UniqueIdentifier>
<UniqueIdentifier>{747a1613-4c01-46ef-ba17-92d2286890ad}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\pssmlt">
<UniqueIdentifier>{a7456898-2253-48d8-abec-9c86311cca64}</UniqueIdentifier>
<UniqueIdentifier>{516a0fc3-a824-4486-b50c-f3165d1d8361}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\photonmapper">
<UniqueIdentifier>{cb9f48b8-6f25-4c9d-9d2c-b1a67cc80427}</UniqueIdentifier>
<UniqueIdentifier>{bddbc784-474a-4cd3-bbea-3123048dbfaa}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\path">
<UniqueIdentifier>{b44ee927-e827-4c46-bbce-c7a1b705b63b}</UniqueIdentifier>
<UniqueIdentifier>{7bba2a7a-8cd3-47bd-9ab2-e33939d4eba6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\mlt">
<UniqueIdentifier>{40540c0e-02d6-4296-bbdf-87dfd9f7f213}</UniqueIdentifier>
<UniqueIdentifier>{32cdfdd7-c3bb-41f2-b433-10165963f9ed}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\bdpt">
<UniqueIdentifier>{430d27a2-66db-4169-bb48-aeb0b65e4d1a}</UniqueIdentifier>
<UniqueIdentifier>{49edc93d-4305-45a8-a6d9-ae283837d46a}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\erpt">
<UniqueIdentifier>{a247e523-dbaf-4fb8-b284-6c8c5cbc09a5}</UniqueIdentifier>
<UniqueIdentifier>{d24cf1e6-a301-42e8-9fc1-26fe0ddc3f04}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\integrators\ptracer">
<UniqueIdentifier>{91d6db52-180b-4dde-9339-807917e42f4e}</UniqueIdentifier>
<UniqueIdentifier>{3df649be-39d5-4416-8776-427a1696c016}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\textures">
<UniqueIdentifier>{8ae0e3a3-87db-4e93-bb20-9d198040ae86}</UniqueIdentifier>
<UniqueIdentifier>{2e68088f-97e2-4dee-91f5-c85e3e36dd74}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\libbidir">
<UniqueIdentifier>{0049f7d1-4211-4010-b53c-3ee99244046e}</UniqueIdentifier>
<UniqueIdentifier>{f7674a86-b0a5-484c-9db3-a20500b9bbf9}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\libpython">
<UniqueIdentifier>{8bddb89b-fa54-448a-a4b3-294f18d45ded}</UniqueIdentifier>
<UniqueIdentifier>{f41987e3-e0b9-431d-b37b-5931db380b09}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mitsuba">
<UniqueIdentifier>{082f589c-eb3f-47a4-b2f6-fbd6d89dec07}</UniqueIdentifier>
<UniqueIdentifier>{88ed597b-50ba-4d6f-bf50-ae8f5fa17789}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mitsuba\render">
<UniqueIdentifier>{a7f59027-bc87-4d28-9b90-eb5be186d8a7}</UniqueIdentifier>
<UniqueIdentifier>{5499a8e9-ef31-4ab9-a58f-d3a36a784004}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mitsuba\core">
<UniqueIdentifier>{f5410d0f-0a22-4579-afbf-8e13db8fa3d5}</UniqueIdentifier>
<UniqueIdentifier>{b74f25a9-ff20-4888-8dfc-57dd968b0b8d}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mitsuba\hw">
<UniqueIdentifier>{ebe2b998-26de-4e92-8618-c739cb43a5f2}</UniqueIdentifier>
<UniqueIdentifier>{18246123-74da-4fee-8581-bd2860451c40}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mitsuba\bidir">
<UniqueIdentifier>{4f4d9d4b-3f44-4d56-9a18-16b94e753706}</UniqueIdentifier>
<UniqueIdentifier>{3fdeab5a-5ccf-41c6-bf05-d9f7f510c741}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup Label="Source Files">
@ -247,9 +247,6 @@
<ClCompile Include="..\src\librender\photonmap.cpp">
<Filter>Source Files\librender</Filter>
</ClCompile>
<ClCompile Include="..\src\librender\track.cpp">
<Filter>Source Files\librender</Filter>
</ClCompile>
<ClCompile Include="..\src\librender\renderjob.cpp">
<Filter>Source Files\librender</Filter>
</ClCompile>
@ -439,6 +436,9 @@
<ClCompile Include="..\src\libhw\vpl.cpp">
<Filter>Source Files\libhw</Filter>
</ClCompile>
<ClCompile Include="..\src\libhw\shadow.cpp">
<Filter>Source Files\libhw</Filter>
</ClCompile>
<ClCompile Include="..\src\libhw\basicshader.cpp">
<Filter>Source Files\libhw</Filter>
</ClCompile>
@ -511,6 +511,12 @@
<ClCompile Include="..\src\libcore\logger.cpp">
<Filter>Source Files\libcore</Filter>
</ClCompile>
<ClCompile Include="..\src\libcore\spline.cpp">
<Filter>Source Files\libcore</Filter>
</ClCompile>
<ClCompile Include="..\src\libcore\track.cpp">
<Filter>Source Files\libcore</Filter>
</ClCompile>
<ClCompile Include="..\src\libcore\formatter.cpp">
<Filter>Source Files\libcore</Filter>
</ClCompile>
@ -709,6 +715,9 @@
<ClCompile Include="..\src\mtsgui\main.cpp">
<Filter>Source Files\mtsgui</Filter>
</ClCompile>
<ClCompile Include="..\src\mtsgui\test_simdtonemap.cpp">
<Filter>Source Files\mtsgui</Filter>
</ClCompile>
<ClCompile Include="..\src\mtsgui\programsettingsdlg.cpp">
<Filter>Source Files\mtsgui</Filter>
</ClCompile>
@ -805,15 +814,9 @@
<ClCompile Include="..\src\utils\addimages.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\src\utils\ttest.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\src\utils\kdbench.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\src\utils\uflakefit.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
<ClCompile Include="..\src\utils\joinrgb.cpp">
<Filter>Source Files\utils</Filter>
</ClCompile>
@ -835,6 +838,9 @@
<ClCompile Include="..\src\shapes\ply\ply_parser.cpp">
<Filter>Source Files\shapes\ply</Filter>
</ClCompile>
<ClCompile Include="..\src\shapes\cube.cpp">
<Filter>Source Files\shapes</Filter>
</ClCompile>
<ClCompile Include="..\src\shapes\serialized.cpp">
<Filter>Source Files\shapes</Filter>
</ClCompile>
@ -853,10 +859,10 @@
<ClCompile Include="..\src\shapes\hair.cpp">
<Filter>Source Files\shapes</Filter>
</ClCompile>
<ClCompile Include="..\src\shapes\ply.cpp">
<ClCompile Include="..\src\shapes\deformable.cpp">
<Filter>Source Files\shapes</Filter>
</ClCompile>
<ClCompile Include="..\src\shapes\animatedinstance.cpp">
<ClCompile Include="..\src\shapes\ply.cpp">
<Filter>Source Files\shapes</Filter>
</ClCompile>
<ClCompile Include="..\src\shapes\cylinder.cpp">
@ -1035,17 +1041,20 @@
<ClInclude Include="..\src\samplers\sobolseq.h">
<Filter>Source Files\samplers</Filter>
</ClInclude>
<ClInclude Include="..\src\libhw\veramono14_dsc.h">
<Filter>Source Files\libhw</Filter>
<ClInclude Include="..\src\libhw\data\veramono14_dsc.h">
<Filter>Source Files\libhw\data</Filter>
</ClInclude>
<ClInclude Include="..\src\libhw\vera14_dsc.h">
<Filter>Source Files\libhw</Filter>
<ClInclude Include="..\src\libhw\data\vera14_dsc.h">
<Filter>Source Files\libhw\data</Filter>
</ClInclude>
<ClInclude Include="..\src\libhw\veramono14_png.h">
<Filter>Source Files\libhw</Filter>
<ClInclude Include="..\src\libhw\data\shaders.h">
<Filter>Source Files\libhw\data</Filter>
</ClInclude>
<ClInclude Include="..\src\libhw\vera14_png.h">
<Filter>Source Files\libhw</Filter>
<ClInclude Include="..\src\libhw\data\veramono14_png.h">
<Filter>Source Files\libhw\data</Filter>
</ClInclude>
<ClInclude Include="..\src\libhw\data\vera14_png.h">
<Filter>Source Files\libhw\data</Filter>
</ClInclude>
<ClInclude Include="..\src\medium\materials.h">
<Filter>Source Files\medium</Filter>
@ -1152,6 +1161,9 @@
<ClInclude Include="..\src\films\banner.h">
<Filter>Source Files\films</Filter>
</ClInclude>
<ClInclude Include="..\src\films\annotations.h">
<Filter>Source Files\films</Filter>
</ClInclude>
<ClInclude Include="..\src\shapes\shapegroup.h">
<Filter>Source Files\shapes</Filter>
</ClInclude>
@ -1278,6 +1290,9 @@
<ClInclude Include="..\include\mitsuba\render\volume.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\sahkdtree4.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\integrator.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
@ -1287,9 +1302,6 @@
<ClInclude Include="..\include\mitsuba\render\texture.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\track.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\render\triaccel_sse.h">
<Filter>Header Files\mitsuba\render</Filter>
</ClInclude>
@ -1425,6 +1437,9 @@
<ClInclude Include="..\include\mitsuba\core\matrix.inl">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\math.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\ssemath.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
@ -1461,6 +1476,9 @@
<ClInclude Include="..\include\mitsuba\core\statistics.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\spline.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\thread.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
@ -1494,6 +1512,9 @@
<ClInclude Include="..\include\mitsuba\core\brent.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\track.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\chisquare.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
@ -1530,9 +1551,6 @@
<ClInclude Include="..\include\mitsuba\core\class.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\stl.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\core\warp.h">
<Filter>Header Files\mitsuba\core</Filter>
</ClInclude>
@ -1614,6 +1632,9 @@
<ClInclude Include="..\include\mitsuba\hw\gpugeometry.h">
<Filter>Header Files\mitsuba\hw</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\shadow.h">
<Filter>Header Files\mitsuba\hw</Filter>
</ClInclude>
<ClInclude Include="..\include\mitsuba\hw\glrenderer.h">
<Filter>Header Files\mitsuba\hw</Filter>
</ClInclude>

View File

@ -6,15 +6,17 @@ if (NOT DEFINED MTS_VERSION)
message(FATAL_ERROR "This file has to be included from the main build file.")
endif()
# Image format definitions
if (PNG_FOUND)
add_definitions(-DMTS_HAS_LIBPNG=1)
endif()
if (JPEG_FOUND)
add_definitions(-DMTS_HAS_LIBJPEG=1)
endif()
if (OPENEXR_FOUND)
add_definitions(-DMTS_HAS_OPENEXR=1)
# Default initial compiler flags which may be modified by advanced users
if (MTS_CMAKE_INIT)
set(MTS_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(MTS_CXX_FLAGS "-fvisibility=hidden -pipe -march=nocona -mfpmath=sse -ffast-math -Wall -Winvalid-pch")
endif()
if (MTS_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "${MTS_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" CACHE
STRING "Flags used by the compiler during all build types." FORCE)
set(MTS_CXX_FLAGS)
endif()
endif()
# Top level configuration definitions
@ -107,15 +109,7 @@ endif()
if (WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(-DWIN64)
endif()
# Main mitsuba include directory
include_directories("include")
# Includes for the common libraries
include_directories(${Boost_INCLUDE_DIRS} ${Eigen_INCLUDE_DIR})
# If we are using the system OpenEXR, add its headers which half.h requires
if (OPENEXR_FOUND)
include_directories(${ILMBASE_INCLUDE_DIRS})
if (MSVC AND MTS_SSE AND NOT CMAKE_CL_64)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:SSE2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
endif()

View File

@ -244,3 +244,23 @@ CMAKE_DEPENDENT_OPTION(BUILD_PYTHON "Build the Python bindings." ON
if (PYTHONLIBS_FOUND AND mts_boost_PYTHON_FOUND)
set (PYTHON_FOUND TRUE)
endif ()
# Includes for the common libraries
include_directories(${Boost_INCLUDE_DIRS} ${Eigen_INCLUDE_DIR})
# If we are using the system OpenEXR, add its headers which half.h requires
if (OPENEXR_FOUND)
include_directories(${ILMBASE_INCLUDE_DIRS})
endif()
# Image format definitions
if (PNG_FOUND)
add_definitions(-DMTS_HAS_LIBPNG=1)
endif()
if (JPEG_FOUND)
add_definitions(-DMTS_HAS_LIBJPEG=1)
endif()
if (OPENEXR_FOUND)
add_definitions(-DMTS_HAS_OPENEXR=1)
endif()

View File

@ -141,14 +141,16 @@ function(mts_win_resource target_filename name ext description)
endif()
set(RC_DESCRIPTION "${description}")
#TODO Add the hg revision number to the version, e.g. 0.0.0-hg000000000000
set(RC_VERSION "${MTS_VERSION}")
set(RC_VERSION_COMMA "${MTS_VERSION}.0")
string(REPLACE "." "," RC_VERSION_COMMA ${RC_VERSION_COMMA})
if (MTS_HAS_VALID_REV)
set(RC_VERSION "${MTS_VERSION}-${MTS_VERSION_BUILD}hg${MTS_REV_ID}")
else()
set(RC_VERSION "${MTS_VERSION}")
endif()
set(RC_VERSION_COMMA "${MTS_VERSION_MAJOR},${MTS_VERSION_MINOR},${MTS_VERSION_PATCH},0")
set(RC_FILENAME "${name}${ext}")
set(RC_NAME "${name}")
#TODO Set the year programmatically
set(RC_YEAR "2012")
# MTS_DATE has the format YYYY.MM.DD
string(SUBSTRING "${MTS_DATE}" 0 4 RC_YEAR)
configure_file("${RC_FILE}" "${target_filename}" ESCAPE_QUOTES @ONLY)
endfunction()
@ -308,15 +310,15 @@ macro (add_mts_plugin _plugin_name)
add_library (${_plugin_name} MODULE ${_plugin_srcs})
endif ()
set(core_libraries "mitsuba-core" "mitsuba-render")
set(_plugin_core_libraries "mitsuba-core" "mitsuba-render")
if (_plugin_MTS_HW)
list(APPEND core_libraries "mitsuba-hw")
list(APPEND _plugin_core_libraries "mitsuba-hw")
endif()
if (_plugin_MTS_BIDIR)
list(APPEND core_libraries "mitsuba-bidir")
list(APPEND _plugin_core_libraries "mitsuba-bidir")
endif()
target_link_libraries (${_plugin_name}
${core_libraries} ${_plugin_LINK_LIBRARIES})
${_plugin_core_libraries} ${_plugin_LINK_LIBRARIES})
set_target_properties (${_plugin_name} PROPERTIES PREFIX "")
if (APPLE)
@ -367,6 +369,7 @@ endif()
# [RES_ICON filename]
# [RES_DESCRIPTION "Description string"]
# [NO_INSTALL]
# [MTS_HW] [MTS_BIDIR]
# [NO_MTS_PCH | PCH pch_header] )
#
# The executable name is taken from the first argument. The target gets
@ -375,6 +378,11 @@ endif()
# (for example, libpng) may be specified after the optionl LINK_LIBRARIES
# keyword.
#
# By default the executables are linked against mitsuba-core and mitsuba-render.
# When MTS_HW is set, the executable will be linked against with mitsuba-hw.
# When MTS_BIDIR is specified, the executable will also be linked against
# mitsuba-bidir.
#
# The optional keyword WIN32, if presents, gets passed to add_executable(...)
# to produce a Windows executable using winmain, thus it won't have a
# console. The NO_INSTALL keyword causes the target not to be installed.
@ -388,7 +396,7 @@ endif()
# builds; other platforms simply ignore this value as with RES_ICON.
#
macro (add_mts_exe _exe_name)
CMAKE_PARSE_ARGUMENTS(_exe "WIN32;NO_INSTALL;NO_MTS_PCH"
CMAKE_PARSE_ARGUMENTS(_exe "WIN32;NO_INSTALL;MTS_HW;MTS_BIDIR;NO_MTS_PCH"
"PCH;RES_ICON;RES_DESCRIPTION" "LINK_LIBRARIES" ${ARGN})
set (_exe_srcs ${_exe_UNPARSED_ARGUMENTS})
if (_exe_WIN32)
@ -425,8 +433,15 @@ macro (add_mts_exe _exe_name)
else ()
add_executable (${_exe_name} ${_exe_TYPE} ${_exe_srcs})
endif ()
target_link_libraries (${_exe_name}
${MTS_CORELIBS} ${_exe_LINK_LIBRARIES})
set(_exe_core_libraries "mitsuba-core" "mitsuba-render")
if (_exe_MTS_HW)
list(APPEND _exe_core_libraries "mitsuba-hw")
endif()
if (_exe_MTS_BIDIR)
list(APPEND _exe_core_libraries "mitsuba-bidir")
endif()
target_link_libraries (${_exe_name} ${_exe_core_libraries} ${_exe_LINK_LIBRARIES})
if (WIN32)
set_target_properties (${_exe_name} PROPERTIES VERSION "${MTS_VERSION}")
endif()

View File

@ -0,0 +1,160 @@
# ============================================================================
# HDRITools - High Dynamic Range Image Tools
# Copyright 2008-2011 Program of Computer Graphics, Cornell University
#
# Distributed under the OSI-approved MIT License (the "License");
# see accompanying file LICENSE for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
# ---------------------------------------------------------------------------
# Primary author:
# Edgar Velazquez-Armendariz <cs#cornell#edu - eva5>
# ============================================================================
# - Sets up the version info variables
# This module provides a function intended to be called ONLY from the root dir:
# MTS_GET_VERSION_INFO()
# This function will read the "include/mitsuba/core/version.h" file and execute
# "hg", setting the following variables:
# MTS_VERSION - Full version string: <major>.<minor>.<patch>
# MTS_VERSION_MAJOR
# MTS_VERSION_MINOR
# MTS_VERSION_PATCH
# MTS_VERSION_BUILD - Simple build number based on MTS_DATE,
# encoded as YYYYMMDD
# MTS_HAS_VALID_REV - Flag to indicate whether MTS_REV_ID is set
# MTS_REV_ID - First 12 digits of the mercurial revision ID
# MTS_DATE - Represents the code date as YYYY.MM.DD
# MTS_MACLS_VERSION - A version for Mac Launch Services from the version and
# code date, in the format nnnnn.nn.nn[hgXXXXXXXXXXXX]
function(MTS_GET_VERSION_INFO)
# Simple, internal macro for zero padding values. Assumes that the number of
# digits is enough. Note that this method overwrites the variable!
macro(ZERO_PAD NUMBER_VAR NUM_DIGITS)
set(_val ${${NUMBER_VAR}})
set(${NUMBER_VAR} "")
foreach(dummy_var RANGE 1 ${NUM_DIGITS})
math(EXPR _digit "${_val} % 10")
set(${NUMBER_VAR} "${_digit}${${NUMBER_VAR}}")
math(EXPR _val "${_val} / 10")
endforeach()
unset(_val)
unset(_digit)
endmacro()
# Uses hg to get the version string and the date of such revision
# Based on info from:
# http://mercurial.selenic.com/wiki/VersioningWithMake (January 2011)
# Try to directly get the information assuming the source is within a repo
find_program(HG_CMD hg DOC "Mercurial command line executable")
mark_as_advanced(HG_CMD)
if (HG_CMD)
execute_process(
COMMAND "${HG_CMD}" -R "${PROJECT_SOURCE_DIR}"
parents --template "{node|short},{date|shortdate}"
OUTPUT_VARIABLE HG_INFO
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (HG_INFO)
# Extract the revision ID and the date
string(REGEX REPLACE "(.+),.+" "\\1" MTS_REV_ID "${HG_INFO}")
string(REGEX REPLACE ".+,(.+)-(.+)-(.+)" "\\1.\\2.\\3"
MTS_DATE "${HG_INFO}")
set(MTS_REV_ID ${MTS_REV_ID} PARENT_SCOPE)
set(MTS_DATE ${MTS_DATE} PARENT_SCOPE)
endif()
endif()
# If that failed, try grabbing the id from .hg_archival.txt, in case a tarball
# made by "hg archive" is being used
if (NOT MTS_REV_ID)
set(HG_ARCHIVAL_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/.hg_archival.txt")
# Try to read from the file generated by "hg archive"
if (EXISTS "${HG_ARCHIVAL_FILENAME}")
file(READ "${HG_ARCHIVAL_FILENAME}" HG_ARCHIVAL_TXT)
# Extract just the first 12 characters of the node
string(REGEX REPLACE ".*node:[ \\t]+(............).*" "\\1"
MTS_REV_ID "${HG_ARCHIVAL_TXT}")
set(MTS_REV_ID ${MTS_REV_ID} PARENT_SCOPE)
endif()
endif()
if (NOT MTS_DATE)
# The Windows "date" command output depends on the regional settings
if (WIN32)
set(GETDATE_CMD "${PROJECT_SOURCE_DIR}/data/windows/getdate.exe")
set(GETDATE_ARGS "")
else()
set(GETDATE_CMD "date")
set(GETDATE_ARGS "+'%Y.%m.%d'")
endif()
execute_process(COMMAND "${GETDATE_CMD}" ${GETDATE_ARGS}
OUTPUT_VARIABLE MTS_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (NOT MTS_DATE)
message(FATAL_ERROR "Unable to get a build date!")
endif()
set(MTS_DATE ${MTS_DATE} PARENT_SCOPE)
endif()
if (MTS_REV_ID)
set (MTS_HAS_VALID_REV 1)
else()
message(WARNING "Unable to find the mercurial revision id.")
set (MTS_HAS_VALID_REV 0)
endif()
set(MTS_HAS_VALID_REV ${MTS_HAS_VALID_REV} PARENT_SCOPE)
# Read version (MTS_VERSION) from include/mitsuba/core/version.h
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/mitsuba/core/version.h" MITSUBA_H REGEX "^#define MTS_VERSION \"[^\"]*\"$")
if (MITSUBA_H MATCHES "^.*MTS_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*$")
set(MTS_VERSION_MAJOR ${CMAKE_MATCH_1})
set(MTS_VERSION_MINOR ${CMAKE_MATCH_2})
set(MTS_VERSION_PATCH ${CMAKE_MATCH_3})
set(MTS_VERSION "${MTS_VERSION_MAJOR}.${MTS_VERSION_MINOR}.${MTS_VERSION_PATCH}" PARENT_SCOPE)
set(MTS_VERSION_MAJOR ${MTS_VERSION_MAJOR} PARENT_SCOPE)
set(MTS_VERSION_MINOR ${MTS_VERSION_MINOR} PARENT_SCOPE)
set(MTS_VERSION_PATCH ${MTS_VERSION_PATCH} PARENT_SCOPE)
else()
message(FATAL_ERROR "The mitsuba version could not be determined!")
endif()
# Make a super simple build number from the date
if (MTS_DATE MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
set(MTS_VERSION_BUILD
"${CMAKE_MATCH_1}${CMAKE_MATCH_2}${CMAKE_MATCH_3}" PARENT_SCOPE)
# Now make a Mac Launch Services version number based on version and date.
# Based on specs from:
# http://lists.apple.com/archives/carbon-dev/2006/Jun/msg00139.html (Feb 2011)
if (MTS_VERSION_MAJOR GREATER 30 OR
MTS_VERSION_MINOR GREATER 14 OR
MTS_VERSION_PATCH GREATER 14 OR
${CMAKE_MATCH_1} GREATER 2032)
message(AUTHOR_WARNING "Mitsuba version violates the Mac LS assumptions")
endif()
math(EXPR _MACLS_MAJOR "(${MTS_VERSION_MAJOR}+1)*256 + (${MTS_VERSION_MINOR}+1)*16 + ${MTS_VERSION_PATCH}+1")
math(EXPR _MACLS_MINOR "((${CMAKE_MATCH_1}-2008)*4) + ((${CMAKE_MATCH_2}-1)*32 + ${CMAKE_MATCH_3})/100")
math(EXPR _MACLS_BUILD "((${CMAKE_MATCH_2}-1)*32 + ${CMAKE_MATCH_3})%100")
ZERO_PAD(_MACLS_MAJOR 4)
ZERO_PAD(_MACLS_MINOR 2)
ZERO_PAD(_MACLS_BUILD 2)
set(MTS_MACLS_VERSION "${_MACLS_MAJOR}.${_MACLS_MINOR}.${_MACLS_BUILD}")
if(MTS_HAS_VALID_REV)
set(MTS_MACLS_VERSION "${MTS_MACLS_VERSION}hg${MTS_REV_ID}")
endif()
set(MTS_MACLS_VERSION ${MTS_MACLS_VERSION} PARENT_SCOPE)
else()
message(FATAL_ERROR
"Mitsuba date has an unexpected format: ${MTS_DATE}")
endif()
endfunction()

View File

@ -90,5 +90,7 @@
<string>YES</string>
<key>BreakpadVendor</key>
<string>the Mitsuba authors</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View File

@ -70,5 +70,7 @@
<string>@MTS_VERSION@</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View File

@ -1,5 +1,6 @@
#!/bin/bash
cp /opt/intel/composer_xe_*/compiler/lib/libiomp5.dylib Mitsuba.app/Contents/Frameworks
install_name_tool -id @rpath/libiomp5.dylib Mitsuba.app/Contents/Frameworks/libiomp5.dylib
find Mitsuba.app/Contents/MacOS/ Mitsuba.app/plugins -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
find Mitsuba.app/Contents/Frameworks/libmitsuba-* -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
find Mitsuba.app/Contents/python -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
find Mitsuba.app/python -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib

View File

@ -1,3 +1,65 @@
mitsuba (0.4.4-1) unstable; urgency=low
* Improved Python support for rendering animations and motion blur
* Photon mapper logic rewrite to account for certain missing specular paths
* Robustness improvements for specular+diffuse materials such as 'plastic'
* Fixed a remaining issue in the instancing frame computation code
* The thindielectric plugin formerly computed incorrect transmittance values
* The cube shape is now centered at the origin by default
* The TLS cleanup logic has been fixed to avoid a potential crash in mtssrv
* Other minor improvements, which are listed in the repository log
-- Wenzel Jakob <wenzel@cs.cornell.edu> Thu, 28 Feb 2013 00:00:00 -0400
mitsuba (0.4.3-1) unstable; urgency=low
* Motion blur: Support for arbitrary linear camera, object, and sensor motion
to produce motion blur in renderings.
* Render-time annotations: added the ability to tag image files with additional
information by means of metadata or text labels.
* Hide directly visible emitters: convenient feature for removing an environment
light source so that an image can be composited onto documents having a
different color.
* Improved instancing: more robust instancing code with support for
non-rigid transformations.
* Threading on Windows: fixed various threading-related issues on Windows that
previously caused crashes and deadlocks.
* Caching: Caching mechanism to further accelerate the loading of
.serialized files.
* File dialogs: Native File Open/Save dialogs are now used on Windows.
* Python: Improved python bindings; easier usage on MacOS X.
* Blender interaction: Fixed a issue where GUI tabs containing scenes created
in Blender could not be cloned.
* Non-uniform scales: All triangle mesh-based shapes now permit
non-uniform scales.
* NaNs and friends: Increased resilience against various numerical corner cases.
* Index-matched participating media: Fixed an unfortunate regression in volpath
regarding index-matched media that was accidentally introduced in 0.4.2.
* roughdiffuse: Fixed texturing support in the roughdiffuse plugin.
* Photon mapping: Fixed some inaccuracies involving participating media when
rendered by the photon mapper and the Beam Radiance Estimate.
* Conductors: Switched Fresnel reflectance computations for conductors to the
exact expressions predicted by geometric optics (an approximation was
previously used).
* New cube shape: Added a cube shape plugin for convenience. This does
exactly what one would expect.
* The rest: As usual, a large number of smaller bugfixes and improvements
were below the threshold and are thus not listed individually. The
repository log has more details.
-- Wenzel Jakob <wenzel@cs.cornell.edu> Tue, 29 Jan 2013 00:00:00 -0400
mitsuba (0.4.2-1) unstable; urgency=low
* Volumetric path tracers: improved sampling when dealing with index-matched medium transitions. This is essentially a re-implementation of an optimization that Mitsuba 0.3.1 already had, but which got lost in the bidirectional rewrite.
* Batch tonemapper: due to an unfortunate bug, the batch tonemapper in the last release produced invalid results for images containing an alpha channel. This is now fixed.
* Shapes: corrected some differential geometry issues in the "cylinder" and "rectangle" shapes.
* MLT: fixed 2-stage MLT, which was producing incorrect results.
* MEPT: fixed the handling of directional light sources.
* Robustness: got rid of various corner-cases that could produce NaNs.
* Filenames: to facilitate loading scenes created on Windows/OSX, the Linux version now resolves files case-insensitively if they could not be found after a case-sensitive search.
* Python: added Python bindings for shapes and triangle meshes. The Python plugin should now be easier to load (previously, this was unfortunately rather difficult on several platforms). The documentation was also given an overhaul.
* Particle tracing: I've decided to disable the adjoint BSDF for shading normals in the particle tracer, since it causes an unacceptable amount of variance in scenes containing poorly tesselated geometry. This affects the plugins ptracer, ppm, sppm and photonmapper.
* Subsurface scattering: fixed parallel network renderings involving the dipole model.
* Homogeneous medium & dipole: added many more material presets by Narasimhan et al.
* OBJ loader: further robustness improvements to the OBJ loader and the associated MTL material translator.
-- Wenzel Jakob <wenzel@cs.cornell.edu> Wed, 31 Oct 2012 00:00:00 -0400
mitsuba (0.4.1-1) unstable; urgency=low
* negative pixel values in textures and environment maps are handled more gracefully.
* minor robustness improvements to the OBJ and COLLADA importers.
@ -35,15 +97,15 @@ mitsuba (0.4.0-1) unstable; urgency=low
mitsuba (0.3.1-1) unstable; urgency=low
* Photon mapper: The photon mapper had some serious issues in the
* Photon mapper: The photon mapper had some serious issues in the
last release. These are now fixed, and it should run faster too.
* On Linux/x86_64, the performance of the single precision exp() and log()
* On Linux/x86_64, the performance of the single precision exp() and log()
math library functions is extremely poor. Mitsuba now uses the double
prevision versions of these functions by default.
* Primitive clipping: Fixed numerical issues that occurred when using
primitive clipping in a double precision build.
* The adaptive integrator now better interacts with certain sub-integrators.
* Instanced analytic shapes (e.g. spheres, cylinders, ..) are now supported,
* Instanced analytic shapes (e.g. spheres, cylinders, ..) are now supported,
and an error involving network rendering with instanced geometry is fixed.
* Fixed a serious issue that could destroy a scene file when saving from a cloned tab!
* Fixed some bad GUI behavior in multi-screen setups
@ -57,30 +119,30 @@ mitsuba (0.3.0-1) unstable; urgency=low
* Added Python bindings that can be used to instantiate plugins
and control rendering processes.
* Spectral rendering: most of the code pertaining to spectral
rendering has seen a significant overhaul. It is now faster and
* Spectral rendering: most of the code pertaining to spectral
rendering has seen a significant overhaul. It is now faster and
in certain cases more accurate.
* Flexible material classes: this release introduces a robust and
very general suite of eight physically-based smooth and rough
* Flexible material classes: this release introduces a robust and
very general suite of eight physically-based smooth and rough
(microfacet-based) material classes.
* Material modifiers: two new material modifiers (bump & coating)
can be applied to BSDFs to create new materials.
* Material verification: the sampling methods of all material
models in Mitsuba are now automatically verified with the help
* Material verification: the sampling methods of all material
models in Mitsuba are now automatically verified with the help
of statistical hypothesis tests (using Chi^2-tests).
* Generated documentation: there is now a javadoc-like system,
which extracts documentation directly from the plugin source code
* Generated documentation: there is now a javadoc-like system,
which extracts documentation directly from the plugin source code
and stitches it into a LaTeX reference document.
* lookAt: Mitsuba inherited a bug from PBRT, where the <lookAt>
tag changed the handedness of the coordinate system. This is now
* lookAt: Mitsuba inherited a bug from PBRT, where the <lookAt>
tag changed the handedness of the coordinate system. This is now
fixed--also, the syntax of this tag has changed to make it easier to read.
* Scene portability: A new conversion tool ensures that old and incompatible
scenes can be translated into the scene description format of the
scenes can be translated into the scene description format of the
most recent version.
* Contributed plugins: Tom Kazimiers and Papas have contributed
* Contributed plugins: Tom Kazimiers and Papas have contributed
implementations of the Preetham Sun & Sky model and the Hanrahan-Krueger
scattering model.
* Photon mapping: The Photon map integrator has been rewritten for
* Photon mapping: The Photon map integrator has been rewritten for
improved accuracy and better performance. Furthermore, the underlying
data structure has been replaced with a ~50% faster implementation.
@ -125,8 +187,8 @@ mitsuba (0.2.0-1) unstable; urgency=low
mitsuba (0.1.3-1) unstable; urgency=low
This is mainly a bugfix release to address a serious regression in the
material system. Other notable changes are:
This is mainly a bugfix release to address a serious regression in the
material system. Other notable changes are:
* Imported scenes now store relative paths
* OBJ importing works on Windows
@ -134,7 +196,7 @@ mitsuba (0.1.3-1) unstable; urgency=low
* The anisotropic Ward BRDF is now supported in the preview
* Faster texture loading
* The renderer now has a testcase framework similar to JUnit
-- Wenzel Jakob <wenzel@cs.cornell.edu> Wed, 8 Sep 2010 09:59:00 -0400
mitsuba (0.1.2-1) unstable; urgency=low
@ -150,8 +212,8 @@ mitsuba (0.1.2-1) unstable; urgency=low
is lacking some required OpenGL features.
* Create default cameras/lightsources if none are specified in a scene
* Support for drag & drop in the user interface
* 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
* 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.
* The realtime preview now has a 'force diffuse' feature to improve
@ -165,6 +227,6 @@ mitsuba (0.1.2-1) unstable; urgency=low
mitsuba (0.1.1-1) unstable; urgency=low
* Initial release
* Initial release
-- Wenzel Jakob <wenzel@cs.cornell.edu> Sat, 17 Jul 2010 23:56:03 -0400

View File

@ -4,10 +4,10 @@ Priority: optional
Maintainer: Wenzel Jakob <wenzel@cs.cornell.edu>
Build-Depends: debhelper (>= 7), build-essential, scons, qt4-dev-tools,
libpng12-dev, libjpeg-dev, libilmbase-dev, libopenexr-dev,
libxerces-c-dev, libboost-dev, libglewmx1.5-dev, libxxf86vm-dev,
libxerces-c-dev, libboost-dev, libglewmx-dev, libxxf86vm-dev,
collada-dom-dev, libboost-system-dev, libboost-filesystem-dev,
libboost-python-dev, libboost-thread-dev, libgl1-mesa-dev,
libglu1-mesa-dev, pkg-config, libeigen3-dev
libglu1-mesa-dev, pkg-config, libeigen3-dev, libxml2-dev
Standards-Version: 3.8.3
Homepage: http://www.mitsuba-renderer.org
@ -24,7 +24,7 @@ Description: Mitsuba renderer
Package: mitsuba-dev
Architecture: any
Depends: qt4-dev-tools, libpng12-dev, libjpeg-dev, libilmbase-dev,
libopenexr-dev, libxerces-c-dev, libboost-dev, libglewmx1.5-dev,
libopenexr-dev, libxerces-c-dev, libboost-dev, libglewmx-dev,
libxxf86vm-dev, collada-dom-dev, libboost-system-dev,
libboost-filesystem-dev, libboost-python-dev, libboost-thread-dev,
libeigen3-dev, mitsuba

View File

@ -1,7 +1,7 @@
Name: mitsuba
Version: 0.4.1
Version: 0.4.4
Release: 1%{?dist}
Summary: Mitsuba renderer
Summary: Mitsuba renderer
Group: Applications/Graphics
License: GPL-3
URL: http://www.mitsuba-renderer.org
@ -10,11 +10,11 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
BuildRequires: gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel eigen3-devel
Requires: boost qt4 OpenEXR-libs xerces-c python libGLEWmx collada-dom
%description
Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased as well as biased techniques and contains heavy optimizations targeted towards current CPU architectures.
Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased as well as biased techniques and contains heavy optimizations targeted towards current CPU architectures.
The program currently runs on Linux, MacOS X and Microsoft Windows and makes use of SSE2 optimizations on x86 and x86_64 platforms. So far, its main use has been as a testbed for algorithm development in computer graphics, but there are many other interesting applications.
Mitsuba comes with a command-line interface as well as a graphical frontend to interactively explore scenes. While navigating, a rough preview is shown that becomes increasingly accurate as soon as all movements are stopped. Once a viewpoint has been chosen, a wide range of rendering techniques can be used to generate images, and their parameters can be tuned from within the program.
Mitsuba comes with a command-line interface as well as a graphical frontend to interactively explore scenes. While navigating, a rough preview is shown that becomes increasingly accurate as soon as all movements are stopped. Once a viewpoint has been chosen, a wide range of rendering techniques can be used to generate images, and their parameters can be tuned from within the program.
%package devel
Summary: Mitsuba development files
Requires: boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel
@ -35,13 +35,14 @@ mkdir -p $RPM_BUILD_ROOT/usr/share/mitsuba/plugins
mkdir -p $RPM_BUILD_ROOT/usr/share/pixmaps
mkdir -p $RPM_BUILD_ROOT/usr/share/applications
mkdir -p $RPM_BUILD_ROOT/usr/include
strip dist/lib* dist/mtsgui dist/mitsuba dist/mtssrv dist/mtsutil
strip dist/lib* dist/mtsgui dist/mitsuba dist/mtssrv dist/mtsutil dist/mtsimport
strip dist/plugins/* dist/python/*/*
cp dist/libmitsuba-*.so $RPM_BUILD_ROOT%{_libdir}
cp dist/mtsgui $RPM_BUILD_ROOT%{_bindir}
cp dist/mitsuba $RPM_BUILD_ROOT%{_bindir}
cp dist/mtssrv $RPM_BUILD_ROOT%{_bindir}
cp dist/mtsutil $RPM_BUILD_ROOT%{_bindir}
cp dist/mtsimport $RPM_BUILD_ROOT%{_bindir}
cp dist/python/2.7/mitsuba.so $RPM_BUILD_ROOT%{_libdir}/python2.7/lib-dynload
cp dist/plugins/* $RPM_BUILD_ROOT/usr/share/mitsuba/plugins
cp -Rdp dist/data $RPM_BUILD_ROOT/usr/share/mitsuba/data
@ -62,6 +63,15 @@ rm -rf $RPM_BUILD_ROOT
/usr/include/*
%changelog
* Thu Feb 28 2013 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.4%{?dist}
- Upgrade to version 0.4.4
* Tue Jan 29 2013 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.3%{?dist}
- Upgrade to version 0.4.3
* Wed Oct 31 2012 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.2%{?dist}
- Upgrade to version 0.4.2
* Wed Oct 10 2012 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.1%{?dist}
- Upgrade to version 0.4.1

View File

@ -10,5 +10,5 @@ Exec=mtsgui %U
TryExec=mtsgui
Terminal=false
StartupNotify=true
MimeType=application/xml
Icon=mitsuba48.png
MimeType=application/xml;image/x-exr;image/x-hdr;
Icon=mitsuba48

View File

@ -42,7 +42,6 @@
#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/tls.h>

View File

@ -26,7 +26,7 @@
<xsd:element name="rgb" type="rgb"/>
<xsd:element name="srgb" type="string"/>
<xsd:element name="blackbody" type="blackbody"/>
<xsd:element name="alias" type="alias"/>
</xsd:choice>
<xsd:attribute name="version" type="xsd:string"/>
@ -43,6 +43,7 @@
<xsd:element name="vector" type="point"/>
<xsd:element name="boolean" type="boolean"/>
<xsd:element name="transform" type="transform"/>
<xsd:element name="animation" type="animation"/>
<xsd:element name="string" type="string"/>
<xsd:element name="spectrum" type="spectrum"/>
<xsd:element name="rgb" type="rgb"/>
@ -50,14 +51,14 @@
<xsd:element name="blackbody" type="blackbody"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="objectBase">
<xsd:attribute name="type" type="xsd:string" use="required"/>
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="object">
<xsd:complexContent>
<xsd:extension base="objectBase">
@ -140,7 +141,7 @@
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<!-- MEDIUM Element -->
<xsd:complexType name="medium">
<xsd:complexContent>
@ -297,7 +298,7 @@
<xsd:complexType name="include">
<xsd:attribute name="filename" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="alias">
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute name="as" type="xsd:string" use="required"/>
@ -314,6 +315,23 @@
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="animationTransform">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="translate" type="translate"/>
<xsd:element name="rotate" type="rotate"/>
<xsd:element name="lookAt" type="lookAt"/>
<xsd:element name="lookat" type="lookAt"/>
<xsd:element name="scale" type="scale"/>
<xsd:element name="matrix" type="matrix"/>
</xsd:choice>
<xsd:attribute name="time" type="doubleType" use="required"/>
</xsd:complexType>
<xsd:complexType name="animation">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="transform" type="animationTransform"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="translate">
<xsd:attribute name="x" type="doubleType"/>
<xsd:attribute name="y" type="doubleType"/>

52
data/windows/getdate.c Normal file
View File

@ -0,0 +1,52 @@
/*============================================================================
HDRITools - High Dynamic Range Image Tools
Copyright 2008-2011 Program of Computer Graphics, Cornell University
Distributed under the OSI-approved MIT License (the "License");
see accompanying file LICENSE for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
-----------------------------------------------------------------------------
Primary author:
Edgar Velazquez-Armendariz <cs#cornell#edu - eva5>
============================================================================*/
#include <stdio.h>
#include <time.h>
int main(int argc, char **argv)
{
time_t ltime;
struct tm *today;
FILE *of;
#if _MSC_VER >= 1400
struct tm timebuf;
#endif
if (argc != 2) {
of = stdout;
} else {
#if _MSC_VER >= 1400
if (fopen_s(&of, argv[1], "w") != 0) return 3;
#else
of = fopen(argv[1], "w");
if (!of) return 3;
#endif
}
time(&ltime);
#if _MSC_VER >= 1400
if (localtime_s(&timebuf, &ltime) != 0) return 1;
today = &timebuf;
#else
today = localtime(&ltime);
if (!today) return 1;
#endif
fprintf(of, "%d.%02d.%02d", (today->tm_year + 1900),
(today->tm_mon + 1), today->tm_mday);
if (of != stdout) fclose(of);
return 0;
}

BIN
data/windows/getdate.exe Normal file

Binary file not shown.

110
data/windows/wmain_stub.cpp Normal file
View File

@ -0,0 +1,110 @@
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2012 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/platform.h>
#if defined(__WINDOWS__)
// Stub for generating UTF-8 command line arguments from wmain (UTF-16)
#include <Windows.h>
extern int mts_main(int argc, char **argv);
namespace {
class ArgsUTF8 {
public:
ArgsUTF8(int argc, wchar_t *wargv[]) :
m_argc(-1), m_argv(NULL), m_data(NULL)
{
if (argc > 0)
m_argc = argc;
else
return;
m_argv = new char*[argc];
int total = 0;
// Pass 1: get the lengths of each converted string an allocate data
for (int i = 0; i < argc; ++i) {
const int lenUtf8 = WideCharToMultiByte(CP_UTF8, 0,
wargv[i], -1, NULL, 0, NULL, NULL);
if (lenUtf8 != 0) {
total += lenUtf8;
m_argv[i] = reinterpret_cast<char*>(lenUtf8);
} else {
m_argc = i;
break;
}
}
if (m_argc < 1)
return;
m_data = new char[total];
int currOffset = 0;
// Pass 2: perform the conversion
for (int i = 0; i < m_argc; ++i) {
int lenUtf8 = reinterpret_cast<int>(m_argv[i]);
m_argv[i] = m_data + currOffset;
lenUtf8 = WideCharToMultiByte(CP_UTF8, 0,
wargv[i], -1, m_argv[i], lenUtf8, NULL, NULL);
if (lenUtf8 != 0) {
currOffset += lenUtf8;
} else {
m_argc = i;
return;
}
}
}
~ArgsUTF8() {
if (m_argv != NULL) {
delete [] m_argv;
}
if (m_data != NULL) {
delete [] m_data;
}
}
inline int argc() const {
return m_argc;
}
inline char** argv() const {
return m_argv;
}
private:
int m_argc;
char** m_argv;
char* m_data;
};
} // namespace
// MSDN Documentation:
// http://msdn.microsoft.com/en-US/library/fzc2cy7w%28v=vs.110%29.aspx
int wmain(int argc, wchar_t *wargv[], wchar_t *envp[]) {
ArgsUTF8 argsUTF8(argc, wargv);
return mts_main(argsUTF8.argc(), argsUTF8.argv());
}
#endif // __WINDOWS__

View File

@ -1,2 +1,7 @@
all:
./gendoc.py
clean:
$(RM) main.pdf
$(RM) plugins_generated.tex
$(RM) *.aux main.bbl main.blg main.log main.out main.toc

View File

@ -1,11 +1,11 @@
\section{Acknowledgments}
I am indebted to my advisor Steve Marschner for allowing me to devote
a significant amount of my research time to this project. His insightful and
a significant amount of my research time to this project. His insightful and
encouraging suggestions have helped transform this program into much more than
I ever thought it would be.
The architecture of Mitsuba as well as some individual components are based on
implementations discussed in: \emph{Physically Based Rendering - From Theory
The architecture of Mitsuba as well as some individual components are based on
implementations discussed in: \emph{Physically Based Rendering - From Theory
To Implementation} by Matt Pharr and Greg Humphreys.
Some of the GUI icons were taken from the Humanity icon set by Canonical Ltd.
@ -13,10 +13,10 @@ The material test scene was created by Jonas Pilo, and the environment map
it uses is courtesy of Bernhard Vogl.
The included index of refraction data files for conductors are copied from
PBRT. They are originally from the Luxpop database (\url{www.luxpop.com})
PBRT. They are originally from the Luxpop database (\url{www.luxpop.com})
and are based on data by Palik et al. \cite{Palik1998Handbook}
and measurements of atomic scattering factors made by the Center For
X-Ray Optics (CXRO) at Berkeley and the Lawrence Livermore National
X-Ray Optics (CXRO) at Berkeley and the Lawrence Livermore National
Laboratory (LLNL).
The following people have kindly contributed code or bugfixes:
@ -28,7 +28,7 @@ The following people have kindly contributed code or bugfixes:
\item Leonhard Gr\"unschlo\ss
\end{itemize}
Mitsuba makes heavy use of the following amazing libraries and tools:
Mitsuba makes heavy use of the following amazing libraries and tools:
\begin{itemize}
\item Qt 4 by Digia
\item OpenEXR by Industrial Light \& Magic

View File

@ -4,18 +4,18 @@ The rendering functionality of Mitsuba can be accessed through
a command line interface and an interactive Qt-based frontend. This section
provides some basic instructions on how to use them.
\subsection{Interactive frontend}
To launch the interactive frontend, run \code{Mitsuba.app} on MacOS,
To launch the interactive frontend, run \code{Mitsuba.app} on MacOS,
\code{mtsgui.exe} on Windows, and \code{mtsgui} on Linux (after sourcing \code{setpath.sh}).
You can also drag and drop scene files onto the application icon or the running program to open them.
A quick video tutorial on using the GUI can be found here: \url{http://vimeo.com/13480342}.
\subsection{Command line interface}
\label{sec:mitsuba}
The \texttt{mitsuba} binary is an alternative non-interactive rendering
The \texttt{mitsuba} binary is an alternative non-interactive rendering
frontend for command-line usage and batch job operation.
To get a listing of the parameters it supports, run
the executable without parameters:
\begin{shell}
$\texttt{\$}$ mitsuba
$\texttt{\$}$ mitsuba
\end{shell}
\begin{console}[label=lst:mitsuba-cli,caption=Command line options of the \texttt{mitsuba} binary]
Mitsuba version $\texttt{\MitsubaVersion}$, Copyright (c) $\texttt{\MitsubaYear}$ Wenzel Jakob
@ -75,18 +75,18 @@ mode of operation is to render a single scene, which is provided as a parameter,
$\texttt{\$}$ mitsuba path-to/my-scene.xml
\end{shell}
It is also possible to connect to network render nodes, which essentially lets Mitsuba parallelize
over additional cores. To do this, pass a semicolon-separated list of machines to
the \code{-c} parameter.
over additional cores. To do this, pass a semicolon-separated list of machines to
the \code{-c} parameter.
\begin{shell}
$\texttt{\$}$ mitsuba -c machine1;machine2;... path-to/my-scene.xml
\end{shell}
There are two different ways in which you can access render nodes:
\begin{itemize}
\item\textbf{Direct}: Here, you create a direct connection to a running \code{mtssrv} instance on
another machine (\code{mtssrv} is the Mitsuba server process). From the the performance
standpoint, this approach should always be preferred over the SSH method described below when there is
another machine (\code{mtssrv} is the Mitsuba server process). From the the performance
standpoint, this approach should always be preferred over the SSH method described below when there is
a choice between them. There are some disadvantages though: first, you need to manually start
\code{mtssrv} on every machine you want to use.
\code{mtssrv} on every machine you want to use.
And perhaps more importantly: the direct communication
protocol makes no provisions for a malicious user on the remote side. It is too costly
@ -98,11 +98,11 @@ For direct connections, you can specify the remote port as follows:
\begin{shell}
$\texttt{\$}$ mitsuba -c machine:1234 path-to/my-scene.xml
\end{shell}
When no port is explicitly specified, Mitsuba uses default value of 7554.
\item \textbf{SSH}:
This approach works as follows: The renderer creates a SSH connection
When no port is explicitly specified, Mitsuba uses default value of 7554.
\item \textbf{SSH}:
This approach works as follows: The renderer creates a SSH connection
to the remote side, where it launches a Mitsuba worker instance.
All subsequent communication then passes through the encrypted link.
All subsequent communication then passes through the encrypted link.
This is completely secure but slower due to the encryption overhead.
If you are rendering a complex scene, there is a good chance that it
won't matter much since most time is spent doing computations rather than
@ -119,18 +119,18 @@ $\texttt{\$}$ mitsuba -c username@machine path-to/my-scene.xml
\begin{shell}
$\texttt{\$}$ mitsuba -c username@machine:/opt/mitsuba path-to/my-scene.xml
\end{shell}
For the SSH connection approach to work, you \emph{must} enable passwordless
For the SSH connection approach to work, you \emph{must} enable passwordless
authentication.
Try opening a terminal window and running the command \code{ssh username@machine}
Try opening a terminal window and running the command \code{ssh username@machine}
(replace with the details of your remote connection).
If you are asked for a password, something is not set up correctly --- please see
If you are asked for a password, something is not set up correctly --- please see
\url{http://www.debian-administration.org/articles/152} for instructions.
On Windows, the situation is a bit more difficult since there is no suitable SSH client by
default. To get SSH connections to work, Mitsuba requires \code{plink.exe} (from PuTTY) to
be on the path. For passwordless authentication with a Linux/OSX-based
server, convert your private key to PuTTY's format using \code{puttygen.exe}.
Afterwards, start \code{pageant.exe} to load and authenticate the key. All
Afterwards, start \code{pageant.exe} to load and authenticate the key. All
of these binaries are available from the PuTTY website.
It is possible to mix the two approaches to access some machines directly and others
@ -152,7 +152,7 @@ machine3.domain.org:7346
Any attribute in the XML-based scene description language can be parameterized from the
command line.
For instance, you can render a scene several times with different reflectance values
on a certain material by changing its description to something like
on a certain material by changing its description to something like
\begin{xml}
<bsdf type="diffuse">
<spectrum name="reflectance" value="$\texttt{\$}$reflectance"/>
@ -160,28 +160,28 @@ on a certain material by changing its description to something like
\end{xml}
and running Mitsuba as follows:
\begin{shell}
$\texttt{\$}$ mitsuba -Dreflectance=0.1 -o ref_0.1.exr scene.xml
$\texttt{\$}$ mitsuba -Dreflectance=0.2 -o ref_0.2.exr scene.xml
$\texttt{\$}$ mitsuba -Dreflectance=0.5 -o ref_0.5.exr scene.xml
$\texttt{\$}$ mitsuba -Dreflectance=0.1 -o ref_0.1.exr scene.xml
$\texttt{\$}$ mitsuba -Dreflectance=0.2 -o ref_0.2.exr scene.xml
$\texttt{\$}$ mitsuba -Dreflectance=0.5 -o ref_0.5.exr scene.xml
\end{shell}
\subsubsection{Writing partial images to disk}
When doing lengthy command line renders on Linux or OSX, it is possible
to send a signal to the process using
\begin{shell}
When doing lengthy command line renders on Linux or OSX, it is possible
to send a signal to the process using
\begin{shell}
$\texttt{\$}$ killall -HUP mitsuba
\end{shell}
This causes the renderer to write out the partially finished
image, after which it continues rendering. This can sometimes be useful to
This causes the renderer to write out the partially finished
image, after which it continues rendering. This can sometimes be useful to
check if everything is working correctly.
\subsubsection{Rendering an animation}
The command line interface is ideally suited for rendering large amounts of files in batch
operation. You can simply pass in the files using a wildcard in the filename.
operation. You can simply pass in the files using a wildcard in the filename.
If you've already rendered a subset of the frames and you only want to complete the remainder,
add the \texttt{-x} flag, and all files with existing output will be skipped. You can also
let the scheduler work on several scenes at once using the \texttt{-j} parameter --- this is
If you've already rendered a subset of the frames and you only want to complete the remainder,
add the \texttt{-x} flag, and all files with existing output will be skipped. You can also
let the scheduler work on several scenes at once using the \texttt{-j} parameter --- this is
especially useful when parallelizing over multiple machines: as some of the participating machines
finish rendering the current frame, they can immediately start working on the next one
instead of having to wait for all other cores to finish. Altogether, you
@ -189,6 +189,13 @@ might start the with parameters such as the following
\begin{shell}
$\texttt{\$}$ mitsuba -xj 2 -c machine1;machine2;... animation/frame_*.xml
\end{shell}
Note that this requires a shell capable of expanding the asterisk into a list of
filenames. The default Windows shell \code{cmd.exe} does not do this---however,
the PowerShell supports the following syntax:
\begin{shell}
dir frame_*.xml | % $\texttt{\{}$ <path to mitsuba.exe> $\texttt{\$\_}$ $\texttt{\}}$
\end{shell}
\subsection{Direct connection server}
\label{sec:mtssrv}
A Mitsuba compute node can be created using the \code{mtssrv} executable. By default,
@ -206,26 +213,26 @@ $\texttt{\$}$ mtssrv -i maxwell.cs.cornell.edu
\end{shell}
As advised in Section~\ref{sec:mitsuba}, it is advised to run \code{mtssrv} \emph{only} in trusted networks.
One nice feature of \code{mtssrv} is that it (like the \code{mitsuba} executable)
also supports the \code{-c} and \code{-s} parameters, which create connections
One nice feature of \code{mtssrv} is that it (like the \code{mitsuba} executable)
also supports the \code{-c} and \code{-s} parameters, which create connections
to additional compute servers.
Using this feature, one can create hierarchies of compute nodes. For instance,
the root \code{mttsrv} instance of such a hierarchy could share its work with a
number of other machines running \code{mtssrv}, and each of these might also
the root \code{mttsrv} instance of such a hierarchy could share its work with a
number of other machines running \code{mtssrv}, and each of these might also
share their work with further machines, and so on...
The parallelization over such hierarchies happens transparently---when
connecting a renderering process to the root node, it sees a machine
The parallelization over such hierarchies happens transparently---when
connecting a renderering process to the root node, it sees a machine
with hundreds or thousands of cores, to which it can submit work without
needing to worry about how exactly it is going to be spread out in
needing to worry about how exactly it is going to be spread out in
the hierarchy.
Such hierarchies are mainly useful to reduce communication bottlenecks when distributing
large resources (such as scenes) to remote machines. Imagine the following hypothetical scenario:
you would like to render a 50MB-sized scene while at home, but rendering is too slow.
you would like to render a 50MB-sized scene while at home, but rendering is too slow.
You decide to tap into some extra machines available
at your workplace, but this usually doesn't make things much faster because of the relatively slow broadband
connection and the need to transmit your scene to every single compute node involved.
connection and the need to transmit your scene to every single compute node involved.
Using \code{mtssrv}, you can
instead designate a central scheduling node at your workplace, which accepts connections and delegates
@ -233,10 +240,10 @@ rendering tasks to the other machines. In this case, you will only have to trans
and the remaining distribution happens over the fast local network at your workplace.
\subsection{Utility launcher}
\label{sec:mtsutil}
When working on a larger project, one often needs to implement various utility programs that
When working on a larger project, one often needs to implement various utility programs that
perform simple tasks, such as applying a filter to an image or processing
a matrix stored in a file. In a framework like Mitsuba, this unfortunately involves
a significant coding overhead in initializing the necessary APIs on all supported platforms.
a matrix stored in a file. In a framework like Mitsuba, this unfortunately involves
a significant coding overhead in initializing the necessary APIs on all supported platforms.
To reduce this tedious work on the side of the programmer, Mitsuba comes with a utility launcher
called \code{mtsutil}.
@ -250,7 +257,7 @@ For a listing of all supported options and utilities, enter the command without
\label{sec:tonemapper}
One particularly useful utility that shall be mentioned here is the batch tonemapper, which
loads EXR/RGBE images and writes tonemapped 8-bit PNG/JPGs. This can save much time when one has to
process many high dynamic-range images such as animation frames using the same basic operations,
process many high dynamic-range images such as animation frames using the same basic operations,
e.g. gamma correction, changing the overall brightness, resizing, cropping, etc. The available
command line options are shown in \lstref{tonemap-cli}.
@ -282,14 +289,14 @@ Options/Arguments:
between [0, 1] chooses between low and high-key images and
'burn' (also [0, 1]) controls how much highlights may burn out
-x Temporal coherence mode: activate this flag when tonemapping
-x Temporal coherence mode: activate this flag when tonemapping
frames of an animation using the '-p' option to avoid flicker
-o file Save the output with a given filename
-t Multithreaded: process several files in parallel
The operations are ordered as follows: 1. crop, 2. resize, 3. color-balance,
4. tonemap, 5. annotate. To simply process a directory full of EXRs in
The operations are ordered as follows: 1. crop, 2. resize, 3. color-balance,
4. tonemap, 5. annotate. To simply process a directory full of EXRs in
parallel, run the following: 'mtsutil tonemap -t path-to-directory/*.exr'
\end{console}

View File

@ -1,23 +1,23 @@
\section{Compiling the renderer}
\label{sec:compiling}
To compile Mitsuba, you will need a recent C++ compiler (e.g. GCC 4.2+ or
Visual Studio 2010) and some additional libraries, which Mitsuba uses internally.
To compile Mitsuba, you will need a recent C++ compiler (e.g. GCC 4.2+ or
Visual Studio 2010) and some additional libraries, which Mitsuba uses internally.
Builds on all supported platforms are done using a unified system
based on SCons (\url{http://www.scons.org}), which is a Python-based
software construction tool. The exact process is different depending on
based on SCons (\url{http://www.scons.org}), which is a Python-based
software construction tool. The exact process is different depending on
which operating system is used and will be explained in the following subsections.
\subsection{Common steps}
To get started, you will need to download a recent version of the Mitsuba source code. Before
doing this, ensure that you have read the licensing agreement
(Section~\ref{sec:license}), and that you abide by its contents. Note that, being a ``viral''
doing this, ensure that you have read the licensing agreement
(Section~\ref{sec:license}), and that you abide by its contents. Note that, being a ``viral''
license, the GPL automatically applies to derivative work. Amongst other things, this
means that Mitsuba's source code is \emph{off-limits} to those who develop rendering
software not distributed under a compatible license.
Check that the Mercurial (\url{http://mercurial.selenic.com/}) versioning
system\footnote{On Windows, you might want to use the convenient TortoiseHG shell
extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.}
Check that the Mercurial (\url{http://mercurial.selenic.com/}) versioning
system\footnote{On Windows, you might want to use the convenient TortoiseHG shell
extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.}
is installed, which is required to fetch the most recent source code release.
Begin by entering the following at the command prompt (or run an equivalent command from a graphical Mercurial frontend):
\begin{shell}
@ -38,7 +38,7 @@ will run extremely slowly. Its main use is to track down elusive bugs.
\paragraph{Windows:}
On Windows, builds can either be performed using the Visual Studio 2010\footnote{No other Visual Studio versions are currently supported.}
compiler or Intel XE Composer (on top of Visual Studio 2010).
Note that Visual Studio 2010 Service Pack 1 \emph{must} be installed or the resulting binaries will crash.
Note that Visual Studio 2010 Service Pack 1 \emph{must} be installed or the resulting binaries will crash.
\begin{description}
\item[\code{build/config-\{win32, win64\}-\{msvc2010, msvc2010-debug\}.py}:] Create 32 or 64 bit binaries using Microsoft Visual C++ version 2010.
The configurations with the suffix \code{-debug} will include debug symbols in all binaries, which run very slowly.
@ -66,7 +66,7 @@ $\texttt{\$}$ cp build/config-linux-gcc.py config.py
\subsection{Compilation flags}
\label{sec:compiling-flags}
There are several flags that affect the behavior of Mitsuba and must be specified at compile time.
These usually don't need to be changed, but if you want to compile Mitsuba for spectral rendering, or
These usually don't need to be changed, but if you want to compile Mitsuba for spectral rendering, or
to use double precision for internal computations then the following may be useful. Otherwise, you may skip ahead to the subsection
that covers your operating system.
@ -77,13 +77,13 @@ The following options are available:
enabled by default (even in release builds).
\item[\texttt{MTS\_KD\_DEBUG}] Enable additional checks in the kd-tree. This
is quite slow and mainly useful to track down bugs when they are suspected.
\item[\texttt{MTS\_KD\_CONSERVE\_MEMORY}] Use a more compact representation
\item[\texttt{MTS\_KD\_CONSERVE\_MEMORY}] Use a more compact representation
for triangle geometry (at the cost of speed). This flag causes Mitsuba to use the somewhat slower
Moeller-Trumbore triangle intersection method instead of the default Wald
intersection test, which has an overhead of 48 bytes per triangle.
Off by default.
\item[\texttt{MTS\_SSE}]Activate optimized SSE routines. On by default.
\item[\texttt{MTS\_HAS\_COHERENT\_RT}]Include coherent ray tracing support (depends on \texttt{MTS\_SSE}). This flag is activated by default.
\item[\texttt{MTS\_HAS\_COHERENT\_RT}]Include coherent ray tracing support (depends on \texttt{MTS\_SSE}). This flag is activated by default.
\item[\texttt{MTS\_DEBUG\_FP}]Generated NaNs and overflows will cause floating point exceptions, which can be caught in a debugger. This is slow and mainly meant as a debugging tool for developers. Off by default.
\item[\texttt{SPECTRUM\_SAMPLES=}$\langle ..\rangle$]This setting defines the number of spectral samples (in the 368-830 $nm$ range) that are used to render scenes. The default is 3 samples, in which case the renderer automatically turns into an RGB-based system. For high-quality spectral rendering, this should be set to 30 or higher.
Refer also to \secref{colorspaces}.
@ -95,24 +95,24 @@ fallback instead of the hardware-accelerated realtime preview.
This is useful when the binary will be executed over a remote link using a
protocol such as RDP (which does not provide the requisite OpenGL features).
\end{description}
All of the default configurations files located in the \texttt{build} directory use the flags
All of the default configurations files located in the \texttt{build} directory use the flags
\code{SINGLE\_PRECISION}, \code{SPECTRUM\_SAMPLES=3}, \code{MTS\_DEBUG}, \code{MTS\_SSE},
as well as \code{MTS\_HAS\_COHERENT\_RT}.
\subsection{Building on Debian or Ubuntu Linux}
\label{sec:compiling-ubuntu}
You'll first need to install a number of dependencies. It is assumed here that you are using a
recent version of Ubuntu Linux (Precise Pangolin / 12.04 LTS or later), hence some of the
You'll first need to install a number of dependencies. It is assumed here that you are using a
recent version of Ubuntu Linux (Precise Pangolin / 12.04 LTS or later), hence some of the
package may be named differently if you are using Debian Linux or another Ubuntu version.
First, run
\begin{shell}
$\text{\$}$ sudo apt-get install build-essential scons mercurial qt4-dev-tools libpng12-dev
libjpeg62-dev libilmbase-dev libxerces-c-dev libboost-all-dev
$\text{\$}$ sudo apt-get install build-essential scons mercurial qt4-dev-tools libpng12-dev
libjpeg62-dev libilmbase-dev libxerces-c-dev libboost-all-dev
libopenexr-dev libglewmx1.5-dev libxxf86vm-dev libpcrecpp0 libeigen3-dev
\end{shell}
To get COLLADA support, you will also need to install the \texttt{collada-dom} packages
or build them from scratch. Here, we install the \code{x86\_64} binaries and development
To get COLLADA support, you will also need to install the \texttt{collada-dom} packages
or build them from scratch. Here, we install the \code{x86\_64} binaries and development
headers that can be found on the Mitsuba website (at \url{http://www.mitsuba-renderer.org/releases/current})
\begin{shell}
$\text{\$}$ sudo dpkg --install collada-dom_*.deb
@ -121,7 +121,7 @@ To start a regular build, run
\begin{shell}
$\text{\$}$ scons
\end{shell}
inside the Mitsuba directory. In the case that you have multiple processors, you might want to parallelize the
inside the Mitsuba directory. In the case that you have multiple processors, you might want to parallelize the
build by appending \code{-j }\emph{core count} to the \code{scons} command.
If all goes well, SCons should finish successfully within a few minutes:
\begin{shell}
@ -129,16 +129,15 @@ scons: $\texttt{done}$ building targets.
\end{shell}
To run the renderer from the command line, you first have to import it into your shell environment:
\begin{shell}
$\text{\$}$ . setpath.sh
$\text{\$}$ source setpath.sh
\end{shell}
(note the period at the beginning -- this assumes that you are using \code{bash}).
Having set up everything, you can now move on to \secref{basics}.
\subsubsection{Creating Debian or Ubuntu Linux packages}
The preferred way of redistristributing executables on Debian or Ubuntu Linux is to create
\code{.deb} package files. To make custom Mitsuba packages, it is strongly recommended
that you work with a pristine installation of the target operating system\footnote{Several commercial graphics
drivers ``pollute'' the OpenGL setup so that the compiled Mitsuba binaries
can only be used on machines using the same drivers. For this reason, it is
that you work with a pristine installation of the target operating system\footnote{Several commercial graphics
drivers ``pollute'' the OpenGL setup so that the compiled Mitsuba binaries
can only be used on machines using the same drivers. For this reason, it is
better to work from a clean boostrapped install.}. This can be done as follows:
first, install \code{debootstrap} and download the most recent operating system release
to a subdirectory. The following example is based on Ubuntu 12.04 LTS (``Precise Pangolin''),
@ -169,18 +168,18 @@ $\text{\$}$ dpkg-buildpackage -nc
After everything has been built, you should find the created package files
in the root directory.
\subsubsection{Releasing Ubuntu packages}
To redistribute Ubuntu packages over the Internet or a local network, it is convenient to
To redistribute Ubuntu packages over the Internet or a local network, it is convenient to
put them into an \code{apt}-compatible repository. To prepare such a
repository, put the two \code{deb}-files built in the last section,
as well as the \code{collada-dom} \code{deb}-files into a public directory
repository, put the two \code{deb}-files built in the last section,
as well as the \code{collada-dom} \code{deb}-files into a public directory
made available by a HTTP server and inside it, run
\begin{shell}
path-to-htdocs$\text{\$}$ dpkg-scanpackages path/to/deb-directory /dev/null | gzip -9c > path/to/deb-directory/Packages.gz
\end{shell}
This will create a respository index file named \code{Packages.gz}.
Note that you must execute this command in the root directory of the
HTTP server's web directory and provide the relative path to the
package files -- otherwise, the index file will specify the wrong package
HTTP server's web directory and provide the relative path to the
package files -- otherwise, the index file will specify the wrong package
paths. Finally, the whole directory can be uploaded to some public location
and then referenced by placing a line following the pattern
\begin{shell}
@ -190,7 +189,7 @@ into the \code{/etc/apt/sources.list} file. This setup is convenient for
distributing a custom Mitsuba build to many Debian or Ubuntu machines running (e.g. to nodes in a rendering cluster).
\subsection{Building on Fedora Core}
You'll first need to install a number of dependencies. It is assumed here
that you are using FC15, hence some of the package may be named differently if you are
that you are using FC15, hence some of the package may be named differently if you are
using another version.
First, run
@ -208,9 +207,8 @@ scons: $\texttt{done}$ building targets.
\end{shell}
To run the renderer from the command line, you first have to import it into your shell environment:
\begin{shell}
$\text{\$}$ . setpath.sh
$\text{\$}$ source setpath.sh
\end{shell}
(note the period at the beginning -- this assumes that you are using \code{bash}).
Having set up everything, you can now move on to \secref{basics}.
\subsubsection{Creating Fedora Core packages}
To create \code{RPM} packages, you will need to install the \code{RPM} development tools:
@ -232,7 +230,7 @@ $\text{\$}$ rpmbuild -bb mitsuba-$\code{\MitsubaVersion}$/data/linux/fedora/mits
\end{shell}
After this command finishes, its output can be found in the directory \code{rpmbuild/RPMS}.
\subsection{Building on Arch Linux}
You'll first need to install a number of dependencies:
You'll first need to install a number of dependencies:
\begin{shell}
$\text{\$}$ sudo pacman -S gcc xerces-c glew openexr boost libpng libjpeg qt scons mercurial python
\end{shell}
@ -261,9 +259,9 @@ scons: $\texttt{done}$ building targets.
\end{shell}
To run the renderer from the command line, you first have to import it into your shell environment:
\begin{shell}
$\text{\$}$ . setpath.sh
$\text{\$}$ source setpath.sh
\end{shell}
(note the period at the beginning -- this assumes that you are using \code{bash}).
Having set up everything, you can now move on to \secref{basics}.
\subsubsection{Creating Arch Linux packages}
Mitsuba ships with a \code{PKGBUILD} file, which automatically builds
@ -292,16 +290,16 @@ There are a few other things that need to be set up: make sure that your
installation of Visual Studio is up to date, since Mitsuba binaries created with versions
prior to Service Pack 1 will crash.
Next, you will need to install Python 2.6.x
(\url{www.python.org}) and SCons\footnote{Note that on some Windows machines, the SCons
installer generates a warning about not finding Python in the registry. In this case, you
can instead run \code{python setup.py install} within the source release of SCons.}
(\url{http://www.scons.org}, any 2.x version will do) and ensure that they are contained in the \code{\%PATH\%}
environment variable so that entering \code{scons} on the command prompt (\code{cmd.exe})
Next, you will need to install Python 2.6.x
(\url{www.python.org}) and SCons\footnote{Note that on some Windows machines, the SCons
installer generates a warning about not finding Python in the registry. In this case, you
can instead run \code{python setup.py install} within the source release of SCons.}
(\url{http://www.scons.org}, any 2.x version will do) and ensure that they are contained in the \code{\%PATH\%}
environment variable so that entering \code{scons} on the command prompt (\code{cmd.exe})
launches the build system.
Having installed all dependencies, run the ``Visual Studio \emph{2010} Command
Prompt'' from the Start Menu (\code{x86} for 32-bit or \code{x64} for 64bit),
Having installed all dependencies, run the ``Visual Studio \emph{2010} Command
Prompt'' from the Start Menu (\code{x86} for 32-bit or \code{x64} for 64bit),
navigate to the Mitsuba directory, and simply run
\begin{shell}
C:\mitsuba\>scons
@ -309,17 +307,17 @@ C:\mitsuba\>scons
In the case that you have multiple processors, you might want to parallelize the build by appending the option \code{-j }\emph{core count} to the \code{scons} command.
If all goes well, the build process will finish successfully after a few
minutes. \emph{Note} that in comparison to the other platforms, you don't have to run the \code{setpath.sh} script at this point.
minutes. \emph{Note} that in comparison to the other platforms, you don't have to run the \code{setpath.sh} script at this point.
All binaries are automatically copied into the \code{dist} directory, and they should be executed directly from there.
\subsubsection{Integration with the Visual Studio interface}
Basic Visual Studio 2010 integration with support for code completion
exists for those who develop Mitsuba code on Windows.
To use the supplied projects, simply double-click on one of the two files \code{build/mitsuba-msvc2010.sln}
Basic Visual Studio 2010 integration with support for code completion
exists for those who develop Mitsuba code on Windows.
To use the supplied projects, simply double-click on one of the two files \code{build/mitsuba-msvc2010.sln}
and \code{build/mitsuba-msvc2010.sln}. These Visual Studio projects still internally
use the SCons-based build system to compile Mitsuba; whatever
use the SCons-based build system to compile Mitsuba; whatever
build configuration is selected within Visual Studio will be used to pick a matching
configuration file from the \texttt{build} directory.
configuration file from the \texttt{build} directory.
\subsection{Building on Mac OS X}
\vspace{-5mm}
@ -332,13 +330,13 @@ configuration file from the \texttt{build} directory.
Compiling Mitsuba's dependencies on Mac OS is a laborious process; for convenience, there
is a repository that provides them in precompiled form. To use this repository, clone it
using Mercurial and rename the directory so that it forms the \code{dependencies} subdirectory
inside the main Mitsuba directory, i.e. run something like
inside the main Mitsuba directory, i.e. run something like
\begin{shell}
$\text{\$}$ cd mitsuba
$\text{\$}$ hg clone https://www.mitsuba-renderer.org/hg/dependencies_macos
$\text{\$}$ mv dependencies_macos dependencies
\end{shell}
You will also need to install SCons (>2.0.0, available at \code{www.scons.org}) and
You will also need to install SCons (>2.0.0, available at \code{www.scons.org}) and
a recent release of XCode, including its command-line compilation tools. Next, run
\begin{shell}
$\text{\$}$ scons
@ -350,7 +348,6 @@ scons: $\texttt{done}$ building targets.
\end{shell}
To run the renderer from the command line, you first have to import it into your shell environment:
\begin{shell}
$\text{\$}$ . setpath.sh
$\text{\$}$ source setpath.sh
\end{shell}
(note the period at the beginning -- this assumes that you are using \code{bash}).

View File

@ -1,7 +1,7 @@
\part{Development guide}
This chapter and the subsequent ones will provide an overview
of the the coding conventions and general architecture of Mitsuba.
You should only read them if if you wish to interface with the API
of the the coding conventions and general architecture of Mitsuba.
You should only read them if if you wish to interface with the API
in some way (e.g. by developing your own plugins). The coding style
section is only relevant if you plan to submit patches that are meant
to become part of the main codebase.
@ -9,15 +9,15 @@ to become part of the main codebase.
\section{Code structure}
Mitsuba is split into four basic support libraries:
\begin{itemize}
\item The core library (\code{libcore}) implements basic functionality such as
\item The core library (\code{libcore}) implements basic functionality such as
cross-platform file and bitmap I/O, data structures, scheduling, as well as logging and plugin management.
\item The rendering library (\code{librender}) contains abstractions
\item The rendering library (\code{librender}) contains abstractions
needed to load and represent scenes containing light sources, shapes, materials, and participating media.
\item The hardware acceleration library (\code{libhw})
implements a cross-platform display library, an object-oriented OpenGL
wrapper, as well as support for rendering interactive previews of scenes.
wrapper, as well as support for rendering interactive previews of scenes.
\item Finally, the bidirectional library (\code{libbidir})
contains a support layer that is used to implement bidirectional rendering algorithms such as
contains a support layer that is used to implement bidirectional rendering algorithms such as
Bidirectional Path Tracing and Metropolis Light Transport.
\end{itemize}
A detailed reference of these APIs is available at
@ -25,11 +25,11 @@ A detailed reference of these APIs is available at
present a few basic examples to get familiar with them.
\section{Coding style}
\paragraph{Indentation:} The Mitsuba codebase uses tabs for indentation,
\paragraph{Indentation:} The Mitsuba codebase uses tabs for indentation,
which expand to \emph{four} spaces. Please make sure that you configure your editor
this way, otherwise the source code layout will look garbled.
\paragraph{Placement of braces:} Opening braces should be placed on the
\paragraph{Placement of braces:} Opening braces should be placed on the
same line to make the best use of vertical space, i.e.
\begin{cpp}
if (x > y) {
@ -54,9 +54,9 @@ if ( x==y ){
..
\end{cpp}
\paragraph{Name format:} Names are always written in camel-case.
\paragraph{Name format:} Names are always written in camel-case.
Classes and structures start with a capital letter, whereas member functions
and attributes start with a lower-case letter. Attributes of classes
and attributes start with a lower-case letter. Attributes of classes
have the prefix \code{m\_}. Here is an example:
\begin{cpp}
class MyClass {
@ -86,14 +86,14 @@ and properly conveys the semantics.
as getters and setters.
\paragraph{Documentation:} Headers files should contain
Doxygen-compatible documentation. It is also a good idea to add
comments to a \code{.cpp} file to explain subtleties of an implemented algorithm.
comments to a \code{.cpp} file to explain subtleties of an implemented algorithm.
However, anything pertaining to the API should go into the header file.
\paragraph{Boost:} Use the boost libraries whenever this helps to save
time or write more compact code.
\paragraph{Classes vs structures:}In Mitsuba, classes usually go onto the heap,
whereas structures may be allocated both on the stack and the heap.
whereas structures may be allocated both on the stack and the heap.
Classes that derive from \code{Object} implement a protected virtual
deconstructor, which explicitly prevents them from being allocated on the stack.
@ -110,6 +110,6 @@ if (..) {
\paragraph{Separation of plugins:}Mitsuba encourages that plugins are only
used via the generic interface they implement. You will find that almost all plugins
(e.g. emitters) don't actually provide a header file, hence they can only be accessed
using the generic \code{Emitter} interface they implement. If any kind of special
interaction between plugins is needed, this is usually an indication that the
using the generic \code{Emitter} interface they implement. If any kind of special
interaction between plugins is needed, this is usually an indication that the
generic interface should be extended to accomodate this.

View File

@ -1,8 +1,8 @@
\section{Scene file format}
\label{sec:format}
Mitsuba uses a very simple and general XML-based format to represent scenes.
Since the framework's philosophy is to represent discrete blocks of functionality as plugins,
a scene file can essentially be interpreted as description that determines which
Mitsuba uses a very simple and general XML-based format to represent scenes.
Since the framework's philosophy is to represent discrete blocks of functionality as plugins,
a scene file can essentially be interpreted as description that determines which
plugins should be instantiated and how they should interface with each other.
In the following, we'll look at a few examples to get a feeling for the scope of the
format.
@ -18,17 +18,17 @@ something like this:
</scene>
\end{xml}
The scene version attribute denotes the release of Mitsuba that was used to
create the scene. This information allows Mitsuba to always correctly process the
create the scene. This information allows Mitsuba to always correctly process the
file irregardless of any potential future changes in the scene description language.
This example already contains the most important things to know about format: you can have
\emph{objects} (such as the objects instantiated by the \code{scene} or \code{shape} tags),
which are allowed to be nested within each other. Each object optionally accepts \emph{properties}
(such as the \code{string} tag), which further characterize its behavior. All objects except
\emph{objects} (such as the objects instantiated by the \code{scene} or \code{shape} tags),
which are allowed to be nested within each other. Each object optionally accepts \emph{properties}
(such as the \code{string} tag), which further characterize its behavior. All objects except
for the root object (the \code{scene}) cause the renderer to search and load a plugin from disk,
hence you must provide the plugin name using \code{type=".."} parameter.
hence you must provide the plugin name using \code{type=".."} parameter.
The object tags also let the renderer know \emph{what kind} of object is to be instantiated: for instance,
The object tags also let the renderer know \emph{what kind} of object is to be instantiated: for instance,
any plugin loaded using the \code{shape} tag must conform to the \emph{Shape} interface, which is
certainly the case for the plugin named \code{obj} (it contains a WaveFront OBJ loader).
Similarly, you could write
@ -40,12 +40,12 @@ Similarly, you could write
</shape>
</scene>
\end{xml}
This loads a different plugin (\code{sphere}) which is still a \emph{Shape}, but instead represents
a sphere configured with a radius of 10 world-space units. Mitsuba ships with
This loads a different plugin (\code{sphere}) which is still a \emph{Shape}, but instead represents
a sphere configured with a radius of 10 world-space units. Mitsuba ships with
a large number of plugins; please refer to the next chapter for a detailed
overview of them.
The most common scene setup is to declare an integrator, some geometry, a sensor (e.g. a camera), a film, a sampler
The most common scene setup is to declare an integrator, some geometry, a sensor (e.g. a camera), a film, a sampler
and one or more emitters. Here is a more complex example:
\begin{xml}
<?xml version="1.0" encoding="utf-8"?>
@ -92,20 +92,20 @@ and one or more emitters. Here is a more complex example:
<shape type="serialized">
<string name="filename" value="lightsource.serialized"/>
<transform name="toWorld">
<translate x="5" x="-3" z="1"/>
<translate x="5" y="-3" z="1"/>
</transform>
<!-- This mesh is an area emitter -->
<emitter type="area">
<rgb name="intensity" value="100,400,100"/>
<rgb name="radiance" value="100,400,100"/>
</emitter>
</shape>
</scene>
\end{xml}
This example introduces several new object types (\code{integrator, sensor, bsdf, sampler, film}, and \code{emitter})
and property types (\code{integer}, \code{transform}, and \code{rgb}).
and property types (\code{integer}, \code{transform}, and \code{rgb}).
As you can see in the example, objects are usually declared at the top level except if there is some
inherent relation that links them to another object. For instance, BSDFs are usually specific to a certain geometric object, so
inherent relation that links them to another object. For instance, BSDFs are usually specific to a certain geometric object, so
they appear as a child object of a shape. Similarly, the sampler and film affect the way in which
rays are generated from the sensor and how it records the resulting radiance samples, hence they are nested inside it.
@ -135,45 +135,45 @@ uses a basic linear RGB representation\footnote{The official
releases all use linear RGB---to do spectral renderings, you will have
to compile Mitsuba yourself.}.
Irrespective of which internal representation is used, Mitsuba supports
several different ways of specifying color information, which is then
several different ways of specifying color information, which is then
converted appropriately.
The preferred way of passing color spectra to the renderer is to explicitly
The preferred way of passing color spectra to the renderer is to explicitly
denote the associated wavelengths of each value:
\begin{xml}
<spectrum name="spectrumProperty" value="400:0.56, 500:0.18, 600:0.58, 700:0.24"/>
\end{xml}
This is a mapping from wavelength in nanometers (before the colon)
This is a mapping from wavelength in nanometers (before the colon)
to a reflectance or intensity value (after the colon).
Values in between are linearly interpolated from the two closest neighbors.
A useful shortcut to get a completely uniform spectrum, it is to provide
A useful shortcut to get a completely uniform spectrum, it is to provide
only a single value:
\begin{xml}
<spectrum name="spectrumProperty" value="0.56"/>
\end{xml}
Another (discouraged) option is to directly provide the spectrum in Mitsuba's
internal representation, avoiding the need for any kind of conversion.
internal representation, avoiding the need for any kind of conversion.
However, this is problematic, since the associated scene will likely not work
anymore when Mitsuba is compiled with a different value of
\texttt{SPECTRUM\_SAMPLES}.
For completeness, the possibility is explained nonetheless. Assuming that
the 360-830$nm$ range is discretized into ten 47$nm$-sized blocks
(i.e. \texttt{SPECTRUM\_SAMPLES} is set to 10), their values can be specified
anymore when Mitsuba is compiled with a different value of
\texttt{SPECTRUM\_SAMPLES}.
For completeness, the possibility is explained nonetheless. Assuming that
the 360-830$nm$ range is discretized into ten 47$nm$-sized blocks
(i.e. \texttt{SPECTRUM\_SAMPLES} is set to 10), their values can be specified
as follows:
\begin{xml}
<spectrum name="spectrumProperty" value=".2, .2, .8, .4, .6, .5, .1, .9, .4, .2"/>
\end{xml}
Another convenient way of providing color spectra is by specifying linear RGB
Another convenient way of providing color spectra is by specifying linear RGB
or sRGB values using floating-point triplets or hex values:
\begin{xml}
<rgb name="spectrumProperty" value="0.2, 0.8, 0.4"/>
<srgb name="spectrumProperty" value="0.4, 0.3, 0.2"/>
<srgb name="spectrumProperty" value="#f9aa34"/>
\end{xml}
When Mitsuba is compiled with the default settings, it internally uses
linear RGB to represent colors, so these values can directly be used.
When Mitsuba is compiled with the default settings, it internally uses
linear RGB to represent colors, so these values can directly be used.
However, when configured for doing spectral rendering, a suitable color
spectrum with the requested RGB reflectance must be found. This is a tricky
problem, since there is an infinite number of spectra with this property.
@ -190,9 +190,9 @@ The \texttt{reflectance} intent is used by default, so remember to
set it to \texttt{illuminant} when defining the brightness of a
light source with the \texttt{<rgb>} tag.
When spectral power or reflectance distributions are obtained from measurements
When spectral power or reflectance distributions are obtained from measurements
(e.g. at 10$nm$ intervals), they are usually quite unwiedy and can clutter
the scene description. For this reason, there is yet another way to pass
the scene description. For this reason, there is yet another way to pass
a spectrum by loading it from an external file:
\begin{xml}
<spectrum name="spectrumProperty" filename="measuredSpectrum.spd"/>
@ -213,23 +213,23 @@ are allowed. Here is an example:
\renderings{
\fbox{\includegraphics[width=10cm]{images/blackbody}}
\hfill\,
\caption{\label{fig:blackbody}A few simulated
\caption{\label{fig:blackbody}A few simulated
black body emitters over a range of temperature values}
}
\label{sec:blackbody}
Finally, it is also possible to specify the spectral distribution of a black body emitter (\figref{blackbody}),
Finally, it is also possible to specify the spectral distribution of a black body emitter (\figref{blackbody}),
where the temperature is given in Kelvin.
\begin{xml}
<blackbody name="spectrumProperty" temperature="5000K"/>
\end{xml}
Note that attaching a black body spectrum to the \texttt{intensity} property
of a emitter introduces physical units into the rendering process of
Mitsuba, which is ordinarily a unitless system\footnote{This means that the
units of pixel values in a rendering are completely dependent on the units of
the user input, including the unit of world-space distance and the units of
of a emitter introduces physical units into the rendering process of
Mitsuba, which is ordinarily a unitless system\footnote{This means that the
units of pixel values in a rendering are completely dependent on the units of
the user input, including the unit of world-space distance and the units of
the light source emission profile.}.
Specifically, the black body spectrum has units of power ($W$) per
Specifically, the black body spectrum has units of power ($W$) per
unit area ($m^{-2}$) per steradian ($sr^{-1}$) per unit wavelength ($nm^{-1}$).
If these units are inconsistent with your scene description, you may use the
optional \texttt{scale} attribute to adjust them, e.g.:
@ -244,11 +244,11 @@ Points and vectors can be specified as follows:
<point name="pointProperty" x="3" y="4" z="5"/>
<vector name="vectorProperty" x="3" y="4" z="5"/>
\end{xml}
It is important that whatever you choose as world-space units (meters, inches, etc.) is
It is important that whatever you choose as world-space units (meters, inches, etc.) is
used consistently in all places.
\subsubsection{Transformations}
Transformations are the only kind of property that require more than a single tag. The idea is that, starting
with the identity, one can build up a transformation using a sequence of commands. For instance, a transformation that
with the identity, one can build up a transformation using a sequence of commands. For instance, a transformation that
does a translation followed by a rotation might be written like this:
\begin{xml}
<transform name="trafoProperty">
@ -276,8 +276,8 @@ choices are available:
\begin{xml}
<matrix value="0 -0.53 0 -1.79 0.92 0 0 8.03 0 0 0.53 0 0 0 0 1"/>
\end{xml}
\item lookat transformations --- this is primarily useful for setting up cameras (and spot lights). The \code{origin} coordinates
specify the camera origin, \code{target} is the point that the camera will look at, and the
\item \code{lookat} transformations --- this is primarily useful for setting up cameras (and spot lights). The \code{origin} coordinates
specify the camera origin, \code{target} is the point that the camera will look at, and the
(optional) \code{up} parameter determines the ``upward'' direction in the final rendered image.
The \code{up} parameter is not needed for spot lights.
\begin{xml}
@ -286,7 +286,38 @@ The \code{up} parameter is not needed for spot lights.
\end{itemize}
Cordinates that are zero (for \code{translate} and \code{rotate}) or one (for \code{scale})
do not explicitly have to be specified.
\subsection{Instancing}
\subsection{Animated transformations}
Most shapes, emitters, and sensors in Mitsuba can accept both normal transformations
and \emph{animated transformations} as parameters. The latter is useful to
render scenes involving motion blur (Figure~\ref{fig:animated-transform}). The syntax used to specify these
is slightly different:
\begin{xml}
<animation name="trafoProperty">
<transform time="0">
.. chained list of transformations as discussed above ..
</transform>
<transform time="1">
.. chained list of transformations as discussed above ..
</transform>
.. additional transformations (optional) ..
</animation>
\end{xml}
\renderings{
\fbox{\includegraphics[width=.6\textwidth]{images/animated_transform}}\hfill\,
\caption{\label{fig:animated-transform}Beware the dragon: a triangle mesh undergoing linear motion with several keyframes (object courtesy of XYZRGB)}
}
Mitsuba then decomposes each transformation into a scale, translation, and
rotation component and interpolates\footnote{Using linear interpolation
for the scale and translation component and spherical linear quaternion
interpolation for the rotation component.} these for intermediate
time values.
It is important to specify appropriate shutter open/close times
to the sensor so that the motion is visible.
\newpage
\subsection{References}
Quite often, you will find yourself using an object (such as a material) in many places. To avoid having
to declare it over and over again, which wastes memory, you can make use of references. Here is an example
of how this works:
@ -297,7 +328,7 @@ of how this works:
</texture>
<bsdf type="diffuse" id="myMaterial">
<!-- Reference the texture named myImage and pass it
<!-- Reference the texture named myImage and pass it
to the BRDF as the reflectance parameter -->
<ref name="reflectance" id="myImage"/>
</bsdf>
@ -311,7 +342,7 @@ of how this works:
</scene>
\end{xml}
By providing a unique \texttt{id} attribute in the
object declaration, the object is bound to that identifier
object declaration, the object is bound to that identifier
upon instantiation.
Referencing this identifier at a later point (using the \texttt{<ref id="..."/>} tag)
will add the instance to the parent object, with no further memory
@ -326,7 +357,7 @@ it cannot be used to instantiate geometry---if this functionality is needed,
take a look at the \pluginref{instance} plugin.
\subsection{Including external files}
A scene can be split into multiple pieces for better readability.
A scene can be split into multiple pieces for better readability.
to include an external file, please use the following command:
\begin{xml}
<include filename="nested-scene.xml"/>

View File

@ -1,6 +1,6 @@
#! /usr/bin/python
#
# This script walks through all plugin files and
#!/usr/bin/env python
#
# This script walks through all plugin files and
# extracts documentation that should go into the
# reference manual
@ -52,11 +52,8 @@ def process(path, target):
fileList += [fname]
fileList = []
# Wrap the walk function to make this work in python 2 and 3.
if pyVer >= 3:
os.walk(path, capture, fileList)
else:
os.path.walk(path, capture, fileList)
for (dirname, subdirs, files) in os.walk(path):
capture(fileList, dirname, files)
ordering = [(findOrderID(fname), fname) for fname in fileList]
ordering = sorted(ordering, key = lambda entry: entry[0])
@ -64,34 +61,40 @@ def process(path, target):
for entry in ordering:
extract(target, entry[1])
os.chdir(os.path.dirname(__file__))
f = open('plugins_generated.tex', 'w')
f.write('\input{section_shapes}\n')
process('../src/shapes', f)
f.write('\input{section_bsdf}\n')
process('../src/bsdfs', f)
f.write('\input{section_textures}\n')
process('../src/textures', f)
f.write('\input{section_subsurface}\n')
process('../src/subsurface', f)
f.write('\input{section_media}\n')
process('../src/medium', f)
f.write('\input{section_phase}\n')
process('../src/phase', f)
f.write('\input{section_volumes}\n')
process('../src/volume', f)
f.write('\input{section_emitters}\n')
process('../src/emitters', f)
f.write('\input{section_sensors}\n')
process('../src/sensors', f)
f.write('\input{section_integrators}\n')
process('../src/integrators', f)
f.write('\input{section_samplers}\n')
process('../src/samplers', f)
f.write('\input{section_films}\n')
process('../src/films', f)
f.write('\input{section_rfilters}\n')
f.close()
os.system('bibtex main.aux')
os.system('pdflatex main.tex')
#os.system('pdflatex main.tex | grep -i warning | grep -v "Package \(typearea\|hyperref\)"')
def process_src(target, src_subdir, section=None):
if section is None:
section = "section_" + src_subdir
target.write('\input{{{0}}}\n'.format(section))
process('../src/{0}'.format(src_subdir), target)
def texify(texfile):
from subprocess import Popen, PIPE, check_call
version = Popen(["pdflatex", "-version"], stdout=PIPE).communicate()[0]
# Call decode() to convert from bytes to string, required in Python 3
if re.match('.*MiKTeX.*', version.decode()):
# MiKTeX's "texify" calls latex/bibtex in tandem automatically
print("Running texify on {0}...".format(texfile))
check_call(['texify', '-pq', texfile])
else:
check_call(['pdflatex', texfile])
check_call(['bibtex', texfile.replace('.tex', '.aux')])
check_call(['pdflatex', texfile])
check_call(['pdflatex', texfile])
os.chdir(os.path.dirname(os.path.abspath(__file__)))
with open('plugins_generated.tex', 'w') as f:
process_src(f, 'shapes')
process_src(f, 'bsdfs', 'section_bsdf')
process_src(f, 'textures')
process_src(f, 'subsurface')
process_src(f, 'medium', 'section_media')
process_src(f, 'phase')
process_src(f, 'volume', 'section_volumes')
process_src(f, 'emitters')
process_src(f, 'sensors')
process_src(f, 'integrators')
process_src(f, 'samplers')
process_src(f, 'films')
process_src(f, 'rfilters')
texify('main.tex')

View File

@ -1,7 +1,7 @@
\section{License}
\label{sec:license}
Mitsuba is licensed under the terms of Version 3 of the GNU General Public License,
which is reproduced here in its entirety. The license itself is copyrighted
which is reproduced here in its entirety. The license itself is copyrighted
\copyright\ 2007 by the Free Software Foundation, Inc. \texttt{http://fsf.org/}.
\subsection{Preamble}

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View File

@ -3,9 +3,9 @@ Suppose you want to design a custom integrator to render scenes in Mitsuba.
There are two general ways you can do this, and which one you should take
mostly depends on the characteristics of your particular integrator.
The framework distinguishes between \emph{sampling-based} integrators and
\emph{generic} ones. A sampling-based integrator is able to generate
(usually unbiased) estimates of the incident radiance along a specified rays, and this
The framework distinguishes between \emph{sampling-based} integrators and
\emph{generic} ones. A sampling-based integrator is able to generate
(usually unbiased) estimates of the incident radiance along a specified rays, and this
is done a large number of times to render a scene. A generic integrator
is more like a black box, where no assumptions are made on how the the image is
created. For instance, the VPL renderer uses OpenGL to rasterize the scene
@ -13,44 +13,44 @@ using hardware acceleration, which certainly doesn't fit into the sampling-based
For that reason, it must be implemented as a generic integrator.
Generally, if you can package up your code to fit into the
\code{SampleIntegrator} interface, you should do it, because you'll get
\code{SamplingIntegrator} interface, you should do it, because you'll get
parallelization and network rendering essentially for free. This is done
by transparently sending instances of your integrator class to all participating cores
and assigning small image blocks for each one to work on. Also, sampling-based
integrators can be nested within some other integrators, such as an
irradiance cache or an adaptive integrator. This cannot be done with generic
integrators due to their black-box nature. Note that it is often still
possible to parallelize generic integrators, but this involves significantly
integrators due to their black-box nature. Note that it is often still
possible to parallelize generic integrators, but this involves significantly
more work.
In this section, we'll design a rather contrived sampling-based integrator,
which renders a monochromatic image of your scene, where the intensity
denotes the distance to the camera. But to get a feel for the overall
framework, we'll start with an even simpler one, that just renders a
In this section, we'll design a rather contrived sampling-based integrator,
which renders a monochromatic image of your scene, where the intensity
denotes the distance to the camera. But to get a feel for the overall
framework, we'll start with an even simpler one, that just renders a
solid-color image.
\subsection{Basic implementation}
In Mitsuba's \code{src/integrators} directory, create a file named
\code{myIntegrator.cpp}.
In Mitsuba's \code{src/integrators} directory, create a file named
\code{myIntegrator.cpp}.
\begin{cpp}
#include <mitsuba/render/scene.h>
MTS_NAMESPACE_BEGIN
class MyIntegrator : public SampleIntegrator {
class MyIntegrator : public SamplingIntegrator {
public:
MTS_DECLARE_CLASS()
};
MTS_IMPLEMENT_CLASS_S(MyIntegrator, false, SampleIntegrator)
MTS_IMPLEMENT_CLASS_S(MyIntegrator, false, SamplingIntegrator)
MTS_EXPORT_PLUGIN(MyIntegrator, "A contrived integrator");
MTS_NAMESPACE_END
\end{cpp}
The \code{scene.h} header file contains all of the dependencies we'll need
for now.
To avoid conflicts with other libraries, the whole framework is located in
a separate namespace named \code{mitsuba}, and the lines starting with
a separate namespace named \code{mitsuba}, and the lines starting with
\code{MTS\_NAMESPACE} ensure that our integrator is placed there
as well.
@ -61,17 +61,17 @@ and serialization/unserialization support. Let's take a look at the second of th
lines, because it contains several important pieces of information:
The suffix \code{S} in \code{MTS\_IMPLEMENT\_CLASS\_S} specifies that this is
a serializable class, which means that it can be sent over the network or
a serializable class, which means that it can be sent over the network or
written to disk and later restored. That also implies that certain methods
need to be provided by the implementation --- we'll add those in a moment.
The three following parameters specify the name of this class (\code{MyIntegrator}),
the fact that it is \emph{not} an abstract class (\code{false}), and the name of its
parent class (\code{SampleIntegrator}).
parent class (\code{SamplingIntegrator}).
Just below, you can see a line that starts with
\code{MTS\_EXPORT\_PLUGIN}. As the name suggests, this line is only necessary
for plugins, and it ensures that the specified class (\code{MyIntegrator}) is
for plugins, and it ensures that the specified class (\code{MyIntegrator}) is
what you want to be instantiated when somebody loads this plugin. It is also
possible to supply a short descriptive string.
\vspace{3mm}
@ -80,7 +80,7 @@ Let's add an instance variable and a constructor:
\begin{cpp}
public:
/// Initialize the integrator with the specified properties
MyIntegrator(const Properties &props) : SampleIntegrator(props) {
MyIntegrator(const Properties &props) : SamplingIntegrator(props) {
Spectrum defaultColor;
defaultColor.fromLinearRGB(0.2f, 0.5f, 0.2f);
m_color = props.getSpectrum("color", defaultColor);
@ -106,41 +106,41 @@ Next, we need to add serialization and unserialization support:
\begin{cpp}
/// Unserialize from a binary data stream
MyIntegrator(Stream *stream, InstanceManager *manager)
: SampleIntegrator(stream, manager) {
: SamplingIntegrator(stream, manager) {
m_color = Spectrum(stream);
}
/// Serialize to a binary data stream
void serialize(Stream *stream, InstanceManager *manager) const {
SampleIntegrator::serialize(stream, manager);
SamplingIntegrator::serialize(stream, manager);
m_color.serialize(stream);
}
\end{cpp}
This makes use of a \emph{stream} abstraction similar in style to Java.
A stream can represent various things, such as a file, a console session, or a
This makes use of a \emph{stream} abstraction similar in style to Java.
A stream can represent various things, such as a file, a console session, or a
network communication link. Especially when dealing with multiple machines,
it is important to realize that the machines may use different binary representations
related to their respective \emph{endianness}. To prevent issues from arising,
the \code{Stream} interface provides many methods for writing and reading
the \code{Stream} interface provides many methods for writing and reading
small chunks of data (e.g. \code{writeShort}, \code{readFloat}, ..),
which automatically perform endianness translation. In our case, the
\code{Spectrum} class already provides serialization/unserialization support,
so we don't really have to do anything.
Note that it is crucial that your code calls the serialization and unserialization
Note that it is crucial that your code calls the serialization and unserialization
implementations of the superclass, since it will also read/write some
information to the stream.
We haven't used the \texttt{manager} parameter yet, so here is a quick overview
of what it does: if many cases, we don't just want to serialize a single class,
but a whole graph of objects. Some may be referenced many
times from different places, and potentially there are even cycles. If we just
naively called the serialization and unserialization implementation of members
recursively within each class, we'd waste much bandwitdth and potentially
times from different places, and potentially there are even cycles. If we just
naively called the serialization and unserialization implementation of members
recursively within each class, we'd waste much bandwitdth and potentially
end up stuck in an infinite recursion.
This is where the instance manager comes in. Every time you want to serialize
a heap-allocated object (suppose it is of type \code{SomeClass}),
a heap-allocated object (suppose it is of type \code{SomeClass}),
instead of calling its serialize method, write
\begin{cpp}
@ -155,7 +155,7 @@ ref<SomeClass> myObject = static_cast<SomeClass *>(manager->getInstance(stream))
Behind the scenes, the object manager adds annotations to the data stream,
which ensure that you will end up with the exact same reference graph on the
remote side, while only one copy of every object is transmitted and no
remote side, while only one copy of every object is transmitted and no
infinite recursion can occur. But we digress -- let's go back to our integrator.
\vspace{3mm}
@ -168,10 +168,11 @@ radiance along a ray differential: here, we simply return the stored color
}
\end{cpp}
Let's try building the plugin: edit the \code{SConstruct} file in the main
directory, and add the following line after the comment ''\code{\# Integrators}'':
Let's try building the plugin: edit the \code{SConscript} file in the
\code{integrator} directory, and add the following line before the
last line containing ''\code{Export('plugins')}'':
\begin{cpp}
plugins += env.SharedLibrary('plugins/myIntegrator', ['src/integrators/myIntegrator.cpp'])
plugins += env.SharedLibrary('myIntegrator', ['myIntegrator.cpp'])
\end{cpp}
After calling, \texttt{scons}, you should be able to use your new integrator
in parallel rendering jobs and you'll get something like this:
@ -182,8 +183,8 @@ That is admittedly not very exciting --- so let's do some actual computation.
\subsection{Visualizing depth}
Add an instance variable \code{Float m\_maxDist;} to the implementation. This
will store the maximum distance from the camera to any object, which is needed
to map distances into the $[0,1]$ range. Note the upper-case \code{Float} ---
this means that either a single- or a double-precision variable is
to map distances into the $[0,1]$ range. Note the upper-case \code{Float} ---
this means that either a single- or a double-precision variable is
substituted based the compilation flags. This variable constitutes local
state, thus it must not be forgotten in the serialization- and unserialization routines:
append
@ -202,18 +203,19 @@ To avoid having to do this every time \code{Li()} is called,
we can override the \code{preprocess} function:
\begin{cpp}
/// Preprocess function -- called on the initiating machine
bool preprocess(const Scene *scene, RenderQueue *queue,
const RenderJob *job, int sceneResID, int cameraResID,
bool preprocess(const Scene *scene, RenderQueue *queue,
const RenderJob *job, int sceneResID, int cameraResID,
int samplerResID) {
SampleIntegrator::preprocess(scene, queue, job, sceneResID,
SamplingIntegrator::preprocess(scene, queue, job, sceneResID,
cameraResID, samplerResID);
const AABB &sceneAABB = scene->getAABB();
Point cameraPosition = scene->getCamera()->getPosition();
/* Find the camera position at t=0 seconds */
Point cameraPosition = scene->getSensor()->getWorldTransform()->eval(0).transformAffine(Point(0.0f));
m_maxDist = - std::numeric_limits<Float>::infinity();
for (int i=0; i<8; ++i)
m_maxDist = std::max(m_maxDist,
m_maxDist = std::max(m_maxDist,
(cameraPosition - sceneAABB.getCorner(i)).length());
return true;
@ -228,13 +230,13 @@ global resource identifiers. When a network render job runs, many associated
pieces of information (the scene, the camera, etc.) are wrapped into global resource chunks
shared amongst all nodes, and these can be referenced using such identifiers.
One important aspect of the \code{preprocess} function is that it is executed
on the initiating node and before any of the parallel rendering begins.
One important aspect of the \code{preprocess} function is that it is executed
on the initiating node and before any of the parallel rendering begins.
This can be used to compute certain things only once. Any
information updated here (such as \code{m\_maxDist}) will be forwarded to the
other nodes before the rendering begins.
Now, replace the body of the \code{Li} method with
Now, replace the body of the \code{Li} method with
\begin{cpp}
if (rRec.rayIntersect(r)) {
Float distance = rRec.its.t;
@ -255,36 +257,36 @@ to intersect a ray against the scene actually works like this:
/* Do something with the intersection stored in 'its' */
}
\end{cpp}
As you can see, we did something slightly different in the distance
As you can see, we did something slightly different in the distance
renderer fragment above (we called \code{RadianceQueryRecord::rayIntersect()}
on the supplied parameter \code{rRec}), and the reason for this is \emph{nesting}.
\subsection{Nesting}
The idea of of nesting is that sampling-based rendering techniques can be
embedded within each other for added flexibility: for instance, one
might concoct a 1-bounce indirect rendering technique complete with
irradiance caching and adaptive integration simply by writing the following
embedded within each other for added flexibility: for instance, one
might concoct a 1-bounce indirect rendering technique complete with
irradiance caching and adaptive integration simply by writing the following
into a scene XML file:
\begin{xml}
<!-- Adaptively integrate using the nested technique -->
<integrator type="adaptive">
<integrator type="adaptive">
<!-- Irradiance caching + final gathering with the nested technique -->
<integrator type="irrcache">
<integrator type="irrcache">
<!-- Simple direct illumination technique -->
<integrator type="direct">
<integrator type="direct">
</integrator>
</integrator>
\end{xml}
To support this kind of complex interaction, some information needs to be passed between the
To support this kind of complex interaction, some information needs to be passed between the
integrators, and the \code{RadianceQueryRecord} parameter of the function
\code{SampleIntegrator::Li} is used for this.
\code{SamplingIntegrator::Li} is used for this.
This brings us back to the odd way of computing an intersection a moment ago:
the reason why we didn't just do this by calling
This brings us back to the odd way of computing an intersection a moment ago:
the reason why we didn't just do this by calling
\code{scene->rayIntersect()} is that our technique might actually be nested
within a parent technique, which has already computed this intersection.
To avoid wasting resources, the function \code{rRec.rayIntersect} first
determines whether an intersection record has already been provided.
If yes, it does nothing. Otherwise, it takes care of computing one.
To avoid wasting resources, the function \code{rRec.rayIntersect} first
determines whether an intersection record has already been provided.
If yes, it does nothing. Otherwise, it takes care of computing one.
The radiance query record also lists the particular \emph{types} of radiance requested
by the parent integrator -- your implementation should respect these as much

View File

@ -1,69 +1,69 @@
\part{Using Mitsuba}
\textbf{Disclaimer:} This is manual documents the usage, file format, and
internal design of the Mitsuba rendering system. It is currently a work
internal design of the Mitsuba rendering system. It is currently a work
in progress, hence some parts may still be incomplete or missing.
\section{About Mitsuba}
Mitsuba is a research-oriented rendering system in the style of PBRT
Mitsuba is a research-oriented rendering system in the style of PBRT
(\url{www.pbrt.org}), from which it derives much inspiration.
It is written in portable C++, implements unbiased as well
as biased techniques, and contains heavy optimizations targeted
towards current CPU architectures.
Mitsuba is extremely modular: it consists of a small set of core libraries
and over 100 different plugins that implement functionality ranging
It is written in portable C++, implements unbiased as well
as biased techniques, and contains heavy optimizations targeted
towards current CPU architectures.
Mitsuba is extremely modular: it consists of a small set of core libraries
and over 100 different plugins that implement functionality ranging
from materials and light sources to complete rendering algorithms.
In comparison to other open source renderers, Mitsuba places a strong
emphasis on experimental rendering techniques, such as path-based
In comparison to other open source renderers, Mitsuba places a strong
emphasis on experimental rendering techniques, such as path-based
formulations of Metropolis Light Transport and volumetric
modeling approaches. Thus, it may be of genuine interest to those who
would like to experiment with such techniques that haven't yet found
their way into mainstream renderers, and it also provides a solid
would like to experiment with such techniques that haven't yet found
their way into mainstream renderers, and it also provides a solid
foundation for research in this domain.
Other design considerations are:
\parheader{Performance:}
Mitsuba provides optimized implementations of the most commonly
Mitsuba provides optimized implementations of the most commonly
used rendering algorithms. By virtue of running on a shared foundation, comparisons between them can
better highlight the merits and limitations of different approaches. This is in contrast to, say,
comparing two completely different rendering products, where technical information on the underlying
better highlight the merits and limitations of different approaches. This is in contrast to, say,
comparing two completely different rendering products, where technical information on the underlying
implementation is often intentionally not provided.
\parheader{Robustness:}
In many cases, physically-based rendering packages force the user to model scenes with the underlying
algorithm (specifically: its convergence behavior) in mind. For instance, glass windows are routinely
replaced with light portals, photons must be manually guided to the relevant parts of a scene, and
interactions with complex materials are taboo, since they cannot be importance sampled exactly.
One focus of Mitsuba will be to develop path-space light transport algorithms, which handle such
In many cases, physically-based rendering packages force the user to model scenes with the underlying
algorithm (specifically: its convergence behavior) in mind. For instance, glass windows are routinely
replaced with light portals, photons must be manually guided to the relevant parts of a scene, and
interactions with complex materials are taboo, since they cannot be importance sampled exactly.
One focus of Mitsuba will be to develop path-space light transport algorithms, which handle such
cases more gracefully.
\parheader{Scalability:} Mitsuba instances can be merged into large clusters, which transparently distribute and
\parheader{Scalability:} Mitsuba instances can be merged into large clusters, which transparently distribute and
jointly execute tasks assigned to them using only node-to-node communcation. It has successfully
scaled to large-scale renderings that involved more than 1000 cores working on a single image.
Most algorithms in Mitsuba are written using a generic parallelization layer, which can tap
Most algorithms in Mitsuba are written using a generic parallelization layer, which can tap
into this cluster-wide parallelism. The principle is that if any component of the renderer produces
work that takes longer than a second or so, it at least ought to use all of the processing power
work that takes longer than a second or so, it at least ought to use all of the processing power
it can get.
The renderer also tries to be very conservative in its use of memory, which allows it to handle
The renderer also tries to be very conservative in its use of memory, which allows it to handle
large scenes (>30 million triangles) and multi-gigabyte heterogeneous volumes on consumer hardware.
\parheader{Realism and accuracy:} Mitsuba comes with a large repository of physically-based
reflectance models for surfaces and participating media. These implementations
are designed so that they can be used to build complex shader networks, while
providing enough flexibility to be compatible with a wide range of different
rendering techniques, including path tracing, photon mapping, hardware-accelerated rendering
rendering techniques, including path tracing, photon mapping, hardware-accelerated rendering
and bidirectional methods.
The unbiased path tracers in Mitsuba are battle-proven and produce
reference-quality results that can be used for predictive rendering, and to verify
implementations of other rendering methods.
The unbiased path tracers in Mitsuba are battle-proven and produce
reference-quality results that can be used for predictive rendering, and to verify
implementations of other rendering methods.
\parheader{Usability:}
Mitsuba comes with a graphical user interface to interactively explore scenes. Once a suitable
viewpoint has been found, it is straightforward to perform renderings using any of the
implemented rendering techniques, while tweaking their parameters to find the most suitable
Mitsuba comes with a graphical user interface to interactively explore scenes. Once a suitable
viewpoint has been found, it is straightforward to perform renderings using any of the
implemented rendering techniques, while tweaking their parameters to find the most suitable
settings. Experimental integration into Blender 2.5 is also available.
\section{Limitations}
@ -72,22 +72,22 @@ However, there are some inherent limitations of the system that users should be
\begin{enumerate}[(i)]
\item \textbf{Wave Optics}: Mitsuba is fundamentally based on the geometric optics toolbox,
which means that it generally does not simulate phenomena that arise due to
the wave properties of light (diffraction, for instance).
the wave properties of light (diffraction, for instance).
\item \textbf{Polarization}: Mitsuba does not account for polarization. In
other words, light is always assumed to be randomly polarized. This can be a problem for
some predictive rendering applications.
\item \textbf{Numerical accuracy}: The accuracy of any result produced with this
system is constrained by the underlying floating point computations.
system is constrained by the underlying floating point computations.
For instance, an intricate scene that can be rendered without problems,
may produce the wrong answer when all objects are translated away from the
origin by a large distance, since floating point numbers are spaced less densely at the
new position. To avoid these sorts of pitfalls, it is good to have a basic
understanding of the IEEE-754 standard.
new position. To avoid these sorts of pitfalls, it is good to have a basic
understanding of the IEEE-754 standard.
\end{enumerate}
\section{License}
Mitsuba is free software and can be redistributed and modified under the terms of the GNU General
Mitsuba is free software and can be redistributed and modified under the terms of the GNU General
Public License (Version 3) as provided by the Free Software Foundation.
\remarks{

View File

@ -92,7 +92,7 @@
}}\hspace*{1cm}}\end{figure}
\setlength\fboxrule\fboxrulebackup
}
\newcommand{\renderings}[1]{
\begin{figure}[htb!]
\setcounter{subfigure}{0}

View File

@ -27,6 +27,7 @@
\usepackage{ifthen}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{footnote} % savenotes environment
% Make sure that ligatures remain searchable in the PDF
\input glyphtounicode
@ -39,8 +40,8 @@
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{3}
\newcommand{\MitsubaVersion}{0.4.1}
\newcommand{\MitsubaYear}{2012}
\newcommand{\MitsubaVersion}{0.4.4}
\newcommand{\MitsubaYear}{2013}
\typearea[current]{last}
\raggedbottom
@ -116,7 +117,7 @@
medium,film,sampler,integrator,emitter,sensor,
translate,rotate,scale,lookat,point,vector,matrix,
include,fscat,volume,alias,rfilter,boolean,
subsurface
subsurface,animation
},
}

View File

@ -2,9 +2,9 @@
\label{sec:miscellaneous}
\subsection{A word about color spaces}
\label{sec:colorspaces}
When using one of the downloadable release builds of Mitsuba, or a version
When using one of the downloadable release builds of Mitsuba, or a version
that was compiled with the default settings, the renderer internally
operates in \emph{RGB mode}: all computations are performed using a representation
operates in \emph{RGB mode}: all computations are performed using a representation
that is based on the three colors red, green, and blue.
More specifically, these are the intensities of the red, green, and blue primaries
@ -14,20 +14,20 @@ rendering. This is an intuitive default which yields fast computations and
satisfactory results for most applications.
Low dynamic range images exported using the \pluginref{ldrfilm} will be stored in a
sRGB-compatible format that accounts for the custom gamma curves mandated by this
sRGB-compatible format that accounts for the custom gamma curves mandated by this
standard. They should display as intended across a wide range of display devices.
When saving high dynamic range output (e.g. OpenEXR, RGBE, or PFM), the computed radiance
values are exported in a linear form (i.e. without having the sRGB gamma curve applied to it),
which is the most common way of storing high dynamic range data.
It is important to keep in mind that other applications may not support this
It is important to keep in mind that other applications may not support this
``linearized sRGB'' space---in particular, the Mac OS preview currently
does not display images with this encoding correctly.
\subsubsection{Spectral mode}
\subsubsection{Spectral rendering}
Some predictive rendering applications will require a more realistic space for
interreflection computations. In such cases, Mitsuba can be switched to \emph{spectral mode}.
This can be done by compiling it with the \code{SPECTRUM\_SAMPLES=}$n$ parameter
This can be done by compiling it with the \code{SPECTRUM\_SAMPLES=}$n$ parameter
(\secref{compiling}), where $n$ is usually between 15 and 30.
Now, all input parameters are converted into color spectra with the specified

View File

@ -5,23 +5,23 @@ The guiding principle is that if an operation can potentially take longer than a
few seconds, it ought to use all the cores it can get.
Here, we will go through a basic example, which will hopefully provide sufficient intuition
to realize more complex tasks.
to realize more complex tasks.
To obtain good (i.e. close to linear) speedups, the parallelization layer depends on
several key assumptions of the task to be parallelized:
\begin{itemize}
\item The task can easily be split up into a discrete number of \emph{work units}, which requires a negligible amount of computation.
\item Each work unit is small in footprint so that it can easily be transferred over the network or shared memory.
\item Each work unit is small in footprint so that it can easily be transferred over the network or shared memory.
\item A work unit constitutes a significant amount of computation, which by far outweighs the cost of transmitting it to another node.
\item The \emph{work result} obtained by processing a work unit is again small in footprint, so that it can easily be transferred back.
\item Merging all work results to a solution of the whole problem requires a negligible amount of additional computation.
\end{itemize}
This essentially corresponds to a parallel version of \emph{Map} (one part of \emph{Map\&Reduce}) and is
ideally suited for most rendering workloads.
This essentially corresponds to a parallel version of \emph{Map} (one part of \emph{Map\&Reduce}) and is
ideally suited for most rendering workloads.
The example we consider here computes a \code{ROT13} ``encryption'' of a string, which
The example we consider here computes a \code{ROT13} ``encryption'' of a string, which
most certainly violates the ``significant amount of computation'' assumption.
It was chosen due to the inherent parallelism and simplicity of this task.
While of course over-engineered to the extreme, the example hopefully
While of course over-engineered to the extreme, the example hopefully
communicates how this framework might be used in more complex scenarios.
We will implement this program as a plugin for the utility launcher \code{mtsutil}, which
@ -49,9 +49,9 @@ MTS_NAMESPACE_END
\end{cpp}
The file must also be added to the build system: insert the line
\begin{shell}
plugins += $\texttt{env}$.SharedLibrary('plugins/rot13', ['src/utils/rot13.cpp'])
plugins += $\texttt{env}$.SharedLibrary('rot13', ['rot13.cpp'])
\end{shell}
into the SConscript (near the comment ``\code{Build the plugins -- utilities}''). After compiling
into the \code{utils/SConscript} file. After compiling
using \code{scons}, the \code{mtsutil} binary should automatically pick up your new utility plugin:
\begin{shell}
$\texttt{\$}$ mtsutil
@ -69,7 +69,7 @@ $\texttt{\$}$ mtsutil rot13
Hello world!
\end{shell}
Our approach for implementing distributed ROT13 will be to treat each character as an
Our approach for implementing distributed ROT13 will be to treat each character as an
indpendent work unit. Since the ordering is lost when sending out work units, we must
also include the position of the character in both the work units and the work results.
@ -78,7 +78,7 @@ For reference, here are the interfaces of \code{WorkUnit} and \code{WorkResult}:
\begin{cpp}
/**
* Abstract work unit. Represents a small amount of information
* that encodes part of a larger processing task.
* that encodes part of a larger processing task.
*/
class MTS_EXPORT_CORE WorkUnit : public Object {
public:
@ -100,7 +100,7 @@ protected:
virtual ~WorkUnit() { }
};
/**
* Abstract work result. Represents the information that encodes
* Abstract work result. Represents the information that encodes
* the result of a processed <tt>WorkUnit</tt> instance.
*/
class MTS_EXPORT_CORE WorkResult : public Object {
@ -125,7 +125,7 @@ In our case, the \code{WorkUnit} implementation then looks like this:
class ROT13WorkUnit : public WorkUnit {
public:
void set(const WorkUnit *workUnit) {
const ROT13WorkUnit *wu =
const ROT13WorkUnit *wu =
static_cast<const ROT13WorkUnit *>(workUnit);
m_char = wu->m_char;
m_pos = wu->m_pos;
@ -135,10 +135,10 @@ public:
m_char = stream->readChar();
m_pos = stream->readInt();
}
void save(Stream *stream) const {
stream->writeChar(m_char);
stream->writeInt(m_pos);
stream->writeInt(m_pos);
}
std::string toString() const {
@ -163,14 +163,14 @@ private:
MTS_IMPLEMENT_CLASS(ROT13WorkUnit, false, WorkUnit)
\end{cpp}
The \code{ROT13WorkResult} implementation is not reproduced since it is almost identical
The \code{ROT13WorkResult} implementation is not reproduced since it is almost identical
(except that it doesn't need the \code{set} method).
The similarity is not true in general: for most algorithms, the work unit and result
The similarity is not true in general: for most algorithms, the work unit and result
will look completely different.
Next, we need a class, which does the actual work of turning a work unit into a work result
(a subclass of \code{WorkProcessor}). Again, we need to implement a range of support
methods to enable the various ways in which work processor instances will be submitted to
methods to enable the various ways in which work processor instances will be submitted to
remote worker nodes and replicated amongst local threads.
\begin{cpp}
class ROT13WorkProcessor : public WorkProcessor {
@ -190,7 +190,7 @@ public:
return new ROT13WorkUnit();
}
ref<WorkResult> createWorkResult() const {
ref<WorkResult> createWorkResult() const {
return new ROT13WorkResult();
}
@ -202,9 +202,9 @@ public:
void prepare() { }
/// Do the actual computation
void process(const WorkUnit *workUnit, WorkResult *workResult,
void process(const WorkUnit *workUnit, WorkResult *workResult,
const bool &stop) {
const ROT13WorkUnit *wu
const ROT13WorkUnit *wu
= static_cast<const ROT13WorkUnit *>(workUnit);
ROT13WorkResult *wr = static_cast<ROT13WorkResult *>(workResult);
wr->setPos(wu->getPos());
@ -252,9 +252,9 @@ public:
}
void processResult(const WorkResult *result, bool cancelled) {
if (cancelled) // indicates a work unit, which was
if (cancelled) // indicates a work unit, which was
return; // cancelled partly through its execution
const ROT13WorkResult *wr =
const ROT13WorkResult *wr =
static_cast<const ROT13WorkResult *>(result);
m_output[wr->getPos()] = wr->getChar();
}
@ -273,7 +273,7 @@ MTS_IMPLEMENT_CLASS(ROT13Process, false, ParallelProcess)
\end{cpp}
The \code{generateWork} method produces work units until we have moved past
the end of the string, after which it returns the status code \code{EFailure}.
Note the method \code{getRequiredPlugins()}: this is necessary to use
Note the method \code{getRequiredPlugins()}: this is necessary to use
the utility across
machines. When communicating with another node, it ensures that the remote side
loads the \code{ROT13*} classes at the right moment.
@ -302,9 +302,9 @@ from the main utility function (the `Hello World' code we wrote earlier). We can
}
\end{cpp}
After compiling everything using \code{scons}, a simple example
involving the utility would be to encode a string (e.g. \code{SECUREBYDESIGN}), while
involving the utility would be to encode a string (e.g. \code{SECUREBYDESIGN}), while
forwarding all computation to a network machine. (\code{-p0} disables
all local worker threads). Adding a verbose flag (\code{-v}) shows
all local worker threads). Adding a verbose flag (\code{-v}) shows
some additional scheduling information:
\begin{shell}
$\texttt{\$}$ mtsutil -vc feynman -p0 rot13 SECUREBYDESIGN

View File

@ -1,9 +1,9 @@
\section{Plugin reference}
\vspace{-2mm}
The following subsections describe the available Mitsuba plugins, usually along
The following subsections describe the available Mitsuba plugins, usually along
with example renderings and a description of what each parameter does.
They are separated into subsections covering textures, surface scattering
models, etc.
models, etc.
Each subsection begins with a brief general description.
The documentation of a plugin always starts on a new page and is preceded
@ -14,7 +14,7 @@ by a table similar to the one below:
\default{\code{false}}
}
\parameter{darkMatter}{\Float}{
Controls the proportionate amount of dark matter present in the scene.
Controls the proportionate amount of dark matter present in the scene.
\default{0.83}
}
}
@ -27,10 +27,10 @@ this description, it can be instantiated from an XML scene file using a custom c
<float name="darkMatter" value="0.4"/>
</integrator>
\end{xml}
In some cases\footnote{Note that obvious parameters are generally omitted.
For instance, all shape plugins accept a surface scattering plugin, but this
is left out from the documentation for brevity.}, plugins also indicate that they accept nested plugins
as input arguments. These can either be \emph{named} or \emph{unnamed}. If
In some cases\footnote{Note that obvious parameters are generally omitted.
For instance, all shape plugins accept a surface scattering plugin, but this
is left out from the documentation for brevity.}, plugins also indicate that they accept nested plugins
as input arguments. These can either be \emph{named} or \emph{unnamed}. If
the \code{amazing} integrator also accepted the following two parameters\vspace{-2mm}
\parameters{
\parameter{\Unnamed}{\Integrator}{A nested integrator which does the actual hard work}

View File

@ -1,14 +1,29 @@
\section{Python integration}
\label{sec:python}
A recent feature of Mitsuba is a simple Python interface to the renderer API.
A recent feature of Mitsuba is a Python interface to the renderer API.
While the interface is still limited at this point, it can already be
used for many useful purposes. To access the API, start your Python
interpreter and enter
\begin{python}
import mitsuba
\end{python}
\paragraph{Mac OS:}
For this to work on MacOS X, you will first have to run the ``\emph{Apple
Menu}$\to$\emph{Command-line access}'' menu item from within Mitsuba.
In the unlikely case that you run into shared library loading issues (this is
taken care of by default), you may have to set the \code{LD\_LIBRARY\_PATH}
environment variable before starting Python so that it points to where the
Mitsuba libraries are installed (e.g. the \code{Mitsuba.app/Contents/Frameworks}
directory).
When Python crashes directly after the \code{import mitsuba} statement,
make sure that Mitsuba is linked against the right Python distribution
(i.e. matching the \code{python} binary you are using). For e.g. Python
2.7, can be done by adjusting the \code{PYTHON27INCLUDE} and
\code{PYTHON27LIBDIR} variables in \code{config.py}. For other versions,
adjust the numbers accordingly.
\paragraph{Windows and Linux:}
On Windows and \emph{non-packaged} Linux builds, you may have to explicitly
specify the required extension search path before issuing the \code{import} command, e.g.:
\begin{python}
@ -29,6 +44,9 @@ os.environ['PATH'] = 'path-to-mitsuba-directory' + os.pathsep + os.environ['PATH
import mitsuba
\end{python}
In rare cases when running on Linux, it may also be necessary to set the
\code{LD\_LIBRARY\_PATH} environment variable before starting Python so that it
points to where the Mitsuba core libraries are installed.
For an overview of the currently exposed API subset, please refer
to the following page: \url{http://www.mitsuba-renderer.org/api/group__libpython.html}.
@ -64,8 +82,8 @@ classes, function, or entire namespaces when running an interactive Python shell
...
\end{shell}
The docstrings list the currently exported functionality, as well as C++ and Python signatures, but they
don't document what these functions actually do. The web API documentation is the preferred source for
this information.
don't document what these functions actually do. The web API documentation is
the preferred source of this information.
\subsection{Basics}
Generally, the Python API tries to mimic the C++ API as closely as possible.
@ -337,3 +355,43 @@ logger.setLogLevel(EDebug)
Log(EInfo, 'Test message')
\end{python}
\subsubsection{Rendering a turntable animation with motion blur}
Rendering a turntable animation is a fairly common task that is
conveniently accomplished via the Python interface. In a turntable
video, the camera rotates around a completely static object or scene.
The following snippet does this for the material test ball scene downloadable
on the main website, complete with motion blur. It assumes that the
scene and scheduler have been set up approriately using one of the previous
snippets.
\begin{python}
sensor = scene.getSensor()
sensor.setShutterOpen(0)
sensor.setShutterOpenTime(1)
stepSize = 5
for i in range(0,360 / stepSize):
rotationCur = Transform.rotate(Vector(0, 0, 1), i*stepSize);
rotationNext = Transform.rotate(Vector(0, 0, 1), (i+1)*stepSize);
trafoCur = Transform.lookAt(rotationCur * Point(0,-6,4),
Point(0, 0, .5), rotationCur * Vector(0, 1, 0))
trafoNext = Transform.lookAt(rotationNext * Point(0,-6,4),
Point(0, 0, .5), rotationNext * Vector(0, 1, 0))
atrafo = AnimatedTransform()
atrafo.appendTransform(0, trafoCur)
atrafo.appendTransform(1, trafoNext)
atrafo.sortAndSimplify()
sensor.setWorldTransform(atrafo)
scene.setDestinationFile('frame_%03i.png' % i)
job = RenderJob('job_%i' % i, scene, queue)
job.start()
queue.waitLeft(0)
queue.join()
\end{python}
A useful property of this approach is that scene loading and initialization
must only take place once. Performance-wise, this compares favourably with
running many separate rendering jobs, e.g. using the \code{mitsuba}
command-line executable.

View File

@ -13,34 +13,34 @@
\label{sec:bsdfs}
Surface scattering models describe the manner in which light interacts
with surfaces in the scene. They conveniently summarize the mesoscopic
scattering processes that take place within the material and
with surfaces in the scene. They conveniently summarize the mesoscopic
scattering processes that take place within the material and
cause it to look the way it does.
This represents one central component of the material system in Mitsuba---another
part of the renderer concerns itself with what happens
\emph{in between} surface interactions. For more information on this aspect,
This represents one central component of the material system in Mitsuba---another
part of the renderer concerns itself with what happens
\emph{in between} surface interactions. For more information on this aspect,
please refer to Sections~\ref{sec:media} and \ref{sec:subsurface}.
This section presents an overview of all surface scattering models that are
This section presents an overview of all surface scattering models that are
supported, along with their parameters.
\subsubsection*{BSDFs}
To achieve realistic results, Mitsuba comes with a library of both
To achieve realistic results, Mitsuba comes with a library of both
general-purpose surface scattering models (smooth or rough glass, metal,
plastic, etc.) and specializations to particular materials (woven cloth,
masks, etc.). Some model plugins fit neither category and can best be described
as \emph{modifiers} that are applied on top of one or more scattering models.
as \emph{modifiers} that are applied on top of one or more scattering models.
Throughout the documentation and within the scene description
Throughout the documentation and within the scene description
language, the word \emph{BSDF} is used synonymously with the term ``surface
scattering model''. This is an abbreviation for \emph{Bidirectional
Scattering Distribution Function}, a more precise technical
term.
scattering model''. This is an abbreviation for \emph{Bidirectional
Scattering Distribution Function}, a more precise technical
term.
In Mitsuba, BSDFs are
In Mitsuba, BSDFs are
assigned to \emph{shapes}, which describe the visible surfaces in
the scene. In the scene description language, this assignment can
either be performed by nesting BSDFs within shapes, or they can
be named and then later referenced by their name.
either be performed by nesting BSDFs within shapes, or they can
be named and then later referenced by their name.
The following fragment shows an example of both kinds of usages:
\begin{xml}
<scene version=$\MtsVer$>
@ -75,35 +75,35 @@ memory usage.
\label{fig:glass-explanation}
Some of the scattering models in Mitsuba need to know
the indices of refraction on the exterior and interior-facing
side of a surface.
side of a surface.
It is therefore important to decompose the mesh into meaningful
separate surfaces corresponding to each index of refraction change.
The example here shows such a decomposition for a water-filled Glass.
}
\end{figure}
A vital consideration when modeling a scene in a physically-based rendering
system is that the used materials do not violate physical properties, and
A vital consideration when modeling a scene in a physically-based rendering
system is that the used materials do not violate physical properties, and
that their arrangement is meaningful. For instance, imagine having designed
an architectural interior scene that looks good except for a white desk that
seems a bit too dark. A closer inspection reveals that it uses a Lambertian
material with a diffuse reflectance of $0.9$.
an architectural interior scene that looks good except for a white desk that
seems a bit too dark. A closer inspection reveals that it uses a Lambertian
material with a diffuse reflectance of $0.9$.
In many rendering systems, it would be feasible to increase the
reflectance value above $1.0$ in such a situation. But in Mitsuba, even a
small surface that reflects a little more light than it receives will
likely break the available rendering algorithms, or cause them to produce otherwise
In many rendering systems, it would be feasible to increase the
reflectance value above $1.0$ in such a situation. But in Mitsuba, even a
small surface that reflects a little more light than it receives will
likely break the available rendering algorithms, or cause them to produce otherwise
unpredictable results. In fact, the right solution in this case would be to switch to
a different the lighting setup that causes more illumination to be received by
the desk and then \emph{reduce} the material's reflectance---after all, it is quite unlikely that
the desk and then \emph{reduce} the material's reflectance---after all, it is quite unlikely that
one could find a real-world desk that reflects 90\% of all incident light.
As another example of the necessity for a meaningful material description, consider
the glass model illustrated in \figref{glass-explanation}. Here, careful thinking
is needed to decompose the object into boundaries that mark index of
the glass model illustrated in \figref{glass-explanation}. Here, careful thinking
is needed to decompose the object into boundaries that mark index of
refraction-changes. If this is done incorrectly and a beam of light can
potentially pass through a sequence of incompatible index of refraction changes (e.g. $1.00\to 1.33$
followed by $1.50\to1.33$), the output is undefined and will quite likely
even contain inaccuracies in parts of the scene that are far
even contain inaccuracies in parts of the scene that are far
away from the glass.

View File

@ -3,7 +3,7 @@
\label{sec:films}
A film defines how conducted measurements are stored and converted into the final
output file that is written to disk at the end of the rendering process. Mitsuba comes with a few
films that can write to high and low dynamic range image formats (OpenEXR, JPEG or PNG), as well
films that can write to high and low dynamic range image formats (OpenEXR, JPEG or PNG), as well
more scientifically oriented data formats (e.g. MATLAB or Mathematica).
In the XML scene description language, a normal film configuration might look as follows
@ -20,7 +20,7 @@ In the XML scene description language, a normal film configuration might look as
<integer name="width" value="1920"/>
<integer name="height" value="1080"/>
<!-- Use a Gaussian reconstruction filter. For
<!-- Use a Gaussian reconstruction filter. For
details on these, refer to the next subsection -->
<rfilter type="gaussian"/>
</film>
@ -28,6 +28,6 @@ In the XML scene description language, a normal film configuration might look as
</scene>
\end{xml}
The \code{film} plugin should be instantiated nested inside a \code{sensor} declaration.
Note how the output filename is never specified---it is automatically inferred
from the scene filename and can be manually overridden by passing the configuration parameter
Note how the output filename is never specified---it is automatically inferred
from the scene filename and can be manually overridden by passing the configuration parameter
\code{-o} to the \code{mitsuba} executable when rendering from the command line.

View File

@ -1,14 +1,14 @@
\newpage
\subsection{Integrators}
\label{sec:integrators}
In Mitsuba, the different rendering techniques are collectively referred to as
In Mitsuba, the different rendering techniques are collectively referred to as
\emph{integrators}, since they perform integration over a high-dimensional
space. Each integrator represents a specific approach for solving
the light transport equation---usually favored in certain scenarios, but
at the same time affected by its own set of intrinsic limitations.
Therefore, it is important to carefully select an integrator based on
user-specified accuracy requirements and properties of the scene to be
rendered.
Therefore, it is important to carefully select an integrator based on
user-specified accuracy requirements and properties of the scene to be
rendered.
In Mitsuba's XML description language, a single integrator
is usually instantiated by declaring it at the top level within the
@ -28,15 +28,15 @@ scene, e.g.
</scene>
\end{xml}
This section gives a brief overview of the available choices
This section gives a brief overview of the available choices
along with their parameters.
\subsubsection*{Choosing an integrator}
Due to the large number of integrators in Mitsuba, the decision of which
Due to the large number of integrators in Mitsuba, the decision of which
one is suitable may seem daunting. Assuming that the goal is to solve
the full light transport equation without approximations, a few integrators
(\pluginref{ao}, \pluginref{direct}, \pluginref{vpl})
can already be ruled out. The adjoint particle tracer \pluginref{ptracer} is
can already be ruled out. The adjoint particle tracer \pluginref{ptracer} is
also rarely used.
The following ``algorithm'' may help to decide amongst the remaining ones:
@ -46,11 +46,11 @@ The following ``algorithm'' may help to decide amongst the remaining ones:
Mitsuba currently comes with three path tracer variations that target different setups: It your
scene contains no media and no surfaces with opacity masks, use the plain path tracer (\pluginref{path}).
Otherwise, use one of the volumetric path tracers (\pluginref[volpathsimple]{volpath\_simple}
Otherwise, use one of the volumetric path tracers (\pluginref[volpathsimple]{volpath\_simple}
or \pluginref{volpath}). The latter is preferable if the scene contains glossy surface scattering models.
\item If step 1 produced poor (i.e. noisy and slowly converging) results, try
\item If step 1 produced poor (i.e. noisy and slowly converging) results, try
the bidirectional path tracer (\pluginref{bdpt}).
\item If steps 1 and 2 failed, the scene contains a relatively difficult lighting setup, potentially
\item If steps 1 and 2 failed, the scene contains a relatively difficult lighting setup, potentially
including interaction with complex materials.
In many cases, these difficulties can be greatly ameliorated by running a ``metropolized'' version
of a path tracer. This is implemented in the Primary Sample Space MLT (\pluginref{pssmlt}) plugin.
@ -69,7 +69,7 @@ method (\pluginref{mlt}, \pluginref{erpt}).
\smallrendering{Max. depth = $\infty$}{pathdepth-all}
\caption{
\label{fig:pathdepths}
These Cornell box renderings demonstrate the visual
These Cornell box renderings demonstrate the visual
effect of a maximum path depth. As the paths
are allowed to grow longer, the color saturation
increases due to multiple scattering interactions
@ -79,13 +79,13 @@ method (\pluginref{mlt}, \pluginref{erpt}).
\end{figure}
Almost all integrators use the concept of \emph{path depth}.
Here, a path refers to a chain of scattering events that
Here, a path refers to a chain of scattering events that
starts at the light source and ends at the eye or sensor.
It is often useful to limit the path depth (\figref{pathdepths})
when rendering scenes for preview purposes, since this reduces the amount
It is often useful to limit the path depth (\figref{pathdepths})
when rendering scenes for preview purposes, since this reduces the amount
of computation that is necessary per pixel. Furthermore, such renderings
usually converge faster and therefore need fewer samples per pixel.
When reference-quality is desired, one should always leave the path
When reference-quality is desired, one should always leave the path
depth unlimited.
\begin{figure}[h!]
@ -95,21 +95,42 @@ depth unlimited.
\vspace{-5mm}
\caption{
\label{fig:path-explanation}
A ray of emitted light is scattered by an object and subsequently
A ray of emitted light is scattered by an object and subsequently
reaches the eye/sensor.
In Mitsuba, this is a \emph{depth-2} path, since it has two edges.
}
\end{figure}
Mitsuba counts depths starting at $1$, which correspond to
visible light sources (i.e. a path that starts at the light
source and ends at the eye or sensor without any scattering
visible light sources (i.e. a path that starts at the light
source and ends at the eye or sensor without any scattering
interaction in between).
A depth-$2$ path (also known as ``direct illumination'') includes
a single scattering event (\figref{path-explanation}).
\subsubsection*{Progressive versus non-progressive}
Some of the rendering techniques in Mitsuba are \emph{progressive}.
What this means is that they display a rough preview, which improves over time.
What this means is that they display a rough preview, which improves over time.
Leaving them running indefinitely will continually reduce noise (in unbiased algorithms
such as Metropolis Light Transport) or noise and bias (in biased
such as Metropolis Light Transport) or noise and bias (in biased
rendering techniques such as Progressive Photon Mapping).
\newpage
\subsubsection*{Hiding directly visible emitters}
\label{sec:hideemitters}
Several rendering algorithms in Mitsuba have a feature to hide directly
visible light sources (e.g. environment maps or area lights). While not
particularly realistic, this feature is often convenient to remove a background
from a rendering so that it can be pasted into a differently-colored document.
Note that only directly visible emitters can be hidden using this feature---a
reflection on a shiny surface will be unaffected. To perform the kind of
compositing shown in Figure~\ref{fig:hideemitters}, it is also necessary to
enable the alpha channel in the scene's film instance (Section~\ref{sec:films}).
\renderings{
\unframedrendering{Daylit smoke rendered with \code{hideEmitters} set to \code{false}
(the default setting)}{integrator_volpath_normal}
\unframedrendering{Rendered with \code{hideEmitters} set to \code{true} and alpha-composited
onto a white background.}{integrator_volpath_hideemitters}
\caption{\label{fig:hideemitters}An example application of the \code{hideEmitters} parameter
together with alpha blending}
}

View File

@ -11,7 +11,7 @@
\caption{Participating media are not limited to smoke or fog: they are
also great for rendering fuzzy materials such as these knitted sweaters
(made using the \pluginref{heterogeneous} and \pluginref{microflake} plugins).
Figure courtesy of Yuksel et al. \cite{Yuksel2012Stitch}, models courtesy of
Figure courtesy of Yuksel et al. \cite{Yuksel2012Stitch}, models courtesy of
Rune Spaans and Christer Sveen.}
}
In Mitsuba, participating media are used to simulate materials ranging from

View File

@ -1,17 +1,17 @@
\newpage
\subsection{Phase functions}
\label{sec:phase}
This section contains a description of all implemented medium scattering models, which
are also known as \emph{phase functions}. These are very similar in principle to surface
scattering models (or \emph{BSDF}s), and essentially describe where light travels after
This section contains a description of all implemented medium scattering models, which
are also known as \emph{phase functions}. These are very similar in principle to surface
scattering models (or \emph{BSDF}s), and essentially describe where light travels after
hitting a particle within the medium.
The most commonly used models for smoke, fog, and other homogeneous media
are isotropic scattering (\pluginref{isotropic}) and the Henyey-Greenstein
are isotropic scattering (\pluginref{isotropic}) and the Henyey-Greenstein
phase function (\pluginref{hg}). Mitsuba also supports \emph{anisotropic}
media, where the behavior of the medium changes depending on the direction
of light propagation (e.g. in volumetric representations of fabric). These
are the Kajiya-Kay (\pluginref{kkay}) and Micro-flake (\pluginref{microflake})
media, where the behavior of the medium changes depending on the direction
of light propagation (e.g. in volumetric representations of fabric). These
are the Kajiya-Kay (\pluginref{kkay}) and Micro-flake (\pluginref{microflake})
models.
Finally, there is also a phase function for simulating scattering in

View File

@ -2,7 +2,7 @@
\subsection{Reconstruction filters}
\label{sec:rfilters}
Image reconstruction filters are responsible for converting a series of radiance samples generated
jointly by the \emph{sampler} and \emph{integrator} into the final output image that will be written
jointly by the \emph{sampler} and \emph{integrator} into the final output image that will be written
to disk at the end of a rendering process.
This section gives a brief overview of the reconstruction filters that are available in Mitsuba.
There is no universally superior filter, and the final choice depends on a trade-off between
@ -15,44 +15,44 @@ near discontinuities, such as a light-shadow transiton.
\begin{description}
\item[Box filter (\code{box}):]
the fastest, but also about the worst possible
reconstruction filter, since it is extremely prone to aliasing.
the fastest, but also about the worst possible
reconstruction filter, since it is extremely prone to aliasing.
It is included mainly for completeness, though some rare situations
may warrant its use.
\item[Tent filter (\code{tent}):]
Simple tent, or triangle filter. This reconstruction filter never
suffers from ringing and usually causes less aliasing than a naive
suffers from ringing and usually causes less aliasing than a naive
box filter. When rendering scenes with sharp brightness discontinuities,
this may be useful; otherwise, negative-lobed filters will be preferable
(e.g. Mitchell-Netravali or Lanczos Sinc)
\item[Gaussian filter (\code{gaussian}):]
this is a windowed Gaussian filter with configurable standard deviation.
It produces pleasing results and never suffers from ringing, but may
It produces pleasing results and never suffers from ringing, but may
occasionally introduce too much blurring.
When no reconstruction filter is explicitly requested, this is the default
choice in Mitsuba.
\item[Mitchell-Netravali filter (\code{mitchell}):]
Separable cubic spline reconstruction filter by Mitchell and Netravali
\cite{Mitchell:1988:Reconstruction}
This is often a good compromise between sharpness and ringing.
This is often a good compromise between sharpness and ringing.
The plugin has two \code{float}-valued parameters named \texttt{B} and \texttt{C} that
The plugin has two \code{float}-valued parameters named \texttt{B} and \texttt{C} that
correspond to the two parameters in the original research paper. By default, these
are set to the recommended value of $1/3$, but can be tweaked if desired.
\item[Catmull-Rom filter (\code{catmullrom}):]
This is a special version of the Mitchell-Netravali filter that has the
This is a special version of the Mitchell-Netravali filter that has the
constants \texttt{B} and \texttt{C} adjusted to produce higher sharpness at the
cost of increased susceptibility to ringing.
\item[Lanczos Sinc filter (\code{lanczos}):]
This is a windowed version of the theoretically optimal low-pass filter.
It is generally one of the best available filters in terms of producing sharp
high-quality output. Its main disadvantage is that it produces strong ringing around
discontinuities, which can become a serious problem when rendering bright objects
with sharp edges (for instance, a directly visible light source will have black
fringing artifacts around it).
It is generally one of the best available filters in terms of producing sharp
high-quality output. Its main disadvantage is that it produces strong ringing around
discontinuities, which can become a serious problem when rendering bright objects
with sharp edges (for instance, a directly visible light source will have black
fringing artifacts around it).
This is also the computationally slowest reconstruction filter.
This plugin has an \code{integer}-valued parameter named \code{lobes}, that
@ -60,19 +60,19 @@ sets the desired number of filter side-lobes. The higher, the closer
the filter will approximate an optimal low-pass filter, but this also
increases the susceptibility to ringing. Values of 2 or 3 are common (3 is the default).
\end{description}
The next section contains a series of comparisons between reconstruction filters. In the first
case, a very high-resolution input image (corresponding to a hypothetical radiance field
The next section contains a series of comparisons between reconstruction filters. In the first
case, a very high-resolution input image (corresponding to a hypothetical radiance field
incident at the camera) is reconstructed at low resolutions.
\newpage
\subsubsection{Reconstruction filter comparison 1: frequency attenuation and aliasing}
\vspace{-2mm}
Here, a high frequency function is reconstructed at low resolutions. A good filter
Here, a high frequency function is reconstructed at low resolutions. A good filter
(e.g. Lanczos Sinc) will capture all oscillations that are representable at the desired
resolution and attenuate the remainder to a uniform gray. The filters are ordered by their
approximate level of success at this benchmark.
\renderings{
\subfloat[A high resolution input image whose frequency decreases
\subfloat[A high resolution input image whose frequency decreases
towards the borders. If you are looking at this on a computer, you may
have to zoom in.]{\fbox{\includegraphics[width=0.43\textwidth]{images/rfilter_sines_input}}}
\hfill
@ -92,7 +92,7 @@ approximate level of success at this benchmark.
}
\newpage
\subsubsection{Reconstruction filter comparison 2: ringing}
This comparison showcases the ringing artifacts that can occur when the rendered
This comparison showcases the ringing artifacts that can occur when the rendered
image contains extreme and discontinuous brightness transitions. The
Mitchell-Netravali, Catmull-Rom, and Lanczos Sinc filters are affected by this problem.
Note the black fringing around the light source in the cropped Cornell box renderings below.

View File

@ -1,16 +1,16 @@
\newpage
\subsection{Sample generators}
\label{sec:samplers}
When rendering an image, Mitsuba has to solve a high-dimensional integration problem that involves the
geometry, materials, lights, and sensors that make up the scene. Because of the mathematical complexity
When rendering an image, Mitsuba has to solve a high-dimensional integration problem that involves the
geometry, materials, lights, and sensors that make up the scene. Because of the mathematical complexity
of these integrals, it is generally impossible to solve them analytically --- instead, they
are solved \emph{numerically} by evaluating the function to be integrated at a large number of
different positions referred to as \emph{samples}. Sample generators are an essential ingredient to this
process: they produce points in a (hypothetical) infinite dimensional hypercube $[0,1]^{\infty}$ that
are solved \emph{numerically} by evaluating the function to be integrated at a large number of
different positions referred to as \emph{samples}. Sample generators are an essential ingredient to this
process: they produce points in a (hypothetical) infinite dimensional hypercube $[0,1]^{\infty}$ that
constitute the canonical representation of these samples.
To do its work, a rendering algorithm, or \emph{integrator}, will send many queries to the sample generator.
Generally, it will request subsequent 1D or 2D components of this infinite-dimensional ``point'' and map
Generally, it will request subsequent 1D or 2D components of this infinite-dimensional ``point'' and map
them into a more convenient space (for instance, positions on surfaces). This allows it to construct
light paths to eventually evaluate the flow of light through the scene.
@ -18,6 +18,6 @@ Since the whole process starts with a large number of points in the abstract spa
it is natural to consider different ways of positioning them. Desirable properties of a sampler are
that it ``randomly'' covers the whole space evenly with samples, but without placing samples too close
to each other. This leads to such notions as \emph{stratified sampling} and \emph{low-discrepancy}
number sequences. The samplers in this section make different guarantees on the quality of generated
samples based on these criteria. To obtain intuition about their behavior, the provided point plots
number sequences. The samplers in this section make different guarantees on the quality of generated
samples based on these criteria. To obtain intuition about their behavior, the provided point plots
illustrate the resulting sample placement.

View File

@ -8,12 +8,12 @@ into a given direction or the irradiance received by a certain surface. The foll
section lists the available choices.
\subsubsection*{Handedness convention}
Sensors in Mitsuba are \emph{right-handed}.
Sensors in Mitsuba are \emph{right-handed}.
Any number of rotations and translations can be applied to them
without changing this property. By default they are located at the
origin and oriented in such a way that in the rendered image, $+X$ points left,
$+Y$ points upwards, and $+Z$ points along the viewing direction.
Left-handed sensors are also supported. To switch the handedness,
flip any one of the axes, e.g. by passing a scale transformation like
flip any one of the axes, e.g. by passing a scale transformation like
\code{<scale x="-1"/>} to the sensor's \code{toWorld} parameter.

View File

@ -5,11 +5,11 @@ This section presents an overview of the shape plugins that are released along w
In Mitsuba, shapes define surfaces that mark transitions between different types of materials. For instance,
a shape could describe a boundary between air and a solid object, such as a piece of rock. Alternatively,
a shape can mark the beginning of a region of space that isn't solid at all, but rather contains a participating
a shape can mark the beginning of a region of space that isn't solid at all, but rather contains a participating
medium, such as smoke or steam. Finally, a shape can be used to create an object that emits light on its own.
Shapes are usually declared along with a surface scattering model (named ``BSDF'', see \secref{bsdfs} for details).
This BSDF characterizes what happens \emph{at the surface}. In the XML scene description language, this might look like
Shapes are usually declared along with a surface scattering model (named ``BSDF'', see \secref{bsdfs} for details).
This BSDF characterizes what happens \emph{at the surface}. In the XML scene description language, this might look like
the following:
\begin{xml}
<scene version=$\MtsVer$>
@ -20,7 +20,7 @@ the following:
... $\code{bsdf}$ parameters ..
</bsdf>
<!-- Alternatively: reference a named BSDF that
<!-- Alternatively: reference a named BSDF that
has been declared previously
<ref id="myBSDF"/>
@ -41,12 +41,12 @@ of the shape. This informs the renderer about what happens in the region of spac
<medium name="interior" type="... medium type ...">
... $\code{medium}$ parameters ...
</medium>
<medium name="exterior" type="... medium type ...">
... $\code{medium}$ parameters ...
</medium>
<!-- Alternatively: reference named media that
<!-- Alternatively: reference named media that
have been declared previously
<ref name="interior" id="myMedium1"/>
@ -58,8 +58,8 @@ of the shape. This informs the renderer about what happens in the region of spac
You may have noticed that the previous XML example dit not make any mention of surface
scattering models (BSDFs). In Mitsuba, such a shape declaration creates an \emph{index-matched} boundary.
This means that incident illumination will pass through the surface without undergoing any kind of
interaction. However, the renderer will still uses the information available in the shape to correctly
This means that incident illumination will pass through the surface without undergoing any kind of
interaction. However, the renderer will still uses the information available in the shape to correctly
account for the medium change.
It is also possible to create \emph{index-mismatched} boundaries between media, where some of
@ -76,7 +76,7 @@ the light is affected by the boundary transition:
<medium name="interior" type="... medium type ...">
... $\code{medium}$ parameters ...
</medium>
<medium name="exterior" type="... medium type ...">
... $\code{medium}$ parameters ...
</medium>

View File

@ -2,11 +2,18 @@
\subsection{Subsurface scattering models}
\label{sec:subsurface}
There are two ways of simulating subsurface scattering within Mitsuba:
participating media and subsurface scattering models. The latter are described
in this section and can be thought of as a first-order approximation of the
former. For this reason, subsurface scattering models should be preferred when
visually appealing output should be generated quickly and the demands on
physical realism are secondary.
participating media and subsurface scattering models.
\begin{description}
\item[Subsurface scattering models:] Described in this section. These can be thought
of as a first-order approximation of what happens inside a participating medium.
They are preferable when visually appealing output should be generated
\emph{quickly} and the demands on accuracy are secondary.
At the moment, there is only one subsurface scattering model (the
\pluginref{dipole}), which is described on the next page.
\item[Participating media:] Described in Section~\ref{sec:media}. When modeling
subsurface scattering using a participating medium, Mitsuba performs a \emph{full}
radiative transport simulation, which correctly accounts for all scattering events.
This is more accurate but generally significantly slower.
\end{description}
At the moment, there is only one subsurface scattering model (the
\pluginref{dipole}), which is described on the next page.

View File

@ -4,6 +4,6 @@
The following section describes the available texture data sources. In Mitsuba,
textures are objects that can be attached to certain
surface scattering model parameters to introduce spatial variation.
In the documentation, these are listed as supporting the ``\Texture'' type.
In the documentation, these are listed as supporting the ``\Texture'' type.
See \secref{bsdfs} for many examples.

View File

@ -25,7 +25,7 @@
MTS_NAMESPACE_BEGIN
/**
* \brief Bidirectional mutatation strategy
* \brief Bidirectional mutation strategy
*
* This class implements a slightly extended version of the bidirectional
* mutation proposed by Veach. The main change is that it builds on top of

View File

@ -165,7 +165,8 @@ public:
* \return The average luminance over the image plane
*/
Float generateSeeds(size_t sampleCount, size_t seedCount,
bool fineGrained, std::vector<PathSeed> &seeds);
bool fineGrained, const Bitmap *importanceMap,
std::vector<PathSeed> &seeds);
/**
* \brief Compute the average luminance over the image plane
@ -181,7 +182,8 @@ public:
* the random number stream of the underlying \ref ReplayableSampler
* to the indicated position and recreates the associated path.
*/
void reconstructPath(const PathSeed &seed, Path &result);
void reconstructPath(const PathSeed &seed,
const Bitmap *importanceMap, Path &result);
/// Return the underlying memory pool
inline MemoryPool &getMemoryPool() { return m_pool; }

View File

@ -83,7 +83,7 @@ public:
* underlying random number generator has been used
* outside of this class
*/
inline void updateSampleIndex(uint64_t index) { m_sampleIndex = index; }
inline void updateSampleIndex(size_t index) { m_sampleIndex = index; }
MTS_DECLARE_CLASS()
protected:

View File

@ -129,6 +129,32 @@ template <typename T> struct TAABB {
return (max + min) * (Scalar) 0.5;
}
/// Return the position of one of the corners (in <tt>0..2^dim-1</tt>)
inline PointType getCorner(int index) const {
PointType result;
for (int d=0; d<PointType::dim; ++d) {
if (index & (1 << d))
result[d] = max[d];
else
result[d] = min[d];
}
return result;
}
/// Return a child bounding box in a interval-, quad-, octtree, etc.
inline TAABB getChild(int index) const {
TAABB result(getCenter());
for (int d=0; d<PointType::dim; ++d) {
if (index & (1 << d))
result.max[d] = max[d];
else
result.min[d] = min[d];
}
return result;
}
/// Check whether a point lies on or inside the bounding box
inline bool contains(const PointType &vec) const {
for (int i=0; i<PointType::dim; ++i)
@ -289,19 +315,17 @@ template <typename T> struct TAABB {
Float t1 = (minVal - origin) * ray.dRcp[i];
Float t2 = (maxVal - origin) * ray.dRcp[i];
if (t1 > t2) {
Float tmp = t1;
t1 = t2;
t2 = tmp;
}
if (t1 > t2)
std::swap(t1, t2);
nearT = std::max(nearT, t1);
farT = std::min(farT, t2);
nearT = std::max(t1, nearT);
farT = std::min(t2, farT);
if (nearT > farT)
if (!(nearT <= farT))
return false;
}
}
return true;
}

View File

@ -250,6 +250,26 @@ public:
EAuto
};
/// List of different rotation/flip types that can be passed to \ref rotateFlip()
enum ERotateFlipType {
ERotateNoneFlipNone = 0,
ERotate180FlipXY = ERotateNoneFlipNone,
ERotate90FlipNone = 1,
ERotate270FlipXY = ERotate90FlipNone,
ERotate180FlipNone = 2,
ERotateNoneFlipXY = ERotate180FlipNone,
ERotate270FlipNone = 3,
ERotate90FlipXY = ERotate270FlipNone,
ERotateNoneFlipX = 4,
ERotate180FlipY = ERotateNoneFlipX,
ERotate90FlipX = 5,
ERotate270FlipY = ERotate90FlipX,
ERotate180FlipX = 6,
ERotateNoneFlipY = ERotate180FlipX,
ERotate270FlipX = 7,
ERotate90FlipY = ERotate270FlipX
};
/**
* \brief Create a bitmap of the specified type and allocate
* the necessary amount of memory
@ -320,6 +340,15 @@ public:
/// Return whether this image has matching width and height
inline bool isSquare() const { return m_size.x == m_size.y; }
/// Return whether this image has an alpha channel
inline bool hasAlpha() const {
return
m_pixelFormat == ELuminanceAlpha ||
m_pixelFormat == ERGBA ||
m_pixelFormat == EXYZA ||
m_pixelFormat == ESpectrumAlpha;
}
/**
* \brief Return the number bits per component
*
@ -393,17 +422,8 @@ public:
/// Draw a rectangle with the specified position and size
void drawRect(const Point2i &offset, const Vector2i &size, const Spectrum &value);
/**
* \brief Color balancing: apply the given scale factors to the
* red, green, and blue channels of the image
*
* When the image is not an \c EFloat16, \c EFloat32, or
* \c EFloat64-based RGB/RGBA image, the function throws an exception
*/
void colorBalance(Float r, Float g, Float b);
/// Draw a filled rectangle with the specified position and size
void fill(const Point2i &offset, const Vector2i &size, const Spectrum &value);
void fillRect(Point2i offset, Vector2i size, const Spectrum &value);
/// Bitmap equality operator (useful for unit-tests etc.)
bool operator==(const Bitmap &bitmap) const;
@ -688,6 +708,9 @@ public:
/// Vertically flip the image contents
void flipVertically();
/// Perform the specified rotatation & flip operation
ref<Bitmap> rotateFlip(ERotateFlipType type) const;
/**
* \brief Accumulate the contents of another bitmap into the
* region of the specified offset
@ -699,7 +722,43 @@ public:
* use different component formats or channels, or when the
* component format is \ref EBitmask.
*/
void accumulate(const Bitmap *bitmap, const Point2i &offset);
void accumulate(const Bitmap *bitmap, Point2i sourceOffset,
Point2i targetOffset, Vector2i size);
/**
* \brief Color balancing: apply the given scale factors to the
* red, green, and blue channels of the image
*
* When the image is not an \c EFloat16, \c EFloat32, or
* \c EFloat64-based RGB/RGBA image, the function throws an exception
*/
void colorBalance(Float r, Float g, Float b);
/**
* Apply a color transformation matrix to the contents of the bitmap
*
* The implementation assumes that the contents have the
* RGB, RGBA, XYZ, or XYZA pixel format and a floating point
* component format.
*/
void applyMatrix(Float matrix[3][3]);
/**
* \brief Accumulate the contents of another bitmap into the
* region of the specified offset
*
* This convenience function calls the main <tt>accumulate()</tt>
* implementation with <tt>size</tt> set to <tt>bitmap->getSize()</tt>
* and <tt>sourceOffset</tt> set to zero. Out-of-bounds regions are
* ignored. It is assumed that <tt>bitmap != this</tt>.
*
* \remark This function throws an exception when the bitmaps
* use different component formats or channels, or when the
* component format is \ref EBitmask.
*/
inline void accumulate(const Bitmap *bitmap, Point2i targetOffset) {
accumulate(bitmap, Point2i(0), targetOffset, bitmap->getSize());
}
/**
* \brief Up- or down-sample this image to a different resolution
@ -747,25 +806,23 @@ public:
inline void setGamma(Float gamma) { m_gamma = gamma; }
/// Set a string-valued metadata field
void setString(const std::string &key, const std::string &value);
inline void setMetadataString(const std::string &key, const std::string &value) {
m_metadata.setString(key, value);
}
/// Return a string-valued metadata field
std::string getString(const std::string &key) const;
/// Return a map of all present metadata
inline std::map<std::string, std::string> &getMetadata() {
return m_metadata;
inline std::string getMetadataString(const std::string &key) const {
return m_metadata.getAsString(key);
}
/// Return a map of all present metadata (const version)
inline const std::map<std::string, std::string> &getMetadata() const {
return m_metadata;
}
/// Return a \ref Properties object containing the image metadata
inline Properties &getMetadata() { return m_metadata; }
/// Set the metadata associated with the bitmap
inline void setMetadata(const std::map<std::string, std::string> &metadata) {
m_metadata = metadata;
}
/// Return a \ref Properties object containing the image metadata (const version)
inline const Properties &getMetadata() const { return m_metadata; }
/// Set the a \ref Properties object containing the image metadata
inline void setMetadata(const Properties &metadata) { m_metadata = metadata; }
//! @}
// ======================================================================
@ -883,9 +940,9 @@ protected:
EComponentFormat m_componentFormat;
Vector2i m_size;
uint8_t *m_data;
std::map<std::string, std::string> m_metadata;
Float m_gamma;
int m_channelCount;
Properties m_metadata;
};
/** \brief Bitmap format conversion helper class

View File

@ -50,9 +50,13 @@
#if defined(__WINDOWS__)
#define ONE_MINUS_EPS_FLT 0.999999940395355225f
#define ONE_MINUS_EPS_DBL 0.999999999999999888
#define RCPOVERFLOW_FLT 2.93873587705571876e-39f
#define RCPOVERFLOW_DBL 5.56268464626800345e-309
#else
#define ONE_MINUS_EPS_FLT 0x1.fffffep-1f
#define ONE_MINUS_EPS_DBL 0x1.fffffffffffff7p-1
#define RCPOVERFLOW_FLT 0x1p-128f
#define RCPOVERFLOW_DBL 0x1p-1024
#endif
#ifdef SINGLE_PRECISION
@ -64,6 +68,7 @@
#define SQRT_TWO 1.41421356237309504880f
#define INV_SQRT_TWO 0.70710678118654752440f
#define ONE_MINUS_EPS ONE_MINUS_EPS_FLT
#define RCPOVERFLOW RCPOVERFLOW_FLT
#else
#define M_E 2.71828182845904523536
#define M_PI 3.14159265358979323846
@ -73,5 +78,6 @@
#define SQRT_TWO 1.41421356237309504880
#define INV_SQRT_TWO 0.70710678118654752440
#define ONE_MINUS_EPS ONE_MINUS_EPS_DBL
#define RCPOVERFLOW RCPOVERFLOW_DBL
#endif
#endif /* __MITSUBA_CORE_CONSTANTS_H */

View File

@ -84,12 +84,24 @@ struct Frame {
return s * v.x + t * v.y + n * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared cosine of the angle between the normal and v */
inline static Float cosTheta2(const Vector &v) {
return v.z * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the cosine of the angle between the normal and v */
inline static Float cosTheta(const Vector &v) {
return v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared sine of the angle between the normal and v */
inline static Float sinTheta2(const Vector &v) {
return 1.0f - v.z * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the sine of the angle between the normal and v */
inline static Float sinTheta(const Vector &v) {
@ -109,9 +121,12 @@ struct Frame {
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared sine of the angle between the normal and v */
inline static Float sinTheta2(const Vector &v) {
return 1.0f - v.z * v.z;
* system, return the squared tangent of the angle between the normal and v */
inline static Float tanTheta2(const Vector &v) {
Float temp = 1 - v.z*v.z;
if (temp <= 0.0f)
return 0.0f;
return temp / (v.z * v.z);
}
/** \brief Assuming that the given direction is in the local coordinate

View File

@ -23,6 +23,9 @@
MTS_NAMESPACE_BEGIN
struct AABB;
class AbstractAnimationTrack;
template <typename T> class AnimationTrack;
class AnimatedTransform;
class Appender;
class Bitmap;
class BlackBodySpectrum;
@ -163,6 +166,11 @@ class WorkResult;
class WorkUnit;
class ZStream;
typedef AnimationTrack<Float> FloatTrack;
typedef AnimationTrack<Quaternion> QuatTrack;
typedef AnimationTrack<Vector> VectorTrack;
typedef AnimationTrack<Point> PointTrack;
MTS_NAMESPACE_END
#if BOOST_VERSION >= 105000

View File

@ -33,8 +33,11 @@ MTS_NAMESPACE_BEGIN
/// Write a Log message to the console (to be used within subclasses of <tt>Object</tt>)
#define Log(level, fmt, ...) do { \
mitsuba::Logger *logger = mitsuba::Thread::getThread()->getLogger(); \
if (level >= logger->getLogLevel()) \
mitsuba::Thread *thread = mitsuba::Thread::getThread(); \
if (EXPECT_NOT_TAKEN(thread == NULL)) \
throw std::runtime_error("Null thread pointer"); \
mitsuba::Logger *logger = thread->getLogger(); \
if (logger != NULL && level >= logger->getLogLevel()) \
logger->log(level, m_theClass, \
__FILE__, __LINE__, fmt, ## __VA_ARGS__); \
} while (0)
@ -44,8 +47,11 @@ MTS_NAMESPACE_BEGIN
* outside of classes that derive from Object)
*/
#define SLog(level, fmt, ...) do { \
mitsuba::Logger *logger = mitsuba::Thread::getThread()->getLogger(); \
if (level >= logger->getLogLevel()) \
mitsuba::Thread *thread = mitsuba::Thread::getThread(); \
if (EXPECT_NOT_TAKEN(thread == NULL)) \
throw std::runtime_error("Null thread pointer"); \
mitsuba::Logger *logger = thread->getLogger(); \
if (logger != NULL && level >= logger->getLogLevel()) \
logger->log(level, NULL, \
__FILE__, __LINE__, fmt, ## __VA_ARGS__); \
} while (0)

View File

@ -31,7 +31,7 @@ MTS_NAMESPACE_BEGIN
* \brief Generic LRU cache implementation
*
* Based on the bimap implementation by Tim Day
* (http://www.bottlenose.demon.co.uk/article/lru.pdf).
* (http://timday.bitbucket.org/lru.html).
*
* This cache does not support multithreading out of the box -- it
* will need to be protected using some form of locking mechanism.

View File

@ -17,94 +17,12 @@
*/
#pragma once
#if !defined(__MITSUBA_CORE_STL_H_)
#define __MITSUBA_CORE_STL_H_
/* Include some SGI STL extensions, which might be missing */
#ifdef __GNUC__
#include <ext/functional>
using __gnu_cxx::select2nd;
using __gnu_cxx::compose1;
#else
#include <functional>
#if !defined(__MITSUBA_CORE_MATH_H_)
#define __MITSUBA_CORE_MATH_H_
/// \cond
// (Don't include in the documentation)
namespace std {
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;
}
};
MTS_NAMESPACE_BEGIN
template <class _Pair> struct _Select2nd : public unary_function<_Pair, typename _Pair::second_type> {
const typename _Pair::second_type& operator()(const _Pair& __x) const {
return __x.second;
}
};
template <class _Pair> struct select1st : public _Select1st<_Pair> {};
template <class _Pair> struct select2nd : public _Select2nd<_Pair> {};
template <class _Operation1, class _Operation2> class unary_compose : public unary_function<typename _Operation2::argument_type, typename _Operation1::result_type> {
protected:
_Operation1 _M_fn1;
_Operation2 _M_fn2;
public:
unary_compose(const _Operation1& __x, const _Operation2& __y) : _M_fn1(__x), _M_fn2(__y) {}
typename _Operation1::result_type operator()(const typename _Operation2::argument_type& __x) const {
return _M_fn1(_M_fn2(__x));
}
};
template <class _Operation1, class _Operation2> inline unary_compose<_Operation1,_Operation2> compose1(const _Operation1& __fn1, const _Operation2& __fn2) {
return unary_compose<_Operation1,_Operation2>(__fn1, __fn2);
}
#if defined(_MSC_VER)
#include <float.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
inline char tolower(char c) {
return ::tolower(c);
}
inline char toupper(char c) {
return ::toupper(c);
}
inline bool isnan(float f) {
return _isnan(f);
}
inline bool isnan(double f) {
return _isnan(f);
}
inline bool isfinite(float f) {
return _finite(f);
}
inline bool isfinite(double f) {
return _finite(f);
}
inline bool isinf(float f) {
return !_finite(f);
}
inline bool isinf(double f) {
return !_finite(f);
}
#endif
};
using std::select2nd;
using std::compose1;
#endif
namespace mitsuba {
namespace math {
#if defined(__LINUX__) && defined(__x86_64__)
/*
@ -211,7 +129,8 @@ namespace math {
#endif
}
}; /* namespace math */
}; /* namespace mitsuba */
MTS_NAMESPACE_END
#if defined(_MSC_VER)
extern "C" {
@ -219,5 +138,5 @@ extern "C" {
extern MTS_EXPORT_CORE double nextafter(double x, double y);
};
#endif
/// @endcond
#endif /* __MITSUBA_CORE_STL_H_ */
#endif /* __MITSUBA_CORE_MATH_H_ */

View File

@ -491,7 +491,7 @@ public:
/// Compute the inverse (Faster than Matrix::invert)
FINLINE bool invert(Matrix2x2 &target) const {
Float det = m[0][0]*m[1][1] - m[0][1]*m[1][0];
if (det == 0)
if (std::abs(det) <= RCPOVERFLOW)
return false;
Float invDet = 1/det;
target.m[0][0] = m[1][1] * invDet;

View File

@ -70,6 +70,10 @@ struct Normal : public TVector3<Float> {
}
};
inline Normal normalize(const Normal &n) {
return n / n.length();
}
MTS_NAMESPACE_END
#endif /* __MITSUBA_CORE_NORMAL_H_ */

View File

@ -140,7 +140,7 @@ public:
perm[i] = i;
/* Build the kd-tree and compute a suitable permutation of the elements */
m_root = build(m_aabb, 0, &perm[0], &temp[0], &perm[0], &perm[m_items.size()]);
m_root = build(m_aabb, 0, &perm[0], &temp[0], &perm[0], &perm[0] + m_items.size());
/* Apply the permutation */
permute_inplace(&m_items[0], perm);

View File

@ -189,6 +189,62 @@ extern MTS_EXPORT_CORE void __mts_set_appdefaults();
#define MTS_AUTORELEASE_BEGIN()
#define MTS_AUTORELEASE_END()
#endif
MTS_NAMESPACE_END
/// \cond
// Try to make MSVC++ behave a bit more like C++
// with an underlying C99 implementation
// (and don't include this in the documentation)
#if defined(_MSC_VER)
#include <float.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
namespace mitsuba {
#if defined(__64BIT__)
typedef long long ssize_t;
#else
typedef long ssize_t;
#endif
};
namespace std {
inline char tolower(char c) {
return ::tolower(c);
}
inline char toupper(char c) {
return ::toupper(c);
}
inline bool isnan(float f) {
return _isnan(f);
}
inline bool isnan(double f) {
return _isnan(f);
}
inline bool isfinite(float f) {
return _finite(f);
}
inline bool isfinite(double f) {
return _finite(f);
}
inline bool isinf(float f) {
return !_finite(f);
}
inline bool isinf(double f) {
return !_finite(f);
}
};
#endif
#endif /* __MITSUBA_CORE_PLATFORM_H_ */

View File

@ -59,6 +59,8 @@ public:
EVector,
/// 4x4 transform for homogeneous coordinates
ETransform,
/// An animated 4x4 transformation
EAnimatedTransform,
/// Discretized color spectrum
ESpectrum,
/// Arbitrary-length string
@ -71,6 +73,14 @@ public:
struct Data {
uint8_t *ptr;
size_t size;
inline bool operator==(const Data &d) const {
return ptr == d.ptr && size == d.size;
}
inline bool operator!=(const Data &d) const {
return !operator==(d);
}
};
/// Construct an empty property container
@ -144,6 +154,15 @@ public:
/// Get a linear transformation (with default)
Transform getTransform(const std::string &name, const Transform &defVal) const;
/// Set an animated linear transformation
void setAnimatedTransform(const std::string &name, const AnimatedTransform *value, bool warnDuplicates = true);
/// Get an animated linear transformation
ref<const AnimatedTransform> getAnimatedTransform(const std::string &name) const;
/// Get an animated linear transformation (with default)
ref<const AnimatedTransform> getAnimatedTransform(const std::string &name, const AnimatedTransform *defVal) const;
/// Get an animated linear transformation (with default)
ref<const AnimatedTransform> getAnimatedTransform(const std::string &name, const Transform &defVal) const;
/// Set a spectral power distribution
void setSpectrum(const std::string &name, const Spectrum &value, bool warnDuplicates = true);
/// Get a spectral power distribution
@ -172,6 +191,15 @@ public:
/// Get a string (with default)
std::string getString(const std::string &name, const std::string &defVal) const;
/// Return one of the parameters (converting it to a string if necessary)
std::string getAsString(const std::string &name) const;
/// Return one of the parameters (converting it to a string if necessary, with default value)
std::string getAsString(const std::string &name, const std::string &defVal) const;
/// Copy an attribute from another Properties object and potentially rename it
void copyAttribute(const Properties &properties,
const std::string &sourceName, const std::string &targetName);
/// Store an array containing the names of all stored properties
void putPropertyNames(std::vector<std::string> &results) const;
@ -206,6 +234,14 @@ public:
/// Assignment operator
void operator=(const Properties &props);
/// Equality comparison operator
bool operator==(const Properties &props) const;
/// Inequality comparision operator
inline bool operator!=(const Properties &props) const {
return !operator==(props);
}
/// Return a string representation
std::string toString() const;
private:

View File

@ -40,7 +40,7 @@ extern const int MTS_EXPORT_CORE primeTable[primeTableSize];
/// Van der Corput radical inverse in base 2 with single precision
inline float radicalInverse2Single(uint32_t n, uint32_t scramble = 0U) {
/* Efficiently reverse the bits in 'n' using binary operations */
#if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))) || defined(__clang__)
n = __builtin_bswap32(n);
#else
n = (n << 16) | (n >> 16);
@ -59,7 +59,7 @@ inline float radicalInverse2Single(uint32_t n, uint32_t scramble = 0U) {
/// Van der Corput radical inverse in base 2 with double precision
inline double radicalInverse2Double(uint64_t n, uint64_t scramble = 0ULL) {
/* Efficiently reverse the bits in 'n' using binary operations */
#if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))) || defined(__clang__)
n = __builtin_bswap64(n);
#else
n = (n << 32) | (n >> 32);
@ -156,25 +156,25 @@ inline uint64_t sampleTEA(uint32_t v0, uint32_t v1, int rounds = 4) {
#if defined(DOUBLE_PRECISION)
inline Float sampleTEAFloat(uint32_t v0, uint32_t v1, int rounds = 4) {
/* Trick from MTGP: generate an uniformly distributed
single precision number in [1,2) and subtract 1. */
union {
single precision number in [1,2) and subtract 1. */
union {
uint64_t u;
float f;
} x;
x.u = (sampleTEA(v0, v1, rounds) >> 12) | 0x3ff0000000000000;
return x.f - 1.0;
double f;
} x;
x.u = (sampleTEA(v0, v1, rounds) >> 12) | 0x3ff0000000000000ULL;
return x.f - 1.0;
}
#else
inline Float sampleTEAFloat(uint32_t v0, uint32_t v1, int rounds = 4) {
/* Trick from MTGP: generate an uniformly distributed
single precision number in [1,2) and subtract 1. */
union {
single precision number in [1,2) and subtract 1. */
union {
uint32_t u;
float f;
} x;
x.u = ((sampleTEA(v0, v1, rounds) & 0xFFFFFFFF) >> 9) | 0x3f800000UL;
return x.f - 1.0f;
} x;
x.u = ((sampleTEA(v0, v1, rounds) & 0xFFFFFFFF) >> 9) | 0x3f800000UL;
return x.f - 1.0f;
}
#endif

View File

@ -35,6 +35,12 @@ extern MTS_EXPORT_CORE float legendreP(int l, float x);
/// Evaluate the l-th Legendre polynomial using recurrence (double precision)
extern MTS_EXPORT_CORE double legendreP(int l, double x);
/// Evaluate an associated Legendre polynomial using recurrence (single precision)
extern MTS_EXPORT_CORE float legendreP(int l, int m, float x);
/// Evaluate an associated Legendre polynomial using recurrence (double precision)
extern MTS_EXPORT_CORE double legendreP(int l, int m, double x);
/// Evaluate the l-th Legendre polynomial and its derivative using recurrence (single precision)
extern MTS_EXPORT_CORE std::pair<float, float> legendrePD(int l, float x);

View File

@ -84,6 +84,11 @@ template <typename T> struct TQuaternion {
return *this;
}
/// Unary negation operator
TQuaternion operator-() const {
return TQuaternion(-v, -w);
}
/// Multiply the quaternion by the given scalar and return the result
TQuaternion operator*(T f) const {
return TQuaternion(v*f, w*f);
@ -132,12 +137,17 @@ template <typename T> struct TQuaternion {
/// Equality test
bool operator==(const TQuaternion &q) const {
return v == q.v && v.w == q.w;
return v == q.v && w == q.w;
}
/// Inequality test
bool operator!=(const TQuaternion &q) const {
return v != q.v || v.w != q.w;
return v != q.v || w != q.w;
}
/// Identity test
bool isIdentity() const {
return v.isZero() && w == 1;
}
/// Return the rotation axis of this quaternion
@ -216,39 +226,41 @@ template <typename T> struct TQuaternion {
}
}
inline static TQuaternion fromTransform(const Transform &trafo) {
return fromMatrix(trafo.getMatrix());
}
/**
* \brief Construct an unit quaternion matching the supplied
* rotation matrix.
*/
static TQuaternion fromTransform(const Transform trafo) {
/// Implementation from PBRT
const Matrix4x4 &m = trafo.getMatrix();
T trace = m.m[0][0] + m.m[1][1] + m.m[2][2];
static TQuaternion fromMatrix(const Matrix4x4 &m) {
// Implementation from PBRT, originally based on the matrix
// and quaternion FAQ (http://www.j3d.org/matrix_faq/matrfaq_latest.html)
T trace = m(0, 0) + m(1, 1) + m(2, 2);
TVector3<T> v; T w;
if (trace > 0.f) {
// Compute w from matrix trace, then xyz
// 4w^2 = m[0][0] + m[1][1] + m[2][2] + m[3][3] (but m[3][3] == 1)
if (trace > Epsilon) {
T s = std::sqrt(trace + 1.0f);
w = s / 2.0f;
w = s * 0.5f;
s = 0.5f / s;
v.x = (m.m[2][1] - m.m[1][2]) * s;
v.y = (m.m[0][2] - m.m[2][0]) * s;
v.z = (m.m[1][0] - m.m[0][1]) * s;
v.x = (m(2, 1) - m(1, 2)) * s;
v.y = (m(0, 2) - m(2, 0)) * s;
v.z = (m(1, 0) - m(0, 1)) * s;
} else {
// Compute largest of $x$, $y$, or $z$, then remaining components
const int nxt[3] = {1, 2, 0};
T q[3];
int i = 0;
if (m.m[1][1] > m.m[0][0]) i = 1;
if (m.m[2][2] > m.m[i][i]) i = 2;
if (m(1, 1) > m(0, 0)) i = 1;
if (m(2, 2) > m(i, i)) i = 2;
int j = nxt[i];
int k = nxt[j];
T s = std::sqrt((m.m[i][i] - (m.m[j][j] + m.m[k][k])) + 1.0);
T s = std::sqrt((m(i, i) - (m(j, j) + m(k, k))) + 1.0f);
q[i] = s * 0.5f;
if (s != 0.f) s = 0.5f / s;
w = (m.m[k][j] - m.m[j][k]) * s;
q[j] = (m.m[j][i] + m.m[i][j]) * s;
q[k] = (m.m[k][i] + m.m[i][k]) * s;
w = (m(k, j) - m(j, k)) * s;
q[j] = (m(j, i) + m(i, j)) * s;
q[k] = (m(k, i) + m(i, k)) * s;
v.x = q[0];
v.y = q[1];
v.z = q[2];
@ -342,8 +354,15 @@ template <typename T> inline TQuaternion<T> normalize(const TQuaternion<T> &q) {
}
template <typename T> inline TQuaternion<T> slerp(const TQuaternion<T> &q1,
const TQuaternion<T> &q2, Float t) {
const TQuaternion<T> &_q2, Float t) {
TQuaternion<T> q2(_q2);
T cosTheta = dot(q1, q2);
if (cosTheta < 0) {
/* Take the short way! */
q2 = -q2;
cosTheta = -cosTheta;
}
if (cosTheta > .9995f) {
// Revert to plain linear interpolation
return normalize(q1 * (1.0f - t) + q2 * t);

View File

@ -417,8 +417,10 @@ public:
*
* Note that the resource's won't be removed until all processes using
* it have terminated)
*
* \return \c false if the resource could not be found
*/
void unregisterResource(int id);
bool unregisterResource(int id);
/**
* \brief Return the ID of a registered resource

View File

@ -21,6 +21,7 @@
#define __MITSUBA_CORE_SHVECTOR_H_
#include <mitsuba/mitsuba.h>
#include <mitsuba/core/quad.h>
#include <boost/numeric/ublas/matrix.hpp>
#include <numeric>
@ -273,12 +274,12 @@ public:
for (int l=0; l<m_bands; ++l) {
for (int m=1; m<=l; ++m) {
Float L = legendre(l, m, cosTheta) * normalization(l, m);
Float L = legendreP(l, m, cosTheta) * normalization(l, m);
operator()(l, -m) += value * SQRT_TWO * sinPhi[m-1] * L;
operator()(l, m) += value * SQRT_TWO * cosPhi[m-1] * L;
}
operator()(l, 0) += value * legendre(l, 0, cosTheta) * normalization(l, 0);
operator()(l, 0) += value * legendreP(l, 0, cosTheta) * normalization(l, 0);
}
}
}
@ -321,9 +322,6 @@ public:
return error/denom;
}
/// Evaluate an associated Legendre polynomial using the usual recurrence formulae
static Float legendre(int l, int m, Float x);
/// Return a normalization coefficient
inline static Float normalization(int l, int m) {
if (l < SH_NORMTBL_SIZE)

View File

@ -440,7 +440,7 @@ public:
/// Divide by a scalar
inline friend TSpectrum operator/(Scalar f, TSpectrum &spec) {
return spec / f;
return TSpectrum(f) / spec;
}
/// Divide by a scalar
@ -493,6 +493,14 @@ public:
return value;
}
/// Component-wise square root
inline TSpectrum safe_sqrt() const {
TSpectrum value;
for (int i=0; i<N; i++)
value.s[i] = math::safe_sqrt(s[i]);
return value;
}
/// Component-wise exponentation
inline TSpectrum exp() const {
TSpectrum value;
@ -710,7 +718,7 @@ public:
/**
* \brief Convert XYZ tristimulus into a plausible spectral
* power distribution
* reflectance or spectral power distribution
*
* The \ref EConversionIntent parameter can be used to provide more
* information on how to solve this highly under-constrained problem.
@ -719,6 +727,34 @@ public:
void fromXYZ(Float x, Float y, Float z,
EConversionIntent intent = EReflectance);
/**
* \brief Convert from a spectral power distribution to
* the perceptually uniform IPT color space by Ebner and Fairchild
*
* This is useful e.g. for computing color differences.
* \c I encodes intensity, \c P (protan) roughly encodes
* red-green color opponency, and \c T (tritan) encodes
* blue-red color opponency. For normalized input, the
* range of attainable values is given by
* \f I\in $[0,1], P,T\in [-1,1]\f$.
*
* In the Python API, this function returns a 3-tuple
* with the result of the operation.
*/
void toIPT(Float &I, Float &P, Float &T) const;
/**
* \brief Convert a color value represented in the IPT
* space into a plausible spectral reflectance or
* spectral power distribution.
*
* The \ref EConversionIntent parameter can be used to provide more
* information on how to solve this highly under-constrained problem.
* The default is \ref EReflectance.
*/
void fromIPT(Float I, Float P, Float T,
EConversionIntent intent = EReflectance);
#if SPECTRUM_SAMPLES == 3
/**
* \brief Convert to linear RGB

View File

@ -0,0 +1,315 @@
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2012 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/>.
*/
#pragma once
#if !defined(__MITSUBA_CORE_SPLINE_H_)
#define __MITSUBA_CORE_SPLINE_H_
#include <mitsuba/mitsuba.h>
MTS_NAMESPACE_BEGIN
/*! \addtogroup libcore */
/*! @{ */
// -----------------------------------------------------------------------
//! @{ \name Functions for evaluating and sampling Catmull-Rom splines
// -----------------------------------------------------------------------
/**
* \brief Evaluate a cubic spline interpolant of a uniformly sampled 1D function
*
* This implementation relies on Catmull-Rom splines, i.e. it uses finite
* differences to approximate the derivatives at the endpoints of each spline
* segment.
*
* \param x
* Evaluation point
* \param values
* Floating point array containing \c size regularly spaced evaluations
* in the range [\c min,\c max] of the function to be approximated.
* \param size
* Denotes the size of the \c values array
* \param min
* Position of the first knot
* \param max
* Position of the last knot
* \param extrapolate
* Extrapolate values when \c x is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt>
* and \c x lies outside of [\c min, \c max]
*/
extern MTS_EXPORT_CORE Float evalCubicInterp1D(Float x, const Float *values,
size_t size, Float min, Float max, bool extrapolate = false);
/**
* \brief Evaluate a cubic spline interpolant of a \a nonuniformly sampled 1D function
*
* This implementation relies on Catmull-Rom splines, i.e. it uses finite
* differences to approximate the derivatives at the endpoints of each spline
* segment.
*
* \param x
* Evaluation point
* \param nodes
* Floating point array containing \c size nonuniformly spaced values
* denoting positions the where the function to be interpolated was evaluated.
* They must be provided in \a increasing order.
* \param values
* Floating point array containing function evaluations matched to
* the entries of \c nodes.
* \param size
* Denotes the size of the \c values array
* \param extrapolate
* Extrapolate values when \c x is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt>
* and \c x lies outside of \a [\c min, \c max]
*/
extern MTS_EXPORT_CORE Float evalCubicInterp1DN(Float x, const Float *nodes,
const Float *values, size_t size, bool extrapolate = false);
/**
* \brief Computes the definite integral over a segment of a uniformly
* sampled 1D Catmull-Rom spline interpolant
*
* This is useful for sampling spline segments as part of an importance
* sampling scheme (in conjunction with \ref sampleCubicInterp1D)
*
* \param idx
* Denotes the desires spline segment (must be between 0 and size-2)
* \param values
* Floating point array containing \c size regularly spaced evaluations
* in the range [\c min,\c max] of the function to be approximated.
* \param size
* Denotes the size of the \c values array
* \param min
* Position of the first knot
* \param max
* Position of the last knot
* \return
* The definite integral over the specified segment
*/
extern MTS_EXPORT_CORE Float integrateCubicInterp1D(size_t idx,
const Float *values, size_t size, Float min, Float max);
/**
* \brief Computes the definite integral over a segment of a \a nonuniformly
* sampled 1D Catmull-Rom spline interpolant
*
* This is useful for sampling spline segments as part of an importance
* sampling scheme (in conjunction with \ref sampleCubicInterp1D)
*
* \param idx
* Denotes the desires spline segment (must be between 0 and size-2)
* \param nodes
* Floating point array containing \c size nonuniformly spaced values
* denoting positions the where the function to be interpolated was evaluated.
* They must be provided in \a increasing order.
* \param values
* Floating point array containing function evaluations matched to
* the entries of \c nodes.
* \param size
* Denotes the size of the \c values array
* \return
* The definite integral over the specified segment
*/
extern MTS_EXPORT_CORE Float integrateCubicInterp1DN(size_t idx,
const Float *nodes, const Float *values, size_t size);
/**
* \brief Importance sample a segment of a uniformly sampled 1D Catmull-Rom
* spline interpolant
*
* \param idx
* Denotes the desires spline segment (must be between 0 and size-2)
* \param values
* Floating point array containing \c size regularly spaced evaluations
* in the range [\c min,\c max] of the function to be approximated.
* \param size
* Denotes the size of the \c values array
* \param min
* Position of the first knot
* \param max
* Position of the last knot
* \param sample
* A uniformly distributed random sample in the interval <tt>[0,1]</tt>
* \param fval
* If set to a non-NULL pointer, this argument will be used to return
* the value of the spline at the sampled position
* \return
* The sampled position
*/
extern MTS_EXPORT_CORE Float sampleCubicInterp1D(size_t idx, Float *values,
size_t size, Float min, Float max, Float sample, Float *fval = NULL);
/**
* \brief Importance sample a segment of a \a nonuniformly sampled 1D Catmull-Rom
* spline interpolant
*
* \param idx
* Denotes the desires spline segment (must be between 0 and size-2)
* \param nodes
* Floating point array containing \c size nonuniformly spaced values
* denoting positions the where the function to be interpolated was evaluated.
* They must be provided in \a increasing order.
* \param values
* Floating point array containing function evaluations matched to
* the entries of \c nodes.
* \param size
* Denotes the size of the \c values array
* \param sample
* A uniformly distributed random sample in the interval <tt>[0,1]</tt>
* \param fval
* If set to a non-NULL pointer, this argument will be used to return
* the value of the spline at the sampled position
* \return
* The sampled position
*/
extern MTS_EXPORT_CORE Float sampleCubicInterp1DN(size_t idx, Float *nodes,
Float *values, size_t size, Float sample, Float *fval = NULL);
/**
* \brief Evaluate a cubic spline interpolant of a uniformly sampled 2D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* patch.
*
* \param p
* Evaluation point
* \param values
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing regularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate.
* \param size
* Denotes the size of the \c values array (along each dimension)
* \param min
* Position of the first knot on each dimension
* \param max
* Position of the last knot on each dimension
* \param extrapolate
* Extrapolate values when \c p is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float evalCubicInterp2D(const Point2 &p, const Float *values,
const Size2 &size, const Point2 &min, const Point2 &max, bool extrapolate = false);
/**
* \brief Evaluate a cubic spline interpolant of a \a nonuniformly sampled 2D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* When the underlying function is sampled on a regular grid, \ref evalCubicInterp2D()
* should be preferred, since value lookups will be considerably faster.
*
* \param p
* Evaluation point
* \param nodes
* Pointer to a list for each dimension denoting the positions where the function
* to be interpolated was evaluated. The <tt>i</tt>-th array must have
* size <tt>size[i]</tt> and contain position values in \a increasing order.
* \param values
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing nonuniformly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate.
* \param size
* Denotes the size of the \c values array (along each dimension)
* \param extrapolate
* Extrapolate values when \c p is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float evalCubicInterp2DN(const Point2 &p, const Float **nodes,
const Float *values, const Size2 &size, bool extrapolate = false);
/**
* \brief Evaluate a cubic spline interpolant of a uniformly sampled 3D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* \param p
* Evaluation point of the interpolant
* \param values
* A 3D floating point array of <tt>size.x*size.y*size.z</tt> cells containing regularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate,
* then 'y', and finally 'z' increments.
* \param size
* Denotes the size of the \c values array (along each dimension)
* \param min
* Position of the first knot on each dimension
* \param max
* Position of the last knot on each dimension
* \param extrapolate
* Extrapolate values when \c p is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float evalCubicInterp3D(const Point3 &p, const Float *values,
const Size3 &size, const Point3 &min, const Point3 &max, bool extrapolate = false);
/**
* \brief Evaluate a cubic spline interpolant of a \a nonuniformly sampled 3D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* When the underlying function is sampled on a regular grid, \ref evalCubicInterp3D()
* should be preferred, since value lookups will be considerably faster.
*
* \param p
* Evaluation point
* \param nodes
* Pointer to a list for each dimension denoting the positions where the function
* to be interpolated was evaluated. The <tt>i</tt>-th array must have
* size <tt>size[i]</tt> and contain position values in \a increasing order.
* \param values
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing nonuniformly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate,
* then 'y', and finally 'z' increments.
* \param size
* Denotes the size of the \c values array (along each dimension)
* \param extrapolate
* Extrapolate values when \c p is out of range? (default: \c false)
* \return
* The interpolated value or zero when <tt>extrapolate=false</tt>tt> and
* \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float evalCubicInterp3DN(const Point3 &p, const Float **nodes,
const Float *values, const Size3 &size, bool extrapolate = false);
//! @}
// -----------------------------------------------------------------------
/*! @} */
MTS_NAMESPACE_END
#endif /* __MITSUBA_CORE_SPLINE_H_ */

View File

@ -153,30 +153,60 @@ public:
/// Write an array of signed shorts (16 bit) to the stream
void writeShortArray(const short *values, size_t size);
/// Write an array of known size of signed shorts (16 bit) to the stream
template <size_t N>
inline void writeShortArray(const short (&values)[N]) {
writeShortArray(&values[0], N);
}
/// Write an unsigned short (16 bit) to the stream
void writeUShort(unsigned short value);
/// Write an array of unsigned shorts (16 bit) to the stream
void writeUShortArray(const unsigned short *values, size_t size);
/// Write an array of known size of unsigned shorts (16 bit) to the stream
template <size_t N>
inline void writeUShortArray(const unsigned short (&values)[N]) {
writeUShortArray(&values[0], N);
}
/// Write a signed int (32 bit) to the stream
void writeInt(int value);
/// Write an array of signed ints (32 bit) to the stream
void writeIntArray(const int *values, size_t size);
/// Write an array of known size of signed ints (32 bit) to the stream
template <size_t N>
inline void writeIntArray(const int (&values)[N]) {
writeIntArray(&values[0], N);
}
/// Write an unsigned int (32 bit) to the stream
void writeUInt(unsigned int value);
/// Write an array of unsigned ints (32 bit) to the stream
void writeUIntArray(const unsigned int *values, size_t size);
/// Write a signed int (32 bit) to the stream
/// Write an array of known size of unsigned ints (32 bit) to the stream
template <size_t N>
inline void writeUIntArray(const unsigned int (&values)[N]) {
writeUIntArray(&values[0], N);
}
/// Write a signed int (64 bit) to the stream
void writeLong(int64_t value);
/// Write an array of signed ints (64 bit) to the stream
void writeLongArray(const int64_t *values, size_t size);
/// Write an array of known size of signed ints (64 bit) to the stream
template <size_t N>
inline void writeLongArray(const int64_t (&values)[N]) {
writeLongArray(&values[0], N);
}
/// Write an unsigned int (64 bit) to the stream
void writeULong(uint64_t value);
@ -186,6 +216,12 @@ public:
/// Write an array of unsigned ints (64 bit) to the stream
void writeULongArray(const uint64_t *values, size_t size);
/// Write an array of known size of unsigned ints (64 bit) to the stream
template <size_t N>
inline void writeULongArray(const uint64_t (&values)[N]) {
writeULongArray(&values[0], N);
}
/// Write a signed character (8 bit) to the stream
void writeChar(char value);
@ -195,24 +231,42 @@ public:
/// Write a boolean (8 bit) to the stream
inline void writeBool(bool value) { writeUChar(value); }
/// Write a half-precision halfing point number (16 bit) to the stream
/// Write a half-precision floating point number (16 bit) to the stream
void writeHalf(half value);
/// Write a half-precision halfing point array (16 bit) to the stream
/// Write a half-precision floating point array (16 bit) to the stream
void writeHalfArray(const half *data, size_t size);
/// Write a known size half-precision floating point array (16 bit) to the stream
template <size_t N>
inline void writeHalfArray(const half (&values)[N]) {
writeHalfArray(&values[0], N);
}
/// Write a single-precision floating point number (32 bit) to the stream
void writeSingle(float value);
/// Write a single-precision floating point array (32 bit) to the stream
void writeSingleArray(const float *data, size_t size);
/// Write a known size single-precision floating point array (32 bit) to the stream
template <size_t N>
inline void writeSingleArray(const float (&values)[N]) {
writeSingleArray(&values[0], N);
}
/// Write a double-precision floating point number (64 bit) to the stream
void writeDouble(double value);
/// Write a double-precision floating point array (64 bit) to the stream
void writeDoubleArray(const double *data, size_t size);
/// Write a known size double-precision floating point array (64 bit) to the stream
template <size_t N>
inline void writeDoubleArray(const double (&values)[N]) {
writeDoubleArray(&values[0], N);
}
/// Write a floating point number (configured precision) to the stream
inline void writeFloat(Float value) {
#ifdef SINGLE_PRECISION
@ -231,6 +285,12 @@ public:
#endif
}
/// Write a known size array of floating point values (configured precision) to the stream
template <size_t N>
inline void writeFloatArray(const Float (&values)[N]) {
writeFloatArray(&values[0], N);
}
/// Return whether we are at the end of the stream
bool isEOF() const;
@ -246,30 +306,60 @@ public:
/// Read an array of signed shorts (16 bit) from the stream
void readShortArray(short *dest, size_t size);
/// Read an array of known size of signed shorts (16 bit) from the stream
template <size_t N>
inline void readShortArray(short (&values)[N]) {
readShortArray(&values[0], N);
}
/// Read an unsigned short (16 bit) from the stream
unsigned short readUShort();
/// Read an array of unsigned shorts (16 bit) from the stream
void readUShortArray(unsigned short *dest, size_t size);
/// Read an array of known size of unsigned shorts (16 bit) from the stream
template <size_t N>
inline void readUShortArray(short (&values)[N]) {
readUShortArray(&values[0], N);
}
/// Read a signed int (32 bit) from the stream
int readInt();
/// Read an array of signed ints (32 bit) from the stream
void readIntArray(int *dst, size_t size);
/// Read an array of known size of signed ints (32 bit) from the stream
template <size_t N>
inline void readIntArray(int (&values)[N]) {
readIntArray(&values[0], N);
}
/// Read an unsigned int (32 bit) from the stream
unsigned int readUInt();
/// Read an array of unsigned ints (32 bit) from the stream
void readUIntArray(unsigned int *dest, size_t size);
/// Read an array of known size of unsigned ints (32 bit) from the stream
template <size_t N>
inline void readUIntArray(int (&values)[N]) {
readUIntArray(&values[0], N);
}
/// Read a signed int (64 bit) from the stream
int64_t readLong();
/// Read an array of signed ints (64 bit) from the stream
void readLongArray(int64_t *dst, size_t size);
/// Read an array of known size of signed ints (64 bit) from the stream
template <size_t N>
inline void readLongArray(int64_t (&values)[N]) {
readLongArray(&values[0], N);
}
/// Read an unsigned int (64 bit) from the stream
uint64_t readULong();
@ -279,6 +369,12 @@ public:
/// Read an array of unsigned ints (64 bit) from the stream
void readULongArray(uint64_t *dst, size_t size);
/// Read an array of known size of unsigned ints (64 bit) from the stream
template <size_t N>
inline void readULongArray(uint64_t (&values)[N]) {
readULongArray(&values[0], N);
}
/// Read a signed character (8 bit) from the stream
char readChar();
@ -288,24 +384,42 @@ public:
/// Read a boolean (8 bit) from the stream
inline bool readBool() { return static_cast<bool> (readUChar()); }
/// Read a half-precision halfing point number (16 bit) from the stream
/// Read a half-precision floating point number (16 bit) from the stream
half readHalf();
/// Read a half-precision halfing point array (16 bit) from the stream
/// Read a half-precision floating point array (16 bit) from the stream
void readHalfArray(half *data, size_t size);
/// Read a known-size half-precision floating point array (16 bit) from the stream
template <size_t N>
inline void readHalfArray(half (&values)[N]) {
readHalfArray(&values[0], N);
}
/// Read a single-precision floating point number (32 bit) from the stream
float readSingle();
/// Read a single-precision floating point array (32 bit) from the stream
void readSingleArray(float *data, size_t size);
/// Read a known-size single-precision floating point array (32 bit) from the stream
template <size_t N>
inline void readSingleArray(float (&values)[N]) {
readSingleArray(&values[0], N);
}
/// 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 *data, size_t size);
/// Read a known-size double-precision floating point array (64 bit) from the stream
template <size_t N>
inline void readDoubleArray(double (&values)[N]) {
readDoubleArray(&values[0], N);
}
/// Write a floating point number (configured precision) to the stream
inline Float readFloat() {
#ifdef SINGLE_PRECISION
@ -324,6 +438,12 @@ public:
#endif
}
/// Read a known-size array of floating point values (configured precision) to the stream
template <size_t N>
inline void readFloatArray(Float (&values)[N]) {
readFloatArray(&values[0], N);
}
/**
* \brief Copy content from this stream into another stream
* \param stream Destination stream
@ -351,12 +471,28 @@ public:
*/
template <typename T> void readArray(T *array, size_t count);
/**
* \brief Read a known-size array from the stream (uses partial template
* specialization to select a method appropriate to the data type)
*/
template <typename T, size_t N> inline void readArray(T (&arr)[N]) {
readArray(&arr[0], N);
}
/**
* \brief Write an array to the stream (uses partial template
* specialization to select a method appropriate to the data type)
*/
template <typename T> void writeArray(const T *array, size_t count);
/**
* \brief Write a known-size array to the stream (uses partial template
* specialization to select a method appropriate to the data type)
*/
template <typename T, size_t N> inline void writeArray(const T (&arr)[N]) {
writeArray(&arr[0], N);
}
//! @}
MTS_DECLARE_CLASS()

View File

@ -185,6 +185,9 @@ extern MTS_EXPORT_CORE int mts_omp_get_thread_num();
#define mts_omp_get_max_threads omp_get_max_threads
#define mts_omp_get_thread_num omp_get_thread_num
#endif
#else
#define mts_omp_get_max_threads() 1
#define mts_omp_get_thread_num() 0
#endif
MTS_NAMESPACE_END

View File

@ -141,7 +141,8 @@ protected:
}
inline static void destruct(void *data) {
delete static_cast<ValueType *>(data);
if (data)
delete static_cast<ValueType *>(data);
}
protected:
detail::ThreadLocalBase m_base;

View File

@ -17,11 +17,12 @@
*/
#pragma once
#if !defined(__MITSUBA_RENDER_TRACK_H_)
#define __MITSUBA_RENDER_TRACK_H_
#if !defined(__MITSUBA_CORE_TRACK_H_)
#define __MITSUBA_CORE_TRACK_H_
#include <mitsuba/core/quat.h>
#include <mitsuba/core/simplecache.h>
#include <set>
MTS_NAMESPACE_BEGIN
@ -31,7 +32,7 @@ template <typename T> class AnimationTrack;
* \brief Base class of animation tracks
* \ingroup librender
*/
class MTS_EXPORT_RENDER AbstractAnimationTrack : public Object {
class MTS_EXPORT_CORE AbstractAnimationTrack : public Object {
template<typename T> friend class AnimationTrack;
public:
enum EType {
@ -65,6 +66,9 @@ public:
/// Serialize to a binary data stream
virtual void serialize(Stream *stream) const = 0;
/// Clone this track
virtual AbstractAnimationTrack *clone() const = 0;
MTS_DECLARE_CLASS()
protected:
AbstractAnimationTrack(EType type, size_t nKeyframes)
@ -82,9 +86,9 @@ protected:
*/
template <typename T> class AnimationTrack : public AbstractAnimationTrack {
public:
typedef T value_type;
typedef T ValueType;
AnimationTrack(EType type, size_t nKeyframes)
AnimationTrack(EType type, size_t nKeyframes = 0)
: AbstractAnimationTrack(type, nKeyframes), m_values(nKeyframes) { }
AnimationTrack(EType type, Stream *stream)
@ -95,11 +99,44 @@ public:
unserialize(stream, m_values[i]);
}
/// Copy constructor
AnimationTrack(const AnimationTrack *track)
: AbstractAnimationTrack(track->getType(), track->getSize()) {
m_times = track->m_times;
m_values = track->m_values;
}
/// Set the value of a certain keyframe
inline void setValue(size_t idx, const value_type &value) { m_values[idx] = value; }
inline void setValue(size_t idx, const ValueType &value) { m_values[idx] = value; }
/// Return the value of a certain keyframe
inline const value_type &getValue(size_t idx) const { return m_values[idx]; }
inline const ValueType &getValue(size_t idx) const { return m_values[idx]; }
/// Reserve space for a certain number of entries
inline void reserve(size_t count) { m_times.reserve(count); m_values.reserve(count); }
/// Append a value
inline void append(Float time, const ValueType &value) {
m_times.push_back(time);
m_values.push_back(value);
}
/// Clone this instance
AbstractAnimationTrack *clone() const {
return new AnimationTrack(this);
}
/// Prepend a transformation to every entry of this track
void prependTransformation(const ValueType &value) {
for (size_t i=0; i<m_values.size(); ++i)
m_values[i] = concatenateTransformations(m_values[i], value);
}
/// Append a transformation to every entry of this track
void appendTransformation(const ValueType &value) {
for (size_t i=0; i<m_values.size(); ++i)
m_values[i] = concatenateTransformations(value, m_values[i]);
}
/// Serialize to a binary data stream
inline void serialize(Stream *stream) const {
@ -111,7 +148,7 @@ public:
}
/// Evaluate the animation track at an arbitrary time value
inline value_type eval(Float time) const {
inline ValueType eval(Float time) const {
SAssert(m_times.size() > 0);
std::vector<Float>::const_iterator entry =
std::lower_bound(m_times.begin(), m_times.end(), time);
@ -126,19 +163,84 @@ public:
}
return lerp(idx0, idx1, t);
}
private:
struct SortPredicate {
inline bool operator()(const std::pair<Float, ValueType> &p1,
const std::pair<Float, ValueType> &p2) const {
return p1.first < p2.first;
}
};
struct UniqueTimePredicate {
inline bool operator()(const std::pair<Float, ValueType> &p1,
const std::pair<Float, ValueType> &p2) const {
return p1.first == p2.first;
}
};
public:
/**
* \brief Sort all animation tracks and remove
* unnecessary data (for user-provided input)
*
* \return \c false if this animation track was deemed to be "trivial"
* after the cleanup (for instance, it only contains (0,0,0) translation operations)
*/
bool sortAndSimplify() {
SAssert(m_values.size() == m_times.size());
if (m_values.size() == 0)
return false;
std::vector< std::pair<Float, ValueType> > temp(m_values.size());
for (size_t i=0; i<m_values.size(); ++i)
temp[i] = std::make_pair(m_times[i], m_values[i]);
std::sort(temp.begin(), temp.end(), SortPredicate());
m_times.clear(); m_values.clear();
m_times.push_back(temp[0].first);
m_values.push_back(temp[0].second);
for (size_t i=1; i<temp.size(); ++i) {
Float time = temp[i].first;
const ValueType &value = temp[i].second;
if (m_times.back() == time)
SLog(EError, "Duplicate time value in animated transformation!");
/* Ignore irrelevant keys */
if (i+1 < temp.size() && value == temp[i+1].second &&
value == m_values.back())
continue;
else if (i+1 == temp.size() && value == m_values.back())
continue;
m_times.push_back(time);
m_values.push_back(value);
}
return !(m_values.size() == 0 || (m_values.size() == 1 && isNoOp(m_values[0])));
}
protected:
/// Evaluate the animation track using linear interpolation
inline value_type lerp(size_t idx0, size_t idx1, Float t) const;
inline ValueType lerp(size_t idx0, size_t idx1, Float t) const;
inline void unserialize(Stream *stream, value_type &value) {
value = stream->readElement<value_type>();
/// Is this a "no-op" transformation?
inline bool isNoOp(const ValueType &value) const;
/// Concatenate two transformations
inline ValueType concatenateTransformations(
const ValueType &value1, const ValueType &value2) const;
inline void unserialize(Stream *stream, ValueType &value) {
value = stream->readElement<ValueType>();
}
inline void serialize(Stream *stream, const value_type &value) const {
stream->writeElement<value_type>(value);
inline void serialize(Stream *stream, const ValueType &value) const {
stream->writeElement<ValueType>(value);
}
private:
std::vector<value_type> m_values;
std::vector<ValueType> m_values;
};
template<typename T> inline T AnimationTrack<T>::lerp(size_t idx0, size_t idx1, Float t) const {
@ -150,6 +252,58 @@ template<> inline Quaternion AnimationTrack<Quaternion>::lerp(size_t idx0, size_
return slerp(m_values[idx0], m_values[idx1], t);
}
template<typename T> inline T AnimationTrack<T>::concatenateTransformations(
const T &value1, const T &value2) const {
return value1 * value2;
}
template<> inline Vector AnimationTrack<Vector>::concatenateTransformations(
const Vector &value1, const Vector &value2) const {
if (m_type == ETranslationXYZ)
return value1 + value2;
else
return Vector(value1.x * value2.x, value1.y * value2.y, value1.z * value2.z);
}
template<> inline Point AnimationTrack<Point>::concatenateTransformations(
const Point &value1, const Point &value2) const {
return value1 + value2;
}
template<> inline Float AnimationTrack<Float>::concatenateTransformations(
const Float &value1, const Float &value2) const {
if (m_type == ETranslationX || m_type == ETranslationY || m_type == ETranslationZ)
return value1 + value2;
else
return value1 * value2;
}
template<typename T> inline bool AnimationTrack<T>::isNoOp(const ValueType &value) const {
return false;
}
template<> inline bool AnimationTrack<Float>::isNoOp(const Float &value) const {
if ((m_type == ETranslationX || m_type == ETranslationY || m_type == ETranslationZ) && value == 0)
return true;
else if ((m_type == ERotationX || m_type == ERotationY || m_type == ERotationZ) && value == 0)
return true;
else if ((m_type == EScaleX || m_type == EScaleY || m_type == EScaleZ) && value == 1)
return true;
return false;
}
template<> inline bool AnimationTrack<Vector>::isNoOp(const Vector &value) const {
if (m_type == ETranslationXYZ && value.isZero())
return true;
else if (m_type == EScaleXYZ && (value.x == 1 && value.y == 1 && value.z == 1))
return true;
return false;
}
template<> inline bool AnimationTrack<Quaternion>::isNoOp(const Quaternion &value) const {
return value.isIdentity();
}
template<> inline void AnimationTrack<Point>::unserialize(Stream *stream, Point &value) {
value = Point(stream);
}
@ -178,10 +332,10 @@ template<> inline void AnimationTrack<Quaternion>::serialize(Stream *stream, con
* \brief Animated transformation with an underlying keyframe representation
* \ingroup librender
*/
class MTS_EXPORT_RENDER AnimatedTransform : public Object {
protected:
class MTS_EXPORT_CORE AnimatedTransform : public Object {
private:
/// Internal functor used by \ref eval() and \ref SimpleCache
struct MTS_EXPORT_RENDER TransformFunctor {
struct MTS_EXPORT_CORE TransformFunctor {
public:
inline TransformFunctor(const std::vector<AbstractAnimationTrack *> &tracks)
: m_tracks(tracks) {}
@ -204,15 +358,40 @@ public:
/// Unserialized an animated transformation from a binary data stream
AnimatedTransform(Stream *stream);
/// Copy constructor
AnimatedTransform(const AnimatedTransform *trafo);
/// Return the number of associated animation tracks
inline size_t getTrackCount() const { return m_tracks.size(); }
/// Find a track of the given type
AbstractAnimationTrack *findTrack(AbstractAnimationTrack::EType type);
/// Find a track of the given type
const AbstractAnimationTrack *findTrack(AbstractAnimationTrack::EType type) const;
/// Look up one of the tracks by index
inline AbstractAnimationTrack *getTrack(size_t idx) { return m_tracks[idx]; }
/// Look up one of the tracks by index (const version)
inline const AbstractAnimationTrack *getTrack(size_t idx) const { return m_tracks[idx]; }
/// Return the used keyframes as a set
void collectKeyframes(std::set<Float> &result) const;
/// Append an animation track
void addTrack(AbstractAnimationTrack *track);
/**
* \brief Convenience function, which appends a linear transformation to the track
*
* Internally, a polar decomposition is used to split the transformation into scale,
* translation, and rotation, which are all separately interpolated.
*
* \remark Remember to run \ref sortAndSimplify() after adding all transformations.
*/
void appendTransform(Float time, const Transform &trafo);
/**
* \brief Compute the transformation for the specified time value
*
@ -221,7 +400,7 @@ public:
* to this function.
*/
inline const Transform &eval(Float t) const {
if (m_tracks.size() == 0)
if (EXPECT_TAKEN(m_tracks.size() == 0))
return m_transform;
else
return m_cache.get(TransformFunctor(m_tracks), t);
@ -230,6 +409,12 @@ public:
/// Is the animation static?
inline bool isStatic() const { return m_tracks.size() == 0; }
/**
* \brief Sort all animation tracks and remove unnecessary
* data (for user-provided input)
*/
void sortAndSimplify();
/// Transform a point by an affine / non-projective matrix
inline Point transformAffine(Float t, const Point &p) const {
return eval(t).transformAffine(p);
@ -290,6 +475,9 @@ public:
eval(t).operator()(r, dest);
}
/// Prepend a scale transformation to the transform (this is often useful)
void prependScale(const Vector &scale);
/// Serialize to a binary data stream
void serialize(Stream *stream) const;
@ -317,4 +505,4 @@ private:
MTS_NAMESPACE_END
#endif /* __MITSUBA_RENDER_TRACK_H_ */
#endif /* __MITSUBA_CORE_TRACK_H_ */

View File

@ -393,6 +393,16 @@ public:
m_invTransform.serialize(stream);
}
/// Equality comparison operator
inline bool operator==(const Transform &trafo) const {
return m_transform == trafo.m_transform;
}
/// Inequality comparison operator
inline bool operator!=(const Transform &trafo) const {
return m_transform != trafo.m_transform;
}
/// Return a string representation
std::string toString() const;
private:

View File

@ -58,9 +58,10 @@ struct MTS_EXPORT_CORE Triangle {
*/
AABB getClippedAABB(const Point *positions, const AABB &aabb) const;
/// Uniformly sample a point on the triangle and return its normal
/// Uniformly sample a point on the triangle and return its normal and UV coordinates
Point sample(const Point *positions, const Normal *normals,
Normal &n, const Point2 &seed) const;
const Point2 *texCoords, Normal &n, Point2 &uv,
const Point2 &seed) const;
/// Calculate the surface area of this triangle
Float surfaceArea(const Point *positions) const;

View File

@ -58,7 +58,7 @@ extern MTS_EXPORT_CORE std::string formatString(const char *pFmt, ...);
extern MTS_EXPORT_CORE std::string timeString(Float time, bool precise = false);
/// Turn a memory size into a human-readable string
extern MTS_EXPORT_CORE std::string memString(size_t size);
extern MTS_EXPORT_CORE std::string memString(size_t size, bool precise = false);
/// Return a string representation of a list of objects
template<class Iterator> std::string containerToString(const Iterator &start, const Iterator &end) {
@ -110,6 +110,9 @@ extern MTS_EXPORT_CORE int getCoreCount();
/// Return the host name of this machine
extern MTS_EXPORT_CORE std::string getHostName();
/// Return the process private memory usage in bytes
extern MTS_EXPORT_CORE size_t getPrivateMemoryUsage();
/// Return the fully qualified domain name of this machine
extern MTS_EXPORT_CORE std::string getFQDN();
@ -172,6 +175,34 @@ static FINLINE uint64_t rdtsc(void) {
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ((uint64_t) lo)| (((uint64_t) hi) << 32);
}
#elif defined(__ARMEL__)
static FINLINE uint64_t rdtsc(void) {
// Code from gperftoos:
// https://code.google.com/p/gperftools/source/browse/trunk/src/base/cycleclock.h
uint32_t pmccntr;
uint32_t pmuseren;
uint32_t pmcntenset;
// Read the user mode perf monitor counter access permissions.
asm volatile ("mrc p15, 0, %0, c9, c14, 0" : "=r" (pmuseren));
if (EXPECT_TAKEN(pmuseren & 1)) { // Allows reading perfmon counters for user mode code.
asm volatile ("mrc p15, 0, %0, c9, c12, 1" : "=r" (pmcntenset));
if (EXPECT_TAKEN(pmcntenset & 0x80000000ul)) { // Is it counting?
asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (pmccntr));
// The counter is set up to count every 64th cycle
return static_cast<uint64_t>(pmccntr) * 64; // Should optimize to << 6
}
}
// Soft-failover, assuming 1.5GHz CPUs
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(_POSIX_CPUTIME)
timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return static_cast<uint64_t>((ts.tv_sec + ts.tv_nsec * 1e-9) * 1.5e9);
#else
timeval tv;
gettimeofday(&tv, NULL);
return static_cast<uint64_t>((tv.tv_sec + tv.tv_usec * 1e-6) * 1.5e9);
#endif
}
#endif
#elif defined(__MSVC__)
static FINLINE __int64 rdtsc(void) {
@ -340,162 +371,6 @@ extern MTS_EXPORT_CORE bool solveQuadratic(Float a, Float b,
extern MTS_EXPORT_CORE bool solveQuadraticDouble(double a, double b,
double c, double &x0, double &x1);
/**
* \brief Evaluate a cubic spline interpolant of a regularly sampled 1D function
*
* This implementation relies on Catmull-Rom splines, i.e. it uses finite
* differences to approximate the derivatives at the endpoints of each spline
* segment.
*
* \param x
* Evaluation point
* \param data
* Floating point array containing \c size regularly spaced evaluations
* in the range [\c min,\c max] of the function to be approximated.
* \param min
* Position of the first knot
* \param max
* Position of the last knot
* \param size
* Denotes the size of the \c data array
* \return
* The interpolated value or zero when \c x lies outside of [\c min, \c max]
*/
extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data,
Float min, Float max, size_t size);
/**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 1D function
*
* This implementation relies on Catmull-Rom splines, i.e. it uses finite
* differences to approximate the derivatives at the endpoints of each spline
* segment.
*
* \param x
* Evaluation point
* \param nodes
* Floating point array containing \c size irregularly spaced values
* denoting positions the where the function to be interpolated was evaluated.
* They must be provided in \a increasing order.
* \param data
* Floating point array containing interpolant values matched to
* the entries of \c nodes.
* \param size
* Denotes the size of the \c data array
* \return
* The interpolated value or zero when \c x lies outside of \a [\c min, \c max]
*/
extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes,
const Float *data, size_t size);
/**
* \brief Evaluate a cubic spline interpolant of a regularly sampled 2D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* patch.
*
* \param p
* Evaluation point
* \param data
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing regularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate.
* \param min
* Position of the first knot on each dimension
* \param max
* Position of the last knot on each dimension
* \param size
* Denotes the size of the \c data array (along each dimension)
* \return
* The interpolated value or zero when \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data,
const Point2 &min, const Point2 &max, const Size2 &size);
/**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 2D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* When the underlying function is sampled on a regular grid, \ref interpCubic2D()
* should be preferred, since data lookups will be considerably faster.
*
* \param p
* Evaluation point
* \param nodes
* Pointer to a list for each dimension denoting the positions where the function
* to be interpolated was evaluated. The <tt>i</tt>-th array must have
* size <tt>size[i]</tt> and contain position values in \a increasing order.
* \param data
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing irregularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate.
* \param size
* Denotes the size of the \c data array (along each dimension)
* \return
* The interpolated value or zero when \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float **nodes,
const Float *data, const Size2 &size);
/**
* \brief Evaluate a cubic spline interpolant of a regularly sampled 3D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* \param p
* Evaluation point of the interpolant
* \param data
* A 3D floating point array of <tt>size.x*size.y*size.z</tt> cells containing regularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate,
* then 'y', and finally 'z' increments.
* \param min
* Position of the first knot on each dimension
* \param max
* Position of the last knot on each dimension
* \param size
* Denotes the size of the \c data array (along each dimension)
* \return
* The interpolated value or zero when \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data,
const Point3 &min, const Point3 &max, const Size3 &size);
/**
* \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 3D function
*
* This implementation relies on a tensor product of Catmull-Rom splines, i.e. it uses
* finite differences to approximate the derivatives at the endpoints of each spline
* region.
*
* When the underlying function is sampled on a regular grid, \ref interpCubic3D()
* should be preferred, since data lookups will be considerably faster.
*
* \param p
* Evaluation point
* \param nodes
* Pointer to a list for each dimension denoting the positions where the function
* to be interpolated was evaluated. The <tt>i</tt>-th array must have
* size <tt>size[i]</tt> and contain position values in \a increasing order.
* \param data
* A 2D floating point array of <tt>size.x*size.y</tt> cells containing irregularly
* spaced evaluations of the function to be interpolated on the domain <tt>[min, max]</tt>.
* Consecutive entries of this array correspond to increments in the 'x' coordinate,
* then 'y', and finally 'z' increments.
* \param size
* Denotes the size of the \c data array (along each dimension)
* \return
* The interpolated value or zero when \c p lies outside of the knot range
*/
extern MTS_EXPORT_CORE Float interpCubic3DIrregular(const Point3 &p, const Float **nodes,
const Float *data, const Size3 &size);
//// Convert radians to degrees
inline Float radToDeg(Float value) { return value * (180.0f / M_PI); }
@ -663,22 +538,99 @@ inline Float fresnelDielectricExt(Float cosThetaI, Float eta) { Float cosThetaT;
return fresnelDielectricExt(cosThetaI, cosThetaT, eta); }
/**
* \brief Calculates the unpolarized fresnel reflection coefficient
* at a planar interface between vacuum and a conductor.
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (approximate scalar version)
*
* The implementation of this function relies on a simplified expression
* that becomes increasingly accurate as k grows.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Real refractive index (wavelength-dependent)
* Relative refractive index (real component)
* \param k
* Imaginary refractive index (wavelength-dependent)
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosThetaI,
extern MTS_EXPORT_CORE Float fresnelConductorApprox(Float cosThetaI,
Float eta, Float k);
/**
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (approximate vectorized version)
*
* The implementation of this function relies on a simplified expression
* that becomes increasingly accurate as k grows.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductorApprox(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/**
* \brief Calculates the diffuse unpolarized fresnel reflectance of
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (accurate scalar version)
*
* The implementation of this function computes the exact unpolarized
* Fresnel reflectance for a complex index of refraction change.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Float fresnelConductorExact(Float cosThetaI,
Float eta, Float k);
/**
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (accurate vectorized version)
*
* The implementation of this function computes the exact unpolarized
* Fresnel reflectance for a complex index of refraction change.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductorExact(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/**
* \brief Calculates the diffuse unpolarized Fresnel reflectance of
* a dielectric material (sometimes referred to as "Fdr").
*
* This value quantifies what fraction of diffuse incident illumination

View File

@ -189,6 +189,13 @@ template <typename T> inline TVector1<T> normalize(const TVector1<T> &v) {
return v / v.length();
}
template <typename T> inline TVector1<T> normalizeStrict(const TVector1<T> &v, const char *errMsg) {
Float length = v.length();
if (length == 0)
SLog(EError, "normalizeStrict(): %s", errMsg);
return v / length;
}
template <> inline TVector1<int> TVector1<int>::operator/(int s) const {
#ifdef MTS_DEBUG
if (s == 0)
@ -207,6 +214,27 @@ template <> inline TVector1<int> &TVector1<int>::operator/=(int s) {
return *this;
}
namespace detail {
// Helper structures to define "length" as a floating point value
template <typename T, bool IsInteger = false> struct VectorLength {
typedef T type;
};
template <typename T> struct VectorLength<T, true> {
typedef Float type;
};
template <> struct VectorLength<uint64_t, true> {
typedef double type;
};
template <> struct VectorLength<int64_t, true> {
typedef double type;
};
}
/**
* \headerfile mitsuba/core/vector.h mitsuba/mitsuba.h
* \brief Parameterizable two-dimensional vector data structure
@ -215,6 +243,7 @@ template <> inline TVector1<int> &TVector1<int>::operator/=(int s) {
template <typename T> struct TVector2 {
typedef T Scalar;
typedef TPoint2<T> PointType;
typedef typename detail::VectorLength<T, std::numeric_limits<T>::is_integer>::type LengthType;
T x, y;
@ -331,8 +360,8 @@ template <typename T> struct TVector2 {
}
/// Return the 2-norm of this vector
T length() const {
return std::sqrt(lengthSquared());
LengthType length() const {
return (LengthType) std::sqrt((LengthType) lengthSquared());
}
/// Return whether or not this vector is identically zero
@ -376,10 +405,21 @@ template <typename T> inline T absDot(const TVector2<T> &v1, const TVector2<T> &
return std::abs(dot(v1, v2));
}
template <typename T> inline T det(const TVector2<T> &v1, const TVector2<T> &v2) {
return v1.x * v2.y - v1.y * v2.x;
}
template <typename T> inline TVector2<T> normalize(const TVector2<T> &v) {
return v / v.length();
}
template <typename T> inline TVector2<T> normalizeStrict(const TVector2<T> &v, const char *errMsg) {
Float length = v.length();
if (length == 0)
SLog(EError, "normalizeStrict(): %s", errMsg);
return v / length;
}
template <> inline TVector2<int> TVector2<int>::operator/(int s) const {
#ifdef MTS_DEBUG
if (s == 0)
@ -407,6 +447,7 @@ template <> inline TVector2<int> &TVector2<int>::operator/=(int s) {
template <typename T> struct TVector3 {
typedef T Scalar;
typedef TPoint3<T> PointType;
typedef typename detail::VectorLength<T, std::numeric_limits<T>::is_integer>::type LengthType;
T x, y, z;
@ -524,8 +565,8 @@ template <typename T> struct TVector3 {
}
/// Return the 2-norm of this vector
T length() const {
return std::sqrt(lengthSquared());
LengthType length() const {
return (LengthType) std::sqrt((LengthType) lengthSquared());
}
/// Return whether or not this vector is identically zero
@ -582,6 +623,13 @@ template <typename T> inline TVector3<T> normalize(const TVector3<T> &v) {
return v / v.length();
}
template <typename T> inline TVector3<T> normalizeStrict(const TVector3<T> &v, const char *errMsg) {
Float length = v.length();
if (length == 0)
SLog(EError, "normalizeStrict(): %s", errMsg);
return v / length;
}
template <> inline TVector3<int> TVector3<int>::operator/(int s) const {
#ifdef MTS_DEBUG
if (s == 0)
@ -611,12 +659,12 @@ template <> inline TVector3<int> &TVector3<int>::operator/=(int s) {
template <typename T> struct TVector4 {
typedef T Scalar;
typedef TPoint4<T> PointType;
typedef typename detail::VectorLength<T, std::numeric_limits<T>::is_integer>::type LengthType;
T x, y, z, w;
/// Number of dimensions
const static int dim = 3;
const static int dim = 4;
/** \brief Construct a new vector without initializing it.
*
@ -730,8 +778,8 @@ template <typename T> struct TVector4 {
}
/// Return the 2-norm of this vector
T length() const {
return std::sqrt(lengthSquared());
LengthType length() const {
return (LengthType) std::sqrt((LengthType) lengthSquared());
}
/// Return whether or not this vector is identically zero
@ -781,6 +829,13 @@ template <typename T> inline TVector4<T> normalize(const TVector4<T> &v) {
return v / v.length();
}
template <typename T> inline TVector4<T> normalizeStrict(const TVector4<T> &v, const char *errMsg) {
Float length = v.length();
if (length == 0)
SLog(EError, "normalizeStrict(): %s", errMsg);
return v / length;
}
template <> inline TVector4<int> TVector4<int>::operator/(int s) const {
#ifdef MTS_DEBUG
if (s == 0)

View File

@ -26,13 +26,13 @@ MTS_NAMESPACE_BEGIN
* \brief Current release of Mitsuba
* \ingroup libcore
*/
#define MTS_VERSION "0.4.1"
#define MTS_VERSION "0.4.4"
/**
* \brief Year of the current release
* \ingroup libcore
*/
#define MTS_YEAR "2012"
#define MTS_YEAR "2013"
/**
* \brief A simple data structure for representing and

View File

@ -114,6 +114,12 @@ public:
/// Warp a uniformly distributed square sample to a 2D tent distribution
static Point2 squareToTent(const Point2 &sample);
/**
* \brief Warp a uniformly distributed sample on [0, 1] to a nonuniform
* tent distribution with nodes <tt>{a, b, c}</tt>
*/
static Float intervalToNonuniformTent(Float a, Float b, Float c, Float sample);
//! @}
// =============================================================
};

View File

@ -76,12 +76,22 @@ public:
/// Allocate memory for a certain font
Font(EFont font);
/// Draw text to the specified bitmap
void drawText(Bitmap *dest, Point2i pos, const std::string &text) const;
/// Compute the size covered by the given string when rendered using this font
Vector2i getSize(const std::string &text) const;
/// Upload the font to the GPU
void init(Renderer *renderer);
/// Free the GPU memory
void cleanup();
/// Convert the underlying bitmap to a different pixel format
void convert(Bitmap::EPixelFormat pixelFormat,
Bitmap::EComponentFormat componentFormat, Float gamma);
/// Return the name of this font
inline const std::string &getName() const { return m_name; }

View File

@ -326,11 +326,14 @@ protected:
* number of GPU pipeline flushes. Draw transparent objects last.
*/
struct MaterialOrder {
inline bool operator()(
const Renderer::TransformedGPUGeometry &g1,
const Renderer::TransformedGPUGeometry &g2) const {
const Shader *shader1 = g1.first->getShader();
const Shader *shader2 = g2.first->getShader();
const std::vector<Renderer::TransformedGPUGeometry> &geo;
MaterialOrder(const std::vector<Renderer::TransformedGPUGeometry> &geo)
: geo(geo) { }
inline bool operator()(size_t idx1, size_t idx2) const {
const Shader *shader1 = geo[idx1].first->getShader();
const Shader *shader2 = geo[idx2].first->getShader();
if (shader1 && (shader1->getFlags() & Shader::ETransparent))
shader1 = NULL;
@ -340,6 +343,19 @@ protected:
return shader1 < shader2;
}
};
/// Helper data structure to keep track of shapes that are undergoing keyframe animations
struct AnimatedGeometryRecord {
const AnimatedTransform *trafo;
ssize_t geometryIndex;
ssize_t opaqueGeometryIndex;
AnimatedGeometryRecord(const AnimatedTransform *trafo,
ssize_t geometryIndex, ssize_t opaqueGeometryIndex) :
trafo(trafo), geometryIndex(geometryIndex),
opaqueGeometryIndex(opaqueGeometryIndex) { }
};
MTS_DECLARE_CLASS()
private:
ref<Renderer> m_renderer;
@ -348,6 +364,7 @@ private:
/* On-GPU geometry references */
std::vector<Renderer::TransformedGPUGeometry> m_geometry;
std::vector<Renderer::TransformedGPUGeometry> m_opaqueGeometry;
std::vector<AnimatedGeometryRecord> m_animatedGeometry;
/* Shader & dependency management */
std::map<std::string, VPLConfiguration> m_configurations;

View File

@ -45,7 +45,7 @@ using std::endl;
#include <mitsuba/core/constants.h>
#include <mitsuba/core/fwd.h>
#include <mitsuba/render/fwd.h>
#include <mitsuba/core/stl.h>
#include <mitsuba/core/math.h>
#include <mitsuba/core/object.h>
#include <mitsuba/core/ref.h>
#include <mitsuba/core/tls.h>

View File

@ -21,7 +21,7 @@
#define __MITSUBA_RENDER_EMITTER_H_
#include <mitsuba/render/common.h>
#include <mitsuba/render/track.h>
#include <mitsuba/core/track.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/core/cobject.h>
#include <mitsuba/render/shader.h>
@ -425,7 +425,7 @@ protected:
/// Virtual destructor
virtual ~AbstractEmitter();
protected:
ref<AnimatedTransform> m_worldTransform;
ref<const AnimatedTransform> m_worldTransform;
ref<Medium> m_medium;
Shape *m_shape;
uint32_t m_type;

View File

@ -61,7 +61,7 @@ public:
virtual void setDestinationFile(const fs::path &filename, uint32_t blockSize) = 0;
/// Develop the film and write the result to the previously specified filename
virtual void develop() = 0;
virtual void develop(const Scene *scene, Float renderTime) = 0;
/**
* \brief Develop the contents of a subregion of the film and store
@ -88,6 +88,9 @@ public:
*/
inline bool hasHighQualityEdges() const { return m_highQualityEdges; }
/// Return whether or not this film records the alpha channel
virtual bool hasAlpha() const = 0;
/// Return the image reconstruction filter
inline ReconstructionFilter *getReconstructionFilter() { return m_filter.get(); }

View File

@ -22,13 +22,6 @@
MTS_NAMESPACE_BEGIN
class AbstractAnimationTrack;
template <typename T> class AnimationTrack;
typedef AnimationTrack<Float> FloatTrack;
typedef AnimationTrack<Quaternion> QuatTrack;
typedef AnimationTrack<Vector> VectorTrack;
typedef AnimationTrack<Point> PointTrack;
class AnimatedTransform;
class BlockedImageProcess;
class BlockedRenderProcess;
class BlockListener;

Some files were not shown because too many files have changed in this diff Show More