Merge with default
1
.hgtags
|
@ -10,3 +10,4 @@ ee26517b27207353b0c8a7d357bcb4977b5d93fb v0.4.0
|
||||||
f1b73d39617071297167cc7ce96f3892f21105fc v0.4.3
|
f1b73d39617071297167cc7ce96f3892f21105fc v0.4.3
|
||||||
bd6ddacdf7955e51d9b80be639c282d4974e6f56 v0.4.4
|
bd6ddacdf7955e51d9b80be639c282d4974e6f56 v0.4.4
|
||||||
454ebc86e4bd5b3c1d5eb6585099e66ccd8522fe v0.4.5
|
454ebc86e4bd5b3c1d5eb6585099e66ccd8522fe v0.4.5
|
||||||
|
e6a8a0178556bbce63a2a154191351aa58285623 v0.5.0
|
||||||
|
|
|
@ -24,6 +24,9 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
|
||||||
PYTHON27LIB = ['boost_python27', 'boost_system']
|
PYTHON27LIB = ['boost_python27', 'boost_system']
|
||||||
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
|
||||||
PYTHON33LIB = ['boost_python33', 'boost_system']
|
PYTHON33LIB = ['boost_python33', 'boost_system']
|
||||||
|
PYTHON34INCLUDE= ['#dependencies/include/python3.4']
|
||||||
|
PYTHON34LIB = ['boost_python34', 'boost_system']
|
||||||
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
COLLADAINCLUDE = ['#dependencies/include/collada-dom', '#dependencies/include/collada-dom/1.4']
|
||||||
COLLADALIB = ['collada14dom24']
|
COLLADALIB = ['collada14dom24']
|
||||||
QTDIR = '#dependencies'
|
QTDIR = '#dependencies'
|
||||||
|
|
|
@ -32,6 +32,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/i386_vc10'
|
QTDIR = '#dependencies/qt/i386_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/i386_vc10'
|
QTDIR = '#dependencies/qt/i386_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/i386_vc10'
|
QTDIR = '#dependencies/qt/i386_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -32,6 +32,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/x64_vc10'
|
QTDIR = '#dependencies/qt/x64_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/x64_vc10'
|
QTDIR = '#dependencies/qt/x64_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/x64_vc10'
|
QTDIR = '#dependencies/qt/x64_vc10'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
||||||
|
|
|
@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc120-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc120-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/x64_vc12'
|
QTDIR = '#dependencies/qt/x64_vc12'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
|
@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc120-mt-1_53', 'python32']
|
||||||
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
PYTHON32INCLUDE = ['#dependencies/include/python32']
|
||||||
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
|
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
|
||||||
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
PYTHON33INCLUDE = ['#dependencies/include/python33']
|
||||||
|
PYTHON34LIB = ['boost_python34-vc120-mt-1_53', 'python34']
|
||||||
|
PYTHON34INCLUDE = ['#dependencies/include/python34']
|
||||||
QTINCLUDE = ['#dependencies/qt/include']
|
QTINCLUDE = ['#dependencies/qt/include']
|
||||||
QTDIR = '#dependencies/qt/x64_vc12'
|
QTDIR = '#dependencies/qt/x64_vc12'
|
||||||
FFTWLIB = ['libfftw-3.3']
|
FFTWLIB = ['libfftw-3.3']
|
|
@ -1,3 +1,24 @@
|
||||||
|
mitsuba (0.5.0-1) unstable; urgency=low
|
||||||
|
* Mitsuba can now perform renderings of images with multiple channels
|
||||||
|
(e.g. a path traced rendering plus surface normals and depth). All
|
||||||
|
channels are rendered in one pass and written to a multi-channel EXR file.
|
||||||
|
* Anton Kaplanyan contributed mtsgui GUI usability tweaks and several
|
||||||
|
MLT-related robustness improvements
|
||||||
|
* Greatly improved Python integration, nice interaction with PyQt and NumPy,
|
||||||
|
Python 3.3. support on all platforms
|
||||||
|
* The 'mfilm' plugin now supports writing binary NumPy files (Joe Kider)
|
||||||
|
* Switch tabs in the gui using Alt+Left/Right keys
|
||||||
|
* Ask whether to stop long-running rendering processes when dragging the
|
||||||
|
mouse in the GUI
|
||||||
|
* Windows 8 compatibility
|
||||||
|
* CMake build system working again (Edgar Velázquez-Armendáriz)
|
||||||
|
* Statistics are now automatically reset between renderings
|
||||||
|
* mtssrv robustness improvements on OSX
|
||||||
|
* The 'thindielectric' plugin still computed incorrect results in some
|
||||||
|
situations, which is now fixed
|
||||||
|
* Added a new 'default' XML tag
|
||||||
|
-- Wenzel Jakob <wenzel@cs.cornell.edu> Tue, 25 Feb 2014 00:00:00 -0400
|
||||||
|
|
||||||
mitsuba (0.4.5-1) unstable; urgency=low
|
mitsuba (0.4.5-1) unstable; urgency=low
|
||||||
* New height field intersection shape
|
* New height field intersection shape
|
||||||
* kd-tree precision improvements when rendering in double precision
|
* kd-tree precision improvements when rendering in double precision
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Name: mitsuba
|
Name: mitsuba
|
||||||
Version: 0.4.5
|
Version: 0.5.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Mitsuba renderer
|
Summary: Mitsuba renderer
|
||||||
Group: Applications/Graphics
|
Group: Applications/Graphics
|
||||||
|
@ -24,7 +24,7 @@ building custom plugins and other extensions for Mitsuba.
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%build
|
%build
|
||||||
cat build/config-linux-gcc.py | sed -e "s/\(boost_[^']*\)/\1-mt/g" > config.py
|
cat build/config-linux-gcc.py | sed -e "s/collada14dom/libcollada-dom2.4-dp/g" | sed -e "s/include\/collada-dom/include\/collada-dom2.4/g" > config.py
|
||||||
scons
|
scons
|
||||||
%install
|
%install
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
@ -66,6 +66,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||||
/usr/include/*
|
/usr/include/*
|
||||||
%changelog
|
%changelog
|
||||||
|
|
||||||
|
* Tue Feb 25 2014 Wenzel Jakob <wenzel@cs.cornell.edu> 0.5.0%{?dist}
|
||||||
|
- Upgrade to version 0.5.0
|
||||||
|
|
||||||
* Sun Nov 10 2013 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.5%{?dist}
|
* Sun Nov 10 2013 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.5%{?dist}
|
||||||
- Upgrade to version 0.4.5
|
- Upgrade to version 0.4.5
|
||||||
|
|
||||||
|
|
|
@ -17,19 +17,22 @@ add_custom_command (
|
||||||
OUTPUT "${SCHEMA_DIR}/scene.xsd"
|
OUTPUT "${SCHEMA_DIR}/scene.xsd"
|
||||||
"${SCHEMA_DIR}/upgrade_0.3.0.xsl"
|
"${SCHEMA_DIR}/upgrade_0.3.0.xsl"
|
||||||
"${SCHEMA_DIR}/upgrade_0.4.0.xsl"
|
"${SCHEMA_DIR}/upgrade_0.4.0.xsl"
|
||||||
|
"${SCHEMA_DIR}/upgrade_0.5.0.xsl"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/scene.xsd" "${SCHEMA_DIR}/scene.xsd"
|
"${CMAKE_CURRENT_SOURCE_DIR}/scene.xsd" "${SCHEMA_DIR}/scene.xsd"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.3.0.xsl" "${SCHEMA_DIR}/upgrade_0.3.0.xsl"
|
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.3.0.xsl" "${SCHEMA_DIR}/upgrade_0.3.0.xsl"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.4.0.xsl" "${SCHEMA_DIR}/upgrade_0.4.0.xsl"
|
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.4.0.xsl" "${SCHEMA_DIR}/upgrade_0.4.0.xsl"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.5.0.xsl" "${SCHEMA_DIR}/upgrade_0.5.0.xsl"
|
||||||
MAIN_DEPENDENCY "scene.xsd"
|
MAIN_DEPENDENCY "scene.xsd"
|
||||||
DEPENDS "scene.xsd" "upgrade_0.3.0.xsl" "upgrade_0.4.0.xsl"
|
DEPENDS "scene.xsd" "upgrade_0.3.0.xsl" "upgrade_0.4.0.xsl" "upgrade_0.5.0.xsl"
|
||||||
COMMENT "Copying XML data: scene schema and upgrade XSL files"
|
COMMENT "Copying XML data: scene schema and upgrade XSL files"
|
||||||
)
|
)
|
||||||
add_custom_target (scene_schema
|
add_custom_target (scene_schema
|
||||||
DEPENDS "${SCHEMA_DIR}/scene.xsd"
|
DEPENDS "${SCHEMA_DIR}/scene.xsd"
|
||||||
"${SCHEMA_DIR}/upgrade_0.3.0.xsl" "${SCHEMA_DIR}/upgrade_0.4.0.xsl"
|
"${SCHEMA_DIR}/upgrade_0.3.0.xsl" "${SCHEMA_DIR}/upgrade_0.4.0.xsl" "${SCHEMA_DIR}/upgrade_0.5.0.xsl"
|
||||||
)
|
)
|
||||||
set_target_properties (scene_schema PROPERTIES FOLDER "data")
|
set_target_properties (scene_schema PROPERTIES FOLDER "data")
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<!-- Update the name of the bump plugin -->
|
<!-- Update the name of the bump plugin -->
|
||||||
<xsl:template match="integrator[@type='bump']/@type">
|
<xsl:template match="bsdf[@type='bump']/@type">
|
||||||
<xsl:attribute name="type">bumpmap</xsl:attribute>
|
<xsl:attribute name="type">bumpmap</xsl:attribute>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
|
@ -513,7 +513,6 @@
|
||||||
author={Kelemen, C. and Szirmay-Kalos, L. and Antal, G. and Csonka, F.},
|
author={Kelemen, C. and Szirmay-Kalos, L. and Antal, G. and Csonka, F.},
|
||||||
booktitle={Computer Graphics Forum},
|
booktitle={Computer Graphics Forum},
|
||||||
volume={21},
|
volume={21},
|
||||||
number={3},
|
|
||||||
pages={531--540},
|
pages={531--540},
|
||||||
year={2002}
|
year={2002}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,8 @@
|
||||||
\setcounter{secnumdepth}{3}
|
\setcounter{secnumdepth}{3}
|
||||||
\setcounter{tocdepth}{3}
|
\setcounter{tocdepth}{3}
|
||||||
|
|
||||||
\newcommand{\MitsubaVersion}{0.4.5}
|
\newcommand{\MitsubaVersion}{0.5.0}
|
||||||
\newcommand{\MitsubaYear}{2013}
|
\newcommand{\MitsubaYear}{2014}
|
||||||
|
|
||||||
\typearea[current]{last}
|
\typearea[current]{last}
|
||||||
\raggedbottom
|
\raggedbottom
|
||||||
|
|
154
doc/python.tex
|
@ -100,6 +100,8 @@ print(trafo * myVector)
|
||||||
\subsection{Recipes}
|
\subsection{Recipes}
|
||||||
The following section contains a series of ``recipes'' on how to do
|
The following section contains a series of ``recipes'' on how to do
|
||||||
certain things with the help of the Python bindings.
|
certain things with the help of the Python bindings.
|
||||||
|
To copy and paste from this chapter, the \LaTeX source code may
|
||||||
|
be more convenient. It is available at the following URL: \url{https://www.mitsuba-renderer.org/repos/mitsuba/files/tip/doc/python.tex}.
|
||||||
|
|
||||||
\subsubsection{Loading a scene}
|
\subsubsection{Loading a scene}
|
||||||
The following script demonstrates how to use the
|
The following script demonstrates how to use the
|
||||||
|
@ -303,6 +305,158 @@ scene.addChild(pmgr.create({
|
||||||
scene.configure()
|
scene.configure()
|
||||||
\end{python}
|
\end{python}
|
||||||
|
|
||||||
|
\subsubsection{Flexible scene generation for rendering in-process and emitting XML}
|
||||||
|
The following example shows how to construct a scene in a way so that it can
|
||||||
|
be rendered in-process or alternatively written to an XML file for later processing.
|
||||||
|
This is the recommended way of integrating Mitsuba into modeling software.
|
||||||
|
Roughly, the approach is to create an ordered dictionary version of the entire
|
||||||
|
scene (named \code{scene\_descr} below) that can either be passed to the
|
||||||
|
\code{PluginManager} or a simple function that turns it into Mitsuba-compatible XML.
|
||||||
|
|
||||||
|
The example below also does instancing via the \pluginref{shapegroup}
|
||||||
|
and \pluginref{instance} plugins to show how referencing can be implemented
|
||||||
|
for such an approach.
|
||||||
|
\begin{python}
|
||||||
|
import mitsuba
|
||||||
|
from mitsuba.core import *
|
||||||
|
from mitsuba.render import *
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
def rgb_spectrum(r, g, b):
|
||||||
|
spec = Spectrum()
|
||||||
|
spec.fromLinearRGB(r, g, b)
|
||||||
|
return spec
|
||||||
|
|
||||||
|
# Map that explains what functionality different plugins implement
|
||||||
|
plugin_type_map ={
|
||||||
|
'sphere' : 'shape',
|
||||||
|
'instance' : 'shape',
|
||||||
|
'shapegroup' : 'shape',
|
||||||
|
'diffuse' : 'bsdf',
|
||||||
|
'orthographic' : 'sensor' # need to complete
|
||||||
|
}
|
||||||
|
|
||||||
|
# Scene description as a big dictionary. The outermost layer
|
||||||
|
# should be ordered so that references can be processed correctly
|
||||||
|
scene_descr = OrderedDict([
|
||||||
|
('type', 'scene'),
|
||||||
|
('shapegroup_0', {
|
||||||
|
'type' : 'shapegroup',
|
||||||
|
'id' : 'my_shapegroup',
|
||||||
|
'some_child_geometry' : {
|
||||||
|
'type' : 'sphere',
|
||||||
|
'bsdf' : {
|
||||||
|
'type' : 'diffuse',
|
||||||
|
'reflectance' : rgb_spectrum(0.5, 0.7, 0.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
('instance_0', {
|
||||||
|
'type' : 'instance',
|
||||||
|
# This is how a reference is specified (type='ref')
|
||||||
|
'reference_to_shapegroup' : {
|
||||||
|
'type' : 'ref',
|
||||||
|
'id' : 'my_shapegroup'
|
||||||
|
},
|
||||||
|
'toWorld' : Transform.translate(Vector(1, 2.5, 3))
|
||||||
|
}),
|
||||||
|
('sensor_0', {
|
||||||
|
'type' : 'orthographic',
|
||||||
|
'toWorld' : Transform.lookAt(Point(0, 0, -1),
|
||||||
|
Point(0, 0, 0), Vector(0, 1, 0)) * Transform.scale(Vector(10, 10, 1))
|
||||||
|
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
def scene_descr_to_xml(descr):
|
||||||
|
import xml.etree.cElementTree as et
|
||||||
|
from xml.dom import minidom
|
||||||
|
|
||||||
|
def property_to_xml(key, value, parent):
|
||||||
|
if type(value) is Transform:
|
||||||
|
el = et.SubElement(parent, 'transform')
|
||||||
|
el.set('name', key)
|
||||||
|
el2 = et.SubElement(el, 'matrix')
|
||||||
|
matrix = value.getMatrix()
|
||||||
|
matrix_str = ""
|
||||||
|
for i in range(4):
|
||||||
|
for j in range(4):
|
||||||
|
matrix_str += "%.15g " % matrix[(i, j)]
|
||||||
|
el2.set('value', matrix_str[:-1])
|
||||||
|
elif type(value) is Spectrum:
|
||||||
|
r, g, b = value.toLinearRGB()
|
||||||
|
el = et.SubElement(parent, 'rgb')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('value', "%.15g %.15g %.15g" % (r, g, b))
|
||||||
|
elif type(value) is Point:
|
||||||
|
el = et.SubElement(parent, 'point')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('x', '%.15g' % value.x)
|
||||||
|
el.set('y', '%.15g' % value.y)
|
||||||
|
el.set('z', '%.15g' % value.z)
|
||||||
|
elif type(value) is Vector:
|
||||||
|
el = et.SubElement(parent, 'vector')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('x', '%.15g' % value.x)
|
||||||
|
el.set('y', '%.15g' % value.y)
|
||||||
|
el.set('z', '%.15g' % value.z)
|
||||||
|
elif type(value) is float:
|
||||||
|
el = et.SubElement(parent, 'float')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('value', '%.15g' % value)
|
||||||
|
elif type(value) is int:
|
||||||
|
el = et.SubElement(parent, 'int')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('value', '%i' % value)
|
||||||
|
elif type(value) is bool:
|
||||||
|
el = et.SubElement(parent, 'boolean')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('value', '%s' % ('true' if value else 'false'))
|
||||||
|
elif type(value) is str:
|
||||||
|
el = et.SubElement(parent, 'string')
|
||||||
|
el.set('name', key)
|
||||||
|
el.set('value', value)
|
||||||
|
else:
|
||||||
|
return None # (More kinds of attributes may need to be supported here..)
|
||||||
|
return el
|
||||||
|
|
||||||
|
def dict_to_xml(name, item, parent):
|
||||||
|
if parent is None:
|
||||||
|
el = et.Element('scene')
|
||||||
|
elif item['type'] == 'ref':
|
||||||
|
el = et.SubElement(parent, 'ref')
|
||||||
|
el.set('name', name)
|
||||||
|
el.set('id', item['id'])
|
||||||
|
else:
|
||||||
|
el = et.SubElement(parent, plugin_type_map[item['type']])
|
||||||
|
el.set('type', item['type'])
|
||||||
|
|
||||||
|
if name:
|
||||||
|
el.set('name', name)
|
||||||
|
if 'id' in item:
|
||||||
|
el.set('id', item['id'])
|
||||||
|
for key, value in item.items():
|
||||||
|
if key == 'id' or key == 'type':
|
||||||
|
continue
|
||||||
|
if type(value) is dict:
|
||||||
|
dict_to_xml(key, value, el)
|
||||||
|
else:
|
||||||
|
property_to_xml(key, value, el)
|
||||||
|
return el
|
||||||
|
|
||||||
|
root = dict_to_xml(None, descr, None)
|
||||||
|
root.set('version', $\texttt{\MitsubaVersion}$)
|
||||||
|
|
||||||
|
# Indent the ElementTree output (unfortunately this involves re-parsing..)
|
||||||
|
return minidom.parseString(
|
||||||
|
et.tostring(root, 'utf-8')).toprettyxml(indent='\t')
|
||||||
|
|
||||||
|
print('Mitsuba version: ')
|
||||||
|
print(PluginManager.getInstance().create(scene_descr))
|
||||||
|
print('XML version: ')
|
||||||
|
print(scene_descr_to_xml(scene_descr))
|
||||||
|
\end{python}
|
||||||
|
|
||||||
\subsubsection{Taking control of the logging system}
|
\subsubsection{Taking control of the logging system}
|
||||||
Many operations in Mitsuba will print one or more log messages
|
Many operations in Mitsuba will print one or more log messages
|
||||||
during their execution. By default, they will be printed to the console,
|
during their execution. By default, they will be printed to the console,
|
||||||
|
|
|
@ -223,6 +223,16 @@ public:
|
||||||
*/
|
*/
|
||||||
EPFM,
|
EPFM,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief PPM (Portable Pixel Map) image format
|
||||||
|
*
|
||||||
|
* The following is supported
|
||||||
|
* <ul>
|
||||||
|
* <li>Loading and saving of \ref EUInt8 and \ref EUInt16 - based RGB bitmaps</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
EPPM,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Joint Photographic Experts Group file format
|
* \brief Joint Photographic Experts Group file format
|
||||||
*
|
*
|
||||||
|
@ -678,12 +688,17 @@ public:
|
||||||
* specified component format. Names for each of the resulting channels should
|
* specified component format. Names for each of the resulting channels should
|
||||||
* be provided via the \c channelNames parameters.
|
* be provided via the \c channelNames parameters.
|
||||||
*
|
*
|
||||||
* This function is currently only used by the \c hdrfilm plugin but located here
|
* This feature is currently used by the \c hdrfilm and \c tiledhdrfilm plugins.
|
||||||
* as it is tied to the internals of this class.
|
|
||||||
*/
|
*/
|
||||||
ref<Bitmap> convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
|
ref<Bitmap> convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
|
||||||
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const;
|
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const;
|
||||||
|
|
||||||
|
/// Similar to the above, but writes to an already existing image
|
||||||
|
static void convertMultiSpectrumAlphaWeight(const Bitmap *source,
|
||||||
|
const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr,
|
||||||
|
const std::vector<EPixelFormat> &pixelFormats,
|
||||||
|
EComponentFormat componentFormat, size_t count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Apply Reinhard et al's tonemapper in chromaticity space
|
* \brief Apply Reinhard et al's tonemapper in chromaticity space
|
||||||
*
|
*
|
||||||
|
@ -1110,6 +1125,12 @@ protected:
|
||||||
/// Write a file using the PFM file format
|
/// Write a file using the PFM file format
|
||||||
void writePFM(Stream *stream) const;
|
void writePFM(Stream *stream) const;
|
||||||
|
|
||||||
|
/// Read a file stored using the PPM file format
|
||||||
|
void readPPM(Stream *stream);
|
||||||
|
|
||||||
|
/// Write a file using the PPM file format
|
||||||
|
void writePPM(Stream *stream) const;
|
||||||
|
|
||||||
/// Read a file stored using the TGA file format
|
/// Read a file stored using the TGA file format
|
||||||
void readTGA(Stream *stream);
|
void readTGA(Stream *stream);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ protected:
|
||||||
* \ingroup libpython
|
* \ingroup libpython
|
||||||
*/
|
*/
|
||||||
class MTS_EXPORT_CORE DefaultFormatter : public Formatter {
|
class MTS_EXPORT_CORE DefaultFormatter : public Formatter {
|
||||||
|
friend class Logger;
|
||||||
public:
|
public:
|
||||||
/// Create a new default formatter
|
/// Create a new default formatter
|
||||||
DefaultFormatter();
|
DefaultFormatter();
|
||||||
|
|
|
@ -26,13 +26,13 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \brief Current release of Mitsuba
|
* \brief Current release of Mitsuba
|
||||||
* \ingroup libcore
|
* \ingroup libcore
|
||||||
*/
|
*/
|
||||||
#define MTS_VERSION "0.4.5"
|
#define MTS_VERSION "0.5.0"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Year of the current release
|
* \brief Year of the current release
|
||||||
* \ingroup libcore
|
* \ingroup libcore
|
||||||
*/
|
*/
|
||||||
#define MTS_YEAR "2013"
|
#define MTS_YEAR "2014"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A simple data structure for representing and
|
* \brief A simple data structure for representing and
|
||||||
|
|
|
@ -28,7 +28,9 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \brief Von Mises-Fisher distribution on the 2-sphere
|
* \brief Von Mises-Fisher distribution on the 2-sphere
|
||||||
*
|
*
|
||||||
* This is a basic implementation, which assumes that the
|
* This is a basic implementation, which assumes that the
|
||||||
* distribution is centered around the Z-axis.
|
* distribution is centered around the Z-axis. All provided
|
||||||
|
* functions are implemented in such a way that they avoid
|
||||||
|
* issues with numerical overflow.
|
||||||
*
|
*
|
||||||
* \author Wenzel Jakob
|
* \author Wenzel Jakob
|
||||||
* \ingroup libcore
|
* \ingroup libcore
|
||||||
|
@ -39,13 +41,21 @@ public:
|
||||||
* \brief Create a new von Mises-Fisher distribution
|
* \brief Create a new von Mises-Fisher distribution
|
||||||
* with the given concentration parameter
|
* with the given concentration parameter
|
||||||
*/
|
*/
|
||||||
VonMisesFisherDistr(Float kappa = 0);
|
explicit inline VonMisesFisherDistr(Float kappa = 0) : m_kappa(kappa) { }
|
||||||
|
|
||||||
|
/// Return the concentration parameter kappa
|
||||||
|
inline void setKappa(Float kappa) {
|
||||||
|
m_kappa = kappa;
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the concentration parameter kappa
|
/// Return the concentration parameter kappa
|
||||||
inline Float getKappa() const {
|
inline Float getKappa() const {
|
||||||
return m_kappa;
|
return m_kappa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the mean cosine of the distribution
|
||||||
|
Float getMeanCosine() const;
|
||||||
|
|
||||||
/// Evaluate the distribution for a given value of cos(theta)
|
/// Evaluate the distribution for a given value of cos(theta)
|
||||||
Float eval(Float cosTheta) const;
|
Float eval(Float cosTheta) const;
|
||||||
|
|
||||||
|
@ -57,12 +67,21 @@ public:
|
||||||
*/
|
*/
|
||||||
Vector sample(const Point2 &sample) const;
|
Vector sample(const Point2 &sample) const;
|
||||||
|
|
||||||
|
/// Return a string representation
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Compute an appropriate concentration parameter so that
|
* \brief Compute an appropriate concentration parameter so that
|
||||||
* the associated vMF distribution takes on the value \c x at its peak
|
* the associated vMF distribution takes on the value \c x at its peak
|
||||||
*/
|
*/
|
||||||
static Float forPeakValue(Float x);
|
static Float forPeakValue(Float x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute an appropriate concentration parameter so that
|
||||||
|
* the associated vMF distribution has the mean cosine \c g.
|
||||||
|
*/
|
||||||
|
static Float forMeanCosine(Float g);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Compute an concentration parameter that approximately
|
* \brief Compute an concentration parameter that approximately
|
||||||
* corresponds to the spherical convolution of two vMF distributions.
|
* corresponds to the spherical convolution of two vMF distributions.
|
||||||
|
|
|
@ -2198,6 +2198,21 @@ protected:
|
||||||
*newEventsLeftEnd = newEventsLeftStart,
|
*newEventsLeftEnd = newEventsLeftStart,
|
||||||
*newEventsRightEnd = newEventsRightStart;
|
*newEventsRightEnd = newEventsRightStart;
|
||||||
|
|
||||||
|
AABBType leftNodeAABB_enlarged(leftNodeAABB),
|
||||||
|
rightNodeAABB_enlarged(rightNodeAABB);
|
||||||
|
|
||||||
|
#if defined(DOUBLE_PRECISION)
|
||||||
|
int axis0 = (bestSplit.axis + 1)%3, axis1 = (bestSplit.axis + 2)%3;
|
||||||
|
leftNodeAABB_enlarged.min[axis0] = rightNodeAABB_enlarged.min[axis0] =
|
||||||
|
nextafterf((float) nodeAABB.min[axis0], -std::numeric_limits<float>::max());
|
||||||
|
leftNodeAABB_enlarged.max[axis0] = rightNodeAABB_enlarged.max[axis0] =
|
||||||
|
nextafterf((float) nodeAABB.max[axis0], std::numeric_limits<float>::max());
|
||||||
|
leftNodeAABB_enlarged.min[axis1] = rightNodeAABB_enlarged.min[axis1] =
|
||||||
|
nextafterf((float) nodeAABB.min[axis1], -std::numeric_limits<float>::max());
|
||||||
|
leftNodeAABB_enlarged.max[axis1] = rightNodeAABB_enlarged.max[axis1] =
|
||||||
|
nextafterf((float) nodeAABB.max[axis1], std::numeric_limits<float>::max());
|
||||||
|
#endif
|
||||||
|
|
||||||
for (EdgeEvent *event = eventStart; event<eventEnd; ++event) {
|
for (EdgeEvent *event = eventStart; event<eventEnd; ++event) {
|
||||||
int classification = storage.get(event->index);
|
int classification = storage.get(event->index);
|
||||||
|
|
||||||
|
@ -2212,11 +2227,11 @@ protected:
|
||||||
generate new events for each side */
|
generate new events for each side */
|
||||||
const IndexType index = event->index;
|
const IndexType index = event->index;
|
||||||
|
|
||||||
AABBType clippedLeft = cast()->getClippedAABB(index, leftNodeAABB);
|
AABBType clippedLeft = cast()->getClippedAABB(index, leftNodeAABB_enlarged);
|
||||||
AABBType clippedRight = cast()->getClippedAABB(index, rightNodeAABB);
|
AABBType clippedRight = cast()->getClippedAABB(index, rightNodeAABB_enlarged);
|
||||||
|
|
||||||
KDAssert(leftNodeAABB.contains(clippedLeft));
|
KDAssert(leftNodeAABB_enlarged.contains(clippedLeft));
|
||||||
KDAssert(rightNodeAABB.contains(clippedRight));
|
KDAssert(rightNodeAABB_enlarged.contains(clippedRight));
|
||||||
|
|
||||||
if (clippedLeft.isValid() && clippedLeft.getSurfaceArea() > 0) {
|
if (clippedLeft.isValid() && clippedLeft.getSurfaceArea() > 0) {
|
||||||
for (int axis=0; axis<PointType::dim; ++axis) {
|
for (int axis=0; axis<PointType::dim; ++axis) {
|
||||||
|
|
|
@ -206,7 +206,7 @@ public:
|
||||||
/// Create a clone of the entire image block
|
/// Create a clone of the entire image block
|
||||||
ref<ImageBlock> clone() const {
|
ref<ImageBlock> clone() const {
|
||||||
ref<ImageBlock> clone = new ImageBlock(m_bitmap->getPixelFormat(),
|
ref<ImageBlock> clone = new ImageBlock(m_bitmap->getPixelFormat(),
|
||||||
m_bitmap->getSize() - Vector2i(2*m_borderSize, 2*m_borderSize), m_filter);
|
m_bitmap->getSize() - Vector2i(2*m_borderSize, 2*m_borderSize), m_filter, m_bitmap->getChannelCount());
|
||||||
copyTo(clone);
|
copyTo(clone);
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,8 +196,15 @@ public:
|
||||||
/* Potentially create a MIP map cache file */
|
/* Potentially create a MIP map cache file */
|
||||||
uint8_t *mmapData = NULL, *mmapPtr = NULL;
|
uint8_t *mmapData = NULL, *mmapPtr = NULL;
|
||||||
if (!cacheFilename.empty()) {
|
if (!cacheFilename.empty()) {
|
||||||
Log(EInfo, "Generating MIP map cache file \"%s\" ..", cacheFilename.c_str());
|
Log(EInfo, "Generating MIP map cache file \"%s\" ..", cacheFilename.string().c_str());
|
||||||
m_mmap = new MemoryMappedFile(cacheFilename, cacheSize);
|
try {
|
||||||
|
m_mmap = new MemoryMappedFile(cacheFilename, cacheSize);
|
||||||
|
} catch (std::runtime_error &e) {
|
||||||
|
Log(EWarn, "Unable to create MIP map cache file \"%s\" -- "
|
||||||
|
"retrying with a temporary file. Error message was: %s",
|
||||||
|
cacheFilename.string().c_str(), e.what());
|
||||||
|
m_mmap = MemoryMappedFile::createTemporary(cacheSize);
|
||||||
|
}
|
||||||
mmapData = mmapPtr = (uint8_t *) m_mmap->getData();
|
mmapData = mmapPtr = (uint8_t *) m_mmap->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +320,7 @@ public:
|
||||||
: m_weightLut(NULL), m_maxAnisotropy(maxAnisotropy) {
|
: m_weightLut(NULL), m_maxAnisotropy(maxAnisotropy) {
|
||||||
m_mmap = new MemoryMappedFile(cacheFilename);
|
m_mmap = new MemoryMappedFile(cacheFilename);
|
||||||
uint8_t *mmapPtr = (uint8_t *) m_mmap->getData();
|
uint8_t *mmapPtr = (uint8_t *) m_mmap->getData();
|
||||||
Log(EInfo, "Mapped MIP map cache file \"%s\" into memory (%s).", cacheFilename.c_str(),
|
Log(EInfo, "Mapped MIP map cache file \"%s\" into memory (%s).", cacheFilename.string().c_str(),
|
||||||
memString(m_mmap->getSize()).c_str());
|
memString(m_mmap->getSize()).c_str());
|
||||||
|
|
||||||
stats::mipStorage += m_mmap->getSize();
|
stats::mipStorage += m_mmap->getSize();
|
||||||
|
|
|
@ -85,8 +85,7 @@ public:
|
||||||
typedef std::map<std::string, ConfigurableObject *> NamedObjectMap;
|
typedef std::map<std::string, ConfigurableObject *> NamedObjectMap;
|
||||||
typedef std::map<std::string, std::string, SimpleStringOrdering> ParameterMap;
|
typedef std::map<std::string, std::string, SimpleStringOrdering> ParameterMap;
|
||||||
|
|
||||||
SceneHandler(const xercesc::SAXParser *parser,
|
SceneHandler(const ParameterMap ¶ms, NamedObjectMap *objects = NULL,
|
||||||
const ParameterMap ¶ms, NamedObjectMap *objects = NULL,
|
|
||||||
bool isIncludedFile = false);
|
bool isIncludedFile = false);
|
||||||
virtual ~SceneHandler();
|
virtual ~SceneHandler();
|
||||||
|
|
||||||
|
@ -115,6 +114,7 @@ public:
|
||||||
);
|
);
|
||||||
virtual void endElement(const XMLCh* const name);
|
virtual void endElement(const XMLCh* const name);
|
||||||
virtual void characters(const XMLCh* const chars, const XMLSize_t length);
|
virtual void characters(const XMLCh* const chars, const XMLSize_t length);
|
||||||
|
virtual void setDocumentLocator(const xercesc::Locator* const locator);
|
||||||
|
|
||||||
inline const Scene *getScene() const { return m_scene.get(); }
|
inline const Scene *getScene() const { return m_scene.get(); }
|
||||||
inline Scene *getScene() { return m_scene; }
|
inline Scene *getScene() { return m_scene; }
|
||||||
|
@ -166,12 +166,7 @@ private:
|
||||||
typedef std::pair<ETag, const Class *> TagEntry;
|
typedef std::pair<ETag, const Class *> TagEntry;
|
||||||
typedef boost::unordered_map<std::string, TagEntry> TagMap;
|
typedef boost::unordered_map<std::string, TagEntry> TagMap;
|
||||||
|
|
||||||
#if defined(__clang__)
|
const xercesc::Locator *m_locator;
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const xercesc::SAXParser *m_parser;
|
|
||||||
xercesc::XMLTranscoder* m_transcoder;
|
xercesc::XMLTranscoder* m_transcoder;
|
||||||
ref<Scene> m_scene;
|
ref<Scene> m_scene;
|
||||||
ParameterMap m_params;
|
ParameterMap m_params;
|
||||||
|
@ -182,10 +177,6 @@ private:
|
||||||
Transform m_transform;
|
Transform m_transform;
|
||||||
ref<AnimatedTransform> m_animatedTransform;
|
ref<AnimatedTransform> m_animatedTransform;
|
||||||
bool m_isIncludedFile;
|
bool m_isIncludedFile;
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -7,10 +7,7 @@ if hasCollada:
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
colladaEnv = mainEnv.Clone()
|
colladaEnv = mainEnv.Clone()
|
||||||
if platform.linux_distribution()[0] == 'Fedora':
|
colladaEnv.Prepend(CXXFLAGS=['-DCOLLADA_DOM_2_4'])
|
||||||
pass # Use old COLLADA-DOM 2.3
|
|
||||||
else: # Everyone else uses 2.4
|
|
||||||
colladaEnv.Prepend(CXXFLAGS=['-DCOLLADA_DOM_2_4'])
|
|
||||||
|
|
||||||
# Build the COLLADA importer if COLLADA-DOM is vailable
|
# Build the COLLADA importer if COLLADA-DOM is vailable
|
||||||
colladaEnv.Append(LIBS=['mitsuba-hw'])
|
colladaEnv.Append(LIBS=['mitsuba-hw'])
|
||||||
|
|
|
@ -215,7 +215,7 @@ public:
|
||||||
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
|
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
|
||||||
props.getString("pixelFormat", "rgb")), " ,");
|
props.getString("pixelFormat", "rgb")), " ,");
|
||||||
std::vector<std::string> channelNames = tokenize(
|
std::vector<std::string> channelNames = tokenize(
|
||||||
props.getString("channelNames", "rgb"), ", ");
|
props.getString("channelNames", ""), ", ");
|
||||||
std::string componentFormat = boost::to_lower_copy(
|
std::string componentFormat = boost::to_lower_copy(
|
||||||
props.getString("componentFormat", "float16"));
|
props.getString("componentFormat", "float16"));
|
||||||
|
|
||||||
|
@ -227,58 +227,64 @@ public:
|
||||||
m_fileFormat = Bitmap::EPFM;
|
m_fileFormat = Bitmap::EPFM;
|
||||||
} else {
|
} else {
|
||||||
Log(EError, "The \"fileFormat\" parameter must either be "
|
Log(EError, "The \"fileFormat\" parameter must either be "
|
||||||
"equal to \"openexr\" or \"rgbe\"!");
|
"equal to \"openexr\", \"pfm\", or \"rgbe\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixelFormats.empty())
|
if (pixelFormats.empty())
|
||||||
Log(EError, "At least one pixel format must be specified!");
|
Log(EError, "At least one pixel format must be specified!");
|
||||||
|
|
||||||
if (m_pixelFormats.size() != 1 && m_channelNames.size() != m_pixelFormats.size())
|
if (pixelFormats.size() != 1 && channelNames.size() != pixelFormats.size())
|
||||||
Log(EError, "Number of channel names must match the number of specified pixel formats!");
|
Log(EError, "Number of channel names must match the number of specified pixel formats!");
|
||||||
|
|
||||||
|
if (pixelFormats.size() != 1 && m_fileFormat != Bitmap::EOpenEXR)
|
||||||
|
Log(EError, "General multi-channel output is only supported when writing OpenEXR files!");
|
||||||
|
|
||||||
for (size_t i=0; i<pixelFormats.size(); ++i) {
|
for (size_t i=0; i<pixelFormats.size(); ++i) {
|
||||||
std::string pixelFormat = pixelFormats[i];
|
std::string pixelFormat = pixelFormats[i];
|
||||||
std::string name = i < channelNames.size() ? channelNames[i] : "";
|
std::string name = i < channelNames.size() ? (channelNames[i] + std::string(".")) : "";
|
||||||
|
|
||||||
if (pixelFormat == "luminance") {
|
if (pixelFormat == "luminance") {
|
||||||
m_pixelFormats.push_back(Bitmap::ELuminance);
|
m_pixelFormats.push_back(Bitmap::ELuminance);
|
||||||
m_channelNames.push_back(name + ".Y");
|
m_channelNames.push_back(name + "Y");
|
||||||
} else if (pixelFormat == "luminancealpha") {
|
} else if (pixelFormat == "luminancealpha") {
|
||||||
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
|
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
|
||||||
m_channelNames.push_back(name + ".Y");
|
m_channelNames.push_back(name + "Y");
|
||||||
m_channelNames.push_back(name + ".A");
|
m_channelNames.push_back(name + "A");
|
||||||
} else if (pixelFormat == "rgb") {
|
} else if (pixelFormat == "rgb") {
|
||||||
m_pixelFormats.push_back(Bitmap::ERGB);
|
m_pixelFormats.push_back(Bitmap::ERGB);
|
||||||
m_channelNames.push_back(name + ".R");
|
m_channelNames.push_back(name + "R");
|
||||||
m_channelNames.push_back(name + ".G");
|
m_channelNames.push_back(name + "G");
|
||||||
m_channelNames.push_back(name + ".B");
|
m_channelNames.push_back(name + "B");
|
||||||
} else if (pixelFormat == "rgba") {
|
} else if (pixelFormat == "rgba") {
|
||||||
m_pixelFormats.push_back(Bitmap::ERGBA);
|
m_pixelFormats.push_back(Bitmap::ERGBA);
|
||||||
m_channelNames.push_back(name + ".R");
|
m_channelNames.push_back(name + "R");
|
||||||
m_channelNames.push_back(name + ".G");
|
m_channelNames.push_back(name + "G");
|
||||||
m_channelNames.push_back(name + ".B");
|
m_channelNames.push_back(name + "B");
|
||||||
m_channelNames.push_back(name + ".A");
|
m_channelNames.push_back(name + "A");
|
||||||
} else if (pixelFormat == "xyz") {
|
} else if (pixelFormat == "xyz") {
|
||||||
m_pixelFormats.push_back(Bitmap::EXYZ);
|
m_pixelFormats.push_back(Bitmap::EXYZ);
|
||||||
if (m_pixelFormats.size() > 1)
|
m_channelNames.push_back(name + "X");
|
||||||
Log(EError, "The XYZ pixel format is not supported for general multi-channel images!");
|
m_channelNames.push_back(name + "Y");
|
||||||
|
m_channelNames.push_back(name + "Z");
|
||||||
} else if (pixelFormat == "xyza") {
|
} else if (pixelFormat == "xyza") {
|
||||||
m_pixelFormats.push_back(Bitmap::EXYZA);
|
m_pixelFormats.push_back(Bitmap::EXYZA);
|
||||||
if (m_pixelFormats.size() > 1)
|
m_channelNames.push_back(name + "X");
|
||||||
Log(EError, "The XYZA pixel format is not supported for general multi-channel images!");
|
m_channelNames.push_back(name + "Y");
|
||||||
|
m_channelNames.push_back(name + "Z");
|
||||||
|
m_channelNames.push_back(name + "A");
|
||||||
} else if (pixelFormat == "spectrum") {
|
} else if (pixelFormat == "spectrum") {
|
||||||
m_pixelFormats.push_back(Bitmap::ESpectrum);
|
m_pixelFormats.push_back(Bitmap::ESpectrum);
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
||||||
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
||||||
m_channelNames.push_back(name + formatString(".%.2f-%.2fnm", coverage.first, coverage.second));
|
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
|
||||||
}
|
}
|
||||||
} else if (pixelFormat == "spectrumalpha") {
|
} else if (pixelFormat == "spectrumalpha") {
|
||||||
m_pixelFormats.push_back(Bitmap::ESpectrumAlpha);
|
m_pixelFormats.push_back(Bitmap::ESpectrumAlpha);
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
||||||
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
||||||
m_channelNames.push_back(name + formatString(".%.2f-%.2fnm", coverage.first, coverage.second));
|
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
|
||||||
}
|
}
|
||||||
m_channelNames.push_back(name + ".A");
|
m_channelNames.push_back(name + "A");
|
||||||
} else {
|
} else {
|
||||||
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
|
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
|
||||||
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
|
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
|
||||||
|
@ -529,13 +535,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAlpha() const {
|
bool hasAlpha() const {
|
||||||
Assert(m_pixelFormats.size() > 0);
|
for (size_t i=0; i<m_pixelFormats.size(); ++i) {
|
||||||
return
|
if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
|
||||||
m_pixelFormats[0] == Bitmap::ELuminanceAlpha ||
|
m_pixelFormats[i] == Bitmap::ERGBA ||
|
||||||
m_pixelFormats[0] == Bitmap::ERGBA ||
|
m_pixelFormats[i] == Bitmap::EXYZA ||
|
||||||
m_pixelFormats[0] == Bitmap::EXYZA ||
|
m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
|
||||||
m_pixelFormats[0] == Bitmap::ESpectrumAlpha ||
|
return true;
|
||||||
m_pixelFormats.size() > 1;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool destinationExists(const fs::path &baseName) const {
|
bool destinationExists(const fs::path &baseName) const {
|
||||||
|
|
|
@ -101,37 +101,78 @@ MTS_NAMESPACE_BEGIN
|
||||||
class TiledHDRFilm : public Film {
|
class TiledHDRFilm : public Film {
|
||||||
public:
|
public:
|
||||||
TiledHDRFilm(const Properties &props) : Film(props), m_output(NULL), m_frameBuffer(NULL) {
|
TiledHDRFilm(const Properties &props) : Film(props), m_output(NULL), m_frameBuffer(NULL) {
|
||||||
std::string pixelFormat = boost::to_lower_copy(
|
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
|
||||||
props.getString("pixelFormat", "rgb"));
|
props.getString("pixelFormat", "rgb")), " ,");
|
||||||
|
std::vector<std::string> channelNames = tokenize(
|
||||||
|
props.getString("channelNames", ""), ", ");
|
||||||
std::string componentFormat = boost::to_lower_copy(
|
std::string componentFormat = boost::to_lower_copy(
|
||||||
props.getString("componentFormat", "float16"));
|
props.getString("componentFormat", "float16"));
|
||||||
|
|
||||||
if (pixelFormat == "luminance") {
|
if (pixelFormats.empty())
|
||||||
m_pixelFormat = Bitmap::ELuminance;
|
Log(EError, "At least one pixel format must be specified!");
|
||||||
} else if (pixelFormat == "luminancealpha") {
|
|
||||||
m_pixelFormat = Bitmap::ELuminanceAlpha;
|
if (pixelFormats.size() != 1 && channelNames.size() != pixelFormats.size())
|
||||||
} else if (pixelFormat == "rgb") {
|
Log(EError, "Number of channel names must match the number of specified pixel formats!");
|
||||||
m_pixelFormat = Bitmap::ERGB;
|
|
||||||
} else if (pixelFormat == "rgba") {
|
for (size_t i=0; i<pixelFormats.size(); ++i) {
|
||||||
m_pixelFormat = Bitmap::ERGBA;
|
std::string pixelFormat = pixelFormats[i];
|
||||||
} else if (pixelFormat == "xyz") {
|
std::string name = i < channelNames.size() ? (channelNames[i] + std::string(".")) : "";
|
||||||
m_pixelFormat = Bitmap::EXYZ;
|
|
||||||
} else if (pixelFormat == "xyza") {
|
if (pixelFormat == "luminance") {
|
||||||
m_pixelFormat = Bitmap::EXYZA;
|
m_pixelFormats.push_back(Bitmap::ELuminance);
|
||||||
} else if (pixelFormat == "spectrum") {
|
m_channelNames.push_back(name + "Y");
|
||||||
m_pixelFormat = Bitmap::ESpectrum;
|
} else if (pixelFormat == "luminancealpha") {
|
||||||
} else if (pixelFormat == "spectrumalpha") {
|
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
|
||||||
m_pixelFormat = Bitmap::ESpectrumAlpha;
|
m_channelNames.push_back(name + "Y");
|
||||||
} else {
|
m_channelNames.push_back(name + "A");
|
||||||
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
|
} else if (pixelFormat == "rgb") {
|
||||||
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
|
m_pixelFormats.push_back(Bitmap::ERGB);
|
||||||
"\"spectrum\", or \"spectrumAlpha\"!");
|
m_channelNames.push_back(name + "R");
|
||||||
|
m_channelNames.push_back(name + "G");
|
||||||
|
m_channelNames.push_back(name + "B");
|
||||||
|
} else if (pixelFormat == "rgba") {
|
||||||
|
m_pixelFormats.push_back(Bitmap::ERGBA);
|
||||||
|
m_channelNames.push_back(name + "R");
|
||||||
|
m_channelNames.push_back(name + "G");
|
||||||
|
m_channelNames.push_back(name + "B");
|
||||||
|
m_channelNames.push_back(name + "A");
|
||||||
|
} else if (pixelFormat == "xyz") {
|
||||||
|
m_pixelFormats.push_back(Bitmap::EXYZ);
|
||||||
|
m_channelNames.push_back(name + "X");
|
||||||
|
m_channelNames.push_back(name + "Y");
|
||||||
|
m_channelNames.push_back(name + "Z");
|
||||||
|
} else if (pixelFormat == "xyza") {
|
||||||
|
m_pixelFormats.push_back(Bitmap::EXYZA);
|
||||||
|
m_channelNames.push_back(name + "X");
|
||||||
|
m_channelNames.push_back(name + "Y");
|
||||||
|
m_channelNames.push_back(name + "Z");
|
||||||
|
m_channelNames.push_back(name + "A");
|
||||||
|
} else if (pixelFormat == "spectrum") {
|
||||||
|
m_pixelFormats.push_back(Bitmap::ESpectrum);
|
||||||
|
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
||||||
|
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
||||||
|
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
|
||||||
|
}
|
||||||
|
} else if (pixelFormat == "spectrumalpha") {
|
||||||
|
m_pixelFormats.push_back(Bitmap::ESpectrumAlpha);
|
||||||
|
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
||||||
|
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
||||||
|
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
|
||||||
|
}
|
||||||
|
m_channelNames.push_back(name + "A");
|
||||||
|
} else {
|
||||||
|
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
|
||||||
|
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
|
||||||
|
"\"spectrum\", or \"spectrumAlpha\"!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPECTRUM_SAMPLES == 3 && (m_pixelFormat == Bitmap::ESpectrum || m_pixelFormat == Bitmap::ESpectrumAlpha))
|
for (size_t i=0; i<m_pixelFormats.size(); ++i) {
|
||||||
Log(EError, "You requested to render a spectral image, but Mitsuba is currently "
|
if (SPECTRUM_SAMPLES == 3 && (m_pixelFormats[i] == Bitmap::ESpectrum || m_pixelFormats[i] == Bitmap::ESpectrumAlpha))
|
||||||
"configured for a RGB flow (i.e. SPECTRUM_SAMPLES = 3). You will need to recompile "
|
Log(EError, "You requested to render a spectral image, but Mitsuba is currently "
|
||||||
"it with a different configuration. Please see the documentation for details.");
|
"configured for a RGB flow (i.e. SPECTRUM_SAMPLES = 3). You will need to recompile "
|
||||||
|
"it with a different configuration. Please see the documentation for details.");
|
||||||
|
}
|
||||||
|
|
||||||
if (componentFormat == "float16") {
|
if (componentFormat == "float16") {
|
||||||
m_componentFormat = Bitmap::EFloat16;
|
m_componentFormat = Bitmap::EFloat16;
|
||||||
|
@ -151,7 +192,12 @@ public:
|
||||||
|
|
||||||
TiledHDRFilm(Stream *stream, InstanceManager *manager)
|
TiledHDRFilm(Stream *stream, InstanceManager *manager)
|
||||||
: Film(stream, manager), m_output(NULL), m_frameBuffer(NULL) {
|
: Film(stream, manager), m_output(NULL), m_frameBuffer(NULL) {
|
||||||
m_pixelFormat = (Bitmap::EPixelFormat) stream->readUInt();
|
m_pixelFormats.resize((size_t) stream->readUInt());
|
||||||
|
for (size_t i=0; i<m_pixelFormats.size(); ++i)
|
||||||
|
m_pixelFormats[i] = (Bitmap::EPixelFormat) stream->readUInt();
|
||||||
|
m_channelNames.resize((size_t) stream->readUInt());
|
||||||
|
for (size_t i=0; i<m_channelNames.size(); ++i)
|
||||||
|
m_channelNames[i] = stream->readString();
|
||||||
m_componentFormat = (Bitmap::EComponentFormat) stream->readUInt();
|
m_componentFormat = (Bitmap::EComponentFormat) stream->readUInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +207,11 @@ public:
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
Film::serialize(stream, manager);
|
Film::serialize(stream, manager);
|
||||||
stream->writeUInt(m_pixelFormat);
|
for (size_t i=0; i<m_pixelFormats.size(); ++i)
|
||||||
|
stream->writeUInt(m_pixelFormats[i]);
|
||||||
|
stream->writeUInt((uint32_t) m_channelNames.size());
|
||||||
|
for (size_t i=0; i<m_channelNames.size(); ++i)
|
||||||
|
stream->writeString(m_channelNames[i]);
|
||||||
stream->writeUInt(m_componentFormat);
|
stream->writeUInt(m_componentFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,15 +219,6 @@ public:
|
||||||
if (m_output)
|
if (m_output)
|
||||||
develop(NULL, 0);
|
develop(NULL, 0);
|
||||||
|
|
||||||
Bitmap::EPixelFormat pixelFormat = m_pixelFormat;
|
|
||||||
#if SPECTRUM_SAMPLES == 3
|
|
||||||
if (pixelFormat == Bitmap::ESpectrum)
|
|
||||||
pixelFormat = Bitmap::ERGB;
|
|
||||||
if (pixelFormat == Bitmap::ESpectrumAlpha)
|
|
||||||
pixelFormat = Bitmap::ERGBA;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
fs::path filename = destFile;
|
fs::path filename = destFile;
|
||||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||||
if (extension != ".exr")
|
if (extension != ".exr")
|
||||||
|
@ -189,19 +230,22 @@ public:
|
||||||
header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL));
|
header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL));
|
||||||
header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION));
|
header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION));
|
||||||
|
|
||||||
if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
|
if (m_pixelFormats.size() == 1) {
|
||||||
Imf::addChromaticities(header, Imf::Chromaticities(
|
/* Write a chromaticity tag when this is possible */
|
||||||
Imath::V2f(1.0f, 0.0f),
|
Bitmap::EPixelFormat pixelFormat = m_pixelFormats[0];
|
||||||
Imath::V2f(0.0f, 1.0f),
|
if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
|
||||||
Imath::V2f(0.0f, 0.0f),
|
Imf::addChromaticities(header, Imf::Chromaticities(
|
||||||
Imath::V2f(1.0f/3.0f, 1.0f/3.0f)));
|
Imath::V2f(1.0f, 0.0f),
|
||||||
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA) {
|
Imath::V2f(0.0f, 1.0f),
|
||||||
Imf::addChromaticities(header, Imf::Chromaticities());
|
Imath::V2f(0.0f, 0.0f),
|
||||||
|
Imath::V2f(1.0f/3.0f, 1.0f/3.0f)));
|
||||||
|
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA) {
|
||||||
|
Imf::addChromaticities(header, Imf::Chromaticities());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Imf::PixelType compType;
|
Imf::PixelType compType;
|
||||||
size_t compStride;
|
size_t compStride;
|
||||||
int channelCount;
|
|
||||||
|
|
||||||
if (m_componentFormat == Bitmap::EFloat16) {
|
if (m_componentFormat == Bitmap::EFloat16) {
|
||||||
compType = Imf::HALF;
|
compType = Imf::HALF;
|
||||||
|
@ -219,62 +263,34 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Imf::ChannelList &channels = header.channels();
|
Imf::ChannelList &channels = header.channels();
|
||||||
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) {
|
for (size_t i=0; i<m_channelNames.size(); ++i)
|
||||||
channels.insert("Y", Imf::Channel(compType));
|
channels.insert(m_channelNames[i].c_str(), Imf::Channel(compType));
|
||||||
channelCount = 1;
|
|
||||||
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA ||
|
|
||||||
pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
|
|
||||||
channels.insert("R", Imf::Channel(compType));
|
|
||||||
channels.insert("G", Imf::Channel(compType));
|
|
||||||
channels.insert("B", Imf::Channel(compType));
|
|
||||||
channelCount = 3;
|
|
||||||
} else if (pixelFormat == Bitmap::ESpectrum || pixelFormat == Bitmap::ESpectrumAlpha) {
|
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
|
||||||
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
|
||||||
std::string name = formatString("%.2f-%.2fnm", coverage.first, coverage.second);
|
|
||||||
channels.insert(name.c_str(), Imf::Channel(compType));
|
|
||||||
}
|
|
||||||
channelCount = SPECTRUM_SAMPLES;
|
|
||||||
} else {
|
|
||||||
Log(EError, "Invalid pixel format!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pixelFormat == Bitmap::ELuminanceAlpha || m_pixelFormat == Bitmap::ERGBA ||
|
|
||||||
m_pixelFormat == Bitmap::ESpectrumAlpha) {
|
|
||||||
channels.insert("A", Imf::Channel(compType));
|
|
||||||
channelCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_output = new Imf::TiledOutputFile(filename.string().c_str(), header);
|
m_output = new Imf::TiledOutputFile(filename.string().c_str(), header);
|
||||||
m_frameBuffer = new Imf::FrameBuffer();
|
m_frameBuffer = new Imf::FrameBuffer();
|
||||||
m_blockSize = (int) blockSize;
|
m_blockSize = (int) blockSize;
|
||||||
m_tile = new Bitmap(m_pixelFormat, m_componentFormat, Vector2i(m_blockSize, m_blockSize));
|
|
||||||
m_blocksH = (m_size.x + blockSize - 1) / blockSize;
|
m_blocksH = (m_size.x + blockSize - 1) / blockSize;
|
||||||
m_blocksV = (m_size.y + blockSize - 1) / blockSize;
|
m_blocksV = (m_size.y + blockSize - 1) / blockSize;
|
||||||
|
|
||||||
m_pixelStride = channelCount * compStride;
|
m_pixelStride = m_channelNames.size() * compStride;
|
||||||
m_rowStride = m_pixelStride * m_blockSize;
|
m_rowStride = m_pixelStride * m_blockSize;
|
||||||
char *ptr = (char *) m_tile->getUInt8Data();
|
|
||||||
|
|
||||||
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) {
|
if (m_pixelFormats.size() == 1) {
|
||||||
m_frameBuffer->insert("Y", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
|
m_tile = new Bitmap(m_pixelFormats[0], m_componentFormat,
|
||||||
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA ||
|
Vector2i(m_blockSize, m_blockSize));
|
||||||
pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
|
} else {
|
||||||
m_frameBuffer->insert("R", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
|
m_tile = new Bitmap(Bitmap::EMultiChannel, m_componentFormat,
|
||||||
m_frameBuffer->insert("G", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
|
Vector2i(m_blockSize, m_blockSize), m_channelNames.size());
|
||||||
m_frameBuffer->insert("B", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
|
m_tile->setChannelNames(m_channelNames);
|
||||||
} else if (pixelFormat == Bitmap::ESpectrum || pixelFormat == Bitmap::ESpectrumAlpha) {
|
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
|
|
||||||
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
|
|
||||||
std::string name = formatString("%f-%fnm", coverage.first, coverage.second);
|
|
||||||
m_frameBuffer->insert(name.c_str(), Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pixelFormat == Bitmap::ERGBA || m_pixelFormat == Bitmap::EXYZA ||
|
char *ptr = (char *) m_tile->getUInt8Data();
|
||||||
m_pixelFormat == Bitmap::ELuminanceAlpha)
|
|
||||||
m_frameBuffer->insert("A", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride));
|
for (size_t i=0; i<m_channelNames.size(); ++i) {
|
||||||
|
m_frameBuffer->insert(m_channelNames[i].c_str(),
|
||||||
|
Imf::Slice(compType, ptr, m_pixelStride, m_rowStride));
|
||||||
|
ptr += compStride;
|
||||||
|
}
|
||||||
|
|
||||||
m_output->setFrameBuffer(*m_frameBuffer);
|
m_output->setFrameBuffer(*m_frameBuffer);
|
||||||
m_peakUsage = 0;
|
m_peakUsage = 0;
|
||||||
|
@ -316,7 +332,6 @@ public:
|
||||||
++m_peakUsage;
|
++m_peakUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t idx = (uint32_t) x + (uint32_t) y * m_blocksH;
|
uint32_t idx = (uint32_t) x + (uint32_t) y * m_blocksH;
|
||||||
m_origBlocks[idx] = copy1;
|
m_origBlocks[idx] = copy1;
|
||||||
m_mergedBlocks[idx] = copy2;
|
m_mergedBlocks[idx] = copy2;
|
||||||
|
@ -388,6 +403,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const Bitmap *source = mergedBlock->getBitmap();
|
const Bitmap *source = mergedBlock->getBitmap();
|
||||||
|
|
||||||
size_t sourceBpp = source->getBytesPerPixel();
|
size_t sourceBpp = source->getBytesPerPixel();
|
||||||
size_t targetBpp = m_tile->getBytesPerPixel();
|
size_t targetBpp = m_tile->getBytesPerPixel();
|
||||||
|
|
||||||
|
@ -400,11 +416,15 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
for (int i=0; i<m_blockSize; ++i) {
|
for (int i=0; i<m_blockSize; ++i) {
|
||||||
cvt->convert(source->getPixelFormat(), 1.0f, sourceData,
|
if (m_pixelFormats.size() == 1)
|
||||||
m_tile->getPixelFormat(), m_tile->getGamma(), targetData,
|
cvt->convert(source->getPixelFormat(), 1.0f, sourceData,
|
||||||
m_tile->getWidth());
|
m_tile->getPixelFormat(), m_tile->getGamma(), targetData,
|
||||||
|
m_tile->getWidth());
|
||||||
|
else
|
||||||
|
Bitmap::convertMultiSpectrumAlphaWeight(source, sourceData,
|
||||||
|
m_tile, targetData, m_pixelFormats, m_componentFormat, m_tile->getWidth());
|
||||||
|
|
||||||
sourceData += source->getWidth() * sourceBpp;
|
sourceData += source->getWidth() * sourceBpp;
|
||||||
targetData += m_tile->getWidth() * targetBpp;
|
targetData += m_tile->getWidth() * targetBpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,11 +490,14 @@ public:
|
||||||
void clear() { /* Do nothing */ }
|
void clear() { /* Do nothing */ }
|
||||||
|
|
||||||
bool hasAlpha() const {
|
bool hasAlpha() const {
|
||||||
return
|
for (size_t i=0; i<m_pixelFormats.size(); ++i) {
|
||||||
m_pixelFormat == Bitmap::ELuminanceAlpha ||
|
if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
|
||||||
m_pixelFormat == Bitmap::ERGBA ||
|
m_pixelFormats[i] == Bitmap::ERGBA ||
|
||||||
m_pixelFormat == Bitmap::EXYZA ||
|
m_pixelFormats[i] == Bitmap::EXYZA ||
|
||||||
m_pixelFormat == Bitmap::ESpectrumAlpha;
|
m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool destinationExists(const fs::path &baseName) const {
|
bool destinationExists(const fs::path &baseName) const {
|
||||||
|
@ -488,7 +511,14 @@ public:
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "TiledHDRFilm[" << endl
|
oss << "TiledHDRFilm[" << endl
|
||||||
<< " size = " << m_size.toString() << "," << endl
|
<< " size = " << m_size.toString() << "," << endl
|
||||||
<< " pixelFormat = " << m_pixelFormat << "," << endl
|
<< " pixelFormat = ";
|
||||||
|
for (size_t i=0; i<m_pixelFormats.size(); ++i)
|
||||||
|
oss << m_pixelFormats[i] << ", ";
|
||||||
|
oss << endl
|
||||||
|
<< " channelNames = ";
|
||||||
|
for (size_t i=0; i<m_channelNames.size(); ++i)
|
||||||
|
oss << "\"" << m_channelNames[i] << "\"" << ", ";
|
||||||
|
oss << endl
|
||||||
<< " componentFormat = " << m_componentFormat << "," << endl
|
<< " componentFormat = " << m_componentFormat << "," << endl
|
||||||
<< " cropOffset = " << m_cropOffset.toString() << "," << endl
|
<< " cropOffset = " << m_cropOffset.toString() << "," << endl
|
||||||
<< " cropSize = " << m_cropSize.toString() << "," << endl
|
<< " cropSize = " << m_cropSize.toString() << "," << endl
|
||||||
|
@ -499,7 +529,8 @@ public:
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
protected:
|
protected:
|
||||||
Bitmap::EPixelFormat m_pixelFormat;
|
std::vector<Bitmap::EPixelFormat> m_pixelFormats;
|
||||||
|
std::vector<std::string> m_channelNames;
|
||||||
Bitmap::EComponentFormat m_componentFormat;
|
Bitmap::EComponentFormat m_componentFormat;
|
||||||
std::vector<ImageBlock *> m_freeBlocks;
|
std::vector<ImageBlock *> m_freeBlocks;
|
||||||
std::map<uint32_t, ImageBlock *> m_origBlocks, m_mergedBlocks;
|
std::map<uint32_t, ImageBlock *> m_origBlocks, m_mergedBlocks;
|
||||||
|
|
|
@ -30,6 +30,7 @@ add_integrator(adaptive misc/adaptive.cpp)
|
||||||
add_integrator(irrcache misc/irrcache.cpp
|
add_integrator(irrcache misc/irrcache.cpp
|
||||||
misc/irrcache_proc.h misc/irrcache_proc.cpp)
|
misc/irrcache_proc.h misc/irrcache_proc.cpp)
|
||||||
add_integrator(multichannel misc/multichannel.cpp)
|
add_integrator(multichannel misc/multichannel.cpp)
|
||||||
|
add_integrator(field misc/field.cpp)
|
||||||
|
|
||||||
# Bidirectional techniques
|
# Bidirectional techniques
|
||||||
add_bidir(bdpt bdpt/bdpt.h bdpt/bdpt.cpp
|
add_bidir(bdpt bdpt/bdpt.h bdpt/bdpt.cpp
|
||||||
|
|
|
@ -17,6 +17,7 @@ plugins += env.SharedLibrary('vpl', ['vpl/vpl.cpp'])
|
||||||
plugins += env.SharedLibrary('adaptive', ['misc/adaptive.cpp'])
|
plugins += env.SharedLibrary('adaptive', ['misc/adaptive.cpp'])
|
||||||
plugins += env.SharedLibrary('irrcache', ['misc/irrcache.cpp', 'misc/irrcache_proc.cpp'])
|
plugins += env.SharedLibrary('irrcache', ['misc/irrcache.cpp', 'misc/irrcache_proc.cpp'])
|
||||||
plugins += env.SharedLibrary('multichannel', ['misc/multichannel.cpp'])
|
plugins += env.SharedLibrary('multichannel', ['misc/multichannel.cpp'])
|
||||||
|
plugins += env.SharedLibrary('field', ['misc/field.cpp'])
|
||||||
|
|
||||||
# Bidirectional techniques
|
# Bidirectional techniques
|
||||||
bidirEnv = env.Clone()
|
bidirEnv = env.Clone()
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
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/render/scene.h>
|
||||||
|
#include <mitsuba/render/renderproc.h>
|
||||||
|
|
||||||
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/*!\plugin{field}{Field extraction integrator}
|
||||||
|
* \order{17}
|
||||||
|
* \parameters{
|
||||||
|
* \parameter{field}{\String}{Denotes the name of the field that should be extracted.
|
||||||
|
* The following choices are possible:
|
||||||
|
* \begin{itemize}
|
||||||
|
* \setlength{\itemsep}{1pt}
|
||||||
|
* \setlength{\parskip}{1pt}
|
||||||
|
* \item \code{position}: 3D position in world space
|
||||||
|
* \item \code{relPosition}: 3D position in camera space
|
||||||
|
* \item \code{distance}: Ray distance to the shading point
|
||||||
|
* \item \code{geoNormal}: Geometric surface normal
|
||||||
|
* \item \code{shNormal}: Shading surface normal
|
||||||
|
* \item \code{uv}: UV coordinate value
|
||||||
|
* \item \code{albedo}: Albedo value of the BSDF
|
||||||
|
* \item \code{shapeIndex}: Integer index of the high-level shape
|
||||||
|
* \item \code{primIndex}: Integer shape primitive index
|
||||||
|
* \end{itemize}
|
||||||
|
* }
|
||||||
|
* \parameter{undefined}{\Spectrum\Or\Float}{Value that should be returned when
|
||||||
|
* there is no intersection \default{0}}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* This integrator extracts a requested field of from the intersection records of shading
|
||||||
|
* points and converts the resulting data into color values. It is meant to be used in conjunction with
|
||||||
|
* \pluginref{multichannel} to dump auxiliary information (such as depth or surface normals
|
||||||
|
* of surfaces seen by the camera) into extra channels of a rendered image, for instance to
|
||||||
|
* create benchmark data for computer vision applications.
|
||||||
|
* Please refer to the documentation of \pluginref{multichannel} for an example.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FieldIntegrator : public SamplingIntegrator {
|
||||||
|
public:
|
||||||
|
enum EField {
|
||||||
|
EPosition,
|
||||||
|
ERelativePosition,
|
||||||
|
EDistance,
|
||||||
|
EGeometricNormal,
|
||||||
|
EShadingNormal,
|
||||||
|
EUV,
|
||||||
|
EAlbedo,
|
||||||
|
EShapeIndex,
|
||||||
|
EPrimIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
FieldIntegrator(const Properties &props) : SamplingIntegrator(props) {
|
||||||
|
std::string field = props.getString("field");
|
||||||
|
|
||||||
|
if (field == "position") {
|
||||||
|
m_field = EPosition;
|
||||||
|
} else if (field == "relPosition") {
|
||||||
|
m_field = ERelativePosition;
|
||||||
|
} else if (field == "distance") {
|
||||||
|
m_field = EDistance;
|
||||||
|
} else if (field == "geoNormal") {
|
||||||
|
m_field = EGeometricNormal;
|
||||||
|
} else if (field == "shNormal") {
|
||||||
|
m_field = EShadingNormal;
|
||||||
|
} else if (field == "uv") {
|
||||||
|
m_field = EUV;
|
||||||
|
} else if (field == "albedo") {
|
||||||
|
m_field = EAlbedo;
|
||||||
|
} else if (field == "shapeIndex") {
|
||||||
|
m_field = EShapeIndex;
|
||||||
|
} else if (field == "primIndex") {
|
||||||
|
m_field = EPrimIndex;
|
||||||
|
} else {
|
||||||
|
Log(EError, "Invalid 'field' parameter. Must be one of 'position', "
|
||||||
|
"'relPosition', 'distance', 'geoNormal', 'shNormal', "
|
||||||
|
"'primIndex', 'shapeIndex', or 'uv'!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.hasProperty("undefined")) {
|
||||||
|
if (props.getType("undefined") == Properties::EFloat)
|
||||||
|
m_undefined = Spectrum(props.getFloat("undefined"));
|
||||||
|
else
|
||||||
|
m_undefined = props.getSpectrum("undefined", Spectrum(0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPECTRUM_SAMPLES != 3 && (m_field == EUV || m_field == EShadingNormal || m_field == EGeometricNormal
|
||||||
|
|| m_field == ERelativePosition || m_field == EPosition)) {
|
||||||
|
Log(EError, "The field integrator implementation requires renderings to be done in RGB when "
|
||||||
|
"extracting positional data or surface normals / UV coordinates.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldIntegrator(Stream *stream, InstanceManager *manager)
|
||||||
|
: SamplingIntegrator(stream, manager) {
|
||||||
|
m_field = (EField) stream->readInt();
|
||||||
|
m_undefined = Spectrum(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
SamplingIntegrator::serialize(stream, manager);
|
||||||
|
stream->writeInt((int) m_field);
|
||||||
|
m_undefined.serialize(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
Spectrum Li(const RayDifferential &ray, RadianceQueryRecord &rRec) const {
|
||||||
|
Spectrum result(m_undefined);
|
||||||
|
|
||||||
|
if (!rRec.rayIntersect(ray))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
Intersection &its = rRec.its;
|
||||||
|
|
||||||
|
switch (m_field) {
|
||||||
|
case EPosition:
|
||||||
|
result.fromLinearRGB(its.p.x, its.p.y, its.p.z);
|
||||||
|
break;
|
||||||
|
case ERelativePosition: {
|
||||||
|
const Sensor *sensor = rRec.scene->getSensor();
|
||||||
|
const Transform &t = sensor->getWorldTransform()->eval(its.t).inverse();
|
||||||
|
Point p = t(its.p);
|
||||||
|
result.fromLinearRGB(p.x, p.y, p.z);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EDistance:
|
||||||
|
result = Spectrum(its.t);
|
||||||
|
break;
|
||||||
|
case EGeometricNormal:
|
||||||
|
result.fromLinearRGB(its.geoFrame.n.x, its.geoFrame.n.y, its.geoFrame.n.z);
|
||||||
|
break;
|
||||||
|
case EShadingNormal:
|
||||||
|
result.fromLinearRGB(its.shFrame.n.x, its.shFrame.n.y, its.shFrame.n.z);
|
||||||
|
break;
|
||||||
|
case EUV:
|
||||||
|
result.fromLinearRGB(its.uv.x, its.uv.y, 0);
|
||||||
|
break;
|
||||||
|
case EAlbedo:
|
||||||
|
result = its.shape->getBSDF()->getDiffuseReflectance(its);
|
||||||
|
break;
|
||||||
|
case EShapeIndex: {
|
||||||
|
const ref_vector<Shape> &shapes = rRec.scene->getShapes();
|
||||||
|
result = Spectrum((Float) -1);
|
||||||
|
for (size_t i=0; i<shapes.size(); ++i) {
|
||||||
|
if (shapes[i] == its.shape) {
|
||||||
|
result = Spectrum((Float) i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EPrimIndex:
|
||||||
|
result = Spectrum((int) its.primIndex);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log(EError, "Internal error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toString() const {
|
||||||
|
return "FieldIntegrator[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
EField m_field;
|
||||||
|
Spectrum m_undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
MTS_IMPLEMENT_CLASS_S(FieldIntegrator, false, SamplingIntegrator)
|
||||||
|
MTS_EXPORT_PLUGIN(FieldIntegrator, "Field extraction integrator");
|
||||||
|
MTS_NAMESPACE_END
|
|
@ -21,9 +21,67 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/*! \plugin{direct}{Multi-channel integrator}
|
/*!\plugin{multichannel}{Multi-channel integrator}
|
||||||
* \order{16}
|
* \order{16}
|
||||||
|
* \parameters{
|
||||||
|
* \parameter{\Unnamed}{\Integrator}{One or more sub-integrators whose output
|
||||||
|
* should be rendered into a combined multi-channel image}
|
||||||
|
* }
|
||||||
*
|
*
|
||||||
|
* The multi-channel integrator groups several sub-integrators together
|
||||||
|
* and invokes them at the same time for each pixel; the result from each
|
||||||
|
* integrator is written into a separate channel of the output image.
|
||||||
|
* This could include things like surface normals or the distance
|
||||||
|
* from the camera (via the \pluginref{field} plugin) or ambient occlusion
|
||||||
|
* (via the \pluginref{ao} plugin).
|
||||||
|
* In this way, this integrator can be a powerful tool for unusual applications
|
||||||
|
* of Mitsuba, e.g. to create reference data for computer vision algorithms. Currently, it only
|
||||||
|
* works with a subset of the other plugins---see the red box for details.
|
||||||
|
*
|
||||||
|
* Thee \code{multichannel} plugin also disables certain checks for negative or infinite
|
||||||
|
* radiance values during rendering that normally cause warnings to be emitted.
|
||||||
|
* This is simply to process extracted fields for which it is fine
|
||||||
|
* to take on such values.
|
||||||
|
*
|
||||||
|
* The following example contains a typical setup for rendering an 7 channel EXR image:
|
||||||
|
* 3 for a path traced image (RGB), 3 for surface normals
|
||||||
|
* (encoded as RGB), and 1 channel for the ray distance measured from the camera.
|
||||||
|
*
|
||||||
|
* \vspace{2mm}
|
||||||
|
* \begin{xml}
|
||||||
|
* <scene>
|
||||||
|
* <integrator type="multichannel">
|
||||||
|
* <integrator type="path"/>
|
||||||
|
* <integrator type="field">
|
||||||
|
* <string name="field" value="shNormal"/>
|
||||||
|
* </integrator>
|
||||||
|
* <integrator type="field">
|
||||||
|
* <string name="field" value="distance"/>
|
||||||
|
* </integrator>
|
||||||
|
* </integrator>
|
||||||
|
*
|
||||||
|
* <sensor type="perspective">
|
||||||
|
* <sampler type="halton">
|
||||||
|
* <integer name="sampleCount" value="32"/>
|
||||||
|
* </sampler>
|
||||||
|
* <film type="hdrfilm">
|
||||||
|
* <string name="pixelFormat" value="rgb, rgb, luminance"/>
|
||||||
|
* <string name="channelNames" value="color, normal, distance"/>
|
||||||
|
* </film>
|
||||||
|
* </sensor>
|
||||||
|
* <!-- **** scene contents **** -->
|
||||||
|
* </scene>
|
||||||
|
* \end{xml}
|
||||||
|
*
|
||||||
|
* \remarks{
|
||||||
|
* \item Requires the \pluginref{hdrfilm} or \pluginref{tiledhdrfilm}.
|
||||||
|
* \item All nested integrators must
|
||||||
|
* conform to Mitsuba's basic \emph{SamplingIntegrator} interface.
|
||||||
|
* Currently, only a few of them do this, including:
|
||||||
|
* \pluginref{field}, \pluginref{ao}, \pluginref{direct}, \pluginref{path},
|
||||||
|
* \pluginref{volpath}, \pluginref[volpathsimple]{volpath\_simple},
|
||||||
|
* and \pluginref{irrcache}.
|
||||||
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MultiChannelIntegrator : public SamplingIntegrator {
|
class MultiChannelIntegrator : public SamplingIntegrator {
|
||||||
|
@ -82,7 +140,9 @@ public:
|
||||||
ref<BlockedRenderProcess> proc = new BlockedRenderProcess(job,
|
ref<BlockedRenderProcess> proc = new BlockedRenderProcess(job,
|
||||||
queue, scene->getBlockSize());
|
queue, scene->getBlockSize());
|
||||||
|
|
||||||
proc->setPixelFormat(Bitmap::EMultiSpectrumAlphaWeight, (int) (m_integrators.size() * SPECTRUM_SAMPLES + 2), false);
|
proc->setPixelFormat(
|
||||||
|
m_integrators.size() > 1 ? Bitmap::EMultiSpectrumAlphaWeight : Bitmap::ESpectrumAlphaWeight,
|
||||||
|
(int) (m_integrators.size() * SPECTRUM_SAMPLES + 2), false);
|
||||||
|
|
||||||
int integratorResID = sched->registerResource(this);
|
int integratorResID = sched->registerResource(this);
|
||||||
proc->bindResource("integrator", integratorResID);
|
proc->bindResource("integrator", integratorResID);
|
||||||
|
|
|
@ -269,12 +269,19 @@ public:
|
||||||
if (m_config.workUnits <= 0) {
|
if (m_config.workUnits <= 0) {
|
||||||
const size_t desiredMutationsPerWorkUnit = 200000;
|
const size_t desiredMutationsPerWorkUnit = 200000;
|
||||||
const size_t cropArea = (size_t) cropSize.x * cropSize.y;
|
const size_t cropArea = (size_t) cropSize.x * cropSize.y;
|
||||||
const size_t workUnits = ((desiredMutationsPerWorkUnit - 1) +
|
const size_t workUnits = ((desiredMutationsPerWorkUnit - 1) +
|
||||||
(cropArea * sampleCount)) / desiredMutationsPerWorkUnit;
|
(cropArea * sampleCount)) / desiredMutationsPerWorkUnit;
|
||||||
Assert(workUnits <= (size_t) std::numeric_limits<int>::max());
|
Assert(workUnits <= (size_t) std::numeric_limits<int>::max());
|
||||||
m_config.workUnits = (int) std::max(workUnits, (size_t) 1);
|
m_config.workUnits = (int) std::max(workUnits, (size_t) 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t luminanceSamples = m_config.luminanceSamples;
|
||||||
|
if (luminanceSamples < (size_t) m_config.workUnits * 10) {
|
||||||
|
luminanceSamples = (size_t) m_config.workUnits * 10;
|
||||||
|
Log(EWarn, "Warning: increasing number of luminance samples to " SIZE_T_FMT,
|
||||||
|
luminanceSamples);
|
||||||
|
}
|
||||||
|
|
||||||
m_config.nMutations = (cropSize.x * cropSize.y *
|
m_config.nMutations = (cropSize.x * cropSize.y *
|
||||||
sampleCount) / m_config.workUnits;
|
sampleCount) / m_config.workUnits;
|
||||||
|
|
||||||
|
@ -295,7 +302,7 @@ public:
|
||||||
ref<MLTProcess> process = new MLTProcess(job, queue,
|
ref<MLTProcess> process = new MLTProcess(job, queue,
|
||||||
m_config, directImage, pathSeeds);
|
m_config, directImage, pathSeeds);
|
||||||
|
|
||||||
m_config.luminance = pathSampler->generateSeeds(m_config.luminanceSamples,
|
m_config.luminance = pathSampler->generateSeeds(luminanceSamples,
|
||||||
m_config.workUnits, true, m_config.importanceMap, pathSeeds);
|
m_config.workUnits, true, m_config.importanceMap, pathSeeds);
|
||||||
|
|
||||||
if (!nested)
|
if (!nested)
|
||||||
|
|
|
@ -328,6 +328,13 @@ public:
|
||||||
m_config.workUnits = (int) std::max(workUnits, (size_t) 1);
|
m_config.workUnits = (int) std::max(workUnits, (size_t) 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t luminanceSamples = m_config.luminanceSamples;
|
||||||
|
if (luminanceSamples < (size_t) m_config.workUnits * 10) {
|
||||||
|
luminanceSamples = (size_t) m_config.workUnits * 10;
|
||||||
|
Log(EWarn, "Warning: increasing number of luminance samples to " SIZE_T_FMT,
|
||||||
|
luminanceSamples);
|
||||||
|
}
|
||||||
|
|
||||||
m_config.nMutations = (cropSize.x * cropSize.y *
|
m_config.nMutations = (cropSize.x * cropSize.y *
|
||||||
sampleCount) / m_config.workUnits;
|
sampleCount) / m_config.workUnits;
|
||||||
|
|
||||||
|
@ -348,7 +355,7 @@ public:
|
||||||
ref<PSSMLTProcess> process = new PSSMLTProcess(job, queue,
|
ref<PSSMLTProcess> process = new PSSMLTProcess(job, queue,
|
||||||
m_config, directImage, pathSeeds);
|
m_config, directImage, pathSeeds);
|
||||||
|
|
||||||
m_config.luminance = pathSampler->generateSeeds(m_config.luminanceSamples,
|
m_config.luminance = pathSampler->generateSeeds(luminanceSamples,
|
||||||
m_config.workUnits, false, m_config.importanceMap, pathSeeds);
|
m_config.workUnits, false, m_config.importanceMap, pathSeeds);
|
||||||
|
|
||||||
if (!nested)
|
if (!nested)
|
||||||
|
|
|
@ -36,15 +36,15 @@ ref<Bitmap> BidirectionalUtils::renderDirectComponent(Scene *scene, int sceneRes
|
||||||
/* Render the direct illumination component separately */
|
/* Render the direct illumination component separately */
|
||||||
ref<Bitmap> directImage = new Bitmap(Bitmap::ERGBA, Bitmap::EFloat32, film->getCropSize());
|
ref<Bitmap> directImage = new Bitmap(Bitmap::ERGBA, Bitmap::EFloat32, film->getCropSize());
|
||||||
bool hasMedia = scene->getMedia().size() > 0;
|
bool hasMedia = scene->getMedia().size() > 0;
|
||||||
|
bool hasDOF = scene->getSensor()->needsApertureSample();
|
||||||
size_t pixelSamples = directSamples;
|
size_t pixelSamples = directSamples;
|
||||||
Properties integratorProps(hasMedia ? "volpath" : "direct");
|
Properties integratorProps(hasMedia ? "volpath" : "direct");
|
||||||
|
|
||||||
if (hasMedia) {
|
if (hasMedia || hasDOF) {
|
||||||
/* Render with a volumetric path tracer */
|
|
||||||
integratorProps.setInteger("maxDepth", 2);
|
integratorProps.setInteger("maxDepth", 2);
|
||||||
} else {
|
} else {
|
||||||
/* No participating media-> we can use the 'direct' plugin, which has
|
/* No participating media / DoF -> we can more carefully
|
||||||
somewhat better control over where to place shading/pixel samples */
|
distribute samples between shading and visibility */
|
||||||
int shadingSamples = 1;
|
int shadingSamples = 1;
|
||||||
while (pixelSamples > 8) {
|
while (pixelSamples > 8) {
|
||||||
pixelSamples /= 2;
|
pixelSamples /= 2;
|
||||||
|
|
|
@ -88,11 +88,12 @@ public:
|
||||||
EXRIStream(Stream *stream) : IStream(stream->toString().c_str()),
|
EXRIStream(Stream *stream) : IStream(stream->toString().c_str()),
|
||||||
m_stream(stream) {
|
m_stream(stream) {
|
||||||
m_offset = stream->getPos();
|
m_offset = stream->getPos();
|
||||||
|
m_size = stream->getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read(char *c, int n) {
|
bool read(char *c, int n) {
|
||||||
m_stream->read(c, n);
|
m_stream->read(c, n);
|
||||||
return m_stream->isEOF();
|
return m_stream->getPos() == m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Imf::Int64 tellg() {
|
Imf::Int64 tellg() {
|
||||||
|
@ -106,7 +107,7 @@ public:
|
||||||
void clear() { }
|
void clear() { }
|
||||||
private:
|
private:
|
||||||
ref<Stream> m_stream;
|
ref<Stream> m_stream;
|
||||||
size_t m_offset;
|
size_t m_offset, m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EXROStream : public Imf::OStream {
|
class EXROStream : public Imf::OStream {
|
||||||
|
@ -166,6 +167,12 @@ static void png_error_func(png_structp png_ptr, png_const_charp msg) {
|
||||||
SLog(EError, "Fatal libpng error: %s\n", msg);
|
SLog(EError, "Fatal libpng error: %s\n", msg);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void png_warn_func(png_structp png_ptr, png_const_charp msg) {
|
||||||
|
if (strstr(msg, "iCCP: known incorrect sRGB profile") != NULL)
|
||||||
|
return;
|
||||||
|
SLog(EWarn, "libpng warning: %s\n", msg);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MTS_HAS_LIBJPEG)
|
#if defined(MTS_HAS_LIBJPEG)
|
||||||
|
@ -298,6 +305,8 @@ Bitmap::Bitmap(EFileFormat format, Stream *stream, const std::string &prefix) :
|
||||||
format = ERGBE;
|
format = ERGBE;
|
||||||
} else if (start[0] == 'P' && (start[1] == 'F' || start[1] == 'f')) {
|
} else if (start[0] == 'P' && (start[1] == 'F' || start[1] == 'f')) {
|
||||||
format = EPFM;
|
format = EPFM;
|
||||||
|
} else if (start[0] == 'P' && start[1] == '6') {
|
||||||
|
format = EPPM;
|
||||||
#if defined(MTS_HAS_LIBJPEG)
|
#if defined(MTS_HAS_LIBJPEG)
|
||||||
} else if (start[0] == 0xFF && start[1] == 0xD8) {
|
} else if (start[0] == 0xFF && start[1] == 0xD8) {
|
||||||
format = EJPEG;
|
format = EJPEG;
|
||||||
|
@ -327,6 +336,7 @@ Bitmap::Bitmap(EFileFormat format, Stream *stream, const std::string &prefix) :
|
||||||
case EOpenEXR: readOpenEXR(stream, prefix); break;
|
case EOpenEXR: readOpenEXR(stream, prefix); break;
|
||||||
case ERGBE: readRGBE(stream); break;
|
case ERGBE: readRGBE(stream); break;
|
||||||
case EPFM: readPFM(stream); break;
|
case EPFM: readPFM(stream); break;
|
||||||
|
case EPPM: readPPM(stream); break;
|
||||||
case ETGA: readTGA(stream); break;
|
case ETGA: readTGA(stream); break;
|
||||||
case EPNG: readPNG(stream); break;
|
case EPNG: readPNG(stream); break;
|
||||||
default:
|
default:
|
||||||
|
@ -349,6 +359,7 @@ void Bitmap::write(EFileFormat format, Stream *stream, int compression) const {
|
||||||
case EOpenEXR: writeOpenEXR(stream); break;
|
case EOpenEXR: writeOpenEXR(stream); break;
|
||||||
case ERGBE: writeRGBE(stream); break;
|
case ERGBE: writeRGBE(stream); break;
|
||||||
case EPFM: writePFM(stream); break;
|
case EPFM: writePFM(stream); break;
|
||||||
|
case EPPM: writePPM(stream); break;
|
||||||
default:
|
default:
|
||||||
Log(EError, "Bitmap::write(): Invalid file format!");
|
Log(EError, "Bitmap::write(): Invalid file format!");
|
||||||
}
|
}
|
||||||
|
@ -1361,7 +1372,7 @@ void Bitmap::convert(Bitmap *target, Float multiplier, Spectrum::EConversionInte
|
||||||
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
||||||
target->getPixelFormat(), target->getGamma(), target->getData(),
|
target->getPixelFormat(), target->getGamma(), target->getData(),
|
||||||
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
||||||
m_channelCount - (hasWeight() ? 1 : 0));
|
m_channelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
|
ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
|
||||||
|
@ -1392,72 +1403,99 @@ ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
|
||||||
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
||||||
pixelFormat, gamma, target->getData(),
|
pixelFormat, gamma, target->getData(),
|
||||||
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
||||||
m_channelCount - (hasWeight() ? 1 : 0));
|
m_channelCount);
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<Bitmap> Bitmap::convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
|
ref<Bitmap> Bitmap::convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
|
||||||
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const {
|
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const {
|
||||||
if (m_componentFormat != EFloat && m_pixelFormat != EMultiSpectrumAlphaWeight)
|
|
||||||
Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!");
|
|
||||||
if (channelNames.size() > std::numeric_limits<uint8_t>::max())
|
if (channelNames.size() > std::numeric_limits<uint8_t>::max())
|
||||||
Log(EError, "convertMultiSpectrumAlphaWeight(): excessive number of channels!");
|
Log(EError, "convertMultiSpectrumAlphaWeight(): excessive number of channels!");
|
||||||
ref<Bitmap> bitmap = new Bitmap(Bitmap::EMultiChannel, Bitmap::EFloat, m_size, (uint8_t) channelNames.size());
|
ref<Bitmap> bitmap = new Bitmap(Bitmap::EMultiChannel, componentFormat,
|
||||||
|
m_size, (uint8_t) channelNames.size());
|
||||||
bitmap->setChannelNames(channelNames);
|
bitmap->setChannelNames(channelNames);
|
||||||
|
convertMultiSpectrumAlphaWeight(this, getUInt8Data(), bitmap,
|
||||||
|
bitmap->getUInt8Data(), pixelFormats, componentFormat,
|
||||||
|
(size_t) m_size.x * (size_t) m_size.y);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
for (int y = 0; y<m_size.y; ++y) {
|
void Bitmap::convertMultiSpectrumAlphaWeight(const Bitmap *source,
|
||||||
for (int x = 0; x<m_size.x; ++x) {
|
const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr,
|
||||||
const Float *srcData = getFloatData() + getChannelCount() * (x+y*m_size.x);
|
const std::vector<EPixelFormat> &pixelFormats,
|
||||||
Float *dstData = bitmap->getFloatData() + bitmap->getChannelCount() * (x+y*m_size.x);
|
EComponentFormat componentFormat, size_t count) {
|
||||||
Float weight = srcData[getChannelCount()-1],
|
if (source->getComponentFormat() != EFloat && source->getPixelFormat() != EMultiSpectrumAlphaWeight)
|
||||||
invWeight = weight == 0 ? 0 : (Float) 1 / weight;
|
Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!");
|
||||||
Float alpha = srcData[getChannelCount()-2] * invWeight;
|
|
||||||
|
|
||||||
for (size_t i=0; i<pixelFormats.size(); ++i) {
|
Float *temp = new Float[count * target->getChannelCount()], *dst = temp;
|
||||||
Spectrum value = ((Spectrum *) srcData)[i] * invWeight;
|
|
||||||
Float r, g, b;
|
for (size_t k = 0; k<count; ++k) {
|
||||||
switch (pixelFormats[i]) {
|
const Float *srcData = (const Float *) sourcePtr + k * source->getChannelCount();
|
||||||
case Bitmap::ELuminance:
|
Float weight = srcData[source->getChannelCount()-1],
|
||||||
*dstData++ = value.getLuminance();
|
invWeight = weight == 0 ? 0 : (Float) 1 / weight;
|
||||||
break;
|
Float alpha = srcData[source->getChannelCount()-2] * invWeight;
|
||||||
case Bitmap::ELuminanceAlpha:
|
|
||||||
*dstData++ = value.getLuminance();
|
for (size_t i=0; i<pixelFormats.size(); ++i) {
|
||||||
*dstData++ = alpha;
|
Spectrum value = ((Spectrum *) srcData)[i] * invWeight;
|
||||||
break;
|
Float tmp0, tmp1, tmp2;
|
||||||
case Bitmap::ERGB:
|
switch (pixelFormats[i]) {
|
||||||
value.toLinearRGB(r, g, b);
|
case Bitmap::ELuminance:
|
||||||
*dstData++ = r;
|
*dst++ = value.getLuminance();
|
||||||
*dstData++ = g;
|
break;
|
||||||
*dstData++ = b;
|
case Bitmap::ELuminanceAlpha:
|
||||||
break;
|
*dst++ = value.getLuminance();
|
||||||
case Bitmap::ERGBA:
|
*dst++ = alpha;
|
||||||
value.toLinearRGB(r, g, b);
|
break;
|
||||||
*dstData++ = r;
|
case Bitmap::EXYZ:
|
||||||
*dstData++ = g;
|
value.toXYZ(tmp0, tmp1, tmp2);
|
||||||
*dstData++ = b;
|
*dst++ = tmp0;
|
||||||
*dstData++ = alpha;
|
*dst++ = tmp1;
|
||||||
break;
|
*dst++ = tmp2;
|
||||||
case Bitmap::ESpectrum:
|
break;
|
||||||
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
|
case Bitmap::EXYZA:
|
||||||
*dstData++ = value[j];
|
value.toXYZ(tmp0, tmp1, tmp2);
|
||||||
break;
|
*dst++ = tmp0;
|
||||||
case Bitmap::ESpectrumAlpha:
|
*dst++ = tmp1;
|
||||||
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
|
*dst++ = tmp2;
|
||||||
*dstData++ = value[j];
|
*dst++ = alpha;
|
||||||
*dstData++ = alpha;
|
break;
|
||||||
break;
|
case Bitmap::ERGB:
|
||||||
default:
|
value.toLinearRGB(tmp0, tmp1, tmp2);
|
||||||
Log(EError, "Unknown pixel format!");
|
*dst++ = tmp0;
|
||||||
}
|
*dst++ = tmp1;
|
||||||
|
*dst++ = tmp2;
|
||||||
|
break;
|
||||||
|
case Bitmap::ERGBA:
|
||||||
|
value.toLinearRGB(tmp0, tmp1, tmp2);
|
||||||
|
*dst++ = tmp0;
|
||||||
|
*dst++ = tmp1;
|
||||||
|
*dst++ = tmp2;
|
||||||
|
*dst++ = alpha;
|
||||||
|
break;
|
||||||
|
case Bitmap::ESpectrum:
|
||||||
|
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
|
||||||
|
*dst++ = value[j];
|
||||||
|
break;
|
||||||
|
case Bitmap::ESpectrumAlpha:
|
||||||
|
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
|
||||||
|
*dst++ = value[j];
|
||||||
|
*dst++ = alpha;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log(EError, "Unknown pixel format!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentFormat != Bitmap::EFloat)
|
const FormatConverter *cvt = FormatConverter::getInstance(
|
||||||
bitmap = bitmap->convert(Bitmap::EMultiChannel, componentFormat);
|
std::make_pair(EFloat, target->getComponentFormat())
|
||||||
|
);
|
||||||
|
|
||||||
return bitmap;
|
cvt->convert(Bitmap::EMultiChannel, 1.0f, temp, Bitmap::EMultiChannel, 1.0f, targetPtr,
|
||||||
|
count, 1.0f, Spectrum::EReflectance, target->getChannelCount());
|
||||||
|
|
||||||
|
delete[] temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bitmap::convert(void *target, EPixelFormat pixelFormat,
|
void Bitmap::convert(void *target, EPixelFormat pixelFormat,
|
||||||
|
@ -1483,7 +1521,7 @@ void Bitmap::convert(void *target, EPixelFormat pixelFormat,
|
||||||
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
cvt->convert(m_pixelFormat, m_gamma, m_data,
|
||||||
pixelFormat, gamma, target,
|
pixelFormat, gamma, target,
|
||||||
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
|
||||||
m_channelCount - (hasWeight() ? 1 : 0));
|
m_channelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixelFormat fmt,
|
template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixelFormat fmt,
|
||||||
|
@ -1990,7 +2028,7 @@ void Bitmap::readPNG(Stream *stream) {
|
||||||
volatile png_bytepp rows = NULL;
|
volatile png_bytepp rows = NULL;
|
||||||
|
|
||||||
/* Create buffers */
|
/* Create buffers */
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &png_error_func, NULL);
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &png_error_func, &png_warn_func);
|
||||||
if (png_ptr == NULL) {
|
if (png_ptr == NULL) {
|
||||||
Log(EError, "readPNG(): Unable to create PNG data structure");
|
Log(EError, "readPNG(): Unable to create PNG data structure");
|
||||||
}
|
}
|
||||||
|
@ -2114,7 +2152,7 @@ void Bitmap::writePNG(Stream *stream, int compression) const {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_error_func, NULL);
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_error_func, &png_warn_func);
|
||||||
if (png_ptr == NULL)
|
if (png_ptr == NULL)
|
||||||
Log(EError, "Error while creating PNG data structure");
|
Log(EError, "Error while creating PNG data structure");
|
||||||
|
|
||||||
|
@ -3368,6 +3406,54 @@ void Bitmap::writePFM(Stream *stream) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitmap::readPPM(Stream *stream) {
|
||||||
|
int field = 0, nChars = 0;
|
||||||
|
|
||||||
|
std::string fields[4];
|
||||||
|
|
||||||
|
while (field < 4) {
|
||||||
|
char c = stream->readChar();
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||||
|
if (nChars != 0) {
|
||||||
|
nChars = 0;
|
||||||
|
++field;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fields[field] += c;
|
||||||
|
++nChars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fields[0] != "P6")
|
||||||
|
Log(EError, "readPPM(): invalid format!");
|
||||||
|
|
||||||
|
int intValues[3];
|
||||||
|
for (int i=0; i<3; ++i) {
|
||||||
|
char *end_ptr = NULL;
|
||||||
|
intValues[i] = strtol(fields[i+1].c_str(), &end_ptr, 10);
|
||||||
|
if (*end_ptr != '\0')
|
||||||
|
SLog(EError, "readPPM(): unable to parse the file header!");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_size.x = intValues[0];
|
||||||
|
m_size.y = intValues[1];
|
||||||
|
m_pixelFormat = ERGB;
|
||||||
|
m_channelCount = 3;
|
||||||
|
m_gamma = -1.0f;
|
||||||
|
m_ownsData = true;
|
||||||
|
m_componentFormat = intValues[2] <= 0xFF ? EUInt8 : EUInt16;
|
||||||
|
size_t size = getBufferSize();
|
||||||
|
m_data = static_cast<uint8_t *>(allocAligned(size));
|
||||||
|
stream->read(m_data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bitmap::writePPM(Stream *stream) const {
|
||||||
|
if (m_pixelFormat != ERGB || (m_componentFormat != EUInt8 && m_componentFormat != EUInt16))
|
||||||
|
Log(EError, "writePPM(): Only 8 or 16-bit RGB images are supported");
|
||||||
|
stream->writeLine(formatString("P6\n%i\n%i\n%i\n", m_size.x, m_size.y,
|
||||||
|
m_componentFormat == EUInt8 ? 0xFF : 0xFFFF).c_str());
|
||||||
|
stream->write(m_data, getBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
void Bitmap::staticInitialization() {
|
void Bitmap::staticInitialization() {
|
||||||
#if defined(MTS_HAS_OPENEXR)
|
#if defined(MTS_HAS_OPENEXR)
|
||||||
/* Prevent races during the OpenEXR initialization */
|
/* Prevent races during the OpenEXR initialization */
|
||||||
|
|
|
@ -206,7 +206,7 @@ void FileStream::seek(size_t pos) {
|
||||||
pos, d->path.string().c_str(), lastErrorText().c_str());
|
pos, d->path.string().c_str(), lastErrorText().c_str());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (fseek(d->file, pos, SEEK_SET)) {
|
if (fseeko(d->file, (off_t) pos, SEEK_SET)) {
|
||||||
Log(EError, "Error while trying to seek to position %i in file \"%s\": %s",
|
Log(EError, "Error while trying to seek to position %i in file \"%s\": %s",
|
||||||
pos, d->path.string().c_str(), strerror(errno));
|
pos, d->path.string().c_str(), strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -223,8 +223,7 @@ size_t FileStream::getPos() const {
|
||||||
}
|
}
|
||||||
return (size_t) pos;
|
return (size_t) pos;
|
||||||
#else
|
#else
|
||||||
long pos;
|
off_t pos = ftello(d->file);
|
||||||
pos = ftell(d->file);
|
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
Log(EError, "Error while looking up the position in file \"%s\": %s",
|
Log(EError, "Error while looking up the position in file \"%s\": %s",
|
||||||
d->path.string().c_str(), strerror(errno));
|
d->path.string().c_str(), strerror(errno));
|
||||||
|
|
|
@ -139,6 +139,11 @@ void Logger::log(ELogLevel level, const Class *theClass,
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DefaultFormatter fmt;
|
||||||
|
fmt.setHaveDate(false);
|
||||||
|
fmt.setHaveLogLevel(false);
|
||||||
|
text = fmt.format(level, theClass,
|
||||||
|
Thread::getThread(), msg, file, line);
|
||||||
throw std::runtime_error(text);
|
throw std::runtime_error(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
|
|
||||||
#include <mitsuba/core/vmf.h>
|
#include <mitsuba/core/vmf.h>
|
||||||
#include <mitsuba/core/warp.h>
|
#include <mitsuba/core/warp.h>
|
||||||
|
#include <mitsuba/core/brent.h>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
VonMisesFisherDistr::VonMisesFisherDistr(Float kappa): m_kappa(kappa) { }
|
|
||||||
|
|
||||||
Float VonMisesFisherDistr::eval(Float cosTheta) const {
|
Float VonMisesFisherDistr::eval(Float cosTheta) const {
|
||||||
if (m_kappa == 0.0f)
|
if (m_kappa == 0.0f)
|
||||||
return INV_FOURPI;
|
return INV_FOURPI;
|
||||||
|
@ -63,22 +63,23 @@ Vector VonMisesFisherDistr::sample(const Point2 &sample) const {
|
||||||
sinPhi * sinTheta, cosTheta);
|
sinPhi * sinTheta, cosTheta);
|
||||||
}
|
}
|
||||||
|
|
||||||
Float VonMisesFisherDistr::forPeakValue(Float x) {
|
Float VonMisesFisherDistr::getMeanCosine() const {
|
||||||
if (x < INV_FOURPI) {
|
if (m_kappa == 0)
|
||||||
return 0.0f;
|
return 0;
|
||||||
} else if (x > 0.795) {
|
Float coth = m_kappa > 6 ? 1 : ((std::exp(2*m_kappa)+1)/(std::exp(2*m_kappa)-1));
|
||||||
return 2 * M_PI * x;
|
return coth-1/m_kappa;
|
||||||
} else {
|
|
||||||
return std::max((Float) 0.0f,
|
|
||||||
(168.479f * x * x + 16.4585f * x - 2.39942f) /
|
|
||||||
(-1.12718f * x * x + 29.1433f * x + 1.0f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Float A3(Float kappa) {
|
static Float A3(Float kappa) {
|
||||||
return 1/ std::tanh(kappa) - 1 / kappa;
|
return 1/ std::tanh(kappa) - 1 / kappa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string VonMisesFisherDistr::toString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "VonMisesFisherDistr[kappa=" << m_kappa << "]";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
static Float dA3(Float kappa) {
|
static Float dA3(Float kappa) {
|
||||||
Float csch = 2.0f /
|
Float csch = 2.0f /
|
||||||
(math::fastexp(kappa)-math::fastexp(-kappa));
|
(math::fastexp(kappa)-math::fastexp(-kappa));
|
||||||
|
@ -110,4 +111,33 @@ Float VonMisesFisherDistr::convolve(Float kappa1, Float kappa2) {
|
||||||
return A3inv(A3(kappa1) * A3(kappa2), std::min(kappa1, kappa2));
|
return A3inv(A3(kappa1) * A3(kappa2), std::min(kappa1, kappa2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Float VonMisesFisherDistr::forPeakValue(Float x) {
|
||||||
|
if (x < INV_FOURPI) {
|
||||||
|
return 0.0f;
|
||||||
|
} else if (x > 0.795) {
|
||||||
|
return 2 * M_PI * x;
|
||||||
|
} else {
|
||||||
|
return std::max((Float) 0.0f,
|
||||||
|
(168.479f * x * x + 16.4585f * x - 2.39942f) /
|
||||||
|
(-1.12718f * x * x + 29.1433f * x + 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Float meanCosineFunctor(Float kappa, Float g) {
|
||||||
|
return VonMisesFisherDistr(kappa).getMeanCosine()-g;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float VonMisesFisherDistr::forMeanCosine(Float g) {
|
||||||
|
if (g == 0)
|
||||||
|
return 0;
|
||||||
|
else if (g < 0)
|
||||||
|
SLog(EError, "Error: vMF distribution cannot be created for g<0.");
|
||||||
|
|
||||||
|
BrentSolver brentSolver(100, 1e-6f);
|
||||||
|
BrentSolver::Result result = brentSolver.solve(
|
||||||
|
boost::bind(&meanCosineFunctor, _1, g), 0, 1000);
|
||||||
|
SAssert(result.success);
|
||||||
|
return result.x;
|
||||||
|
}
|
||||||
|
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -14,6 +14,8 @@ for ver in hasPython:
|
||||||
pythonEnv.Append(CPPDEFINES = [['MTS_BUILD_MODULE', 'MTS_MODULE_PYTHON']])
|
pythonEnv.Append(CPPDEFINES = [['MTS_BUILD_MODULE', 'MTS_MODULE_PYTHON']])
|
||||||
pythonEnv['SHLIBPREFIX']=''
|
pythonEnv['SHLIBPREFIX']=''
|
||||||
pythonEnv.RelaxCompilerSettings()
|
pythonEnv.RelaxCompilerSettings()
|
||||||
|
pythonEnv.Append(LIBS=['mitsuba-bidir'])
|
||||||
|
pythonEnv.Append(LIBPATH=['#src/libbidir'])
|
||||||
|
|
||||||
if pythonEnv.has_key('XERCESINCLUDE'):
|
if pythonEnv.has_key('XERCESINCLUDE'):
|
||||||
pythonEnv.Prepend(CPPPATH=pythonEnv['XERCESINCLUDE'])
|
pythonEnv.Prepend(CPPPATH=pythonEnv['XERCESINCLUDE'])
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <mitsuba/core/mstream.h>
|
#include <mitsuba/core/mstream.h>
|
||||||
#include <mitsuba/core/cstream.h>
|
#include <mitsuba/core/cstream.h>
|
||||||
#include <mitsuba/core/qmc.h>
|
#include <mitsuba/core/qmc.h>
|
||||||
|
#include <mitsuba/core/vmf.h>
|
||||||
#include <mitsuba/core/shvector.h>
|
#include <mitsuba/core/shvector.h>
|
||||||
#include <mitsuba/core/sshstream.h>
|
#include <mitsuba/core/sshstream.h>
|
||||||
#include <mitsuba/render/scenehandler.h>
|
#include <mitsuba/render/scenehandler.h>
|
||||||
|
@ -506,6 +507,7 @@ bp::object cast(ConfigurableObject *obj) {
|
||||||
TryCast(Medium);
|
TryCast(Medium);
|
||||||
TryCast(VolumeDataSource);
|
TryCast(VolumeDataSource);
|
||||||
TryCast(Film);
|
TryCast(Film);
|
||||||
|
TryCast(PerspectiveCamera);
|
||||||
TryCast(ProjectiveCamera);
|
TryCast(ProjectiveCamera);
|
||||||
TryCast(Sensor);
|
TryCast(Sensor);
|
||||||
TryCast(Emitter);
|
TryCast(Emitter);
|
||||||
|
@ -525,13 +527,13 @@ static bp::object pluginmgr_createobject_2(PluginManager *mgr, const Class *cls,
|
||||||
return cast(mgr->createObject(cls, props));
|
return cast(mgr->createObject(cls, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dict) {
|
static ConfigurableObject *pluginmgr_create_helper(PluginManager *manager, bp::dict dict, std::map<std::string, ConfigurableObject *> &objs) {
|
||||||
Properties properties;
|
Properties properties;
|
||||||
bp::list list = dict.items();
|
bp::list items = dict.items();
|
||||||
std::map<std::string, ConfigurableObject *> children;
|
std::map<std::string, ConfigurableObject *> children;
|
||||||
|
|
||||||
for (int i=0; i<bp::len(list); ++i) {
|
for (bp::stl_input_iterator<bp::tuple> it(items), end; it!=end; ++it) {
|
||||||
bp::tuple tuple = bp::extract<bp::tuple>(list[i]);
|
bp::tuple tuple = *it;
|
||||||
std::string name = bp::extract<std::string>(tuple[0]);
|
std::string name = bp::extract<std::string>(tuple[0]);
|
||||||
bp::extract<bp::dict> extractDict(tuple[1]);
|
bp::extract<bp::dict> extractDict(tuple[1]);
|
||||||
bp::extract<std::string> extractString(tuple[1]);
|
bp::extract<std::string> extractString(tuple[1]);
|
||||||
|
@ -542,8 +544,13 @@ static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dic
|
||||||
SLog(EError, "'type' property must map to a string!");
|
SLog(EError, "'type' property must map to a string!");
|
||||||
else
|
else
|
||||||
properties.setPluginName(extractString());
|
properties.setPluginName(extractString());
|
||||||
|
} else if (name == "id") {
|
||||||
|
if (!extractString.check())
|
||||||
|
SLog(EError, "'id' property must map to a string!");
|
||||||
|
else
|
||||||
|
properties.setID(extractString());
|
||||||
} else if (extractDict.check()) {
|
} else if (extractDict.check()) {
|
||||||
children[name] = pluginmgr_create(manager, extractDict());
|
children[name] = pluginmgr_create_helper(manager, extractDict(), objs);
|
||||||
} else if (extractConfigurableObject.check()) {
|
} else if (extractConfigurableObject.check()) {
|
||||||
children[name] = extractConfigurableObject();
|
children[name] = extractConfigurableObject();
|
||||||
} else {
|
} else {
|
||||||
|
@ -552,10 +559,23 @@ static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dic
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurableObject *object;
|
ConfigurableObject *object;
|
||||||
if (properties.getPluginName() == "scene")
|
if (properties.getPluginName() == "scene") {
|
||||||
object = new Scene(properties);
|
object = new Scene(properties);
|
||||||
else
|
} else if (properties.getPluginName() == "ref") {
|
||||||
|
std::string id = properties.getID();
|
||||||
|
if (id == "unnamed")
|
||||||
|
SLog(EError, "id parameter of reference is missing!");
|
||||||
|
if (objs.find(id) == objs.end())
|
||||||
|
SLog(EError, "Could not find referenced object with id \"%s\"", id.c_str());
|
||||||
|
return objs[id];
|
||||||
|
} else {
|
||||||
object = manager->createObject(properties);
|
object = manager->createObject(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.getID() != "unnamed") {
|
||||||
|
objs[properties.getID()] = object;
|
||||||
|
object->incRef();
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map<std::string, ConfigurableObject *>::iterator it = children.begin();
|
for (std::map<std::string, ConfigurableObject *>::iterator it = children.begin();
|
||||||
it != children.end(); ++it) {
|
it != children.end(); ++it) {
|
||||||
|
@ -567,6 +587,15 @@ static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dic
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dict) {
|
||||||
|
std::map<std::string, ConfigurableObject *> objs;
|
||||||
|
ConfigurableObject *result = pluginmgr_create_helper(manager, dict, objs);
|
||||||
|
for (std::map<std::string, ConfigurableObject *>::iterator it = objs.begin();
|
||||||
|
it != objs.end(); ++it)
|
||||||
|
it->second->decRef();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static bp::tuple mkCoordinateSystem(const Vector &n) {
|
static bp::tuple mkCoordinateSystem(const Vector &n) {
|
||||||
Vector s, t;
|
Vector s, t;
|
||||||
coordinateSystem(n, s, t);
|
coordinateSystem(n, s, t);
|
||||||
|
@ -1030,6 +1059,9 @@ void export_core() {
|
||||||
coreModule.attr("Epsilon") = Epsilon;
|
coreModule.attr("Epsilon") = Epsilon;
|
||||||
coreModule.attr("ShadowEpsilon") = ShadowEpsilon;
|
coreModule.attr("ShadowEpsilon") = ShadowEpsilon;
|
||||||
coreModule.attr("DeltaEpsilon") = DeltaEpsilon;
|
coreModule.attr("DeltaEpsilon") = DeltaEpsilon;
|
||||||
|
coreModule.attr("SPECTRUM_SAMPLES") = SPECTRUM_SAMPLES;
|
||||||
|
coreModule.attr("MTS_VERSION") = MTS_VERSION;
|
||||||
|
coreModule.attr("MTS_YEAR") = MTS_YEAR;
|
||||||
|
|
||||||
bp::class_<Class, boost::noncopyable>("Class", bp::no_init)
|
bp::class_<Class, boost::noncopyable>("Class", bp::no_init)
|
||||||
.def("getName", &Class::getName, BP_RETURN_CONSTREF)
|
.def("getName", &Class::getName, BP_RETURN_CONSTREF)
|
||||||
|
@ -1264,6 +1296,7 @@ void export_core() {
|
||||||
BP_CLASS(Bitmap, Object, (bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &>()))
|
BP_CLASS(Bitmap, Object, (bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &>()))
|
||||||
.def(bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &, int>())
|
.def(bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &, int>())
|
||||||
.def(bp::init<Bitmap::EFileFormat, Stream *>())
|
.def(bp::init<Bitmap::EFileFormat, Stream *>())
|
||||||
|
.def(bp::init<Bitmap::EFileFormat, Stream *, std::string>())
|
||||||
.def("getPixelFormat", &Bitmap::getPixelFormat)
|
.def("getPixelFormat", &Bitmap::getPixelFormat)
|
||||||
.def("getComponentFormat", &Bitmap::getComponentFormat)
|
.def("getComponentFormat", &Bitmap::getComponentFormat)
|
||||||
.def("getSize", &Bitmap::getSize, BP_RETURN_VALUE)
|
.def("getSize", &Bitmap::getSize, BP_RETURN_VALUE)
|
||||||
|
@ -1361,6 +1394,7 @@ void export_core() {
|
||||||
.value("EOpenEXR", Bitmap::EOpenEXR)
|
.value("EOpenEXR", Bitmap::EOpenEXR)
|
||||||
.value("ETGA", Bitmap::ETGA)
|
.value("ETGA", Bitmap::ETGA)
|
||||||
.value("EPFM", Bitmap::EPFM)
|
.value("EPFM", Bitmap::EPFM)
|
||||||
|
.value("EPPM", Bitmap::EPPM)
|
||||||
.value("ERGBE", Bitmap::ERGBE)
|
.value("ERGBE", Bitmap::ERGBE)
|
||||||
.value("EBMP", Bitmap::EBMP)
|
.value("EBMP", Bitmap::EBMP)
|
||||||
.value("EJPEG", Bitmap::EJPEG)
|
.value("EJPEG", Bitmap::EJPEG)
|
||||||
|
@ -2263,6 +2297,20 @@ void export_core() {
|
||||||
.def("getMillisecondsSinceStart", &Timer::getMillisecondsSinceStart)
|
.def("getMillisecondsSinceStart", &Timer::getMillisecondsSinceStart)
|
||||||
.def("getSecondsSinceStart", &Timer::getSecondsSinceStart);
|
.def("getSecondsSinceStart", &Timer::getSecondsSinceStart);
|
||||||
|
|
||||||
|
BP_STRUCT(VonMisesFisherDistr, bp::init<Float>())
|
||||||
|
.def("getKappa", &VonMisesFisherDistr::getKappa)
|
||||||
|
.def("setKappa", &VonMisesFisherDistr::setKappa)
|
||||||
|
.def("eval", &VonMisesFisherDistr::eval)
|
||||||
|
.def("getMeanCosine", &VonMisesFisherDistr::getMeanCosine)
|
||||||
|
.def("sample", &VonMisesFisherDistr::sample, BP_RETURN_VALUE)
|
||||||
|
.def("forMeanCosine", &VonMisesFisherDistr::forMeanCosine)
|
||||||
|
.def("forPeakValue", &VonMisesFisherDistr::forPeakValue)
|
||||||
|
.def("convolve", &VonMisesFisherDistr::convolve)
|
||||||
|
.def("__repr__", &VonMisesFisherDistr::toString)
|
||||||
|
.staticmethod("forMeanCosine")
|
||||||
|
.staticmethod("forPeakValue")
|
||||||
|
.staticmethod("convolve");
|
||||||
|
|
||||||
bp::detail::current_scope = oldScope;
|
bp::detail::current_scope = oldScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -626,6 +626,14 @@ void export_render() {
|
||||||
.def("setFarClip", &ProjectiveCamera::setFarClip)
|
.def("setFarClip", &ProjectiveCamera::setFarClip)
|
||||||
.def("setFocusDistance", &ProjectiveCamera::setFocusDistance);
|
.def("setFocusDistance", &ProjectiveCamera::setFocusDistance);
|
||||||
|
|
||||||
|
BP_CLASS(PerspectiveCamera, ProjectiveCamera, bp::no_init)
|
||||||
|
.def("getXFov", &PerspectiveCamera::getXFov)
|
||||||
|
.def("setXFov", &PerspectiveCamera::setXFov)
|
||||||
|
.def("getYFov", &PerspectiveCamera::getYFov)
|
||||||
|
.def("setYFov", &PerspectiveCamera::setYFov)
|
||||||
|
.def("getDiagonalFov", &PerspectiveCamera::getDiagonalFov)
|
||||||
|
.def("setDiagonalFov", &PerspectiveCamera::setDiagonalFov);
|
||||||
|
|
||||||
BP_CLASS(Integrator, ConfigurableObject, bp::no_init)
|
BP_CLASS(Integrator, ConfigurableObject, bp::no_init)
|
||||||
.def("preprocess", &Integrator::preprocess)
|
.def("preprocess", &Integrator::preprocess)
|
||||||
.def("render", &Integrator::render)
|
.def("render", &Integrator::render)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <xercesc/parsers/SAXParser.hpp>
|
#include <xercesc/parsers/SAXParser.hpp>
|
||||||
#include <xercesc/framework/MemBufInputSource.hpp>
|
#include <xercesc/framework/MemBufInputSource.hpp>
|
||||||
#include <xercesc/util/TransService.hpp>
|
#include <xercesc/util/TransService.hpp>
|
||||||
|
#include <xercesc/sax/Locator.hpp>
|
||||||
#include <mitsuba/render/scenehandler.h>
|
#include <mitsuba/render/scenehandler.h>
|
||||||
#include <mitsuba/core/fresolver.h>
|
#include <mitsuba/core/fresolver.h>
|
||||||
#include <mitsuba/render/scene.h>
|
#include <mitsuba/render/scene.h>
|
||||||
|
@ -38,24 +39,21 @@ XERCES_CPP_NAMESPACE_USE
|
||||||
|
|
||||||
#define TRANSCODE_BLOCKSIZE 2048
|
#define TRANSCODE_BLOCKSIZE 2048
|
||||||
|
|
||||||
#if !defined(__OSX__)
|
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
|
||||||
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
|
level, NULL, __FILE__, __LINE__, "In file \"%s\" (near line %i): " fmt, \
|
||||||
level, NULL, __FILE__, __LINE__, "Near file offset %i: " fmt, \
|
m_locator ? transcode(m_locator->getSystemId()).c_str() : "<unknown>", \
|
||||||
(int) m_parser->getSrcOffset(), ## __VA_ARGS__)
|
m_locator ? m_locator->getLineNumber() : -1, \
|
||||||
#else
|
## __VA_ARGS__)
|
||||||
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
|
|
||||||
level, NULL, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*CleanupFun) ();
|
typedef void (*CleanupFun) ();
|
||||||
typedef boost::unordered_set<CleanupFun> CleanupSet;
|
typedef boost::unordered_set<CleanupFun> CleanupSet;
|
||||||
static PrimitiveThreadLocal<CleanupSet> __cleanup_tls;
|
static PrimitiveThreadLocal<CleanupSet> __cleanup_tls;
|
||||||
|
|
||||||
SceneHandler::SceneHandler(const SAXParser *parser,
|
SceneHandler::SceneHandler(const ParameterMap ¶ms,
|
||||||
const ParameterMap ¶ms, NamedObjectMap *namedObjects,
|
NamedObjectMap *namedObjects, bool isIncludedFile) : m_params(params),
|
||||||
bool isIncludedFile) : m_parser(parser), m_params(params),
|
|
||||||
m_namedObjects(namedObjects), m_isIncludedFile(isIncludedFile) {
|
m_namedObjects(namedObjects), m_isIncludedFile(isIncludedFile) {
|
||||||
m_pluginManager = PluginManager::getInstance();
|
m_pluginManager = PluginManager::getInstance();
|
||||||
|
m_locator = NULL;
|
||||||
|
|
||||||
if (m_isIncludedFile) {
|
if (m_isIncludedFile) {
|
||||||
SAssert(namedObjects != NULL);
|
SAssert(namedObjects != NULL);
|
||||||
|
@ -119,6 +117,10 @@ SceneHandler::~SceneHandler() {
|
||||||
delete m_namedObjects;
|
delete m_namedObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneHandler::setDocumentLocator(const xercesc::Locator* const locator) {
|
||||||
|
m_locator = locator;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneHandler::clear() {
|
void SceneHandler::clear() {
|
||||||
if (!m_isIncludedFile) {
|
if (!m_isIncludedFile) {
|
||||||
for (NamedObjectMap::iterator it = m_namedObjects->begin();
|
for (NamedObjectMap::iterator it = m_namedObjects->begin();
|
||||||
|
@ -665,14 +667,10 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
||||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
||||||
|
|
||||||
/* Set the handler and start parsing */
|
/* Set the handler and start parsing */
|
||||||
SceneHandler *handler = new SceneHandler(parser, m_params, m_namedObjects, true);
|
SceneHandler *handler = new SceneHandler(m_params, m_namedObjects, true);
|
||||||
parser->setDoNamespaces(true);
|
parser->setDoNamespaces(true);
|
||||||
parser->setDocumentHandler(handler);
|
parser->setDocumentHandler(handler);
|
||||||
parser->setErrorHandler(handler);
|
parser->setErrorHandler(handler);
|
||||||
#if !defined(__OSX__)
|
|
||||||
/// Not supported on OSX
|
|
||||||
parser->setCalculateSrcOfs(true);
|
|
||||||
#endif
|
|
||||||
fs::path path = resolver->resolve(context.attributes["filename"]);
|
fs::path path = resolver->resolve(context.attributes["filename"]);
|
||||||
XMLLog(EInfo, "Parsing included file \"%s\" ..", path.filename().string().c_str());
|
XMLLog(EInfo, "Parsing included file \"%s\" ..", path.filename().string().c_str());
|
||||||
parser->parse(path.c_str());
|
parser->parse(path.c_str());
|
||||||
|
@ -741,7 +739,11 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
object = m_pluginManager->createObject(tag.second, props);
|
try {
|
||||||
|
object = m_pluginManager->createObject(tag.second, props);
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
XMLLog(EError, "Error while creating object: %s", ex.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -831,9 +833,8 @@ ref<Scene> SceneHandler::loadScene(const fs::path &filename, const ParameterMap
|
||||||
parser->setValidationSchemaFullChecking(true);
|
parser->setValidationSchemaFullChecking(true);
|
||||||
parser->setValidationScheme(SAXParser::Val_Always);
|
parser->setValidationScheme(SAXParser::Val_Always);
|
||||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
||||||
parser->setCalculateSrcOfs(true);
|
|
||||||
|
|
||||||
SceneHandler *handler = new SceneHandler(parser, params);
|
SceneHandler *handler = new SceneHandler(params);
|
||||||
parser->setDoNamespaces(true);
|
parser->setDoNamespaces(true);
|
||||||
parser->setDocumentHandler(handler);
|
parser->setDocumentHandler(handler);
|
||||||
parser->setErrorHandler(handler);
|
parser->setErrorHandler(handler);
|
||||||
|
@ -858,9 +859,8 @@ ref<Scene> SceneHandler::loadSceneFromString(const std::string &content, const P
|
||||||
parser->setValidationSchemaFullChecking(true);
|
parser->setValidationSchemaFullChecking(true);
|
||||||
parser->setValidationScheme(SAXParser::Val_Always);
|
parser->setValidationScheme(SAXParser::Val_Always);
|
||||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
||||||
parser->setCalculateSrcOfs(true);
|
|
||||||
|
|
||||||
SceneHandler *handler = new SceneHandler(parser, params);
|
SceneHandler *handler = new SceneHandler(params);
|
||||||
parser->setDoNamespaces(true);
|
parser->setDoNamespaces(true);
|
||||||
parser->setDocumentHandler(handler);
|
parser->setDocumentHandler(handler);
|
||||||
parser->setErrorHandler(handler);
|
parser->setErrorHandler(handler);
|
||||||
|
|
|
@ -48,42 +48,43 @@ static MaterialEntry materialData[] = {
|
||||||
|
|
||||||
/* From "Acquiring Scattering Properties of Participating Media by Dilution"
|
/* From "Acquiring Scattering Properties of Participating Media by Dilution"
|
||||||
by Narasimhan, Gupta, Donner, Ramamoorthi, Nayar, Jensen (SIGGRAPH 2006) */
|
by Narasimhan, Gupta, Donner, Ramamoorthi, Nayar, Jensen (SIGGRAPH 2006) */
|
||||||
{ "Lowfat Milk", { 0.9124f, 1.0744f, 1.2492f }, { 0.0002f, 0.0004f, 0.0008f }, { 0.9320f, 0.9020f, 0.8590f }, 1.33f },
|
{ "Lowfat Milk", { 13.1157f, 15.4445f, 17.9572f }, { 0.00287f, 0.00575f, 0.01150f }, { 0.93200f, 0.90200f, 0.85900f }, 1.33f },
|
||||||
{ "Reduced Milk", { 1.0748f, 1.2209f, 1.3931f }, { 0.0002f, 0.0004f, 0.0010f }, { 0.8190f, 0.7970f, 0.7460f }, 1.33f },
|
{ "Reduced Milk", { 13.7335f, 15.6003f, 17.8007f }, { 0.00256f, 0.00511f, 0.01278f }, { 0.81900f, 0.79700f, 0.74600f }, 1.33f },
|
||||||
{ "Regular Milk", { 1.1873f, 1.3293f, 1.4589f }, { 0.0001f, 0.0003f, 0.0013f }, { 0.7500f, 0.7140f, 0.6810f }, 1.33f },
|
{ "Regular Milk", { 18.2052f, 20.3826f, 22.3698f }, { 0.00153f, 0.00460f, 0.01993f }, { 0.75000f, 0.71400f, 0.68100f }, 1.33f },
|
||||||
{ "Espresso", { 0.2707f, 0.2828f, 0.2970f }, { 0.1669f, 0.2287f, 0.3078f }, { 0.9070f, 0.8960f, 0.8800f }, 1.33f },
|
{ "Espresso", { 7.78262f, 8.13050f, 8.53875f }, { 4.79838f, 6.57512f, 8.84925f }, { 0.90700f, 0.89600f, 0.88000f }, 1.33f },
|
||||||
{ "Mint Mocha Coffee", { 0.0916f, 0.1081f, 0.1460f }, { 0.0984f, 0.1519f, 0.2040f }, { 0.9100f, 0.9070f, 0.9140f }, 1.33f },
|
{ "Mint Mocha Coffee", { 3.51133f, 4.14383f, 5.59667f }, { 3.77200f, 5.82283f, 7.82000f }, { 0.91000f, 0.90700f, 0.91400f }, 1.33f },
|
||||||
{ "Lowfat Soy Milk", { 0.1418f, 0.1620f, 0.2715f }, { 0.0001f, 0.0005f, 0.0025f }, { 0.8500f, 0.8530f, 0.8420f }, 1.33f },
|
{ "Lowfat Soy Milk", { 2.03838f, 2.32875f, 3.90281f }, { 0.00144f, 0.00719f, 0.03594f }, { 0.85000f, 0.85300f, 0.84200f }, 1.33f },
|
||||||
{ "Regular Soy Milk", { 0.2433f, 0.2714f, 0.4563f }, { 0.0001f, 0.0005f, 0.0034f }, { 0.8730f, 0.8580f, 0.8320f }, 1.33f },
|
{ "Regular Soy Milk", { 4.66325f, 5.20183f, 8.74575f }, { 0.00192f, 0.00958f, 0.06517f }, { 0.87300f, 0.85800f, 0.83200f }, 1.33f },
|
||||||
{ "Lowfat Chocolate Milk", { 0.4277f, 0.4998f, 0.5723f }, { 0.0005f, 0.0016f, 0.0068f }, { 0.9340f, 0.9270f, 0.9160f }, 1.33f },
|
{ "Lowfat Chocolate Milk", { 9.83710f, 11.4954f, 13.1629f }, { 0.01150f, 0.03680f, 0.15640f }, { 0.93400f, 0.92700f, 0.91600f }, 1.33f },
|
||||||
{ "Regular Chocolate Milk", { 0.7352f, 0.9142f, 1.0588f }, { 0.0007f, 0.0030f, 0.0100f }, { 0.8620f, 0.8380f, 0.8060f }, 1.33f },
|
{ "Regular Chocolate Milk", { 10.5685f, 13.1416f, 15.2202f }, { 0.01006f, 0.04313f, 0.14375f }, { 0.86200f, 0.83800f, 0.80600f }, 1.33f },
|
||||||
{ "Coke", { 0.0177f, 0.0208f, 0.0000f }, { 0.6966f, 1.1480f, 1.7169f }, { 0.9650f, 0.9720f, 0.9685f }, 1.33f },
|
{ "Coke", { 0.00254f, 0.00299f, 0.00000f }, { 0.10014f, 0.16503f, 0.24680f }, { 0.96500f, 0.97200f, 0.00000f }, 1.33f },
|
||||||
{ "Pepsi", { 0.0058f, 0.0141f, 0.0000f }, { 0.6375f, 0.9849f, 1.4420f }, { 0.9260f, 0.9790f, 0.9525f }, 1.33f },
|
{ "Pepsi", { 0.00083f, 0.00203f, 0.00000f }, { 0.09164f, 0.14158f, 0.20729f }, { 0.92600f, 0.97900f, 0.00000f }, 1.33f },
|
||||||
{ "Sprite", { 0.0069f, 0.0089f, 0.0089f }, { 0.1230f, 0.1194f, 0.1306f }, { 0.9430f, 0.9530f, 0.9520f }, 1.33f },
|
{ "Sprite", { 0.00011f, 0.00014f, 0.00014f }, { 0.00189f, 0.00183f, 0.00200f }, { 0.94300f, 0.95300f, 0.95200f }, 1.33f },
|
||||||
{ "Gatorade", { 0.2392f, 0.2927f, 0.3745f }, { 0.1617f, 0.1258f, 0.0579f }, { 0.9330f, 0.9330f, 0.9350f }, 1.33f },
|
{ "Gatorade", { 0.03668f, 0.04488f, 0.05742f }, { 0.02479f, 0.01929f, 0.00888f }, { 0.93300f, 0.93300f, 0.93500f }, 1.33f },
|
||||||
{ "Chardonnay", { 0.0030f, 0.0047f, 0.0069f }, { 0.1547f, 0.1701f, 0.3443f }, { 0.9140f, 0.9580f, 0.9750f }, 1.33f },
|
{ "Chardonnay", { 0.00021f, 0.00033f, 0.00048f }, { 0.01078f, 0.01186f, 0.02400f }, { 0.91400f, 0.95800f, 0.97500f }, 1.33f },
|
||||||
{ "White Zinfandel", { 0.0031f, 0.0048f, 0.0066f }, { 0.1732f, 0.2322f, 0.2847f }, { 0.9190f, 0.9430f, 0.9720f }, 1.33f },
|
{ "White Zinfandel", { 0.00022f, 0.00033f, 0.00046f }, { 0.01207f, 0.01618f, 0.01984f }, { 0.91900f, 0.94300f, 0.97200f }, 1.33f },
|
||||||
{ "Merlot", { 0.0053f, 0.0000f, 0.0000f }, { 0.7586f, 1.6429f, 1.9196f }, { 0.9740f, 0.9740f, 0.9740f }, 1.33f },
|
{ "Merlot", { 0.00081f, 0.00000f, 0.00000f }, { 0.11632f, 0.25191f, 0.29434f }, { 0.97400f, 0.00000f, 0.00000f }, 1.33f },
|
||||||
{ "Budweiser Beer", { 0.0037f, 0.0069f, 0.0074f }, { 0.1449f, 0.3141f, 0.7286f }, { 0.9170f, 0.9560f, 0.9820f }, 1.33f },
|
{ "Budweiser Beder", { 0.00029f, 0.00055f, 0.00059f }, { 0.01149f, 0.02491f, 0.05779f }, { 0.91700f, 0.95600f, 0.98200f }, 1.33f },
|
||||||
{ "Coors Light Beer", { 0.0027f, 0.0055f, 0.0000f }, { 0.0268f, 0.0608f, 0.1521f }, { 0.9180f, 0.9660f, 0.9420f }, 1.33f },
|
{ "Coors Light Beer", { 0.00062f, 0.00127f, 0.00000f }, { 0.00616f, 0.01398f, 0.03498f }, { 0.91800f, 0.96600f, 0.00000f }, 1.33f },
|
||||||
{ "Clorox", { 0.1425f, 0.1723f, 0.1928f }, { 0.0175f, 0.0777f, 0.1372f }, { 0.9120f, 0.9050f, 0.8920f }, 1.33f },
|
{ "Clorox", { 0.02731f, 0.03302f, 0.03695f }, { 0.00335f, 0.01489f, 0.02630f }, { 0.91200f, 0.90500f, 0.89200f }, 1.33f },
|
||||||
{ "Apple Juice", { 0.0201f, 0.0243f, 0.0323f }, { 0.1014f, 0.1858f, 0.4084f }, { 0.9470f, 0.9490f, 0.9450f }, 1.33f },
|
{ "Apple Juice", { 0.00257f, 0.00311f, 0.00413f }, { 0.01296f, 0.02374f, 0.05218f }, { 0.94700f, 0.94900f, 0.94500f }, 1.33f },
|
||||||
{ "Cranberry Juice", { 0.0128f, 0.0155f, 0.0196f }, { 0.2572f, 0.6145f, 0.8104f }, { 0.9470f, 0.9510f, 0.9740f }, 1.33f },
|
{ "Cranberry Juice", { 0.00196f, 0.00238f, 0.00301f }, { 0.03944f, 0.09422f, 0.12426f }, { 0.94700f, 0.95100f, 0.97400f }, 1.33f },
|
||||||
{ "Grape Juice", { 0.0072f, 0.0000f, 0.0000f }, { 0.5428f, 1.2500f, 1.5300f }, { 0.9610f, 0.9610f, 0.9610f }, 1.33f },
|
{ "Grape Juice", { 0.00138f, 0.00000f, 0.00000f }, { 0.10404f, 0.23958f, 0.29325f }, { 0.96100f, 0.00000f, 0.00000f }, 1.33f },
|
||||||
{ "Ruby Grapefruit Juice", { 0.1617f, 0.1606f, 0.1669f }, { 0.0896f, 0.1911f, 0.2636f }, { 0.9290f, 0.9290f, 0.9310f }, 1.33f },
|
{ "Ruby Grapefruit Juice", { 0.15496f, 0.15391f, 0.15995f }, { 0.08587f, 0.18314f, 0.25262f }, { 0.92900f, 0.92900f, 0.93100f }, 1.33f },
|
||||||
{ "White Grapefruit Juice", { 0.3513f, 0.3669f, 0.5237f }, { 0.0096f, 0.0131f, 0.0395f }, { 0.5480f, 0.5450f, 0.5650f }, 1.33f },
|
{ "White Grapefruit Juice", { 0.50499f, 0.52742f, 0.75282f }, { 0.01380f, 0.01883f, 0.05678f }, { 0.54800f, 0.54500f, 0.56500f }, 1.33f },
|
||||||
{ "Shampoo", { 0.0104f, 0.0114f, 0.0147f }, { 0.0184f, 0.0596f, 0.0805f }, { 0.9100f, 0.9050f, 0.9200f }, 1.33f },
|
{ "Shampoo", { 0.00797f, 0.00874f, 0.01127f }, { 0.01411f, 0.04569f, 0.06172f }, { 0.91000f, 0.90500f, 0.92000f }, 1.33f },
|
||||||
{ "Strawberry Shampoo", { 0.0028f, 0.0032f, 0.0033f }, { 0.0189f, 0.0756f, 0.0989f }, { 0.9270f, 0.9350f, 0.9940f }, 1.33f },
|
{ "Strawberry Shampoo", { 0.00215f, 0.00245f, 0.00253f }, { 0.01449f, 0.05796f, 0.07582f }, { 0.92700f, 0.93500f, 0.99400f }, 1.33f },
|
||||||
{ "Head & Shoulders Shampoo", { 0.2791f, 0.2890f, 0.3086f }, { 0.0883f, 0.1637f, 0.2125f }, { 0.9110f, 0.8960f, 0.8840f }, 1.33f },
|
{ "Head & Shoulders Shampoo", { 0.26747f, 0.27696f, 0.29574f }, { 0.08462f, 0.15688f, 0.20365f }, { 0.91100f, 0.89600f, 0.88400f }, 1.33f },
|
||||||
{ "Lemon Tea Powder", { 0.0798f, 0.0898f, 0.1073f }, { 0.2602f, 0.4902f, 0.7727f }, { 0.9460f, 0.9460f, 0.9490f }, 1.33f },
|
{ "Lemon Tea Powder", { 0.74489f, 0.83823f, 1.00158f }, { 2.42881f, 4.57573f, 7.21270f }, { 0.94600f, 0.94600f, 0.94900f }, 1.33f },
|
||||||
{ "Orange Juice Powder", { 0.1928f, 0.2132f, 0.2259f }, { 0.1449f, 0.3441f, 0.7863f }, { 0.9190f, 0.9180f, 0.9220f }, 1.33f },
|
{ "Orange Juice Powder", { 0.00193f, 0.00213f, 0.00226f }, { 0.00145f, 0.00344f, 0.00786f }, { 0.91900f, 0.91800f, 0.92200f }, 1.33f },
|
||||||
{ "Pink Lemonade Powder", { 0.1235f, 0.1334f, 0.1305f }, { 0.1165f, 0.2366f, 0.3195f }, { 0.9020f, 0.9020f, 0.9040f }, 1.33f },
|
{ "Pink Lemonade Powder", { 0.00123f, 0.00133f, 0.00131f }, { 0.00116f, 0.00237f, 0.00320f }, { 0.90200f, 0.90200f, 0.90400f }, 1.33f },
|
||||||
{ "Cappuccino Powder", { 0.0654f, 0.0882f, 0.1568f }, { 0.1920f, 0.2654f, 0.3272f }, { 0.8490f, 0.8430f, 0.9260f }, 1.33f },
|
{ "Cappuccino Powder", { 12.2094f, 16.4659f, 29.2727f }, { 35.8441f, 49.5470f, 61.0844f }, { 0.84900f, 0.84300f, 0.92600f }, 1.33f },
|
||||||
{ "Salt Powder", { 0.2485f, 0.2822f, 0.3216f }, { 0.5115f, 0.5863f, 0.6147f }, { 0.8020f, 0.7930f, 0.8210f }, 1.33f },
|
{ "Salt Powder", { 0.13805f, 0.15677f, 0.17865f }, { 0.28415f, 0.32570f, 0.34148f }, { 0.80200f, 0.79300f, 0.82100f }, 1.33f },
|
||||||
{ "Sugar Powder", { 0.0145f, 0.0162f, 0.0202f }, { 0.0650f, 0.1597f, 0.2578f }, { 0.9210f, 0.9190f, 0.9310f }, 1.33f },
|
{ "Sugar Powder", { 0.00282f, 0.00315f, 0.00393f }, { 0.01264f, 0.03105f, 0.05012f }, { 0.92100f, 0.91900f, 0.93100f }, 1.33f },
|
||||||
{ "Suisse Mocha", { 0.3223f, 0.3583f, 0.4148f }, { 0.1875f, 0.2893f, 0.3796f }, { 0.9070f, 0.8940f, 0.8880f }, 1.33f },
|
{ "Suisse Mocha Powder", { 30.0848f, 33.4452f, 38.7191f }, { 17.5020f, 27.0044f, 35.4334f }, { 0.90700f, 0.89400f, 0.88800f }, 1.33f },
|
||||||
|
{ "Pacific Ocean Surface Water", { 0.00180f, 0.00183f, 0.00228f }, { 0.03184f, 0.03132f, 0.03015f }, { 0.90200f, 0.82500f, 0.91400f }, 1.33f },
|
||||||
|
|
||||||
{ NULL, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, 0.0f }
|
{ NULL, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, 0.0f }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &sigmaA, Spectrum &g, Float *eta = NULL) {
|
static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &sigmaA, Spectrum &g, Float *eta = NULL) {
|
||||||
|
@ -197,3 +198,4 @@ static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __MATERIAL_DATA_H */
|
#endif /* __MATERIAL_DATA_H */
|
||||||
|
|
||||||
|
|
|
@ -328,13 +328,9 @@ int mitsuba_app(int argc, char **argv) {
|
||||||
parser->setValidationSchemaFullChecking(true);
|
parser->setValidationSchemaFullChecking(true);
|
||||||
parser->setValidationScheme(SAXParser::Val_Always);
|
parser->setValidationScheme(SAXParser::Val_Always);
|
||||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
||||||
#if !defined(__OSX__)
|
|
||||||
/// Not supported on OSX
|
|
||||||
parser->setCalculateSrcOfs(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set the handler */
|
/* Set the handler */
|
||||||
SceneHandler *handler = new SceneHandler(parser, parameters);
|
SceneHandler *handler = new SceneHandler(parameters);
|
||||||
parser->setDoNamespaces(true);
|
parser->setDoNamespaces(true);
|
||||||
parser->setDocumentHandler(handler);
|
parser->setDocumentHandler(handler);
|
||||||
parser->setErrorHandler(handler);
|
parser->setErrorHandler(handler);
|
||||||
|
@ -375,6 +371,8 @@ int mitsuba_app(int argc, char **argv) {
|
||||||
thr->start();
|
thr->start();
|
||||||
|
|
||||||
renderQueue->waitLeft(numParallelScenes-1);
|
renderQueue->waitLeft(numParallelScenes-1);
|
||||||
|
if (i+1 < argc && numParallelScenes == 1)
|
||||||
|
Statistics::getInstance()->resetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for all render processes to finish */
|
/* Wait for all render processes to finish */
|
||||||
|
|
|
@ -159,13 +159,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Collect zombie processes */
|
|
||||||
#if !defined(__WINDOWS__)
|
|
||||||
void collect_zombies(int s) {
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__OSX__)
|
#if defined(__OSX__)
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
#endif
|
#endif
|
||||||
|
@ -213,13 +206,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
#if !defined(__WINDOWS__)
|
#if !defined(__WINDOWS__)
|
||||||
/* Avoid zombies processes when running the server */
|
/* Avoid zombies processes when running the server */
|
||||||
struct sigaction sa;
|
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
|
||||||
sa.sa_handler = collect_zombies;
|
SLog(EWarn, "Error in signal(): %s!", strerror(errno));
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
|
|
||||||
if (sigaction(SIGCHLD, &sa, NULL) == -1)
|
|
||||||
SLog(EWarn, "Error in sigaction(): %s!", strerror(errno));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qRegisterMetaType<ELogLevel>("ELogLevel");
|
qRegisterMetaType<ELogLevel>("ELogLevel");
|
||||||
|
|
|
@ -585,8 +585,8 @@ void MainWindow::on_actionOpen_triggered() {
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(),
|
QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(),
|
||||||
settings.value("fileDir").toString(),
|
settings.value("fileDir").toString(),
|
||||||
tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.png *.jpg *.jpeg);;"
|
tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.ppm *.png *.jpg *.jpeg);;"
|
||||||
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm);;"
|
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm *.ppm);;"
|
||||||
"Low dynamic-range images (*.png *.jpg *.jpeg)"));
|
"Low dynamic-range images (*.png *.jpg *.jpeg)"));
|
||||||
|
|
||||||
QStringList::ConstIterator it = fileNames.constBegin();
|
QStringList::ConstIterator it = fileNames.constBegin();
|
||||||
|
@ -605,8 +605,8 @@ void MainWindow::onOpenDialogClose(int reason) { /* unused */ }
|
||||||
|
|
||||||
void MainWindow::on_actionOpen_triggered() {
|
void MainWindow::on_actionOpen_triggered() {
|
||||||
QFileDialog *dialog = new QFileDialog(this, Qt::Sheet);
|
QFileDialog *dialog = new QFileDialog(this, Qt::Sheet);
|
||||||
dialog->setNameFilter(tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.png *.jpg *.jpeg);;"
|
dialog->setNameFilter(tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.ppm *.png *.jpg *.jpeg);;"
|
||||||
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm);;Low "
|
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm *.ppm);;Low "
|
||||||
"dynamic-range images (*.png *.jpg *.jpeg)"));
|
"dynamic-range images (*.png *.jpg *.jpeg)"));
|
||||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
dialog->setAcceptMode(QFileDialog::AcceptOpen);
|
dialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
|
@ -690,7 +690,7 @@ retry:
|
||||||
ret = QMessageBox::question(this, tr("Version mismatch -- update scene file?"),
|
ret = QMessageBox::question(this, tr("Version mismatch -- update scene file?"),
|
||||||
QString("The requested scene file is from an older version of Mitsuba "
|
QString("The requested scene file is from an older version of Mitsuba "
|
||||||
"(%1). To work with version %2, it will need to be updated. If you "
|
"(%1). To work with version %2, it will need to be updated. If you "
|
||||||
"continue, Mitsuba will perform a fully automated upgrade (note that a "
|
"continue, Mitsuba will perform a fully automated upgrade (a "
|
||||||
"backup copy will be made).\n\nProceed?")
|
"backup copy will be made).\n\nProceed?")
|
||||||
.arg(version.toString().c_str())
|
.arg(version.toString().c_str())
|
||||||
.arg(MTS_VERSION), QMessageBox::Yes | QMessageBox::Cancel);
|
.arg(MTS_VERSION), QMessageBox::Yes | QMessageBox::Cancel);
|
||||||
|
@ -825,6 +825,7 @@ void MainWindow::updateUI() {
|
||||||
ui->actionClose->setEnabled(hasTab);
|
ui->actionClose->setEnabled(hasTab);
|
||||||
ui->actionDuplicateTab->setEnabled(hasTab);
|
ui->actionDuplicateTab->setEnabled(hasTab);
|
||||||
ui->actionAdjustSize->setEnabled(hasTab);
|
ui->actionAdjustSize->setEnabled(hasTab);
|
||||||
|
ui->actionCopyImage->setEnabled(hasTab);
|
||||||
ui->actionShowKDTree->setEnabled(hasScene);
|
ui->actionShowKDTree->setEnabled(hasScene);
|
||||||
ui->actionShowKDTree->setChecked(hasScene && context->showKDTree);
|
ui->actionShowKDTree->setChecked(hasScene && context->showKDTree);
|
||||||
ui->actionSceneDescription->setEnabled(hasScene);
|
ui->actionSceneDescription->setEnabled(hasScene);
|
||||||
|
@ -888,6 +889,7 @@ void MainWindow::on_tabBar_customContextMenuRequested(const QPoint &pt) {
|
||||||
menu.addAction(ui->actionDuplicateTab);
|
menu.addAction(ui->actionDuplicateTab);
|
||||||
if (tabIndex == ui->tabBar->currentIndex())
|
if (tabIndex == ui->tabBar->currentIndex())
|
||||||
menu.addAction(ui->actionAdjustSize);
|
menu.addAction(ui->actionAdjustSize);
|
||||||
|
menu.addAction(ui->actionCopyImage);
|
||||||
menu.addAction(ui->actionClose);
|
menu.addAction(ui->actionClose);
|
||||||
menu.exec(ui->tabBar->mapToGlobal(pt));
|
menu.exec(ui->tabBar->mapToGlobal(pt));
|
||||||
m_contextIndex = -1;
|
m_contextIndex = -1;
|
||||||
|
@ -1482,6 +1484,10 @@ inline float toSRGB(float value) {
|
||||||
return 1.055f * std::pow(value, 0.41666f) - 0.055f;
|
return 1.055f * std::pow(value, 0.41666f) - 0.055f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionCopyImage_triggered() {
|
||||||
|
exportImage("__clipboard__");
|
||||||
|
}
|
||||||
|
|
||||||
#if MTSGUI_STATIC_QFILEDIALOG
|
#if MTSGUI_STATIC_QFILEDIALOG
|
||||||
|
|
||||||
void MainWindow::on_actionExportImage_triggered() {
|
void MainWindow::on_actionExportImage_triggered() {
|
||||||
|
@ -1492,6 +1498,7 @@ void MainWindow::on_actionExportImage_triggered() {
|
||||||
"High dynamic range OpenEXR image (*.exr);;"
|
"High dynamic range OpenEXR image (*.exr);;"
|
||||||
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
|
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
|
||||||
"High dynamic range Portable Float Map image (*.pfm);;"
|
"High dynamic range Portable Float Map image (*.pfm);;"
|
||||||
|
"High dynamic range Portable Pixel Map image (*.ppm);;"
|
||||||
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
|
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
@ -1510,6 +1517,7 @@ void MainWindow::on_actionExportImage_triggered() {
|
||||||
"High dynamic range OpenEXR image (*.exr);;"
|
"High dynamic range OpenEXR image (*.exr);;"
|
||||||
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
|
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
|
||||||
"High dynamic range Portable Float Map image (*.pfm);;"
|
"High dynamic range Portable Float Map image (*.pfm);;"
|
||||||
|
"High dynamic range Portable Pixel Map image (*.ppm);;"
|
||||||
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
|
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
@ -1548,29 +1556,30 @@ void MainWindow::onExportDialogClose(int reason) {
|
||||||
|
|
||||||
void MainWindow::exportImage(const QString &fileName) {
|
void MainWindow::exportImage(const QString &fileName) {
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
|
Bitmap::EComponentFormat compFormat = Bitmap::EInvalid;
|
||||||
Bitmap::EFileFormat format;
|
Bitmap::EFileFormat format;
|
||||||
bool isHDR = true;
|
|
||||||
if (fileName.endsWith(".exr")) {
|
if (fileName.endsWith(".exr")) {
|
||||||
format = Bitmap::EOpenEXR;
|
format = Bitmap::EOpenEXR;
|
||||||
} else if (fileName.endsWith(".png")) {
|
} else if (fileName.endsWith(".png") || fileName == "__clipboard__") {
|
||||||
format = Bitmap::EPNG;
|
format = Bitmap::EPNG;
|
||||||
isHDR = false;
|
compFormat = Bitmap::EUInt8;
|
||||||
} else if (fileName.endsWith(".hdr") || fileName.endsWith(".rgbe")) {
|
} else if (fileName.endsWith(".hdr") || fileName.endsWith(".rgbe")) {
|
||||||
format = Bitmap::ERGBE;
|
format = Bitmap::ERGBE;
|
||||||
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
||||||
format = Bitmap::EJPEG;
|
format = Bitmap::EJPEG;
|
||||||
isHDR = false;
|
compFormat = Bitmap::EUInt8;
|
||||||
} else if (fileName.endsWith(".pfm")) {
|
} else if (fileName.endsWith(".pfm")) {
|
||||||
format = Bitmap::EPFM;
|
format = Bitmap::EPFM;
|
||||||
|
} else if (fileName.endsWith(".ppm")) {
|
||||||
|
format = Bitmap::EPPM;
|
||||||
|
compFormat = Bitmap::EUInt16;
|
||||||
} else {
|
} else {
|
||||||
SLog(EError, "Unknown file type -- the filename must end in either"
|
SLog(EError, "Unknown file type -- the filename must end in either"
|
||||||
" .exr, .rgbe, .hdr, .pfm, .png, .jpg, or .jpeg");
|
" .exr, .rgbe, .hdr, .pfm, .ppm, .png, .jpg, or .jpeg");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<FileStream> fs = new FileStream(toFsPath(fileName),
|
|
||||||
FileStream::ETruncReadWrite);
|
|
||||||
|
|
||||||
const int currentIndex = ui->tabBar->currentIndex();
|
const int currentIndex = ui->tabBar->currentIndex();
|
||||||
const SceneContext *ctx = m_context[currentIndex];
|
const SceneContext *ctx = m_context[currentIndex];
|
||||||
|
|
||||||
|
@ -1578,7 +1587,7 @@ void MainWindow::exportImage(const QString &fileName) {
|
||||||
ui->glView->downloadFramebuffer();
|
ui->glView->downloadFramebuffer();
|
||||||
|
|
||||||
ref<Bitmap> bitmap = ctx->framebuffer;
|
ref<Bitmap> bitmap = ctx->framebuffer;
|
||||||
if (!isHDR) {
|
if (compFormat == Bitmap::EUInt8 || compFormat == Bitmap::EUInt16) {
|
||||||
/* Tonemap the image */
|
/* Tonemap the image */
|
||||||
if (ctx->toneMappingMethod == EReinhard) {
|
if (ctx->toneMappingMethod == EReinhard) {
|
||||||
Float logAvgLuminance = 0, maxLuminance = 0; /* Unused */
|
Float logAvgLuminance = 0, maxLuminance = 0; /* Unused */
|
||||||
|
@ -1589,13 +1598,24 @@ void MainWindow::exportImage(const QString &fileName) {
|
||||||
ctx->reinhardKey, burn);
|
ctx->reinhardKey, burn);
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap = bitmap->convert(Bitmap::ERGB, Bitmap::EUInt8,
|
bitmap = bitmap->convert(Bitmap::ERGB, compFormat,
|
||||||
ctx->srgb ? (Float) -1 : ctx->gamma,
|
ctx->srgb ? (Float) -1 : ctx->gamma,
|
||||||
ctx->toneMappingMethod == EReinhard
|
ctx->toneMappingMethod == EReinhard
|
||||||
? (Float) 1.0f : std::pow((Float) 2, ctx->exposure));
|
? (Float) 1.0f : std::pow((Float) 2, ctx->exposure));
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap->write(format, fs);
|
if (fileName == "__clipboard__") {
|
||||||
|
QImage image(bitmap->getWidth(), bitmap->getHeight(), QImage::Format_RGB888);
|
||||||
|
size_t scanlineSize = (size_t) bitmap->getWidth() * 3 * sizeof(uint8_t);
|
||||||
|
for (int i=0; i<bitmap->getHeight(); ++i)
|
||||||
|
memcpy(image.scanLine(i), bitmap->getUInt8Data() + scanlineSize * i, scanlineSize);
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
clipboard->setPixmap(QPixmap::fromImage(image));
|
||||||
|
} else {
|
||||||
|
ref<FileStream> fs = new FileStream(toFsPath(fileName),
|
||||||
|
FileStream::ETruncReadWrite);
|
||||||
|
bitmap->write(format, fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,7 @@ private slots:
|
||||||
void on_actionFocusAll_triggered();
|
void on_actionFocusAll_triggered();
|
||||||
void on_actionSceneDescription_triggered();
|
void on_actionSceneDescription_triggered();
|
||||||
void on_actionEnableCommandLine_triggered();
|
void on_actionEnableCommandLine_triggered();
|
||||||
|
void on_actionCopyImage_triggered();
|
||||||
void on_tabBar_currentChanged(int index);
|
void on_tabBar_currentChanged(int index);
|
||||||
bool on_tabBar_tabCloseRequested(int index);
|
bool on_tabBar_tabCloseRequested(int index);
|
||||||
void on_tabBar_tabMoved(int from, int to);
|
void on_tabBar_tabMoved(int from, int to);
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionSave"/>
|
<addaction name="actionSave"/>
|
||||||
<addaction name="actionSaveAs"/>
|
<addaction name="actionSaveAs"/>
|
||||||
|
<addaction name="actionCopyImage"/>
|
||||||
<addaction name="actionExportImage"/>
|
<addaction name="actionExportImage"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionClose"/>
|
<addaction name="actionClose"/>
|
||||||
|
@ -475,6 +476,14 @@
|
||||||
<string>Ctrl+F</string>
|
<string>Ctrl+F</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionCopyImage">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Copy image</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+C</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionFeedback">
|
<action name="actionFeedback">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Report &Feedback</string>
|
<string>Report &Feedback</string>
|
||||||
|
|
Before Width: | Height: | Size: 892 B After Width: | Height: | Size: 1008 B |
Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 568 B After Width: | Height: | Size: 477 B |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 291 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 597 B |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 708 B After Width: | Height: | Size: 694 B |
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 459 B |
Before Width: | Height: | Size: 504 B After Width: | Height: | Size: 561 B |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 997 B |
Before Width: | Height: | Size: 775 B After Width: | Height: | Size: 967 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 682 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 964 B After Width: | Height: | Size: 1017 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 202 B |
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 897 B |
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 899 B |
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 895 B |
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 1000 B |
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 629 B |
Before Width: | Height: | Size: 652 B After Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 682 B After Width: | Height: | Size: 744 B |
|
@ -48,7 +48,7 @@ void SceneLoader::run() {
|
||||||
QFileInfo fileInfo(m_filename);
|
QFileInfo fileInfo(m_filename);
|
||||||
QString suffix = fileInfo.suffix().toLower();
|
QString suffix = fileInfo.suffix().toLower();
|
||||||
|
|
||||||
SceneHandler *handler = new SceneHandler(parser, m_parameters);
|
SceneHandler *handler = new SceneHandler(m_parameters);
|
||||||
m_result = new SceneContext();
|
m_result = new SceneContext();
|
||||||
try {
|
try {
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
@ -67,7 +67,7 @@ void SceneLoader::run() {
|
||||||
m_result->diffuseReceivers = settings.value("preview_diffuseReceivers", false).toBool();
|
m_result->diffuseReceivers = settings.value("preview_diffuseReceivers", false).toBool();
|
||||||
|
|
||||||
if (suffix == "exr" || suffix == "png" || suffix == "jpg" || suffix == "jpeg" ||
|
if (suffix == "exr" || suffix == "png" || suffix == "jpg" || suffix == "jpeg" ||
|
||||||
suffix == "hdr" || suffix == "rgbe" || suffix == "pfm") {
|
suffix == "hdr" || suffix == "rgbe" || suffix == "pfm" || suffix == "ppm") {
|
||||||
/* This is an image, not a scene */
|
/* This is an image, not a scene */
|
||||||
ref<FileStream> fs = new FileStream(toFsPath(m_filename), FileStream::EReadOnly);
|
ref<FileStream> fs = new FileStream(toFsPath(m_filename), FileStream::EReadOnly);
|
||||||
ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, fs);
|
ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, fs);
|
||||||
|
@ -87,10 +87,6 @@ void SceneLoader::run() {
|
||||||
parser->setValidationSchemaFullChecking(true);
|
parser->setValidationSchemaFullChecking(true);
|
||||||
parser->setValidationScheme(SAXParser::Val_Always);
|
parser->setValidationScheme(SAXParser::Val_Always);
|
||||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
|
||||||
#if !defined(__OSX__)
|
|
||||||
/// Not supported on OSX
|
|
||||||
parser->setCalculateSrcOfs(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set the SAX handler */
|
/* Set the SAX handler */
|
||||||
parser->setDoNamespaces(true);
|
parser->setDoNamespaces(true);
|
||||||
|
|
|
@ -448,7 +448,7 @@ public:
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "PerspectiveCamera[" << endl
|
oss << "PerspectiveCamera[" << endl
|
||||||
<< " xfov = " << m_xfov << "," << endl
|
<< " fov = [" << getXFov() << ", " << getYFov() << "]," << endl
|
||||||
<< " nearClip = " << m_nearClip << "," << endl
|
<< " nearClip = " << m_nearClip << "," << endl
|
||||||
<< " farClip = " << m_farClip << "," << endl
|
<< " farClip = " << m_farClip << "," << endl
|
||||||
<< " worldTransform = " << indent(m_worldTransform.toString()) << "," << endl
|
<< " worldTransform = " << indent(m_worldTransform.toString()) << "," << endl
|
||||||
|
|