Merge with default

metadata
Edgar Velazquez-Armendariz 2014-04-02 15:58:32 -04:00
commit 2963094267
104 changed files with 1161 additions and 382 deletions

View File

@ -10,3 +10,4 @@ ee26517b27207353b0c8a7d357bcb4977b5d93fb v0.4.0
f1b73d39617071297167cc7ce96f3892f21105fc v0.4.3
bd6ddacdf7955e51d9b80be639c282d4974e6f56 v0.4.4
454ebc86e4bd5b3c1d5eb6585099e66ccd8522fe v0.4.5
e6a8a0178556bbce63a2a154191351aa58285623 v0.5.0

View File

@ -24,6 +24,9 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -25,6 +25,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -24,6 +24,8 @@ PYTHON27LIBDIR = ['/System/Library/Frameworks/Python.framework/Versions/2.7/lib'
PYTHON27LIB = ['boost_python27', 'boost_system']
PYTHON33INCLUDE= ['#dependencies/include/python3.3']
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']
COLLADALIB = ['collada14dom24']
QTDIR = '#dependencies'

View File

@ -32,6 +32,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/i386_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/i386_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/i386_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -32,6 +32,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/x64_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/x64_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc100-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc100-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc100-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/x64_vc10'
FFTWLIB = ['libfftw-3.3']

View File

@ -30,6 +30,8 @@ PYTHON32LIB = ['boost_python32-vc120-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc120-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/x64_vc12'
FFTWLIB = ['libfftw-3.3']

View File

@ -33,6 +33,8 @@ PYTHON32LIB = ['boost_python32-vc120-mt-1_53', 'python32']
PYTHON32INCLUDE = ['#dependencies/include/python32']
PYTHON33LIB = ['boost_python33-vc120-mt-1_53', 'python33']
PYTHON33INCLUDE = ['#dependencies/include/python33']
PYTHON34LIB = ['boost_python34-vc120-mt-1_53', 'python34']
PYTHON34INCLUDE = ['#dependencies/include/python34']
QTINCLUDE = ['#dependencies/qt/include']
QTDIR = '#dependencies/qt/x64_vc12'
FFTWLIB = ['libfftw-3.3']

View File

@ -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
* New height field intersection shape
* kd-tree precision improvements when rendering in double precision

View File

@ -1,5 +1,5 @@
Name: mitsuba
Version: 0.4.5
Version: 0.5.0
Release: 1%{?dist}
Summary: Mitsuba renderer
Group: Applications/Graphics
@ -24,7 +24,7 @@ building custom plugins and other extensions for Mitsuba.
%prep
%setup -q
%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
%install
rm -rf $RPM_BUILD_ROOT
@ -66,6 +66,9 @@ rm -rf $RPM_BUILD_ROOT
/usr/include/*
%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}
- Upgrade to version 0.4.5

View File

@ -17,19 +17,22 @@ add_custom_command (
OUTPUT "${SCHEMA_DIR}/scene.xsd"
"${SCHEMA_DIR}/upgrade_0.3.0.xsl"
"${SCHEMA_DIR}/upgrade_0.4.0.xsl"
"${SCHEMA_DIR}/upgrade_0.5.0.xsl"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/scene.xsd" "${SCHEMA_DIR}/scene.xsd"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/upgrade_0.3.0.xsl" "${SCHEMA_DIR}/upgrade_0.3.0.xsl"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${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"
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"
)
add_custom_target (scene_schema
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")

View File

@ -12,7 +12,7 @@
</xsl:template>
<!-- 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:template>

View File

@ -513,7 +513,6 @@
author={Kelemen, C. and Szirmay-Kalos, L. and Antal, G. and Csonka, F.},
booktitle={Computer Graphics Forum},
volume={21},
number={3},
pages={531--540},
year={2002}
}

View File

@ -40,8 +40,8 @@
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{3}
\newcommand{\MitsubaVersion}{0.4.5}
\newcommand{\MitsubaYear}{2013}
\newcommand{\MitsubaVersion}{0.5.0}
\newcommand{\MitsubaYear}{2014}
\typearea[current]{last}
\raggedbottom

View File

@ -100,6 +100,8 @@ print(trafo * myVector)
\subsection{Recipes}
The following section contains a series of ``recipes'' on how to do
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}
The following script demonstrates how to use the
@ -303,6 +305,158 @@ scene.addChild(pmgr.create({
scene.configure()
\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}
Many operations in Mitsuba will print one or more log messages
during their execution. By default, they will be printed to the console,

View File

@ -223,6 +223,16 @@ public:
*/
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
*
@ -678,12 +688,17 @@ public:
* specified component format. Names for each of the resulting channels should
* be provided via the \c channelNames parameters.
*
* This function is currently only used by the \c hdrfilm plugin but located here
* as it is tied to the internals of this class.
* This feature is currently used by the \c hdrfilm and \c tiledhdrfilm plugins.
*/
ref<Bitmap> convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
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
*
@ -1110,6 +1125,12 @@ protected:
/// Write a file using the PFM file format
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
void readTGA(Stream *stream);

View File

@ -67,6 +67,7 @@ protected:
* \ingroup libpython
*/
class MTS_EXPORT_CORE DefaultFormatter : public Formatter {
friend class Logger;
public:
/// Create a new default formatter
DefaultFormatter();

View File

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

View File

@ -28,7 +28,9 @@ MTS_NAMESPACE_BEGIN
* \brief Von Mises-Fisher distribution on the 2-sphere
*
* 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
* \ingroup libcore
@ -39,13 +41,21 @@ public:
* \brief Create a new von Mises-Fisher distribution
* 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
inline Float getKappa() const {
return m_kappa;
}
/// Return the mean cosine of the distribution
Float getMeanCosine() const;
/// Evaluate the distribution for a given value of cos(theta)
Float eval(Float cosTheta) const;
@ -57,12 +67,21 @@ public:
*/
Vector sample(const Point2 &sample) const;
/// Return a string representation
std::string toString() const;
/**
* \brief Compute an appropriate concentration parameter so that
* the associated vMF distribution takes on the value \c x at its peak
*/
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
* corresponds to the spherical convolution of two vMF distributions.

View File

@ -2198,6 +2198,21 @@ protected:
*newEventsLeftEnd = newEventsLeftStart,
*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) {
int classification = storage.get(event->index);
@ -2212,11 +2227,11 @@ protected:
generate new events for each side */
const IndexType index = event->index;
AABBType clippedLeft = cast()->getClippedAABB(index, leftNodeAABB);
AABBType clippedRight = cast()->getClippedAABB(index, rightNodeAABB);
AABBType clippedLeft = cast()->getClippedAABB(index, leftNodeAABB_enlarged);
AABBType clippedRight = cast()->getClippedAABB(index, rightNodeAABB_enlarged);
KDAssert(leftNodeAABB.contains(clippedLeft));
KDAssert(rightNodeAABB.contains(clippedRight));
KDAssert(leftNodeAABB_enlarged.contains(clippedLeft));
KDAssert(rightNodeAABB_enlarged.contains(clippedRight));
if (clippedLeft.isValid() && clippedLeft.getSurfaceArea() > 0) {
for (int axis=0; axis<PointType::dim; ++axis) {

View File

@ -206,7 +206,7 @@ public:
/// Create a clone of the entire image block
ref<ImageBlock> clone() const {
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);
return clone;
}

View File

@ -196,8 +196,15 @@ public:
/* Potentially create a MIP map cache file */
uint8_t *mmapData = NULL, *mmapPtr = NULL;
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());
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();
}
@ -313,7 +320,7 @@ public:
: m_weightLut(NULL), m_maxAnisotropy(maxAnisotropy) {
m_mmap = new MemoryMappedFile(cacheFilename);
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());
stats::mipStorage += m_mmap->getSize();

View File

@ -85,8 +85,7 @@ public:
typedef std::map<std::string, ConfigurableObject *> NamedObjectMap;
typedef std::map<std::string, std::string, SimpleStringOrdering> ParameterMap;
SceneHandler(const xercesc::SAXParser *parser,
const ParameterMap &params, NamedObjectMap *objects = NULL,
SceneHandler(const ParameterMap &params, NamedObjectMap *objects = NULL,
bool isIncludedFile = false);
virtual ~SceneHandler();
@ -115,6 +114,7 @@ public:
);
virtual void endElement(const XMLCh* const name);
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 Scene *getScene() { return m_scene; }
@ -166,12 +166,7 @@ private:
typedef std::pair<ETag, const Class *> TagEntry;
typedef boost::unordered_map<std::string, TagEntry> TagMap;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif
const xercesc::SAXParser *m_parser;
const xercesc::Locator *m_locator;
xercesc::XMLTranscoder* m_transcoder;
ref<Scene> m_scene;
ParameterMap m_params;
@ -182,10 +177,6 @@ private:
Transform m_transform;
ref<AnimatedTransform> m_animatedTransform;
bool m_isIncludedFile;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
};
MTS_NAMESPACE_END

View File

@ -7,9 +7,6 @@ if hasCollada:
import platform
colladaEnv = mainEnv.Clone()
if platform.linux_distribution()[0] == 'Fedora':
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

View File

@ -215,7 +215,7 @@ public:
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
props.getString("pixelFormat", "rgb")), " ,");
std::vector<std::string> channelNames = tokenize(
props.getString("channelNames", "rgb"), ", ");
props.getString("channelNames", ""), ", ");
std::string componentFormat = boost::to_lower_copy(
props.getString("componentFormat", "float16"));
@ -227,58 +227,64 @@ public:
m_fileFormat = Bitmap::EPFM;
} else {
Log(EError, "The \"fileFormat\" parameter must either be "
"equal to \"openexr\" or \"rgbe\"!");
"equal to \"openexr\", \"pfm\", or \"rgbe\"!");
}
if (pixelFormats.empty())
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!");
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) {
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") {
m_pixelFormats.push_back(Bitmap::ELuminance);
m_channelNames.push_back(name + ".Y");
m_channelNames.push_back(name + "Y");
} else if (pixelFormat == "luminancealpha") {
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
m_channelNames.push_back(name + ".Y");
m_channelNames.push_back(name + ".A");
m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "A");
} else if (pixelFormat == "rgb") {
m_pixelFormats.push_back(Bitmap::ERGB);
m_channelNames.push_back(name + ".R");
m_channelNames.push_back(name + ".G");
m_channelNames.push_back(name + ".B");
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");
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);
if (m_pixelFormats.size() > 1)
Log(EError, "The XYZ pixel format is not supported for general multi-channel images!");
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);
if (m_pixelFormats.size() > 1)
Log(EError, "The XYZA pixel format is not supported for general multi-channel images!");
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));
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 + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
}
m_channelNames.push_back(name + ".A");
m_channelNames.push_back(name + "A");
} else {
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
@ -529,13 +535,14 @@ public:
}
bool hasAlpha() const {
Assert(m_pixelFormats.size() > 0);
return
m_pixelFormats[0] == Bitmap::ELuminanceAlpha ||
m_pixelFormats[0] == Bitmap::ERGBA ||
m_pixelFormats[0] == Bitmap::EXYZA ||
m_pixelFormats[0] == Bitmap::ESpectrumAlpha ||
m_pixelFormats.size() > 1;
for (size_t i=0; i<m_pixelFormats.size(); ++i) {
if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
m_pixelFormats[i] == Bitmap::ERGBA ||
m_pixelFormats[i] == Bitmap::EXYZA ||
m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
return true;
}
return false;
}
bool destinationExists(const fs::path &baseName) const {

View File

@ -101,37 +101,78 @@ MTS_NAMESPACE_BEGIN
class TiledHDRFilm : public Film {
public:
TiledHDRFilm(const Properties &props) : Film(props), m_output(NULL), m_frameBuffer(NULL) {
std::string pixelFormat = boost::to_lower_copy(
props.getString("pixelFormat", "rgb"));
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
props.getString("pixelFormat", "rgb")), " ,");
std::vector<std::string> channelNames = tokenize(
props.getString("channelNames", ""), ", ");
std::string componentFormat = boost::to_lower_copy(
props.getString("componentFormat", "float16"));
if (pixelFormats.empty())
Log(EError, "At least one pixel format must be specified!");
if (pixelFormats.size() != 1 && channelNames.size() != pixelFormats.size())
Log(EError, "Number of channel names must match the number of specified pixel formats!");
for (size_t i=0; i<pixelFormats.size(); ++i) {
std::string pixelFormat = pixelFormats[i];
std::string name = i < channelNames.size() ? (channelNames[i] + std::string(".")) : "";
if (pixelFormat == "luminance") {
m_pixelFormat = Bitmap::ELuminance;
m_pixelFormats.push_back(Bitmap::ELuminance);
m_channelNames.push_back(name + "Y");
} else if (pixelFormat == "luminancealpha") {
m_pixelFormat = Bitmap::ELuminanceAlpha;
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "A");
} else if (pixelFormat == "rgb") {
m_pixelFormat = Bitmap::ERGB;
m_pixelFormats.push_back(Bitmap::ERGB);
m_channelNames.push_back(name + "R");
m_channelNames.push_back(name + "G");
m_channelNames.push_back(name + "B");
} else if (pixelFormat == "rgba") {
m_pixelFormat = Bitmap::ERGBA;
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_pixelFormat = Bitmap::EXYZ;
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_pixelFormat = Bitmap::EXYZA;
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_pixelFormat = Bitmap::ESpectrum;
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_pixelFormat = Bitmap::ESpectrumAlpha;
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) {
if (SPECTRUM_SAMPLES == 3 && (m_pixelFormats[i] == Bitmap::ESpectrum || m_pixelFormats[i] == Bitmap::ESpectrumAlpha))
Log(EError, "You requested to render a spectral image, but Mitsuba is currently "
"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") {
m_componentFormat = Bitmap::EFloat16;
@ -151,7 +192,12 @@ public:
TiledHDRFilm(Stream *stream, InstanceManager *manager)
: 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();
}
@ -161,7 +207,11 @@ public:
void serialize(Stream *stream, InstanceManager *manager) const {
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);
}
@ -169,15 +219,6 @@ public:
if (m_output)
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;
std::string extension = boost::to_lower_copy(filename.extension().string());
if (extension != ".exr")
@ -189,6 +230,9 @@ public:
header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL));
header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION));
if (m_pixelFormats.size() == 1) {
/* Write a chromaticity tag when this is possible */
Bitmap::EPixelFormat pixelFormat = m_pixelFormats[0];
if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
Imf::addChromaticities(header, Imf::Chromaticities(
Imath::V2f(1.0f, 0.0f),
@ -198,10 +242,10 @@ public:
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA) {
Imf::addChromaticities(header, Imf::Chromaticities());
}
}
Imf::PixelType compType;
size_t compStride;
int channelCount;
if (m_componentFormat == Bitmap::EFloat16) {
compType = Imf::HALF;
@ -219,62 +263,34 @@ public:
}
Imf::ChannelList &channels = header.channels();
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) {
channels.insert("Y", 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++;
}
for (size_t i=0; i<m_channelNames.size(); ++i)
channels.insert(m_channelNames[i].c_str(), Imf::Channel(compType));
m_output = new Imf::TiledOutputFile(filename.string().c_str(), header);
m_frameBuffer = new Imf::FrameBuffer();
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_blocksV = (m_size.y + blockSize - 1) / blockSize;
m_pixelStride = channelCount * compStride;
m_pixelStride = m_channelNames.size() * compStride;
m_rowStride = m_pixelStride * m_blockSize;
if (m_pixelFormats.size() == 1) {
m_tile = new Bitmap(m_pixelFormats[0], m_componentFormat,
Vector2i(m_blockSize, m_blockSize));
} else {
m_tile = new Bitmap(Bitmap::EMultiChannel, m_componentFormat,
Vector2i(m_blockSize, m_blockSize), m_channelNames.size());
m_tile->setChannelNames(m_channelNames);
}
char *ptr = (char *) m_tile->getUInt8Data();
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) {
m_frameBuffer->insert("Y", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA ||
pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
m_frameBuffer->insert("R", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
m_frameBuffer->insert("G", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
m_frameBuffer->insert("B", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
} 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;
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;
}
}
if (m_pixelFormat == Bitmap::ERGBA || m_pixelFormat == Bitmap::EXYZA ||
m_pixelFormat == Bitmap::ELuminanceAlpha)
m_frameBuffer->insert("A", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride));
m_output->setFrameBuffer(*m_frameBuffer);
m_peakUsage = 0;
@ -316,7 +332,6 @@ public:
++m_peakUsage;
}
uint32_t idx = (uint32_t) x + (uint32_t) y * m_blocksH;
m_origBlocks[idx] = copy1;
m_mergedBlocks[idx] = copy2;
@ -388,6 +403,7 @@ public:
}
const Bitmap *source = mergedBlock->getBitmap();
size_t sourceBpp = source->getBytesPerPixel();
size_t targetBpp = m_tile->getBytesPerPixel();
@ -400,9 +416,13 @@ public:
);
for (int i=0; i<m_blockSize; ++i) {
if (m_pixelFormats.size() == 1)
cvt->convert(source->getPixelFormat(), 1.0f, sourceData,
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;
targetData += m_tile->getWidth() * targetBpp;
@ -470,11 +490,14 @@ public:
void clear() { /* Do nothing */ }
bool hasAlpha() const {
return
m_pixelFormat == Bitmap::ELuminanceAlpha ||
m_pixelFormat == Bitmap::ERGBA ||
m_pixelFormat == Bitmap::EXYZA ||
m_pixelFormat == Bitmap::ESpectrumAlpha;
for (size_t i=0; i<m_pixelFormats.size(); ++i) {
if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
m_pixelFormats[i] == Bitmap::ERGBA ||
m_pixelFormats[i] == Bitmap::EXYZA ||
m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
return true;
}
return false;
}
bool destinationExists(const fs::path &baseName) const {
@ -488,7 +511,14 @@ public:
std::ostringstream oss;
oss << "TiledHDRFilm[" << 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
<< " cropOffset = " << m_cropOffset.toString() << "," << endl
<< " cropSize = " << m_cropSize.toString() << "," << endl
@ -499,7 +529,8 @@ public:
MTS_DECLARE_CLASS()
protected:
Bitmap::EPixelFormat m_pixelFormat;
std::vector<Bitmap::EPixelFormat> m_pixelFormats;
std::vector<std::string> m_channelNames;
Bitmap::EComponentFormat m_componentFormat;
std::vector<ImageBlock *> m_freeBlocks;
std::map<uint32_t, ImageBlock *> m_origBlocks, m_mergedBlocks;

View File

@ -30,6 +30,7 @@ add_integrator(adaptive misc/adaptive.cpp)
add_integrator(irrcache misc/irrcache.cpp
misc/irrcache_proc.h misc/irrcache_proc.cpp)
add_integrator(multichannel misc/multichannel.cpp)
add_integrator(field misc/field.cpp)
# Bidirectional techniques
add_bidir(bdpt bdpt/bdpt.h bdpt/bdpt.cpp

View File

@ -17,6 +17,7 @@ plugins += env.SharedLibrary('vpl', ['vpl/vpl.cpp'])
plugins += env.SharedLibrary('adaptive', ['misc/adaptive.cpp'])
plugins += env.SharedLibrary('irrcache', ['misc/irrcache.cpp', 'misc/irrcache_proc.cpp'])
plugins += env.SharedLibrary('multichannel', ['misc/multichannel.cpp'])
plugins += env.SharedLibrary('field', ['misc/field.cpp'])
# Bidirectional techniques
bidirEnv = env.Clone()

View File

@ -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

View File

@ -21,9 +21,67 @@
MTS_NAMESPACE_BEGIN
/*! \plugin{direct}{Multi-channel integrator}
/*!\plugin{multichannel}{Multi-channel integrator}
* \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 {
@ -82,7 +140,9 @@ public:
ref<BlockedRenderProcess> proc = new BlockedRenderProcess(job,
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);
proc->bindResource("integrator", integratorResID);

View File

@ -275,6 +275,13 @@ public:
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 *
sampleCount) / m_config.workUnits;
@ -295,7 +302,7 @@ public:
ref<MLTProcess> process = new MLTProcess(job, queue,
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);
if (!nested)

View File

@ -328,6 +328,13 @@ public:
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 *
sampleCount) / m_config.workUnits;
@ -348,7 +355,7 @@ public:
ref<PSSMLTProcess> process = new PSSMLTProcess(job, queue,
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);
if (!nested)

View File

@ -36,15 +36,15 @@ ref<Bitmap> BidirectionalUtils::renderDirectComponent(Scene *scene, int sceneRes
/* Render the direct illumination component separately */
ref<Bitmap> directImage = new Bitmap(Bitmap::ERGBA, Bitmap::EFloat32, film->getCropSize());
bool hasMedia = scene->getMedia().size() > 0;
bool hasDOF = scene->getSensor()->needsApertureSample();
size_t pixelSamples = directSamples;
Properties integratorProps(hasMedia ? "volpath" : "direct");
if (hasMedia) {
/* Render with a volumetric path tracer */
if (hasMedia || hasDOF) {
integratorProps.setInteger("maxDepth", 2);
} else {
/* No participating media-> we can use the 'direct' plugin, which has
somewhat better control over where to place shading/pixel samples */
/* No participating media / DoF -> we can more carefully
distribute samples between shading and visibility */
int shadingSamples = 1;
while (pixelSamples > 8) {
pixelSamples /= 2;

View File

@ -88,11 +88,12 @@ public:
EXRIStream(Stream *stream) : IStream(stream->toString().c_str()),
m_stream(stream) {
m_offset = stream->getPos();
m_size = stream->getSize();
}
bool read(char *c, int n) {
m_stream->read(c, n);
return m_stream->isEOF();
return m_stream->getPos() == m_size;
}
Imf::Int64 tellg() {
@ -106,7 +107,7 @@ public:
void clear() { }
private:
ref<Stream> m_stream;
size_t m_offset;
size_t m_offset, m_size;
};
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);
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
#if defined(MTS_HAS_LIBJPEG)
@ -298,6 +305,8 @@ Bitmap::Bitmap(EFileFormat format, Stream *stream, const std::string &prefix) :
format = ERGBE;
} else if (start[0] == 'P' && (start[1] == 'F' || start[1] == 'f')) {
format = EPFM;
} else if (start[0] == 'P' && start[1] == '6') {
format = EPPM;
#if defined(MTS_HAS_LIBJPEG)
} else if (start[0] == 0xFF && start[1] == 0xD8) {
format = EJPEG;
@ -327,6 +336,7 @@ Bitmap::Bitmap(EFileFormat format, Stream *stream, const std::string &prefix) :
case EOpenEXR: readOpenEXR(stream, prefix); break;
case ERGBE: readRGBE(stream); break;
case EPFM: readPFM(stream); break;
case EPPM: readPPM(stream); break;
case ETGA: readTGA(stream); break;
case EPNG: readPNG(stream); break;
default:
@ -349,6 +359,7 @@ void Bitmap::write(EFileFormat format, Stream *stream, int compression) const {
case EOpenEXR: writeOpenEXR(stream); break;
case ERGBE: writeRGBE(stream); break;
case EPFM: writePFM(stream); break;
case EPPM: writePPM(stream); break;
default:
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,
target->getPixelFormat(), target->getGamma(), target->getData(),
(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,
@ -1392,72 +1403,99 @@ ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
cvt->convert(m_pixelFormat, m_gamma, m_data,
pixelFormat, gamma, target->getData(),
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
m_channelCount - (hasWeight() ? 1 : 0));
m_channelCount);
return target;
}
ref<Bitmap> Bitmap::convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
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())
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);
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) {
for (int x = 0; x<m_size.x; ++x) {
const Float *srcData = getFloatData() + getChannelCount() * (x+y*m_size.x);
Float *dstData = bitmap->getFloatData() + bitmap->getChannelCount() * (x+y*m_size.x);
Float weight = srcData[getChannelCount()-1],
void Bitmap::convertMultiSpectrumAlphaWeight(const Bitmap *source,
const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr,
const std::vector<EPixelFormat> &pixelFormats,
EComponentFormat componentFormat, size_t count) {
if (source->getComponentFormat() != EFloat && source->getPixelFormat() != EMultiSpectrumAlphaWeight)
Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!");
Float *temp = new Float[count * target->getChannelCount()], *dst = temp;
for (size_t k = 0; k<count; ++k) {
const Float *srcData = (const Float *) sourcePtr + k * source->getChannelCount();
Float weight = srcData[source->getChannelCount()-1],
invWeight = weight == 0 ? 0 : (Float) 1 / weight;
Float alpha = srcData[getChannelCount()-2] * invWeight;
Float alpha = srcData[source->getChannelCount()-2] * invWeight;
for (size_t i=0; i<pixelFormats.size(); ++i) {
Spectrum value = ((Spectrum *) srcData)[i] * invWeight;
Float r, g, b;
Float tmp0, tmp1, tmp2;
switch (pixelFormats[i]) {
case Bitmap::ELuminance:
*dstData++ = value.getLuminance();
*dst++ = value.getLuminance();
break;
case Bitmap::ELuminanceAlpha:
*dstData++ = value.getLuminance();
*dstData++ = alpha;
*dst++ = value.getLuminance();
*dst++ = alpha;
break;
case Bitmap::EXYZ:
value.toXYZ(tmp0, tmp1, tmp2);
*dst++ = tmp0;
*dst++ = tmp1;
*dst++ = tmp2;
break;
case Bitmap::EXYZA:
value.toXYZ(tmp0, tmp1, tmp2);
*dst++ = tmp0;
*dst++ = tmp1;
*dst++ = tmp2;
*dst++ = alpha;
break;
case Bitmap::ERGB:
value.toLinearRGB(r, g, b);
*dstData++ = r;
*dstData++ = g;
*dstData++ = b;
value.toLinearRGB(tmp0, tmp1, tmp2);
*dst++ = tmp0;
*dst++ = tmp1;
*dst++ = tmp2;
break;
case Bitmap::ERGBA:
value.toLinearRGB(r, g, b);
*dstData++ = r;
*dstData++ = g;
*dstData++ = b;
*dstData++ = alpha;
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)
*dstData++ = value[j];
*dst++ = value[j];
break;
case Bitmap::ESpectrumAlpha:
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
*dstData++ = value[j];
*dstData++ = alpha;
*dst++ = value[j];
*dst++ = alpha;
break;
default:
Log(EError, "Unknown pixel format!");
}
}
}
}
if (componentFormat != Bitmap::EFloat)
bitmap = bitmap->convert(Bitmap::EMultiChannel, componentFormat);
const FormatConverter *cvt = FormatConverter::getInstance(
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,
@ -1483,7 +1521,7 @@ void Bitmap::convert(void *target, EPixelFormat pixelFormat,
cvt->convert(m_pixelFormat, m_gamma, m_data,
pixelFormat, gamma, target,
(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,
@ -1990,7 +2028,7 @@ void Bitmap::readPNG(Stream *stream) {
volatile png_bytepp rows = NULL;
/* 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) {
Log(EError, "readPNG(): Unable to create PNG data structure");
}
@ -2114,7 +2152,7 @@ void Bitmap::writePNG(Stream *stream, int compression) const {
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)
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() {
#if defined(MTS_HAS_OPENEXR)
/* Prevent races during the OpenEXR initialization */

View File

@ -206,7 +206,7 @@ void FileStream::seek(size_t pos) {
pos, d->path.string().c_str(), lastErrorText().c_str());
}
#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",
pos, d->path.string().c_str(), strerror(errno));
}
@ -223,8 +223,7 @@ size_t FileStream::getPos() const {
}
return (size_t) pos;
#else
long pos;
pos = ftell(d->file);
off_t pos = ftello(d->file);
if (pos == -1) {
Log(EError, "Error while looking up the position in file \"%s\": %s",
d->path.string().c_str(), strerror(errno));

View File

@ -139,6 +139,11 @@ void Logger::log(ELogLevel level, const Class *theClass,
__debugbreak();
#endif
DefaultFormatter fmt;
fmt.setHaveDate(false);
fmt.setHaveLogLevel(false);
text = fmt.format(level, theClass,
Thread::getThread(), msg, file, line);
throw std::runtime_error(text);
}
}

View File

@ -18,11 +18,11 @@
#include <mitsuba/core/vmf.h>
#include <mitsuba/core/warp.h>
#include <mitsuba/core/brent.h>
#include <boost/bind.hpp>
MTS_NAMESPACE_BEGIN
VonMisesFisherDistr::VonMisesFisherDistr(Float kappa): m_kappa(kappa) { }
Float VonMisesFisherDistr::eval(Float cosTheta) const {
if (m_kappa == 0.0f)
return INV_FOURPI;
@ -63,22 +63,23 @@ Vector VonMisesFisherDistr::sample(const Point2 &sample) const {
sinPhi * sinTheta, cosTheta);
}
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));
}
Float VonMisesFisherDistr::getMeanCosine() const {
if (m_kappa == 0)
return 0;
Float coth = m_kappa > 6 ? 1 : ((std::exp(2*m_kappa)+1)/(std::exp(2*m_kappa)-1));
return coth-1/m_kappa;
}
static Float A3(Float 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) {
Float csch = 2.0f /
(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));
}
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

View File

@ -14,6 +14,8 @@ for ver in hasPython:
pythonEnv.Append(CPPDEFINES = [['MTS_BUILD_MODULE', 'MTS_MODULE_PYTHON']])
pythonEnv['SHLIBPREFIX']=''
pythonEnv.RelaxCompilerSettings()
pythonEnv.Append(LIBS=['mitsuba-bidir'])
pythonEnv.Append(LIBPATH=['#src/libbidir'])
if pythonEnv.has_key('XERCESINCLUDE'):
pythonEnv.Prepend(CPPPATH=pythonEnv['XERCESINCLUDE'])

View File

@ -18,6 +18,7 @@
#include <mitsuba/core/mstream.h>
#include <mitsuba/core/cstream.h>
#include <mitsuba/core/qmc.h>
#include <mitsuba/core/vmf.h>
#include <mitsuba/core/shvector.h>
#include <mitsuba/core/sshstream.h>
#include <mitsuba/render/scenehandler.h>
@ -506,6 +507,7 @@ bp::object cast(ConfigurableObject *obj) {
TryCast(Medium);
TryCast(VolumeDataSource);
TryCast(Film);
TryCast(PerspectiveCamera);
TryCast(ProjectiveCamera);
TryCast(Sensor);
TryCast(Emitter);
@ -525,13 +527,13 @@ static bp::object pluginmgr_createobject_2(PluginManager *mgr, const Class *cls,
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;
bp::list list = dict.items();
bp::list items = dict.items();
std::map<std::string, ConfigurableObject *> children;
for (int i=0; i<bp::len(list); ++i) {
bp::tuple tuple = bp::extract<bp::tuple>(list[i]);
for (bp::stl_input_iterator<bp::tuple> it(items), end; it!=end; ++it) {
bp::tuple tuple = *it;
std::string name = bp::extract<std::string>(tuple[0]);
bp::extract<bp::dict> extractDict(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!");
else
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()) {
children[name] = pluginmgr_create(manager, extractDict());
children[name] = pluginmgr_create_helper(manager, extractDict(), objs);
} else if (extractConfigurableObject.check()) {
children[name] = extractConfigurableObject();
} else {
@ -552,10 +559,23 @@ static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dic
}
ConfigurableObject *object;
if (properties.getPluginName() == "scene")
if (properties.getPluginName() == "scene") {
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);
}
if (properties.getID() != "unnamed") {
objs[properties.getID()] = object;
object->incRef();
}
for (std::map<std::string, ConfigurableObject *>::iterator it = children.begin();
it != children.end(); ++it) {
@ -567,6 +587,15 @@ static ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dic
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) {
Vector s, t;
coordinateSystem(n, s, t);
@ -1030,6 +1059,9 @@ void export_core() {
coreModule.attr("Epsilon") = Epsilon;
coreModule.attr("ShadowEpsilon") = ShadowEpsilon;
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)
.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 &>()))
.def(bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &, int>())
.def(bp::init<Bitmap::EFileFormat, Stream *>())
.def(bp::init<Bitmap::EFileFormat, Stream *, std::string>())
.def("getPixelFormat", &Bitmap::getPixelFormat)
.def("getComponentFormat", &Bitmap::getComponentFormat)
.def("getSize", &Bitmap::getSize, BP_RETURN_VALUE)
@ -1361,6 +1394,7 @@ void export_core() {
.value("EOpenEXR", Bitmap::EOpenEXR)
.value("ETGA", Bitmap::ETGA)
.value("EPFM", Bitmap::EPFM)
.value("EPPM", Bitmap::EPPM)
.value("ERGBE", Bitmap::ERGBE)
.value("EBMP", Bitmap::EBMP)
.value("EJPEG", Bitmap::EJPEG)
@ -2263,6 +2297,20 @@ void export_core() {
.def("getMillisecondsSinceStart", &Timer::getMillisecondsSinceStart)
.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;
}

View File

@ -626,6 +626,14 @@ void export_render() {
.def("setFarClip", &ProjectiveCamera::setFarClip)
.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)
.def("preprocess", &Integrator::preprocess)
.def("render", &Integrator::render)

View File

@ -27,6 +27,7 @@
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/sax/Locator.hpp>
#include <mitsuba/render/scenehandler.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/render/scene.h>
@ -38,24 +39,21 @@ XERCES_CPP_NAMESPACE_USE
#define TRANSCODE_BLOCKSIZE 2048
#if !defined(__OSX__)
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
level, NULL, __FILE__, __LINE__, "Near file offset %i: " fmt, \
(int) m_parser->getSrcOffset(), ## __VA_ARGS__)
#else
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
level, NULL, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
#endif
level, NULL, __FILE__, __LINE__, "In file \"%s\" (near line %i): " fmt, \
m_locator ? transcode(m_locator->getSystemId()).c_str() : "<unknown>", \
m_locator ? m_locator->getLineNumber() : -1, \
## __VA_ARGS__)
typedef void (*CleanupFun) ();
typedef boost::unordered_set<CleanupFun> CleanupSet;
static PrimitiveThreadLocal<CleanupSet> __cleanup_tls;
SceneHandler::SceneHandler(const SAXParser *parser,
const ParameterMap &params, NamedObjectMap *namedObjects,
bool isIncludedFile) : m_parser(parser), m_params(params),
SceneHandler::SceneHandler(const ParameterMap &params,
NamedObjectMap *namedObjects, bool isIncludedFile) : m_params(params),
m_namedObjects(namedObjects), m_isIncludedFile(isIncludedFile) {
m_pluginManager = PluginManager::getInstance();
m_locator = NULL;
if (m_isIncludedFile) {
SAssert(namedObjects != NULL);
@ -119,6 +117,10 @@ SceneHandler::~SceneHandler() {
delete m_namedObjects;
}
void SceneHandler::setDocumentLocator(const xercesc::Locator* const locator) {
m_locator = locator;
}
void SceneHandler::clear() {
if (!m_isIncludedFile) {
for (NamedObjectMap::iterator it = m_namedObjects->begin();
@ -665,14 +667,10 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
/* 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->setDocumentHandler(handler);
parser->setErrorHandler(handler);
#if !defined(__OSX__)
/// Not supported on OSX
parser->setCalculateSrcOfs(true);
#endif
fs::path path = resolver->resolve(context.attributes["filename"]);
XMLLog(EInfo, "Parsing included file \"%s\" ..", path.filename().string().c_str());
parser->parse(path.c_str());
@ -741,7 +739,11 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
}
} else {
try {
object = m_pluginManager->createObject(tag.second, props);
} catch (const std::exception &ex) {
XMLLog(EError, "Error while creating object: %s", ex.what());
}
}
}
break;
@ -831,9 +833,8 @@ ref<Scene> SceneHandler::loadScene(const fs::path &filename, const ParameterMap
parser->setValidationSchemaFullChecking(true);
parser->setValidationScheme(SAXParser::Val_Always);
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
parser->setCalculateSrcOfs(true);
SceneHandler *handler = new SceneHandler(parser, params);
SceneHandler *handler = new SceneHandler(params);
parser->setDoNamespaces(true);
parser->setDocumentHandler(handler);
parser->setErrorHandler(handler);
@ -858,9 +859,8 @@ ref<Scene> SceneHandler::loadSceneFromString(const std::string &content, const P
parser->setValidationSchemaFullChecking(true);
parser->setValidationScheme(SAXParser::Val_Always);
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
parser->setCalculateSrcOfs(true);
SceneHandler *handler = new SceneHandler(parser, params);
SceneHandler *handler = new SceneHandler(params);
parser->setDoNamespaces(true);
parser->setDocumentHandler(handler);
parser->setErrorHandler(handler);

View File

@ -48,40 +48,41 @@ static MaterialEntry materialData[] = {
/* From "Acquiring Scattering Properties of Participating Media by Dilution"
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 },
{ "Reduced Milk", { 1.0748f, 1.2209f, 1.3931f }, { 0.0002f, 0.0004f, 0.0010f }, { 0.8190f, 0.7970f, 0.7460f }, 1.33f },
{ "Regular Milk", { 1.1873f, 1.3293f, 1.4589f }, { 0.0001f, 0.0003f, 0.0013f }, { 0.7500f, 0.7140f, 0.6810f }, 1.33f },
{ "Espresso", { 0.2707f, 0.2828f, 0.2970f }, { 0.1669f, 0.2287f, 0.3078f }, { 0.9070f, 0.8960f, 0.8800f }, 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 },
{ "Lowfat Soy Milk", { 0.1418f, 0.1620f, 0.2715f }, { 0.0001f, 0.0005f, 0.0025f }, { 0.8500f, 0.8530f, 0.8420f }, 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 },
{ "Lowfat Chocolate Milk", { 0.4277f, 0.4998f, 0.5723f }, { 0.0005f, 0.0016f, 0.0068f }, { 0.9340f, 0.9270f, 0.9160f }, 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 },
{ "Coke", { 0.0177f, 0.0208f, 0.0000f }, { 0.6966f, 1.1480f, 1.7169f }, { 0.9650f, 0.9720f, 0.9685f }, 1.33f },
{ "Pepsi", { 0.0058f, 0.0141f, 0.0000f }, { 0.6375f, 0.9849f, 1.4420f }, { 0.9260f, 0.9790f, 0.9525f }, 1.33f },
{ "Sprite", { 0.0069f, 0.0089f, 0.0089f }, { 0.1230f, 0.1194f, 0.1306f }, { 0.9430f, 0.9530f, 0.9520f }, 1.33f },
{ "Gatorade", { 0.2392f, 0.2927f, 0.3745f }, { 0.1617f, 0.1258f, 0.0579f }, { 0.9330f, 0.9330f, 0.9350f }, 1.33f },
{ "Chardonnay", { 0.0030f, 0.0047f, 0.0069f }, { 0.1547f, 0.1701f, 0.3443f }, { 0.9140f, 0.9580f, 0.9750f }, 1.33f },
{ "White Zinfandel", { 0.0031f, 0.0048f, 0.0066f }, { 0.1732f, 0.2322f, 0.2847f }, { 0.9190f, 0.9430f, 0.9720f }, 1.33f },
{ "Merlot", { 0.0053f, 0.0000f, 0.0000f }, { 0.7586f, 1.6429f, 1.9196f }, { 0.9740f, 0.9740f, 0.9740f }, 1.33f },
{ "Budweiser Beer", { 0.0037f, 0.0069f, 0.0074f }, { 0.1449f, 0.3141f, 0.7286f }, { 0.9170f, 0.9560f, 0.9820f }, 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 },
{ "Clorox", { 0.1425f, 0.1723f, 0.1928f }, { 0.0175f, 0.0777f, 0.1372f }, { 0.9120f, 0.9050f, 0.8920f }, 1.33f },
{ "Apple Juice", { 0.0201f, 0.0243f, 0.0323f }, { 0.1014f, 0.1858f, 0.4084f }, { 0.9470f, 0.9490f, 0.9450f }, 1.33f },
{ "Cranberry Juice", { 0.0128f, 0.0155f, 0.0196f }, { 0.2572f, 0.6145f, 0.8104f }, { 0.9470f, 0.9510f, 0.9740f }, 1.33f },
{ "Grape Juice", { 0.0072f, 0.0000f, 0.0000f }, { 0.5428f, 1.2500f, 1.5300f }, { 0.9610f, 0.9610f, 0.9610f }, 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 },
{ "White Grapefruit Juice", { 0.3513f, 0.3669f, 0.5237f }, { 0.0096f, 0.0131f, 0.0395f }, { 0.5480f, 0.5450f, 0.5650f }, 1.33f },
{ "Shampoo", { 0.0104f, 0.0114f, 0.0147f }, { 0.0184f, 0.0596f, 0.0805f }, { 0.9100f, 0.9050f, 0.9200f }, 1.33f },
{ "Strawberry Shampoo", { 0.0028f, 0.0032f, 0.0033f }, { 0.0189f, 0.0756f, 0.0989f }, { 0.9270f, 0.9350f, 0.9940f }, 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 },
{ "Lemon Tea Powder", { 0.0798f, 0.0898f, 0.1073f }, { 0.2602f, 0.4902f, 0.7727f }, { 0.9460f, 0.9460f, 0.9490f }, 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 },
{ "Pink Lemonade Powder", { 0.1235f, 0.1334f, 0.1305f }, { 0.1165f, 0.2366f, 0.3195f }, { 0.9020f, 0.9020f, 0.9040f }, 1.33f },
{ "Cappuccino Powder", { 0.0654f, 0.0882f, 0.1568f }, { 0.1920f, 0.2654f, 0.3272f }, { 0.8490f, 0.8430f, 0.9260f }, 1.33f },
{ "Salt Powder", { 0.2485f, 0.2822f, 0.3216f }, { 0.5115f, 0.5863f, 0.6147f }, { 0.8020f, 0.7930f, 0.8210f }, 1.33f },
{ "Sugar Powder", { 0.0145f, 0.0162f, 0.0202f }, { 0.0650f, 0.1597f, 0.2578f }, { 0.9210f, 0.9190f, 0.9310f }, 1.33f },
{ "Suisse Mocha", { 0.3223f, 0.3583f, 0.4148f }, { 0.1875f, 0.2893f, 0.3796f }, { 0.9070f, 0.8940f, 0.8880f }, 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", { 13.7335f, 15.6003f, 17.8007f }, { 0.00256f, 0.00511f, 0.01278f }, { 0.81900f, 0.79700f, 0.74600f }, 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", { 7.78262f, 8.13050f, 8.53875f }, { 4.79838f, 6.57512f, 8.84925f }, { 0.90700f, 0.89600f, 0.88000f }, 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", { 2.03838f, 2.32875f, 3.90281f }, { 0.00144f, 0.00719f, 0.03594f }, { 0.85000f, 0.85300f, 0.84200f }, 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", { 9.83710f, 11.4954f, 13.1629f }, { 0.01150f, 0.03680f, 0.15640f }, { 0.93400f, 0.92700f, 0.91600f }, 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.00254f, 0.00299f, 0.00000f }, { 0.10014f, 0.16503f, 0.24680f }, { 0.96500f, 0.97200f, 0.00000f }, 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.00011f, 0.00014f, 0.00014f }, { 0.00189f, 0.00183f, 0.00200f }, { 0.94300f, 0.95300f, 0.95200f }, 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.00021f, 0.00033f, 0.00048f }, { 0.01078f, 0.01186f, 0.02400f }, { 0.91400f, 0.95800f, 0.97500f }, 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.00081f, 0.00000f, 0.00000f }, { 0.11632f, 0.25191f, 0.29434f }, { 0.97400f, 0.00000f, 0.00000f }, 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.00062f, 0.00127f, 0.00000f }, { 0.00616f, 0.01398f, 0.03498f }, { 0.91800f, 0.96600f, 0.00000f }, 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.00257f, 0.00311f, 0.00413f }, { 0.01296f, 0.02374f, 0.05218f }, { 0.94700f, 0.94900f, 0.94500f }, 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.00138f, 0.00000f, 0.00000f }, { 0.10404f, 0.23958f, 0.29325f }, { 0.96100f, 0.00000f, 0.00000f }, 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.50499f, 0.52742f, 0.75282f }, { 0.01380f, 0.01883f, 0.05678f }, { 0.54800f, 0.54500f, 0.56500f }, 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.00215f, 0.00245f, 0.00253f }, { 0.01449f, 0.05796f, 0.07582f }, { 0.92700f, 0.93500f, 0.99400f }, 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.74489f, 0.83823f, 1.00158f }, { 2.42881f, 4.57573f, 7.21270f }, { 0.94600f, 0.94600f, 0.94900f }, 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.00123f, 0.00133f, 0.00131f }, { 0.00116f, 0.00237f, 0.00320f }, { 0.90200f, 0.90200f, 0.90400f }, 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.13805f, 0.15677f, 0.17865f }, { 0.28415f, 0.32570f, 0.34148f }, { 0.80200f, 0.79300f, 0.82100f }, 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 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 }
};
@ -197,3 +198,4 @@ static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &
MTS_NAMESPACE_END
#endif /* __MATERIAL_DATA_H */

View File

@ -328,13 +328,9 @@ int mitsuba_app(int argc, char **argv) {
parser->setValidationSchemaFullChecking(true);
parser->setValidationScheme(SAXParser::Val_Always);
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
#if !defined(__OSX__)
/// Not supported on OSX
parser->setCalculateSrcOfs(true);
#endif
/* Set the handler */
SceneHandler *handler = new SceneHandler(parser, parameters);
SceneHandler *handler = new SceneHandler(parameters);
parser->setDoNamespaces(true);
parser->setDocumentHandler(handler);
parser->setErrorHandler(handler);
@ -375,6 +371,8 @@ int mitsuba_app(int argc, char **argv) {
thr->start();
renderQueue->waitLeft(numParallelScenes-1);
if (i+1 < argc && numParallelScenes == 1)
Statistics::getInstance()->resetAll();
}
/* Wait for all render processes to finish */

View File

@ -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__)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
@ -213,13 +206,8 @@ int main(int argc, char *argv[]) {
#if !defined(__WINDOWS__)
/* Avoid zombies processes when running the server */
struct sigaction sa;
sa.sa_handler = collect_zombies;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
SLog(EWarn, "Error in sigaction(): %s!", strerror(errno));
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
SLog(EWarn, "Error in signal(): %s!", strerror(errno));
#endif
qRegisterMetaType<ELogLevel>("ELogLevel");

View File

@ -585,8 +585,8 @@ void MainWindow::on_actionOpen_triggered() {
QSettings settings;
QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(),
settings.value("fileDir").toString(),
tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.png *.jpg *.jpeg);;"
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm);;"
tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.ppm *.png *.jpg *.jpeg);;"
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm *.ppm);;"
"Low dynamic-range images (*.png *.jpg *.jpeg)"));
QStringList::ConstIterator it = fileNames.constBegin();
@ -605,8 +605,8 @@ void MainWindow::onOpenDialogClose(int reason) { /* unused */ }
void MainWindow::on_actionOpen_triggered() {
QFileDialog *dialog = new QFileDialog(this, Qt::Sheet);
dialog->setNameFilter(tr("All supported formats (*.xml *.exr *.rgbe *.hdr *.pfm *.png *.jpg *.jpeg);;"
"Mitsuba scenes (*.xml);;High dynamic-range images (*.exr *.rgbe *.hdr *.pfm);;Low "
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 *.ppm);;Low "
"dynamic-range images (*.png *.jpg *.jpeg)"));
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setAcceptMode(QFileDialog::AcceptOpen);
@ -690,7 +690,7 @@ retry:
ret = QMessageBox::question(this, tr("Version mismatch -- update scene file?"),
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 "
"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?")
.arg(version.toString().c_str())
.arg(MTS_VERSION), QMessageBox::Yes | QMessageBox::Cancel);
@ -825,6 +825,7 @@ void MainWindow::updateUI() {
ui->actionClose->setEnabled(hasTab);
ui->actionDuplicateTab->setEnabled(hasTab);
ui->actionAdjustSize->setEnabled(hasTab);
ui->actionCopyImage->setEnabled(hasTab);
ui->actionShowKDTree->setEnabled(hasScene);
ui->actionShowKDTree->setChecked(hasScene && context->showKDTree);
ui->actionSceneDescription->setEnabled(hasScene);
@ -888,6 +889,7 @@ void MainWindow::on_tabBar_customContextMenuRequested(const QPoint &pt) {
menu.addAction(ui->actionDuplicateTab);
if (tabIndex == ui->tabBar->currentIndex())
menu.addAction(ui->actionAdjustSize);
menu.addAction(ui->actionCopyImage);
menu.addAction(ui->actionClose);
menu.exec(ui->tabBar->mapToGlobal(pt));
m_contextIndex = -1;
@ -1482,6 +1484,10 @@ inline float toSRGB(float value) {
return 1.055f * std::pow(value, 0.41666f) - 0.055f;
}
void MainWindow::on_actionCopyImage_triggered() {
exportImage("__clipboard__");
}
#if MTSGUI_STATIC_QFILEDIALOG
void MainWindow::on_actionExportImage_triggered() {
@ -1492,6 +1498,7 @@ void MainWindow::on_actionExportImage_triggered() {
"High dynamic range OpenEXR image (*.exr);;"
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
"High dynamic range Portable Float Map image (*.pfm);;"
"High dynamic range Portable Pixel Map image (*.ppm);;"
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
if (!fileName.isEmpty()) {
QSettings settings;
@ -1510,6 +1517,7 @@ void MainWindow::on_actionExportImage_triggered() {
"High dynamic range OpenEXR image (*.exr);;"
"High dynamic range Radiance RGBE image (*.rgbe *.hdr);;"
"High dynamic range Portable Float Map image (*.pfm);;"
"High dynamic range Portable Pixel Map image (*.ppm);;"
"Tonemapped low dynamic range image (*.png *.jpg *.jpeg)"));
QSettings settings;
@ -1548,29 +1556,30 @@ void MainWindow::onExportDialogClose(int reason) {
void MainWindow::exportImage(const QString &fileName) {
if (!fileName.isEmpty()) {
Bitmap::EComponentFormat compFormat = Bitmap::EInvalid;
Bitmap::EFileFormat format;
bool isHDR = true;
if (fileName.endsWith(".exr")) {
format = Bitmap::EOpenEXR;
} else if (fileName.endsWith(".png")) {
} else if (fileName.endsWith(".png") || fileName == "__clipboard__") {
format = Bitmap::EPNG;
isHDR = false;
compFormat = Bitmap::EUInt8;
} else if (fileName.endsWith(".hdr") || fileName.endsWith(".rgbe")) {
format = Bitmap::ERGBE;
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
format = Bitmap::EJPEG;
isHDR = false;
compFormat = Bitmap::EUInt8;
} else if (fileName.endsWith(".pfm")) {
format = Bitmap::EPFM;
} else if (fileName.endsWith(".ppm")) {
format = Bitmap::EPPM;
compFormat = Bitmap::EUInt16;
} else {
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;
}
ref<FileStream> fs = new FileStream(toFsPath(fileName),
FileStream::ETruncReadWrite);
const int currentIndex = ui->tabBar->currentIndex();
const SceneContext *ctx = m_context[currentIndex];
@ -1578,7 +1587,7 @@ void MainWindow::exportImage(const QString &fileName) {
ui->glView->downloadFramebuffer();
ref<Bitmap> bitmap = ctx->framebuffer;
if (!isHDR) {
if (compFormat == Bitmap::EUInt8 || compFormat == Bitmap::EUInt16) {
/* Tonemap the image */
if (ctx->toneMappingMethod == EReinhard) {
Float logAvgLuminance = 0, maxLuminance = 0; /* Unused */
@ -1589,15 +1598,26 @@ void MainWindow::exportImage(const QString &fileName) {
ctx->reinhardKey, burn);
}
bitmap = bitmap->convert(Bitmap::ERGB, Bitmap::EUInt8,
bitmap = bitmap->convert(Bitmap::ERGB, compFormat,
ctx->srgb ? (Float) -1 : ctx->gamma,
ctx->toneMappingMethod == EReinhard
? (Float) 1.0f : std::pow((Float) 2, ctx->exposure));
}
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);
}
}
}
void MainWindow::on_actionSave_triggered() {
SceneContext *context = m_context[ui->tabBar->currentIndex()];

View File

@ -172,6 +172,7 @@ private slots:
void on_actionFocusAll_triggered();
void on_actionSceneDescription_triggered();
void on_actionEnableCommandLine_triggered();
void on_actionCopyImage_triggered();
void on_tabBar_currentChanged(int index);
bool on_tabBar_tabCloseRequested(int index);
void on_tabBar_tabMoved(int from, int to);

View File

@ -128,6 +128,7 @@
<addaction name="separator"/>
<addaction name="actionSave"/>
<addaction name="actionSaveAs"/>
<addaction name="actionCopyImage"/>
<addaction name="actionExportImage"/>
<addaction name="separator"/>
<addaction name="actionClose"/>
@ -475,6 +476,14 @@
<string>Ctrl+F</string>
</property>
</action>
<action name="actionCopyImage">
<property name="text">
<string>&amp;Copy image</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="actionFeedback">
<property name="text">
<string>Report &amp;Feedback</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 B

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 911 B

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 B

After

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 964 B

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 1000 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 667 B

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 B

After

Width:  |  Height:  |  Size: 744 B

View File

@ -48,7 +48,7 @@ void SceneLoader::run() {
QFileInfo fileInfo(m_filename);
QString suffix = fileInfo.suffix().toLower();
SceneHandler *handler = new SceneHandler(parser, m_parameters);
SceneHandler *handler = new SceneHandler(m_parameters);
m_result = new SceneContext();
try {
QSettings settings;
@ -67,7 +67,7 @@ void SceneLoader::run() {
m_result->diffuseReceivers = settings.value("preview_diffuseReceivers", false).toBool();
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 */
ref<FileStream> fs = new FileStream(toFsPath(m_filename), FileStream::EReadOnly);
ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, fs);
@ -87,10 +87,6 @@ void SceneLoader::run() {
parser->setValidationSchemaFullChecking(true);
parser->setValidationScheme(SAXParser::Val_Always);
parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
#if !defined(__OSX__)
/// Not supported on OSX
parser->setCalculateSrcOfs(true);
#endif
/* Set the SAX handler */
parser->setDoNamespaces(true);

View File

@ -448,7 +448,7 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "PerspectiveCamera[" << endl
<< " xfov = " << m_xfov << "," << endl
<< " fov = [" << getXFov() << ", " << getYFov() << "]," << endl
<< " nearClip = " << m_nearClip << "," << endl
<< " farClip = " << m_farClip << "," << endl
<< " worldTransform = " << indent(m_worldTransform.toString()) << "," << endl

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