diff --git a/.hgtags b/.hgtags index 4c18e738..9f9ab9e1 100644 --- a/.hgtags +++ b/.hgtags @@ -7,3 +7,4 @@ cb6e89af8012fac22cc0f3c5ad247c98c701bdda v0.3.0 ee26517b27207353b0c8a7d357bcb4977b5d93fb v0.4.0 7db07694ea00eb1655f7a1adcc3ae880e8e116f9 v0.4.1 13a39b11aceee517c19d2e2cec2e6b875546062c v0.4.2 +f1b73d39617071297167cc7ce96f3892f21105fc v0.4.3 diff --git a/build/mitsuba-msvc2010.vcxproj b/build/mitsuba-msvc2010.vcxproj index 1ee777d5..fb1a61ec 100644 --- a/build/mitsuba-msvc2010.vcxproj +++ b/build/mitsuba-msvc2010.vcxproj @@ -125,13 +125,15 @@ - + - + - + - + + + @@ -203,6 +205,8 @@ + + @@ -287,14 +291,14 @@ + + - - @@ -385,6 +389,8 @@ + + @@ -409,6 +415,8 @@ + + @@ -431,6 +439,8 @@ + + @@ -455,8 +465,6 @@ - - @@ -511,6 +519,8 @@ + + @@ -629,8 +639,6 @@ - - @@ -757,6 +765,8 @@ + + @@ -805,6 +815,10 @@ + + + + @@ -937,6 +951,8 @@ + + @@ -1001,12 +1017,8 @@ - - - - @@ -1021,6 +1033,8 @@ + + @@ -1033,9 +1047,9 @@ - + - + diff --git a/build/mitsuba-msvc2010.vcxproj.filters b/build/mitsuba-msvc2010.vcxproj.filters index 2a0fca14..353385b3 100644 --- a/build/mitsuba-msvc2010.vcxproj.filters +++ b/build/mitsuba-msvc2010.vcxproj.filters @@ -9,136 +9,136 @@ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - {b54fb131-7e86-4e08-bba2-828939a038ff} + {81dd9e3e-7bca-44a1-a313-76fb5af5ab0c} - {62e70ba9-1509-4ecb-9c06-8de3ef48cd47} + {7112f301-f6d5-4351-ae06-4a29910a3766} - {81da027f-f282-46cb-a88d-abc84969dbf8} + {15522c16-64b9-487e-b9fe-dea0094cb5c1} - {8364b08a-50e5-471b-bfaa-4e45915df101} + {4df10a81-6f13-45ae-9a39-ce009db3a659} - {bb52270c-4a49-423b-ad02-4a7c042295c2} + {0c722d61-5189-477d-b242-2fa2ad26c83c} - {c4330c75-0353-41ab-a809-1471f359aec6} + {d849b48a-b61d-4540-81ab-f5228fd6fa93} + + + {32a38ee8-b255-4e23-8efc-9491fc27c645} - {0f1ec875-44fb-46b2-9116-26d659410d97} + {9f6ef52b-2504-4722-a200-7aaa9603088a} - {ab910bc2-a0a5-4f02-8232-396937071149} + {6c49af9f-8cac-477f-825b-ccb368e313c6} - {dff3f942-f016-4bad-aa2c-63c444401a94} + {182aef81-5fdf-4eb1-a7d3-5b1d7d5de2b5} - {855b0594-d28c-486a-b081-72991219654e} + {81241aff-695b-4556-bf46-e9d3ac4aa7fb} - {08449c4a-89f1-4b5b-a756-2bd2f03bf566} - - - {8437086b-afc9-48b6-a358-53d4df044974} + {f4218b48-d878-435b-915a-8da9727666b1} - {d9802d62-8614-401a-afa6-941271c63386} + {e6e1a06f-b795-4a12-9b0c-0c730e0b2ac6} - {65e0e20a-2809-4352-8c81-69a0a3824fa9} + {231a82e9-6b4b-4a95-995c-8abd0b6149b3} - {8ea19f58-a2c0-4a30-bc79-817da2f1a1ed} + {4c70e19a-a935-4b0f-88e3-10683b03f66c} - {753c9d80-ceb0-4932-8097-5c7cac92e091} + {4a433329-84ca-4a8b-938e-4d06c21ec6ff} - {b4290489-566b-4576-847b-392b4c45f1f1} + {4414bb60-269f-4934-9dc9-58bbed35bc1d} - {ad07dceb-214e-42e1-933d-c8ceeecd1389} + {4bc23857-f9a2-453d-bc64-8c9ebc5aff42} - {3ee94c12-30fb-4f65-8781-f7b5e8a95db2} + {a9318f22-caaa-40af-b8fc-9b8051ec0859} - {813aba46-5b9d-4290-9a31-18e77952929e} + {fba5da81-e3f2-4fbe-98d7-807aaa2c2cf3} - {55bcc3cd-7f6b-4bb6-b22e-b731ed0451fb} + {abd6883d-375b-4d85-bb93-12952995332d} - {6ebccae2-fbfd-4a3f-9bfc-7e9dbd2b6d74} + {4c9fdf84-d6a6-47f8-8d58-c01ed8351fa0} - {a339ab19-2bed-4d03-afdc-d73223648b72} + {366f9975-2268-4124-81b9-87e7c2c03b1e} - {87b01999-0b73-481b-b8fa-b66f594f65be} + {8d2d02ea-1957-4256-8046-f525d13e7ba5} - {5870cf94-fb1b-44c0-90f2-32c3c8cbf6b7} + {8438e074-8733-4689-95ba-86145dd9fd9d} - {90263b28-e65b-4d41-92cb-a0d1dac22564} + {9d35d85d-280c-49ef-869a-ffaa0602f9f5} - {453d13c1-1847-4a18-8f2e-028913b4ec43} + {6df94c72-e89d-451e-ad6b-160ea0313077} - {e4baad7e-ee3c-4085-961f-2851c0ed2b8f} + {7bec8429-3bb9-4dfd-8008-a10c675a9818} - {a7ab51c2-5596-458f-b5f0-1129dc3dbbf5} + {747a1613-4c01-46ef-ba17-92d2286890ad} - {a7456898-2253-48d8-abec-9c86311cca64} + {516a0fc3-a824-4486-b50c-f3165d1d8361} - {cb9f48b8-6f25-4c9d-9d2c-b1a67cc80427} + {bddbc784-474a-4cd3-bbea-3123048dbfaa} - {b44ee927-e827-4c46-bbce-c7a1b705b63b} + {7bba2a7a-8cd3-47bd-9ab2-e33939d4eba6} - {40540c0e-02d6-4296-bbdf-87dfd9f7f213} + {32cdfdd7-c3bb-41f2-b433-10165963f9ed} - {430d27a2-66db-4169-bb48-aeb0b65e4d1a} + {49edc93d-4305-45a8-a6d9-ae283837d46a} - {a247e523-dbaf-4fb8-b284-6c8c5cbc09a5} + {d24cf1e6-a301-42e8-9fc1-26fe0ddc3f04} - {91d6db52-180b-4dde-9339-807917e42f4e} + {3df649be-39d5-4416-8776-427a1696c016} - {8ae0e3a3-87db-4e93-bb20-9d198040ae86} + {2e68088f-97e2-4dee-91f5-c85e3e36dd74} - {0049f7d1-4211-4010-b53c-3ee99244046e} + {f7674a86-b0a5-484c-9db3-a20500b9bbf9} - {8bddb89b-fa54-448a-a4b3-294f18d45ded} + {f41987e3-e0b9-431d-b37b-5931db380b09} - {082f589c-eb3f-47a4-b2f6-fbd6d89dec07} + {88ed597b-50ba-4d6f-bf50-ae8f5fa17789} - {a7f59027-bc87-4d28-9b90-eb5be186d8a7} + {5499a8e9-ef31-4ab9-a58f-d3a36a784004} - {f5410d0f-0a22-4579-afbf-8e13db8fa3d5} + {b74f25a9-ff20-4888-8dfc-57dd968b0b8d} - {ebe2b998-26de-4e92-8618-c739cb43a5f2} + {18246123-74da-4fee-8581-bd2860451c40} - {4f4d9d4b-3f44-4d56-9a18-16b94e753706} + {3fdeab5a-5ccf-41c6-bf05-d9f7f510c741} @@ -247,9 +247,6 @@ Source Files\librender - - Source Files\librender - Source Files\librender @@ -439,6 +436,9 @@ Source Files\libhw + + Source Files\libhw + Source Files\libhw @@ -511,6 +511,12 @@ Source Files\libcore + + Source Files\libcore + + + Source Files\libcore + Source Files\libcore @@ -709,6 +715,9 @@ Source Files\mtsgui + + Source Files\mtsgui + Source Files\mtsgui @@ -805,15 +814,9 @@ Source Files\utils - - Source Files\utils - Source Files\utils - - Source Files\utils - Source Files\utils @@ -835,6 +838,9 @@ Source Files\shapes\ply + + Source Files\shapes + Source Files\shapes @@ -853,10 +859,10 @@ Source Files\shapes - + Source Files\shapes - + Source Files\shapes @@ -1035,17 +1041,20 @@ Source Files\samplers - - Source Files\libhw + + Source Files\libhw\data - - Source Files\libhw + + Source Files\libhw\data - - Source Files\libhw + + Source Files\libhw\data - - Source Files\libhw + + Source Files\libhw\data + + + Source Files\libhw\data Source Files\medium @@ -1152,6 +1161,9 @@ Source Files\films + + Source Files\films + Source Files\shapes @@ -1278,6 +1290,9 @@ Header Files\mitsuba\render + + Header Files\mitsuba\render + Header Files\mitsuba\render @@ -1287,9 +1302,6 @@ Header Files\mitsuba\render - - Header Files\mitsuba\render - Header Files\mitsuba\render @@ -1425,6 +1437,9 @@ Header Files\mitsuba\core + + Header Files\mitsuba\core + Header Files\mitsuba\core @@ -1461,6 +1476,9 @@ Header Files\mitsuba\core + + Header Files\mitsuba\core + Header Files\mitsuba\core @@ -1494,6 +1512,9 @@ Header Files\mitsuba\core + + Header Files\mitsuba\core + Header Files\mitsuba\core @@ -1530,9 +1551,6 @@ Header Files\mitsuba\core - - Header Files\mitsuba\core - Header Files\mitsuba\core @@ -1614,6 +1632,9 @@ Header Files\mitsuba\hw + + Header Files\mitsuba\hw + Header Files\mitsuba\hw diff --git a/data/linux/debian/changelog b/data/linux/debian/changelog index 561acd80..1443a9e7 100644 --- a/data/linux/debian/changelog +++ b/data/linux/debian/changelog @@ -1,3 +1,39 @@ +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 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. @@ -50,15 +86,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 @@ -72,30 +108,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 - tag changed the handedness of the coordinate system. This is now + * lookAt: Mitsuba inherited a bug from PBRT, where the + tag changed the handedness of the coordinate system. This is now fixed--also, the syntax of this tag has changed to make it easier to read. * Scene portability: A new conversion tool ensures that old and incompatible - scenes can be translated into the scene description format of the + 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. @@ -140,8 +176,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 @@ -149,7 +185,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 Wed, 8 Sep 2010 09:59:00 -0400 mitsuba (0.1.2-1) unstable; urgency=low @@ -165,8 +201,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 @@ -180,6 +216,6 @@ mitsuba (0.1.2-1) unstable; urgency=low mitsuba (0.1.1-1) unstable; urgency=low - * Initial release + * Initial release -- Wenzel Jakob Sat, 17 Jul 2010 23:56:03 -0400 diff --git a/data/linux/fedora/mitsuba.spec b/data/linux/fedora/mitsuba.spec index aeb0a0f3..5aa083ee 100644 --- a/data/linux/fedora/mitsuba.spec +++ b/data/linux/fedora/mitsuba.spec @@ -1,7 +1,7 @@ Name: mitsuba -Version: 0.4.2 +Version: 0.4.3 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 @@ -63,6 +63,9 @@ rm -rf $RPM_BUILD_ROOT /usr/include/* %changelog +* Tue Jan 29 2013 Wenzel Jakob 0.4.3%{?dist} +- Upgrade to version 0.4.3 + * Wed Oct 31 2012 Wenzel Jakob 0.4.2%{?dist} - Upgrade to version 0.4.2 diff --git a/doc/format.tex b/doc/format.tex index d837adde..de82cf4a 100644 --- a/doc/format.tex +++ b/doc/format.tex @@ -97,7 +97,7 @@ and one or more emitters. Here is a more complex example: - + @@ -289,7 +289,7 @@ do not explicitly have to be specified. \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. The syntax used to specify these +render scenes involving motion blur (Figure~\ref{fig:animated-transform}). The syntax used to specify these is slightly different: \begin{xml} @@ -304,6 +304,11 @@ is slightly different: .. additional transformations (optional) .. \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 @@ -311,7 +316,7 @@ 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 diff --git a/doc/images/animated_transform.jpg b/doc/images/animated_transform.jpg new file mode 100644 index 00000000..fd287ab1 Binary files /dev/null and b/doc/images/animated_transform.jpg differ diff --git a/doc/images/annotation_example.jpg b/doc/images/annotation_example.jpg new file mode 100644 index 00000000..0420429f Binary files /dev/null and b/doc/images/annotation_example.jpg differ diff --git a/doc/images/shape_cube_basic.jpg b/doc/images/shape_cube_basic.jpg new file mode 100644 index 00000000..d5f26251 Binary files /dev/null and b/doc/images/shape_cube_basic.jpg differ diff --git a/doc/images/shape_cube_parameterization.jpg b/doc/images/shape_cube_parameterization.jpg new file mode 100644 index 00000000..d9f34781 Binary files /dev/null and b/doc/images/shape_cube_parameterization.jpg differ diff --git a/doc/main.tex b/doc/main.tex index f4b3c7a0..1ed7ad5c 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -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.2} -\newcommand{\MitsubaYear}{2012} +\newcommand{\MitsubaVersion}{0.4.3} +\newcommand{\MitsubaYear}{2013} \typearea[current]{last} \raggedbottom diff --git a/include/mitsuba/core/platform.h b/include/mitsuba/core/platform.h index 88ca7594..9f72838f 100644 --- a/include/mitsuba/core/platform.h +++ b/include/mitsuba/core/platform.h @@ -203,13 +203,14 @@ MTS_NAMESPACE_END #define snprintf _snprintf #define vsnprintf _vsnprintf -#define strncasecmp _strnicmp +namespace mitsuba { #if defined(__64BIT__) typedef long long ssize_t; #else typedef long ssize_t; #endif +}; namespace std { inline char tolower(char c) { diff --git a/include/mitsuba/core/util.h b/include/mitsuba/core/util.h index 7bd67cb6..37b7c8db 100644 --- a/include/mitsuba/core/util.h +++ b/include/mitsuba/core/util.h @@ -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 std::string containerToString(const Iterator &start, const Iterator &end) { diff --git a/include/mitsuba/render/scenehandler.h b/include/mitsuba/render/scenehandler.h index 268967f8..d878f93a 100644 --- a/include/mitsuba/render/scenehandler.h +++ b/include/mitsuba/render/scenehandler.h @@ -68,6 +68,9 @@ private: # pragma warning( pop ) #endif +/// Push a cleanup handler to be executed after loading the scene is done +extern MTS_EXPORT_RENDER void pushSceneCleanupHandler(void (*cleanup)()); + /** * \brief XML parser for Mitsuba scene files. To be used with the * SAX interface of Xerces-C++. @@ -101,9 +104,6 @@ public: /// Free the memory taken up by staticInitialization() static void staticShutdown(); - /// Push a cleanup handler to be executed after loading the scene is done - static void pushCleanupHandler(void (*cleanup)()); - // ----------------------------------------------------------------------- // Implementation of the SAX DocumentHandler interface // ----------------------------------------------------------------------- @@ -136,8 +136,7 @@ protected: private: struct ParseContext { inline ParseContext(ParseContext *_parent) - : parent(_parent) { - } + : parent(_parent) { } ParseContext *parent; Properties properties; diff --git a/src/bsdfs/coating.cpp b/src/bsdfs/coating.cpp index 1c4f77c2..ec37de9a 100644 --- a/src/bsdfs/coating.cpp +++ b/src/bsdfs/coating.cpp @@ -419,7 +419,8 @@ protected: class SmoothCoatingShader : public Shader { public: SmoothCoatingShader(Renderer *renderer, Float eta, const BSDF *nested, - const Texture *sigmaA) : Shader(renderer, EBSDFShader), m_nested(nested), m_sigmaA(sigmaA), m_eta(eta) { + const Texture *sigmaA) : Shader(renderer, EBSDFShader), + m_nested(nested), m_sigmaA(sigmaA), m_eta(eta) { m_nestedShader = renderer->registerShaderForResource(m_nested.get()); m_sigmaAShader = renderer->registerShaderForResource(m_sigmaA.get()); m_R0 = fresnelDielectricExt(1.0f, eta); @@ -467,15 +468,15 @@ public: << "vec3 " << evalName << "_refract(vec3 wi, out float T) {" << endl << " float cosThetaI = cosTheta(wi);" << endl << " bool entering = cosThetaI > 0.0;" << endl - << " float eta = " << evalName << "_eta;" << endl - << " float sinThetaTSqr = eta * eta * sinTheta2(wi);" << endl + << " float invEta = 1.0 / " << evalName << "_eta;" << endl + << " float sinThetaTSqr = invEta * invEta * sinTheta2(wi);" << endl << " if (sinThetaTSqr >= 1.0) {" << endl << " T = 0.0; /* Total internal reflection */" << endl << " return vec3(0.0);" << endl << " } else {" << endl << " float cosThetaT = sqrt(1.0 - sinThetaTSqr);" << endl << " T = 1.0 - " << evalName << "_schlick(1.0 - abs(cosThetaI));" << endl - << " return vec3(eta*wi.x, eta*wi.y, entering ? cosThetaT : -cosThetaT);" << endl + << " return vec3(invEta*wi.x, invEta*wi.y, entering ? cosThetaT : -cosThetaT);" << endl << " }" << endl << "}" << endl << endl @@ -512,10 +513,11 @@ public: << " 1/abs(cosTheta(woPrime))));" << endl << " if (cosTheta(wi)*cosTheta(wo) > 0) {" << endl << " vec3 H = normalize(wi + wo);" << endl + << " if (H.z < 0) H = -H;" << endl << " float D = " << evalName << "_D(H)" << ";" << endl << " float G = " << evalName << "_G(H, wi, wo);" << endl - << " float F = " << evalName << "_schlick(1-dot(wi, H));" << endl - << " result += vec3(F * D * G / (4*cosTheta(wi)));" << endl + << " float F = " << evalName << "_schlick(1-abs(dot(wi, H)));" << endl + << " result += vec3(abs(F * D * G) / abs(4*cosTheta(wi)));" << endl << " }" << endl << " return result;" << endl << "}" << endl diff --git a/src/bsdfs/microfacet.h b/src/bsdfs/microfacet.h index 16799e97..9fbf7538 100644 --- a/src/bsdfs/microfacet.h +++ b/src/bsdfs/microfacet.h @@ -84,7 +84,11 @@ public: * (For lower roughness values, please switch to the smooth BSDF variants) */ Float transformRoughness(Float value) const { - value = std::max(value, (Float) 1e-5f); + #if defined(SINGLE_PRECISION) + value = std::max(value, (Float) 1e-3f); + #else + value = std::max(value, (Float) 1e-5f); + #endif if (m_type == EPhong || m_type == EAshikhminShirley) value = std::max(2 / (value * value) - 2, (Float) 0.1f); return value; diff --git a/src/bsdfs/plastic.cpp b/src/bsdfs/plastic.cpp index 4f11f242..5c1999f6 100644 --- a/src/bsdfs/plastic.cpp +++ b/src/bsdfs/plastic.cpp @@ -339,7 +339,7 @@ public: Spectrum diff = m_diffuseReflectance->eval(bRec.its); if (m_nonlinear) - diff /= Spectrum(1.0f) - m_fdrInt*diff; + diff /= Spectrum(1.0f) - diff*m_fdrInt; else diff /= 1 - m_fdrInt; @@ -357,6 +357,7 @@ public: bRec.sampledType = EDiffuseReflection; Spectrum diff = m_diffuseReflectance->eval(bRec.its); + diff /= Spectrum(1.0f) - m_fdrInt*diff; if (m_nonlinear) diff /= Spectrum(1.0f) - diff*m_fdrInt; else @@ -424,14 +425,14 @@ public: bRec.wo = Warp::squareToCosineHemisphere(sample); Float Fo = fresnelDielectricExt(Frame::cosTheta(bRec.wo), m_eta); - pdf = Warp::squareToCosineHemispherePdf(bRec.wo); - Spectrum diff = m_diffuseReflectance->eval(bRec.its); if (m_nonlinear) diff /= Spectrum(1.0f) - diff*m_fdrInt; else diff /= 1 - m_fdrInt; + pdf = Warp::squareToCosineHemispherePdf(bRec.wo); + return diff * (m_invEta2 * (1-Fi) * (1-Fo)); } } diff --git a/src/bsdfs/roughcoating.cpp b/src/bsdfs/roughcoating.cpp index 0622316d..d11362e9 100644 --- a/src/bsdfs/roughcoating.cpp +++ b/src/bsdfs/roughcoating.cpp @@ -554,7 +554,7 @@ public: << "vec3 " << evalName << "_refract(vec3 wi, out float T) {" << endl << " float cosThetaI = cosTheta(wi);" << endl << " bool entering = cosThetaI > 0.0;" << endl - << " float invEta = " << evalName << "_eta;" << endl + << " float invEta = 1.0 / " << evalName << "_eta;" << endl << " float sinThetaTSqr = invEta * invEta * sinTheta2(wi);" << endl << " if (sinThetaTSqr >= 1.0) {" << endl << " T = 0.0; /* Total internal reflection */" << endl diff --git a/src/films/annotations.h b/src/films/annotations.h index 6d041e03..3ae47777 100644 --- a/src/films/annotations.h +++ b/src/films/annotations.h @@ -75,48 +75,68 @@ void annotate(const Scene *scene, const Properties &properties, if (!(strt = strchr((char *) value.c_str(), '$'))) break; - if (strncasecmp(strt, "$rendertime", 11) == 0) { - value.replace(strt-value.c_str(), 11, timeString(renderTime)); - } else if (strncasecmp(strt, "$memusage", 11) == 0) { - value.replace(strt-value.c_str(), 11, memString(getPrivateMemoryUsage())); - } else { - char *par1, *par2; - if (!(par1 = strchr(strt, '['))) - break; - if (!(par2 = strchr(par1, ']'))) - break; + char *par1, *par2; + if (!(par1 = strchr(strt, '['))) + break; + if (!(par2 = strchr(par1, ']'))) + break; - std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1); - std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1); - propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end()); - propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end()); + std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1); + std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1); + propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end()); + propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end()); - if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'")) - SLog(EError, "Encountered invalid key '%s'", propKey.c_str()); + if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'")) + SLog(EError, "Encountered invalid key '%s'", propKey.c_str()); - propKey = propKey.substr(1, propKey.length()-2); + propKey = propKey.substr(1, propKey.length()-2); - const ConfigurableObject *source = NULL; - if (propSource == "film") - source = scene->getFilm(); - else if (propSource == "sampler") - source = scene->getSampler(); - else if (propSource == "sensor") - source = scene->getSensor(); - else if (propSource == "integrator") - source = scene->getIntegrator(); - else - SLog(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str()); + const ConfigurableObject *source = NULL; + if (propSource == "scene") + source = scene; + else if (propSource == "film") + source = scene->getFilm(); + else if (propSource == "sampler") + source = scene->getSampler(); + else if (propSource == "sensor") + source = scene->getSensor(); + else if (propSource == "integrator") + source = scene->getIntegrator(); + else + SLog(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str()); - std::string replacement; + std::string replacement; + + if (source == scene) { + if (propKey == "renderTime") { + replacement = timeString(renderTime); + } else if (propKey == "renderTimePrecise") { + replacement = timeString(renderTime, true); + } else if (propKey == "memUsage") { + replacement = memString(getPrivateMemoryUsage()); + } else if (propKey == "memUsagePrecise") { + replacement = memString(getPrivateMemoryUsage(), true); + } else if (propKey == "coreCount") { + replacement = formatString("%i", Scheduler::getInstance()->getCoreCount()); + } else if (propKey == "blockSize") { + replacement = formatString("%i", scene->getBlockSize()); + } else if (propKey == "sourceFile") { + replacement = scene->getSourceFile().string(); + } else if (propKey == "destFile") { + replacement = scene->getDestinationFile().string(); + } + } + + if (replacement.empty()) { if (propKey == "type") replacement = source->getProperties().getPluginName(); else replacement = source->getProperties().getAsString(propKey); - - value.replace(strt-value.c_str(), par2-strt+1, replacement); } + + value.replace(strt-value.c_str(), par2-strt+1, replacement); } + if (labelAnnotation) { Vector2i size = font->getSize(value); bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f)); diff --git a/src/films/hdrfilm.cpp b/src/films/hdrfilm.cpp index 8bb01a3c..d8113755 100644 --- a/src/films/hdrfilm.cpp +++ b/src/films/hdrfilm.cpp @@ -117,33 +117,89 @@ MTS_NAMESPACE_BEGIN * * \end{xml} * - * \subsubsection*{Annotations:} + * \subsubsection*{Render-time annotations:} * \label{sec:film-annotations} - * The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support an additional - * feature referred to as \emph{annotations}, which can be quite useful under - * certain circumstances. - * + * The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support a + * feature referred to as \emph{render-time annotations} to facilitate + * record keeping. * Annotations are used to embed useful information inside a rendered image so * that this information is later available to anyone viewing the image. * Exemplary uses of this feature might be to store the frame or take number, - * camera parameters, or other relevant scene information. - * - * Annotations can either be created by means of a \emph{tag}, which is an entry - * in the metadata table of the image file (does not modify the actual image data), - * or a \emph{text} label which is ``burned'' into the image. + * rendering time, memory usage, camera parameters, or other relevant scene + * information. * + * Currently, two different types are supported: a \code{metadata} annotation + * creates an entry in the metadata table of the image, which is preferable + * when the image contents should not be touched. Alternatively, a \code{label} + * annotation creates a line of text that is overlaid on top of the image. Note + * that this is only visible when opening the output file (i.e. the line is not + * shown in the interactive viewer). * The syntax of this looks as follows: * * \begin{xml} - * - * - * + * + * + * * * - * + * * * \end{xml} + * + * The \code{value="..."} argument may also include certain keywords that will be + * evaluated and substituted when the rendered image is written to disk. A list all available + * keywords is provided in Table~\ref{tbl:film-keywords}. + * + * Apart from querying the render time, + * memory usage, and other scene-related information, it is also possible + * to `paste' an existing parameter that was provided to another plugin---for instance,the + * the camera transform matrix would be obtained as \code{\$sensor['toWorld']}. The name of + * the active integrator plugin is given by \code{\$integrator['type']}, and so on. + * All of these can be mixed to build larger fragments, as following example demonstrates. + * The result of this annotation is shown in Figure~\ref{fig:annotation-example}. + * \begin{xml}[mathescape=false] + * + * \end{xml} + * \vspace{1cm} + * \renderings{ + * \fbox{\includegraphics[width=.8\textwidth]{images/annotation_example}}\hfill\, + * \caption{\label{fig:annotation-example}A demonstration of the label annotation feature + * given the example string shown above.} + * } + * \vspace{2cm} + * \begin{table}[htb] + * \centering + * \begin{savenotes} + * \begin{tabular}{ll} + * \toprule + * \code{\$scene['renderTime']}& Image render time, use \code{renderTimePrecise} for more digits.\\ + * \code{\$scene['memUsage']}& Mitsuba memory usage\footnote{The definition of this quantity unfortunately + * varies a bit from platform to platform. On Linux and Windows, it denotes the total + * amount of allocated RAM and disk-based memory that is private to the process (i.e. not + * shared or shareable), which most intuitively captures the amount of memory required for + * rendering. On OSX, it denotes the working set size---roughly speaking, this is the + * amount of RAM apportioned to the process (i.e. excluding disk-based memory).}. + * Use \code{memUsagePrecise} for more digits.\\ + * \code{\$scene['coreCount']}& Number of local and remote cores working on the rendering job\\ + * \code{\$scene['blockSize']}& Block size used to parallelize up the rendering workload\\ + * \code{\$scene['sourceFile']}& Source file name\\ + * \code{\$scene['destFile']}& Destination file name\\ + * \code{\$integrator['..']}& Copy a named integrator parameter\\ + * \code{\$sensor['..']}& Copy a named sensor parameter\\ + * \code{\$sampler['..']}& Copy a named sampler parameter\\ + * \code{\$film['..']}& Copy a named film parameter\\ + * \bottomrule + * \end{tabular} + * \end{savenotes} + * \caption{\label{tbl:film-keywords}A list of all special + * keywords supported by the annotation feature} + * \end{table} + * */ + class HDRFilm : public Film { public: HDRFilm(const Properties &props) : Film(props) { diff --git a/src/integrators/photonmapper/photonmapper.cpp b/src/integrators/photonmapper/photonmapper.cpp index 91d3ac15..d77c7fbc 100644 --- a/src/integrators/photonmapper/photonmapper.cpp +++ b/src/integrators/photonmapper/photonmapper.cpp @@ -435,9 +435,17 @@ public: return LiSurf * transmittance + LiMedium; unsigned int bsdfType = bsdf->getType() & BSDF::EAll; - bool isDiffuse = (bsdfType == BSDF::EDiffuseReflection); - if (isDiffuse || cacheQuery) { + /* Irradiance cachq query -> trat as diffuse */ + bool isDiffuse = (bsdfType == BSDF::EDiffuseReflection) || cacheQuery; + + bool hasSpecular = bsdfType & BSDF::EDelta; + + /* Exhaustively recurse into all specular lobes? */ + bool exhaustiveSpecular = rRec.depth < m_maxSpecularDepth && !cacheQuery; + + if (isDiffuse) { + /* 1. Diffuse indirect */ int maxDepth = m_maxDepth == -1 ? INT_MAX : (m_maxDepth-rRec.depth); if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance && m_globalPhotonMap.get()) LiSurf += m_globalPhotonMap->estimateIrradiance(its.p, @@ -449,53 +457,55 @@ public: m_causticLookupSize) * bsdf->getDiffuseReflectance(its) * INV_PI; } - if ((bsdfType & BSDF::EDelta) && rRec.depth < m_maxSpecularDepth && !cacheQuery) { - if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) { - int compCount = bsdf->getComponentCount(); - RadianceQueryRecord rRec2; - for (int i=0; igetType(i); - if (!(type & BSDF::EDelta)) - continue; - /* Sample the BSDF and recurse */ - BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance); - bRec.component = i; - Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f)); - if (bsdfVal.isZero()) - continue; + if (hasSpecular && exhaustiveSpecular + && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance)) { + /* 1. Specular indirect */ + int compCount = bsdf->getComponentCount(); + RadianceQueryRecord rRec2; + for (int i=0; igetType(i); + if (!(type & BSDF::EDelta)) + continue; + /* Sample the BSDF and recurse */ + BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance); + bRec.component = i; + Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.5f)); + if (bsdfVal.isZero()) + continue; - rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance); - RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time); - if (its.isMediumTransition()) - rRec2.medium = its.getTargetMedium(bsdfRay.d); + rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance); + RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time); + if (its.isMediumTransition()) + rRec2.medium = its.getTargetMedium(bsdfRay.d); - LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2); - } + LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2); } - } else if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance) { - /* Estimate the direct illumination if this is requested */ - Point2 *sampleArray; - Point2 sample; - int numEmitterSamples = m_directSamples, - numBSDFSamples; + } - Float weightLum, weightBSDF; + /* Estimate the direct illumination if this is requested */ + int numEmitterSamples = m_directSamples, numBSDFSamples; + Float weightLum, weightBSDF; + Point2 *sampleArray; + Point2 sample; - if (rRec.depth > 1 || cacheQuery || adaptiveQuery) { - /* This integrator is used recursively by another integrator. - Be less accurate as this sample will not directly be observed. */ - numBSDFSamples = numEmitterSamples = 1; - weightLum = weightBSDF = 1.0f; + if (rRec.depth > 1 || cacheQuery || adaptiveQuery) { + /* This integrator is used recursively by another integrator. + Be less accurate as this sample will not directly be observed. */ + numBSDFSamples = numEmitterSamples = 1; + weightLum = weightBSDF = 1.0f; + } else { + if (isDiffuse) { + numBSDFSamples = m_directSamples; + weightBSDF = weightLum = m_invEmitterSamples; } else { - if (isDiffuse) { - numBSDFSamples = m_directSamples; - weightBSDF = weightLum = m_invEmitterSamples; - } else { - numBSDFSamples = m_glossySamples; - weightLum = m_invEmitterSamples; - weightBSDF = m_invGlossySamples; - } + numBSDFSamples = m_glossySamples; + weightLum = m_invEmitterSamples; + weightBSDF = m_invGlossySamples; } + } + + if ((bsdfType & BSDF::ESmooth) && (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance)) { + DirectSamplingRecord dRec(its); if (numEmitterSamples > 1) { sampleArray = rRec.sampler->next2DArray(m_directSamples); @@ -503,45 +513,62 @@ public: sample = rRec.nextSample2D(); sampleArray = &sample; } - DirectSamplingRecord dRec(its); - if (bsdf->getType() & BSDF::ESmooth) { - for (int i=0; isampleAttenuatedEmitterDirect( - dRec, its, rRec.medium, interactions, - sampleArray[i], rRec.sampler); + for (int i=0; isampleAttenuatedEmitterDirect( + dRec, its, rRec.medium, interactions, + sampleArray[i], rRec.sampler); - /* Estimate the direct illumination if this is requested */ - if (!value.isZero()) { - const Emitter *emitter = static_cast(dRec.object); + /* Estimate the direct illumination if this is requested */ + if (!value.isZero()) { + const Emitter *emitter = static_cast(dRec.object); - /* Allocate a record for querying the BSDF */ - BSDFSamplingRecord bRec(its, its.toLocal(dRec.d)); + /* Allocate a record for querying the BSDF */ + BSDFSamplingRecord bRec(its, its.toLocal(dRec.d)); - /* Evaluate BSDF * cos(theta) */ - const Spectrum bsdfVal = bsdf->eval(bRec); + /* Evaluate BSDF * cos(theta) */ + const Spectrum bsdfVal = bsdf->eval(bRec); - if (!bsdfVal.isZero()) { - /* Calculate prob. of having sampled that direction - using BSDF sampling */ - Float bsdfPdf = (emitter->isOnSurface() - && dRec.measure == ESolidAngle - && interactions == 0) - ? bsdf->pdf(bRec) : (Float) 0.0f; + if (!bsdfVal.isZero()) { + /* Calculate prob. of having sampled that direction + using BSDF sampling */ - /* Weight using the power heuristic */ - const Float weight = miWeight(dRec.pdf * numEmitterSamples, - bsdfPdf * numBSDFSamples) * weightLum; - LiSurf += value * bsdfVal * weight; - } + if (!hasSpecular || exhaustiveSpecular) + bRec.typeMask = BSDF::ESmooth; + + Float bsdfPdf = (emitter->isOnSurface() + && dRec.measure == ESolidAngle + && interactions == 0) + ? bsdf->pdf(bRec) : (Float) 0.0f; + + /* Weight using the power heuristic */ + const Float weight = miWeight(dRec.pdf * numEmitterSamples, + bsdfPdf * numBSDFSamples) * weightLum; + + LiSurf += value * bsdfVal * weight; } } } + } - /* ==================================================================== */ - /* BSDF sampling */ - /* ==================================================================== */ + /* ==================================================================== */ + /* BSDF sampling */ + /* ==================================================================== */ + /* Sample direct compontent via BSDF sampling if this is generally requested AND + the BSDF is smooth, or there is a delta component that was not handled by the + exhaustive sampling loop above */ + bool bsdfSampleDirect = (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance) && + ((bsdfType & BSDF::ESmooth) || (hasSpecular && !exhaustiveSpecular)); + + /* Sample indirect component via BSDF sampling if this is generally requested AND + the BSDF is non-diffuse (diffuse is handled by the global photon map) + or there is a delta component that was not handled by the exhaustive sampling loop + above. */ + bool bsdfSampleIndirect = (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && + !isDiffuse && ((bsdfType & BSDF::ESmooth) || (hasSpecular && !exhaustiveSpecular)); + + if (bsdfSampleDirect || bsdfSampleIndirect) { if (numBSDFSamples > 1) { sampleArray = rRec.sampler->next2DArray( std::max(m_directSamples, m_glossySamples)); @@ -552,9 +579,13 @@ public: RadianceQueryRecord rRec2; Intersection &bsdfIts = rRec2.its; + DirectSamplingRecord dRec; for (int i=0; isample(bRec, bsdfPdf, sampleArray[i]); if (bsdfVal.isZero()) @@ -567,12 +598,12 @@ public: bool hitEmitter = false; if (scene->rayIntersect(bsdfRay, bsdfIts)) { /* Intersected something - check if it was a luminaire */ - if (bsdfIts.isEmitter()) { + if (bsdfIts.isEmitter() && bsdfSampleDirect) { value = bsdfIts.Le(-bsdfRay.d); dRec.setQuery(bsdfRay, bsdfIts); hitEmitter = true; } - } else { + } else if (bsdfSampleDirect) { /* Intersected nothing -- perhaps there is an environment map? */ const Emitter *env = scene->getEnvironmentEmitter(); @@ -584,8 +615,7 @@ public: } if (hitEmitter) { - const Float emitterPdf = (!(bRec.sampledType & BSDF::EDelta)) ? - scene->pdfEmitterDirect(dRec) : 0; + const Float emitterPdf = scene->pdfEmitterDirect(dRec); Spectrum transmittance = rRec2.medium ? rRec2.medium->evalTransmittance(Ray(bsdfRay, 0, bsdfIts.t)) : Spectrum(1.0f); @@ -597,7 +627,7 @@ public: } /* Recurse */ - if (!isDiffuse && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && !cacheQuery) { + if (bsdfSampleIndirect) { rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadianceNoEmission); rRec2.type ^= RadianceQueryRecord::EIntersection; @@ -608,35 +638,6 @@ public: LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2) * weightBSDF; } } - } else if (!isDiffuse && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && !cacheQuery) { - int numBSDFSamples = (rRec.depth > 1 || adaptiveQuery) ? 1 : m_glossySamples; - Float weightBSDF; - Point2 *sampleArray; - Point2 sample; - - if (numBSDFSamples > 1) { - sampleArray = rRec.sampler->next2DArray( - std::max(m_directSamples, m_glossySamples)); - weightBSDF = m_invGlossySamples; - } else { - sample = rRec.nextSample2D(); sampleArray = &sample; - weightBSDF = 1.0f; - } - - RadianceQueryRecord rRec2; - for (int i=0; isample(bRec, bsdfPdf, sampleArray[i]); - if (bsdfVal.isZero()) - continue; - rRec2.recursiveQuery(rRec, - RadianceQueryRecord::ERadianceNoEmission); - - RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time); - LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2) * weightBSDF; - } } return LiSurf * transmittance + LiMedium; diff --git a/src/libcore/sched_remote.cpp b/src/libcore/sched_remote.cpp index d11e763a..95f737c5 100644 --- a/src/libcore/sched_remote.cpp +++ b/src/libcore/sched_remote.cpp @@ -325,14 +325,7 @@ StreamBackend::StreamBackend(const std::string &thrName, Scheduler *scheduler, m_memStream->setByteOrder(Stream::ENetworkByteOrder); } -StreamBackend::~StreamBackend() { - if (m_stream->getClass()->derivesFrom(MTS_CLASS(SocketStream))) { - SocketStream *sstream = static_cast(m_stream.get()); - Log(EInfo, "Closing connection to %s - received %i KB / sent %i KB", - sstream->getPeer().c_str(), (int) (sstream->getReceivedBytes() / 1024), - (int) (sstream->getSentBytes() / 1024)); - } -} +StreamBackend::~StreamBackend() { } void StreamBackend::run() { if (m_detach) @@ -489,6 +482,13 @@ void StreamBackend::run() { Log(EWarn, "Removing stray resource %i", (*it).first); m_scheduler->unregisterResource((*it).second); } + + if (m_stream->getClass()->derivesFrom(MTS_CLASS(SocketStream))) { + SocketStream *sstream = static_cast(m_stream.get()); + Log(EInfo, "Closing connection to %s - received %i KB / sent %i KB", + sstream->getPeer().c_str(), (int) (sstream->getReceivedBytes() / 1024), + (int) (sstream->getSentBytes() / 1024)); + } } void StreamBackend::sendCancellation(int id, int numLost) { diff --git a/src/libcore/util.cpp b/src/libcore/util.cpp index c0cbb270..afe999ac 100644 --- a/src/libcore/util.cpp +++ b/src/libcore/util.cpp @@ -123,19 +123,6 @@ std::string indent(const std::string &string, int amount) { return oss.str(); } -std::string memString(size_t size) { - Float value = (Float) size; - const char *prefixes[] = { - "B", "KiB", "MiB", "GiB", "TiB", "PiB" - }; - int prefix = 0; - while (prefix < 5 && value > 1024.0f) { - value /= 1024.0f; ++prefix; - } - return formatString(prefix == 0 ? - "%.0f %s" : "%.2f %s", value, prefixes[prefix]); -} - void * __restrict allocAligned(size_t size) { #if defined(__WINDOWS__) return _aligned_malloc(size, L1_CACHE_LINE_SIZE); @@ -809,8 +796,6 @@ Float fresnelDiffuseReflectance(Float eta, bool fast) { } std::string timeString(Float time, bool precise) { - std::ostringstream os; - if (std::isnan(time) || std::isinf(time)) return "inf"; @@ -825,12 +810,31 @@ std::string timeString(Float time, bool precise) { } } + std::ostringstream os; os << std::setprecision(precise ? 4 : 1) << std::fixed << time << suffix; return os.str(); } +std::string memString(size_t size, bool precise) { + Float value = (Float) size; + const char *suffixes[] = { + "B", "KiB", "MiB", "GiB", "TiB", "PiB" + }; + int suffix = 0; + while (suffix < 5 && value > 1024.0f) { + value /= 1024.0f; ++suffix; + } + + std::ostringstream os; + os << std::setprecision(suffix == 0 ? 0 : (precise ? 4 : 1)) + << std::fixed << value << suffixes[suffix]; + + return os.str(); +} + + Float hypot2(Float a, Float b) { Float r; if (std::abs(a) > std::abs(b)) { diff --git a/src/librender/scenehandler.cpp b/src/librender/scenehandler.cpp index 7c77e75b..947421d8 100644 --- a/src/librender/scenehandler.cpp +++ b/src/librender/scenehandler.cpp @@ -274,7 +274,7 @@ void SceneHandler::startElement(const XMLCh* const xmlName, m_context.push(context); } -void SceneHandler::pushCleanupHandler(void (*cleanup)()) { +void pushSceneCleanupHandler(void (*cleanup)()) { __cleanup_tls.get().insert(cleanup); } diff --git a/src/medium/materials.h b/src/medium/materials.h index b31de859..50812f01 100644 --- a/src/medium/materials.h +++ b/src/medium/materials.h @@ -161,8 +161,12 @@ static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum & sigmaA = sigmaT - sigmaS; } - if (props.hasProperty("g")) - g = Spectrum(props.getFloat("g")); + if (props.hasProperty("g")) { + if (props.getType("g") == Properties::ESpectrum) + g = props.getSpectrum("g"); + else + g = Spectrum(props.getFloat("g")); + } if (g.min() <= -1 || g.max() >= 1) SLog(EError, "The anisotropy parameter 'g' must be in the range (-1, 1)!"); diff --git a/src/mtsgui/SConscript b/src/mtsgui/SConscript index 85ec98da..c4c4bc33 100644 --- a/src/mtsgui/SConscript +++ b/src/mtsgui/SConscript @@ -72,9 +72,6 @@ if hasQt: else: qtSources = [x for x in qtSources if (not isinstance(x, str) or 'cocoa' not in x)] - if sys.platform == 'win32': - qtSources += qtEnv.StaticObject('qtmain_win.cpp') - mtsgui = qtEnv.Program('mtsgui', qtSources) if sys.platform == 'darwin': qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @rpath/QtGui $TARGET') diff --git a/src/mtsgui/aboutdlg.cpp b/src/mtsgui/aboutdlg.cpp index 191cfa43..aa541777 100644 --- a/src/mtsgui/aboutdlg.cpp +++ b/src/mtsgui/aboutdlg.cpp @@ -82,6 +82,7 @@ AboutDialog::AboutDialog(QWidget *parent) : SPECTRUM_SAMPLES).c_str(); ui->label->setText(ui->label->text().replace("MTS_VERSION", MTS_VERSION)); + ui->label->setText(ui->label->text().replace("MTS_YEAR", MTS_YEAR)); ui->label->setText(ui->label->text().replace("CONFIG_FLAGS", configFlags)); #if defined(__OSX__) diff --git a/src/mtsgui/aboutdlg.ui b/src/mtsgui/aboutdlg.ui index dc53785f..26fe8301 100644 --- a/src/mtsgui/aboutdlg.ui +++ b/src/mtsgui/aboutdlg.ui @@ -81,7 +81,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">About Mitsuba</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version MTS_VERSION<br />Configuration flags: <span style=" font-family:'Courier New,courier';">CONFIG_FLAGS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2012 Wenzel Jakob &lt;<a href="mailto:wenzel@cs.cornell.edu"><span style=" text-decoration: underline; color:#0000ff;">wenzel@cs.cornell.edu</span></a>&gt;</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © MTS_YEAR Wenzel Jakob &lt;<a href="mailto:wenzel@cs.cornell.edu"><span style=" text-decoration: underline; color:#0000ff;">wenzel@cs.cornell.edu</span></a>&gt;</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Licensed under the <a href="http://www.gnu.org/licenses/gpl-3.0.html"><span style=" text-decoration: underline; color:#0000ff;">GNU GPL, Version 3</span></a>.</p></body></html> diff --git a/src/mtsgui/symlinks_install.c b/src/mtsgui/symlinks_install.c index 058c8a7c..34e1b039 100644 --- a/src/mtsgui/symlinks_install.c +++ b/src/mtsgui/symlinks_install.c @@ -85,11 +85,12 @@ int main(int argc, char **argv) { install(argv[1], "mtsimport"); installPython(argv[1], "2.6"); installPython(argv[1], "2.7"); - struct passwd *pw = getpwuid(atoi(argv[2])); - appendShellConfig(pw->pw_dir, ".bashrc", "\nexport LD_LIBRARY_PATH=%s/Contents/Frameworks:$LD_LIBRARY_PATH\n", argv[1]); - appendShellConfig(pw->pw_dir, ".zshrc", "\nexport LD_LIBRARY_PATH=%s/Contents/Frameworks:$LD_LIBRARY_PATH\n", argv[1]); - appendShellConfig(pw->pw_dir, ".cshrc", "\nsetenv LD_LIBRARY_PATH %s/Contents/Frameworks:${LD_LIBRARY_PATH}\n", argv[1]); + /// this is not required anymore as of Mitsuba 0.4.3 + //struct passwd *pw = getpwuid(atoi(argv[2])); + //appendShellConfig(pw->pw_dir, ".bashrc", "\nexport LD_LIBRARY_PATH=%s/Contents/Frameworks:$LD_LIBRARY_PATH\n", argv[1]); + //appendShellConfig(pw->pw_dir, ".zshrc", "\nexport LD_LIBRARY_PATH=%s/Contents/Frameworks:$LD_LIBRARY_PATH\n", argv[1]); + //appendShellConfig(pw->pw_dir, ".cshrc", "\nsetenv LD_LIBRARY_PATH %s/Contents/Frameworks:${LD_LIBRARY_PATH}\n", argv[1]); return 0; } diff --git a/src/shapes/CMakeLists.txt b/src/shapes/CMakeLists.txt index e59f2b84..6c73ab39 100644 --- a/src/shapes/CMakeLists.txt +++ b/src/shapes/CMakeLists.txt @@ -15,6 +15,7 @@ add_shape(rectangle rectangle.cpp) add_shape(disk disk.cpp) add_shape(sphere sphere.cpp) add_shape(cylinder cylinder.cpp) +add_shape(cube cube.cpp) add_shape(hair hair.h hair.cpp) add_shape(shapegroup shapegroup.h shapegroup.cpp) add_shape(instance instance.h instance.cpp) diff --git a/src/shapes/SConscript b/src/shapes/SConscript index 0d8a266d..db9f0728 100644 --- a/src/shapes/SConscript +++ b/src/shapes/SConscript @@ -11,6 +11,7 @@ plugins += env.SharedLibrary('cylinder', ['cylinder.cpp']) plugins += env.SharedLibrary('hair', ['hair.cpp']) plugins += env.SharedLibrary('shapegroup', ['shapegroup.cpp']) plugins += env.SharedLibrary('instance', ['instance.cpp']) +plugins += env.SharedLibrary('cube', ['cube.cpp']) #plugins += env.SharedLibrary('deformable', ['deformable.cpp']) Export('plugins') diff --git a/src/shapes/cube.cpp b/src/shapes/cube.cpp new file mode 100644 index 00000000..19b9841a --- /dev/null +++ b/src/shapes/cube.cpp @@ -0,0 +1,115 @@ +/* + 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 . +*/ + +#include +#include + +MTS_NAMESPACE_BEGIN + +static Float CubeData_vertexPositions[][3] = {{1, 0, 0}, {1, 0, 1}, {0, 0, 1}, {0, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 1, 1}, {1, 1, 1}, {1, 0, 0}, {1, 1, 0}, {1, 1, 1}, {1, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}, {0, 0, 1}, {0, 0, 1}, {0, 1, 1}, {0, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 0, 0}, {0, 0, 0}, {0, 1, 0}}; + +static Float CubeData_vertexNormals[][3] = {{0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}}; + +static Float CubeData_texcoords[][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; + +static uint32_t CubeData_triangles[][3] = {{0, 1, 2}, {3, 0, 2}, {4, 5, 6}, {7, 4, 6}, {8, 9, 10}, {11, 8, 10}, {12, 13, 14}, {15, 12, 14}, {16, 17, 18}, {19, 16, 18}, {20, 21, 22}, {23, 20, 22}}; + +/*!\plugin{cube}{Cube intersection primitive} + * \order{0} + * \parameters{ + * \parameter{toWorld}{\Transform\Or\Animation}{ + * Specifies an optional linear object-to-world transformation. + * \default{none (i.e. object space $=$ world space)} + * } + * \parameter{flipNormals}{\Boolean}{ + * Is the cube inverted, i.e. should the normal vectors + * be flipped? \default{\code{false}, i.e. the normals point outside} + * } + * } + * + * \renderings{ + * \rendering{Basic example, see \lstref{cube-basic}} + * {shape_cube_basic} + * \rendering{A textured and stretched cube with the default parameterization + * (Listing~\ref{lst:cube-example})} + * {shape_cube_parameterization} + * } + * + * This shape plugin describes a simple cube/cuboid intersection primitive. By + * default, it creates a cube between the world-space positions $(0, 0, 0)$ and $(1,1,1)$. + * However, an arbitrary linear transformation may be specified to translate, rotate, scale + * or skew it as desired. The parameterization of this shape maps every face onto the + * rectangle $[0,1]^2$ in $uv$ space. + * \vspace{5mm} + * \begin{xml}[caption={Example of a textured and stretched cube}, label=lst:cube-example] + * + * + * + * + * + * + * + * + * + * + * + * \end{xml} + */ +class Cube : public TriMesh { +public: + Cube(const Properties &props) : TriMesh(props) { + m_name = props.getID(); + m_triangleCount = 12; + m_vertexCount = 24; + m_positions = new Point[m_vertexCount]; + m_texcoords = new Point2[m_vertexCount]; + m_normals = new Normal[m_vertexCount]; + m_triangles = new Triangle[m_triangleCount]; + + Transform toWorld = props.getTransform("toWorld", Transform()); + for (uint32_t i=0; i -#include #include #include #include @@ -31,6 +30,9 @@ MTS_NAMESPACE_BEGIN +/* Avoid having to include scenehandler.h */ +extern MTS_EXPORT_RENDER void pushSceneCleanupHandler(void (*cleanup)()); + /*!\plugin{serialized}{Serialized mesh loader} * \order{7} * \parameters{ @@ -57,7 +59,6 @@ MTS_NAMESPACE_BEGIN * } * \parameter{toWorld}{\Transform\Or\Animation}{ * Specifies an optional linear object-to-world transformation. - * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} * } * } @@ -185,7 +186,7 @@ public: } if (m_normals) { for (size_t i=0; i m_fstream; }; - struct FileStreamCache : LRUCache, - boost::shared_ptr > { + typedef LRUCache, + boost::shared_ptr > MeshLoaderCache; + class FileStreamCache : MeshLoaderCache { + public: inline boost::shared_ptr get(const fs::path& path) { bool dummy; - return LRUCache::get(path, dummy); + return MeshLoaderCache::get(path, dummy); } - FileStreamCache() : LRUCache(MTS_SERIALIZED_CACHE_SIZE, - &boost::make_shared) {} + FileStreamCache() : MeshLoaderCache(MTS_SERIALIZED_CACHE_SIZE, + &FileStreamCache::create) { } + + private: + inline static boost::shared_ptr create(const fs::path &path) { + return boost::make_shared(path); + } }; /// Release all currently held offset caches / file streams @@ -281,7 +289,7 @@ private: if (EXPECT_NOT_TAKEN(cache == NULL)) { cache = new FileStreamCache(); m_cache.set(cache); - SceneHandler::pushCleanupHandler(&SerializedMesh::flushCache); + mitsuba::pushSceneCleanupHandler(&SerializedMesh::flushCache); } boost::shared_ptr meshLoader = cache->get(filePath);