Merge with upstream

metadata
Edgar Velazquez-Armendariz 2013-01-21 17:40:21 -05:00
commit 40cfc60ee7
31 changed files with 742 additions and 216 deletions

View File

@ -20,7 +20,7 @@ if sys.platform == 'win32':
# Set an application icon on Windows
resources += [ env.RES('data/windows/mitsuba_res.rc') ]
# Convert the command line args from UTF-8 to UTF-16
winstubs += [os.path.abspath('data/windows/wmain_stub.cpp')]
winstubs += [ env.SharedObject('#data/windows/wmain_stub.cpp') ]
Export('winstubs')
def build(scriptFile, exports = [], duplicate = 0):

View File

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

View File

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

View File

@ -42,7 +42,7 @@
#include <mitsuba/core/constants.h>
#include <mitsuba/core/fwd.h>
#include <mitsuba/render/fwd.h>
#include <mitsuba/core/stl.h>
#include <mitsuba/core/math.h>
#include <mitsuba/core/object.h>
#include <mitsuba/core/ref.h>
#include <mitsuba/core/tls.h>

View File

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

View File

@ -393,17 +393,8 @@ public:
/// Draw a rectangle with the specified position and size
void drawRect(const Point2i &offset, const Vector2i &size, const Spectrum &value);
/**
* \brief Color balancing: apply the given scale factors to the
* red, green, and blue channels of the image
*
* When the image is not an \c EFloat16, \c EFloat32, or
* \c EFloat64-based RGB/RGBA image, the function throws an exception
*/
void colorBalance(Float r, Float g, Float b);
/// Draw a filled rectangle with the specified position and size
void fill(const Point2i &offset, const Vector2i &size, const Spectrum &value);
void fillRect(Point2i offset, Vector2i size, const Spectrum &value);
/// Bitmap equality operator (useful for unit-tests etc.)
bool operator==(const Bitmap &bitmap) const;
@ -699,7 +690,43 @@ public:
* use different component formats or channels, or when the
* component format is \ref EBitmask.
*/
void accumulate(const Bitmap *bitmap, const Point2i &offset);
void accumulate(const Bitmap *bitmap, Point2i sourceOffset,
Point2i targetOffset, Vector2i size);
/**
* \brief Color balancing: apply the given scale factors to the
* red, green, and blue channels of the image
*
* When the image is not an \c EFloat16, \c EFloat32, or
* \c EFloat64-based RGB/RGBA image, the function throws an exception
*/
void colorBalance(Float r, Float g, Float b);
/**
* Apply a color transformation matrix to the contents of the bitmap
*
* The implementation assumes that the contents have the
* RGB, RGBA, XYZ, or XYZA pixel format and a floating point
* component format.
*/
void applyMatrix(Float matrix[3][3]);
/**
* \brief Accumulate the contents of another bitmap into the
* region of the specified offset
*
* This convenience function calls the main <tt>accumulate()</tt>
* implementation with <tt>size</tt> set to <tt>bitmap->getSize()</tt>
* and <tt>sourceOffset</tt> set to zero. Out-of-bounds regions are
* ignored. It is assumed that <tt>bitmap != this</tt>.
*
* \remark This function throws an exception when the bitmaps
* use different component formats or channels, or when the
* component format is \ref EBitmask.
*/
inline void accumulate(const Bitmap *bitmap, Point2i targetOffset) {
accumulate(bitmap, Point2i(0), targetOffset, bitmap->getSize());
}
/**
* \brief Up- or down-sample this image to a different resolution

View File

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

View File

@ -493,6 +493,14 @@ public:
return value;
}
/// Component-wise square root
inline TSpectrum safe_sqrt() const {
TSpectrum value;
for (int i=0; i<N; i++)
value.s[i] = math::safe_sqrt(s[i]);
return value;
}
/// Component-wise exponentation
inline TSpectrum exp() const {
TSpectrum value;

View File

@ -20,90 +20,6 @@
#if !defined(__MITSUBA_CORE_STL_H_)
#define __MITSUBA_CORE_STL_H_
/* Include some SGI STL extensions, which might be missing */
#ifdef __GNUC__
#include <ext/functional>
using __gnu_cxx::select2nd;
using __gnu_cxx::compose1;
#else
#include <functional>
/// \cond
// (Don't include in the documentation)
namespace std {
template <class _Pair> struct _Select1st : public unary_function<_Pair, typename _Pair::first_type> {
const typename _Pair::first_type& operator()(const _Pair& __x) const {
return __x.first;
}
};
template <class _Pair> struct _Select2nd : public unary_function<_Pair, typename _Pair::second_type> {
const typename _Pair::second_type& operator()(const _Pair& __x) const {
return __x.second;
}
};
template <class _Pair> struct select1st : public _Select1st<_Pair> {};
template <class _Pair> struct select2nd : public _Select2nd<_Pair> {};
template <class _Operation1, class _Operation2> class unary_compose : public unary_function<typename _Operation2::argument_type, typename _Operation1::result_type> {
protected:
_Operation1 _M_fn1;
_Operation2 _M_fn2;
public:
unary_compose(const _Operation1& __x, const _Operation2& __y) : _M_fn1(__x), _M_fn2(__y) {}
typename _Operation1::result_type operator()(const typename _Operation2::argument_type& __x) const {
return _M_fn1(_M_fn2(__x));
}
};
template <class _Operation1, class _Operation2> inline unary_compose<_Operation1,_Operation2> compose1(const _Operation1& __fn1, const _Operation2& __fn2) {
return unary_compose<_Operation1,_Operation2>(__fn1, __fn2);
}
#if defined(_MSC_VER)
#include <float.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
inline char tolower(char c) {
return ::tolower(c);
}
inline char toupper(char c) {
return ::toupper(c);
}
inline bool isnan(float f) {
return _isnan(f);
}
inline bool isnan(double f) {
return _isnan(f);
}
inline bool isfinite(float f) {
return _finite(f);
}
inline bool isfinite(double f) {
return _finite(f);
}
inline bool isinf(float f) {
return !_finite(f);
}
inline bool isinf(double f) {
return !_finite(f);
}
#endif
};
using std::select2nd;
using std::compose1;
#endif
namespace mitsuba {
namespace math {
#if defined(__LINUX__) && defined(__x86_64__)

View File

@ -507,22 +507,99 @@ inline Float fresnelDielectricExt(Float cosThetaI, Float eta) { Float cosThetaT;
return fresnelDielectricExt(cosThetaI, cosThetaT, eta); }
/**
* \brief Calculates the unpolarized fresnel reflection coefficient
* at a planar interface between vacuum and a conductor.
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (approximate scalar version)
*
* The implementation of this function relies on a simplified expression
* that becomes increasingly accurate as k grows.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Real refractive index (wavelength-dependent)
* Relative refractive index (real component)
* \param k
* Imaginary refractive index (wavelength-dependent)
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosThetaI,
extern MTS_EXPORT_CORE Float fresnelConductorApprox(Float cosThetaI,
Float eta, Float k);
/**
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (approximate vectorized version)
*
* The implementation of this function relies on a simplified expression
* that becomes increasingly accurate as k grows.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductorApprox(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/**
* \brief Calculates the diffuse unpolarized fresnel reflectance of
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (accurate scalar version)
*
* The implementation of this function computes the exact unpolarized
* Fresnel reflectance for a complex index of refraction change.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Float fresnelConductorExact(Float cosThetaI,
Float eta, Float k);
/**
* \brief Calculates the unpolarized Fresnel reflection coefficient
* at a planar interface having a complex-valued relative index of
* refraction (accurate vectorized version)
*
* The implementation of this function computes the exact unpolarized
* Fresnel reflectance for a complex index of refraction change.
*
* The name of this function is a slight misnomer, since it supports
* the general case of a complex-valued relative index of refraction
* (rather than being restricted to conductors)
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Relative refractive index (real component)
* \param k
* Relative refractive index (imaginary component)
* \ingroup libpython
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductorExact(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/**
* \brief Calculates the diffuse unpolarized Fresnel reflectance of
* a dielectric material (sometimes referred to as "Fdr").
*
* This value quantifies what fraction of diffuse incident illumination

View File

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

View File

@ -74,6 +74,9 @@ public:
/// Serialize to a binary data stream
virtual void serialize(Stream *stream, InstanceManager *manager) const;
/// Return the underlying bitmap representation (if any)
virtual ref<Bitmap> getBitmap() const;
MTS_DECLARE_CLASS()
protected:
Texture(const Properties &props);

View File

@ -20,6 +20,7 @@
#include <mitsuba/core/fresolver.h>
#include <mitsuba/hw/basicshader.h>
#include <boost/algorithm/string.hpp>
#include "ior.h"
MTS_NAMESPACE_BEGIN
@ -29,11 +30,12 @@ MTS_NAMESPACE_BEGIN
* \parameters{
* \parameter{material}{\String}{Name of a material preset, see
* \tblref{conductor-iors}.\!\default{\texttt{Cu} / copper}}
* \parameter{eta}{\Spectrum}{Real part of the material's index
* of refraction \default{based on the value of \texttt{material}}}
* \parameter{k}{\Spectrum}{Imaginary part of the material's index of
* refraction, also known as absorption coefficient.
* \default{based on the value of \texttt{material}}}
* \parameter{eta, k}{\Spectrum}{Real and imaginary components of the material's index of
* refraction \default{based on the value of \texttt{material}}}
* \parameter{extEta}{\Float\Or\String}{
* Real-valued index of refraction of the surrounding dielectric,
* or a material name of a dielectric \default{\code{air}}
* }
* \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
* factor that can be used to modulate the specular reflection component. Note
* that for physical realism, this parameter should never be touched. \default{1.0}}
@ -154,21 +156,23 @@ public:
m_specularReflectance = new ConstantSpectrumTexture(
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
std::string material = props.getString("material", "Cu");
std::string materialName = props.getString("material", "Cu");
Spectrum materialEta, materialK;
if (boost::to_lower_copy(material) == "none") {
materialEta = Spectrum(0.0f);
materialK = Spectrum(1.0f);
Spectrum intEta, intK;
if (boost::to_lower_copy(materialName) == "none") {
intEta = Spectrum(0.0f);
intK = Spectrum(1.0f);
} else {
materialEta.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + material + ".eta.spd")));
materialK.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + material + ".k.spd")));
intEta.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + materialName + ".eta.spd")));
intK.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + materialName + ".k.spd")));
}
m_eta = props.getSpectrum("eta", materialEta);
m_k = props.getSpectrum("k", materialK);
Float extEta = lookupIOR(props, "extEta", "air");
m_eta = props.getSpectrum("eta", intEta) / extEta;
m_k = props.getSpectrum("k", intK) / extEta;
}
SmoothConductor(Stream *stream, InstanceManager *manager)
@ -229,7 +233,7 @@ public:
return Spectrum(0.0f);
return m_specularReflectance->eval(bRec.its) *
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
fresnelConductorExact(Frame::cosTheta(bRec.wi), m_eta, m_k);
}
Float pdf(const BSDFSamplingRecord &bRec, EMeasure measure) const {
@ -260,7 +264,7 @@ public:
bRec.eta = 1.0f;
return m_specularReflectance->eval(bRec.its) *
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
fresnelConductorExact(Frame::cosTheta(bRec.wi), m_eta, m_k);
}
Spectrum sample(BSDFSamplingRecord &bRec, Float &pdf, const Point2 &sample) const {
@ -277,7 +281,7 @@ public:
pdf = 1;
return m_specularReflectance->eval(bRec.its) *
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
fresnelConductorExact(Frame::cosTheta(bRec.wi), m_eta, m_k);
}
Float getRoughness(const Intersection &its, int component) const {
@ -320,7 +324,7 @@ public:
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
/* Compute the reflectance at perpendicular incidence */
m_R0 = fresnelConductor(1.0f, eta, k);
m_R0 = fresnelConductorExact(1.0f, eta, k);
m_alpha = 0.4f;
}

View File

@ -20,6 +20,7 @@
#include <mitsuba/render/bsdf.h>
#include <mitsuba/hw/basicshader.h>
#include "microfacet.h"
#include "ior.h"
MTS_NAMESPACE_BEGIN
@ -32,15 +33,15 @@ MTS_NAMESPACE_BEGIN
* used to model the surface roughness.
* \begin{enumerate}[(i)]
* \item \code{beckmann}: Physically-based distribution derived from
* Gaussian random surfaces. This is the default.
* Gaussian random surfaces. This is the default.\vspace{-1mm}
* \item \code{ggx}: New distribution proposed by
* Walter et al. \cite{Walter07Microfacet}, which is meant to better handle
* the long tails observed in measurements of ground surfaces.
* Renderings with this distribution may converge slowly.
* Renderings with this distribution may converge slowly.\vspace{-1mm}
* \item \code{phong}: Classical $\cos^p\theta$ distribution.
* Due to the underlying microfacet theory,
* the use of this distribution here leads to more realistic
* behavior than the separately available \pluginref{phong} plugin.
* behavior than the separately available \pluginref{phong} plugin.\vspace{-1mm}
* \item \code{as}: Anisotropic Phong-style microfacet distribution proposed by
* Ashikhmin and Shirley \cite{Ashikhmin2005Anisotropic}.\vspace{-3mm}
* \end{enumerate}
@ -59,11 +60,12 @@ MTS_NAMESPACE_BEGIN
* }
* \parameter{material}{\String}{Name of a material preset, see
* \tblref{conductor-iors}.\!\default{\texttt{Cu} / copper}}
* \parameter{eta}{\Spectrum}{Real part of the material's index
* of refraction \default{based on the value of \texttt{material}}}
* \parameter{k}{\Spectrum}{Imaginary part of the material's index of
* refraction (the absorption coefficient).
* \default{based on \texttt{material}}}
* \parameter{eta, k}{\Spectrum}{Real and imaginary components of the material's index of
* refraction \default{based on the value of \texttt{material}}}
* \parameter{extEta}{\Float\Or\String}{
* Real-valued index of refraction of the surrounding dielectric,
* or a material name of a dielectric \default{\code{air}}
* }
* \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
* factor that can be used to modulate the specular reflection component. Note
* that for physical realism, this parameter should never be touched. \default{1.0}}
@ -158,21 +160,23 @@ public:
m_specularReflectance = new ConstantSpectrumTexture(
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
std::string material = props.getString("material", "Cu");
Spectrum materialEta, materialK;
std::string materialName = props.getString("material", "Cu");
if (boost::to_lower_copy(material) == "none") {
materialEta = Spectrum(0.0f);
materialK = Spectrum(1.0f);
Spectrum intEta, intK;
if (boost::to_lower_copy(materialName) == "none") {
intEta = Spectrum(0.0f);
intK = Spectrum(1.0f);
} else {
materialEta.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + material + ".eta.spd")));
materialK.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + material + ".k.spd")));
intEta.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + materialName + ".eta.spd")));
intK.fromContinuousSpectrum(InterpolatedSpectrum(
fResolver->resolve("data/ior/" + materialName + ".k.spd")));
}
m_eta = props.getSpectrum("eta", materialEta);
m_k = props.getSpectrum("k", materialK);
Float extEta = lookupIOR(props, "extEta", "air");
m_eta = props.getSpectrum("eta", intEta) / extEta;
m_k = props.getSpectrum("k", intK) / extEta;
m_distribution = MicrofacetDistribution(
props.getString("distribution", "beckmann")
@ -262,7 +266,7 @@ public:
return Spectrum(0.0f);
/* Fresnel factor */
const Spectrum F = fresnelConductor(dot(bRec.wi, H), m_eta, m_k);
const Spectrum F = fresnelConductorExact(dot(bRec.wi, H), m_eta, m_k);
/* Smith's shadow-masking function */
const Float G = m_distribution.G(bRec.wi, bRec.wo, H, alphaU, alphaV);
@ -324,7 +328,7 @@ public:
if (Frame::cosTheta(bRec.wo) <= 0)
return Spectrum(0.0f);
const Spectrum F = fresnelConductor(dot(bRec.wi, m),
const Spectrum F = fresnelConductorExact(dot(bRec.wi, m),
m_eta, m_k);
Float numerator = m_distribution.eval(m, alphaU, alphaV)
@ -367,7 +371,7 @@ public:
if (Frame::cosTheta(bRec.wo) <= 0)
return Spectrum(0.0f);
const Spectrum F = fresnelConductor(dot(bRec.wi, m),
const Spectrum F = fresnelConductorExact(dot(bRec.wi, m),
m_eta, m_k);
Float numerator = m_distribution.eval(m, alphaU, alphaV)
@ -460,7 +464,7 @@ public:
m_alphaVShader = renderer->registerShaderForResource(m_alphaV.get());
/* Compute the reflectance at perpendicular incidence */
m_R0 = fresnelConductor(1.0f, eta, k);
m_R0 = fresnelConductorExact(1.0f, eta, k);
}
bool isComplete() const {

View File

@ -20,6 +20,7 @@
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/bitmap.h>
#include <mitsuba/core/statistics.h>
#include <mitsuba/hw/font.h>
#include <boost/algorithm/string.hpp>
#include "banner.h"
@ -114,7 +115,33 @@ MTS_NAMESPACE_BEGIN
* <boolean name="banner" value="false"/>
* </film>
* \end{xml}
*
* \subsubsection*{Annotations:}
* \label{sec:film-annotations}
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support an additional
* feature referred to as \emph{annotations}, which can be quite useful under
* certain circumstances.
*
* Annotations are used to embed useful information inside a rendered image so
* that this information is later available to anyone viewing the image.
* Exemplary uses of this feature might be to store the frame or take number,
* camera parameters, or other relevant scene information.
*
* Annotations can either be created by means of a \emph{tag}, which is an entry
* in the metadata table of the image file (does not modify the actual image data),
* or a \emph{text} label which is ``burned'' into the image.
*
* The syntax of this looks as follows:
*
* \begin{xml}
* <film type="ldrfilm">
* <!-- Create a new metadata entry 'my_tag_name' and set it to the value 'my_tag_value' -->
* <string name="tag('my_tag_name')" value="my_tag_value"/>
*
* <!-- Add the label 'Hello' at the image position X=50, Y=80 -->
* <string name="text(50,80)" value="Hello!"/>
* </film>
* \end{xml}
*/
class HDRFilm : public Film {
public:
@ -204,6 +231,25 @@ public:
}
std::vector<std::string> keys = props.getPropertyNames();
for (size_t i=0; i<keys.size(); ++i) {
std::string key = boost::to_lower_copy(keys[i]);
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) {
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]);
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) {
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
if (args.size() != 2)
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
Annotation annotation;
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
annotation.text = props.getString(keys[i]);
m_annotations.push_back(annotation);
}
}
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
}
@ -321,6 +367,23 @@ public:
}
}
if (!m_annotations.empty()) {
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), 1.0f);
for (size_t i=0; i<m_annotations.size(); ++i) {
const Point2i &offset = m_annotations[i].offset;
const std::string &text = m_annotations[i].text;
Vector2i size = font->getSize(text);
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
font->drawText(bitmap, offset, text);
}
}
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
it != m_tags.end(); ++it)
bitmap->getMetadata()[it->first] = it->second;
fs::path filename = m_destFile;
std::string extension = boost::to_lower_copy(filename.extension().string());
std::string properExtension = (m_fileFormat == Bitmap::EOpenEXR) ? ".exr" : ".rgbe";
@ -367,6 +430,11 @@ public:
MTS_DECLARE_CLASS()
protected:
struct Annotation {
Point2i offset;
std::string text;
};
Bitmap::EFileFormat m_fileFormat;
Bitmap::EPixelFormat m_pixelFormat;
Bitmap::EComponentFormat m_componentFormat;
@ -374,6 +442,9 @@ protected:
bool m_attachLog;
fs::path m_destFile;
ref<ImageBlock> m_storage;
std::vector<Annotation> m_annotations;
std::map<std::string, std::string> m_tags;
};
MTS_IMPLEMENT_CLASS_S(HDRFilm, false, Film)

View File

@ -20,6 +20,7 @@
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/bitmap.h>
#include <mitsuba/core/statistics.h>
#include <mitsuba/hw/font.h>
#include <boost/algorithm/string.hpp>
#include "banner.h"
@ -113,6 +114,9 @@ MTS_NAMESPACE_BEGIN
* The RGB values exported by this plugin correspond to the ITU-R Rec. BT. 709-3
* primaries with a D65 white point. When $\texttt{gamma}$ is set to $\code{-1}$ (the default),
* the output is in the sRGB color space and will display as intended on compatible devices.
*
* Note that this plugin supports render-time \emph{annotations}, which
* are described on page~\pageref{sec:film-annotations}.
*/
class LDRFilm : public Film {
public:
@ -176,6 +180,25 @@ public:
m_reinhardKey = props.getFloat("key", 0.18f);
m_reinhardBurn = props.getFloat("burn", 0.0);
std::vector<std::string> keys = props.getPropertyNames();
for (size_t i=0; i<keys.size(); ++i) {
std::string key = boost::to_lower_copy(keys[i]);
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) {
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]);
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) {
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
if (args.size() != 2)
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
Annotation annotation;
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
annotation.text = props.getString(keys[i]);
m_annotations.push_back(annotation);
}
}
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
}
@ -313,6 +336,23 @@ public:
}
}
if (!m_annotations.empty()) {
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), m_gamma);
for (size_t i=0; i<m_annotations.size(); ++i) {
const Point2i &offset = m_annotations[i].offset;
const std::string &text = m_annotations[i].text;
Vector2i size = font->getSize(text);
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
font->drawText(bitmap, offset, text);
}
}
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
it != m_tags.end(); ++it)
bitmap->getMetadata()[it->first] = it->second;
fs::path filename = m_destFile;
std::string extension = boost::to_lower_copy(filename.extension().string());
std::string expectedExtension;
@ -367,6 +407,11 @@ public:
MTS_DECLARE_CLASS()
protected:
struct Annotation {
Point2i offset;
std::string text;
};
Bitmap::EFileFormat m_fileFormat;
Bitmap::EPixelFormat m_pixelFormat;
bool m_hasBanner;
@ -375,6 +420,9 @@ protected:
ref<ImageBlock> m_storage;
ETonemapMethod m_tonemapMethod;
Float m_exposure, m_reinhardKey, m_reinhardBurn;
std::vector<Annotation> m_annotations;
std::map<std::string, std::string> m_tags;
};
MTS_IMPLEMENT_CLASS_S(LDRFilm, false, Film)

View File

@ -432,7 +432,7 @@ public:
bool develop(const Point2i &sourceOffset, const Vector2i &size,
const Point2i &targetOffset, Bitmap *target) const {
target->fill(targetOffset, size, Spectrum(0.0f));
target->fillRect(targetOffset, size, Spectrum(0.0f));
return false; /* Not supported by the tiled EXR film! */
}

View File

@ -130,8 +130,7 @@ public:
if (phaseVal != 0) {
/* Calculate prob. of having sampled that direction using
phase function sampling */
Float phasePdf = (emitter->isOnSurface() && dRec.measure == ESolidAngle
&& interactions == 0)
Float phasePdf = (emitter->isOnSurface() && dRec.measure == ESolidAngle)
? phase->pdf(pRec) : (Float) 0.0f;
/* Weight using the power heuristic */

View File

@ -430,47 +430,59 @@ void Bitmap::flipVertically() {
}
}
void Bitmap::accumulate(const Bitmap *bitmap, const Point2i &offset) {
void Bitmap::accumulate(const Bitmap *bitmap, Point2i sourceOffset,
Point2i targetOffset, Vector2i size) {
Assert(getPixelFormat() == bitmap->getPixelFormat() &&
getComponentFormat() == bitmap->getComponentFormat() &&
getChannelCount() == bitmap->getChannelCount());
const int
offsetX = std::max(offset.x, 0),
offsetY = std::max(offset.y, 0),
endX = std::min(offset.x + bitmap->getSize().x, m_size.x),
endY = std::min(offset.y + bitmap->getSize().y, m_size.y);
Vector2i offsetIncrease(
std::max(0, std::max(-sourceOffset.x, -targetOffset.x)),
std::max(0, std::max(-sourceOffset.y, -targetOffset.y))
);
if (offsetX >= endX || offsetY >= endY)
sourceOffset += offsetIncrease;
targetOffset += offsetIncrease;
size -= offsetIncrease;
Vector2i sizeDecrease(
std::max(0, std::max(sourceOffset.x + size.x - bitmap->getWidth(), targetOffset.x + size.x - getWidth())),
std::max(0, std::max(sourceOffset.y + size.y - bitmap->getHeight(), targetOffset.y + size.y - getHeight())));
size -= sizeDecrease;
if (size.x <= 0 || size.y <= 0)
return;
const size_t
columns = (endX - offsetX) * m_channelCount,
columns = size.x * m_channelCount,
pixelStride = getBytesPerPixel(),
sourceStride = bitmap->getSize().x * pixelStride,
targetStride = m_size.x * pixelStride;
sourceStride = bitmap->getWidth() * pixelStride,
targetStride = getWidth() * pixelStride;
const uint8_t *source = bitmap->getUInt8Data() +
(offsetX - offset.x + (offsetY - offset.y) * bitmap->getSize().x) * pixelStride;
(sourceOffset.x + sourceOffset.y * (size_t) bitmap->getWidth()) * pixelStride;
uint8_t *target = m_data +
(offsetX + offsetY * m_size.x) * pixelStride;
(targetOffset.x + targetOffset.y * (size_t) m_size.x) * pixelStride;
for (int y = offsetY; y < endY; ++y) {
for (int y = 0; y < size.y; ++y) {
switch (m_componentFormat) {
case EUInt8:
for (size_t i = 0; i < columns; ++i)
((uint8_t *) target)[i] += ((uint8_t *) source)[i];
((uint8_t *) target)[i] = (uint8_t) std::min(0xFF, ((uint8_t *) source)[i] + ((uint8_t *) target)[i]);
break;
case EUInt16:
for (size_t i = 0; i < columns; ++i)
((uint16_t *) target)[i] += ((uint16_t *) source)[i];
((uint16_t *) target)[i] = (uint16_t) std::min(0xFFFF, ((uint16_t *) source)[i] + ((uint16_t *) target)[i]);
break;
case EUInt32:
for (size_t i = 0; i < columns; ++i)
((uint32_t *) target)[i] += ((uint32_t *) source)[i];
((uint32_t *) target)[i] = std::min((uint32_t) 0xFFFFFFFFUL, ((uint32_t *) source)[i] + ((uint32_t *) target)[i]);
break;
case EFloat16:
@ -554,8 +566,9 @@ void Bitmap::setPixel(const Point2i &pos, const Spectrum &value) {
}
void Bitmap::drawHLine(int y, int x1, int x2, const Spectrum &value) {
AssertEx( y >= 0 && y < m_size.y &&
x1 >= 0 && x2 < m_size.x, "Bitmap::drawVLine(): out of bounds!");
if (y < 0 || y >= m_size.y)
return;
x1 = std::max(x1, 0); x2 = std::min(x2, m_size.x-1);
const FormatConverter *cvt = FormatConverter::getInstance(
std::make_pair(EFloat, m_componentFormat)
@ -574,8 +587,9 @@ void Bitmap::drawHLine(int y, int x1, int x2, const Spectrum &value) {
}
void Bitmap::drawVLine(int x, int y1, int y2, const Spectrum &value) {
AssertEx( x >= 0 && x < m_size.x &&
y1 >= 0 && y2 < m_size.y, "Bitmap::drawVLine(): out of bounds!");
if (x < 0 || x >= m_size.x)
return;
y1 = std::max(y1, 0); y2 = std::min(y2, m_size.y-1);
const FormatConverter *cvt = FormatConverter::getInstance(
std::make_pair(EFloat, m_componentFormat)
@ -601,9 +615,12 @@ void Bitmap::drawRect(const Point2i &offset, const Vector2i &size, const Spectru
drawVLine(offset.x + size.x - 1, offset.y, offset.y + size.y - 1, value);
}
void Bitmap::fill(const Point2i &offset, const Vector2i &size, const Spectrum &value) {
AssertEx(offset.x >= 0 && offset.x + size.x <= m_size.x &&
offset.y >= 0 && offset.y + size.y <= m_size.y, "Bitmap::fill(): out of bounds!");
void Bitmap::fillRect(Point2i offset, Vector2i size, const Spectrum &value) {
int sx = std::max(0, -offset.x), sy = std::max(0, -offset.y);
size.x -= sx; size.y -= sy; offset.x += sx; offset.y += sy;
size.x -= std::max(0, offset.x + size.x - m_size.x);
size.y -= std::max(0, offset.y + size.y - m_size.y);
const FormatConverter *cvt = FormatConverter::getInstance(
std::make_pair(EFloat, m_componentFormat)
@ -995,6 +1012,79 @@ ref<Bitmap> Bitmap::crop(const Point2i &offset, const Vector2i &size) const {
return result;
}
void Bitmap::applyMatrix(Float matrix_[3][3]) {
int stride = 0;
if (m_pixelFormat == ERGB || m_pixelFormat == EXYZ)
stride = 3;
else if (m_pixelFormat == ERGBA || m_pixelFormat == EXYZA)
stride = 4;
else
Log(EError, "Bitmap::applyMatrix(): unsupported pixel format!");
size_t pixels = (size_t) m_size.x * (size_t) m_size.y;
switch (m_componentFormat) {
case EFloat16: {
float matrix[3][3];
half *data = getFloat16Data();
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
matrix[i][j] = (float) matrix_[i][j];
for (size_t i=0; i<pixels; ++i) {
float result[3] = { 0.0f, 0.0f, 0.0f };
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
result[i] += matrix[i][j] * (float) data[j];
for (int i=0; i<3; ++i)
data[i] = (half) result[i];
data += stride;
}
}
break;
case EFloat32: {
float matrix[3][3], *data = getFloat32Data();
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
matrix[i][j] = (float) matrix_[i][j];
for (size_t i=0; i<pixels; ++i) {
float result[3] = { 0.0f, 0.0f, 0.0f };
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
result[i] += matrix[i][j] * data[j];
for (int i=0; i<3; ++i)
data[i] = result[i];
data += stride;
}
}
break;
case EFloat64: {
double matrix[3][3], *data = getFloat64Data();
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
matrix[i][j] = (double) matrix_[i][j];
for (size_t i=0; i<pixels; ++i) {
double result[3] = { 0.0, 0.0, 0.0 };
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
result[i] += matrix[i][j] * data[j];
for (int i=0; i<3; ++i)
data[i] = result[i];
data += stride;
}
}
break;
default:
Log(EError, "Bitmap::applyMatrix(): unsupported component format!");
}
}
/// Bitmap resampling utility function
template <typename Scalar> static void resample(const ReconstructionFilter *rfilter,
ReconstructionFilter::EBoundaryCondition bch,

View File

@ -78,9 +78,9 @@ void Class::initializeOnce(Class *theClass) {
}
void Class::staticInitialization() {
std::for_each(__classes->begin(), __classes->end(),
compose1(std::ptr_fun(initializeOnce),
select2nd<ClassMap::value_type>()));
for (ClassMap::iterator it = __classes->begin();
it != __classes->end(); ++it)
initializeOnce(it->second);
m_isInitialized = true;
}

View File

@ -586,18 +586,84 @@ Float fresnelDielectricExt(Float cosThetaI_, Float &cosThetaT_, Float eta) {
return 0.5f * (Rs * Rs + Rp * Rp);
}
Spectrum fresnelConductor(Float cosThetaI, const Spectrum &eta, const Spectrum &k) {
Spectrum tmp = (eta*eta + k*k) * (cosThetaI * cosThetaI);
Float fresnelConductorApprox(Float cosThetaI, Float eta, Float k) {
Float cosThetaI2 = cosThetaI*cosThetaI;
Spectrum rParl2 = (tmp - (eta * (2.0f * cosThetaI)) + Spectrum(1.0f))
/ (tmp + (eta * (2.0f * cosThetaI)) + Spectrum(1.0f));
Float tmp = (eta*eta + k*k) * cosThetaI2;
Float Rp2 = (tmp - (eta * (2 * cosThetaI)) + 1)
/ (tmp + (eta * (2 * cosThetaI)) + 1);
Float tmpF = eta*eta + k*k;
Float Rs2 = (tmpF - (eta * (2 * cosThetaI)) + cosThetaI2) /
(tmpF + (eta * (2 * cosThetaI)) + cosThetaI2);
return 0.5f * (Rp2 + Rs2);
}
Spectrum fresnelConductorApprox(Float cosThetaI, const Spectrum &eta, const Spectrum &k) {
Float cosThetaI2 = cosThetaI*cosThetaI;
Spectrum tmp = (eta*eta + k*k) * cosThetaI2;
Spectrum Rp2 = (tmp - (eta * (2 * cosThetaI)) + Spectrum(1.0f))
/ (tmp + (eta * (2 * cosThetaI)) + Spectrum(1.0f));
Spectrum tmpF = eta*eta + k*k;
Spectrum rPerp2 = (tmpF - (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI)) /
(tmpF + (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI));
Spectrum Rs2 = (tmpF - (eta * (2 * cosThetaI)) + Spectrum(cosThetaI2)) /
(tmpF + (eta * (2 * cosThetaI)) + Spectrum(cosThetaI2));
return (rParl2 + rPerp2) / 2.0f;
return 0.5f * (Rp2 + Rs2);
}
Float fresnelConductorExact(Float cosThetaI, Float eta, Float k) {
/* Modified from "Optics" by K.D. Moeller, University Science Books, 1988 */
Float cosThetaI2 = cosThetaI*cosThetaI,
sinThetaI2 = 1-cosThetaI2,
sinThetaI4 = sinThetaI2*sinThetaI2;
Float temp1 = eta*eta - k*k - sinThetaI2,
a2pb2 = math::safe_sqrt(temp1*temp1 + 4*k*k*eta*eta),
a = math::safe_sqrt(0.5f * (a2pb2 + temp1));
Float term1 = a2pb2 + cosThetaI2,
term2 = 2*a*cosThetaI;
Float Rs2 = (term1 - term2) / (term1 + term2);
Float term3 = a2pb2*cosThetaI2 + sinThetaI4,
term4 = term2*sinThetaI2;
Float Rp2 = Rs2 * (term3 - term4) / (term3 + term4);
return 0.5f * (Rp2 + Rs2);
}
Spectrum fresnelConductorExact(Float cosThetaI, const Spectrum &eta, const Spectrum &k) {
/* Modified from "Optics" by K.D. Moeller, University Science Books, 1988 */
Float cosThetaI2 = cosThetaI*cosThetaI,
sinThetaI2 = 1-cosThetaI2,
sinThetaI4 = sinThetaI2*sinThetaI2;
Spectrum temp1 = eta*eta - k*k - Spectrum(sinThetaI2),
a2pb2 = (temp1*temp1 + k*k*eta*eta*4).safe_sqrt(),
a = ((a2pb2 + temp1) * 0.5f).safe_sqrt();
Spectrum term1 = a2pb2 + Spectrum(cosThetaI2),
term2 = a*(2*cosThetaI);
Spectrum Rs2 = (term1 - term2) / (term1 + term2);
Spectrum term3 = a2pb2*cosThetaI2 + Spectrum(sinThetaI4),
term4 = term2*sinThetaI2;
Spectrum Rp2 = Rs2 * (term3 - term4) / (term3 + term4);
return 0.5f * (Rp2 + Rs2);
}
Vector reflect(const Vector &wi, const Normal &n) {

View File

@ -74,6 +74,70 @@ Font::Font(EFont font) {
dscStream->read(m_kerningMatrix, 256*256);
}
void Font::convert(Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat, Float gamma) {
m_bitmap = m_bitmap->convert(pixelFormat, componentFormat, gamma);
}
void Font::drawText(Bitmap *dest, Point2i pos, const std::string &text) const {
int initial = pos.x;
for (size_t i=0; i<text.length(); i++) {
char character = text[i];
if (character == '\r')
continue;
if (character == '\n') {
pos.x = initial;
pos.y += (int) (getMaxVerticalBearing()*4.0/3.0);
continue;
}
const Font::Glyph &glyph = getGlyph(character);
Point2i targetOffset = pos + Vector2i(
glyph.horizontalBearing,
getMaxVerticalBearing() - glyph.verticalBearing - 1
);
Point2i sourceOffset(
glyph.tx.x * m_bitmap->getWidth(),
glyph.tx.y * m_bitmap->getHeight());
dest->accumulate(m_bitmap.get(), sourceOffset, targetOffset, glyph.size);
pos.x += glyph.horizontalAdvance;
if (i+1 < text.length())
pos.x += getKerning(character, text[i+1]);
}
}
Vector2i Font::getSize(const std::string &text) const {
Vector2i size(0, getMaxVerticalBearing());
int pos = 0;
for (size_t i=0; i<text.length(); i++) {
char character = text[i];
if (character == '\r')
continue;
if (character == '\n') {
size.y += getMaxVerticalBearing()*(4.0 / 3.0);
size.x = std::max(size.x, pos);
pos = 0;
continue;
}
const Font::Glyph &glyph = getGlyph(character);
pos += glyph.horizontalAdvance;
if (i+1 < text.length())
pos += getKerning(character, text[i+1]);
}
size.x = std::max(size.x, pos);
return size;
}
void Font::init(Renderer *renderer) {
m_texture = renderer->createGPUTexture(m_name, m_bitmap);
m_texture->setFilterType(GPUTexture::ENearest);

View File

@ -79,10 +79,10 @@ void initializeFramework() {
if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &initializeFramework, &hm)) {
std::vector<WCHAR> lpFilename(MAX_PATH);
// Try to get the path with the default MAX_PATH length (260 chars)
DWORD nSize = GetModuleFileNameW(hm, &lpFilename[0], MAX_PATH);
// Adjust the buffer size in case if was too short
while (nSize == lpFilename.size()) {
lpFilename.resize(nSize * 2);
@ -175,7 +175,7 @@ public:
bp::extract<Transform> extractTransform(value);
bp::extract<Spectrum> extractSpectrum(value);
if (extractString.check()) {
if (extractString.check()){
props.setString(name, extractString());
} else if (extractBoolean.check() && PyObject_IsInstance(value.ptr(), (PyObject *) &PyBool_Type)) {
props.setBoolean(name, extractBoolean());
@ -205,6 +205,12 @@ struct path_to_python_str {
};
struct TSpectrum_to_Spectrum {
static PyObject* convert(const TSpectrum<Float, 3> &spectrum) {
return bp::incref(bp::object(Spectrum(spectrum)).ptr());
}
};
static void Matrix4x4_setItem(Matrix4x4 *matrix, bp::tuple tuple, Float value) {
if (bp::len(tuple) != 2)
SLog(EError, "Invalid matrix indexing operation, required a tuple of length 2");
@ -472,6 +478,43 @@ Vector refract3(const Vector &wi, const Normal &n, Float eta) {
return refract(wi, n, eta);
}
void bitmap_applyMatrix(Bitmap *bitmap, bp::list list) {
int length = bp::len(list);
if (length != 9)
SLog(EError, "Require a color matrix specified as a list with 9 entries!");
Float matrix[3][3];
int idx = 0;
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
matrix[i][j] = bp::extract<Float>(list[idx++]);
bitmap->applyMatrix(matrix);
}
void bitmap_write(Bitmap *bitmap, Bitmap::EFileFormat fmt, Stream *stream) {
bitmap->write(fmt, stream);
}
ref<Bitmap> bitmap_convert_1(Bitmap *bitmap, Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat,
Float gamma, Float multiplier, Spectrum::EConversionIntent intent) {
return bitmap->convert(pixelFormat, componentFormat, gamma, multiplier, intent);
}
ref<Bitmap> bitmap_convert_2(Bitmap *bitmap, Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat,
Float gamma, Float multiplier) {
return bitmap->convert(pixelFormat, componentFormat, gamma, multiplier);
}
ref<Bitmap> bitmap_convert_3(Bitmap *bitmap, Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat,
Float gamma) {
return bitmap->convert(pixelFormat, componentFormat, gamma);
}
ref<Bitmap> bitmap_convert_4(Bitmap *bitmap, Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat) {
return bitmap->convert(pixelFormat, componentFormat);
}
Transform transform_glOrthographic1(Float clipNear, Float clipFar) {
return Transform::glOrthographic(clipNear, clipFar);
@ -489,6 +532,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(fromXYZ_overloads, fromXYZ, 3, 4)
void export_core() {
bp::to_python_converter<fs::path, path_to_python_str>();
bp::to_python_converter<TSpectrum<Float, 3>, TSpectrum_to_Spectrum>();
bp::implicitly_convertible<std::string, fs::path>();
bp::object coreModule(
@ -708,17 +752,23 @@ void export_core() {
.def("clear", &InterpolatedSpectrum::clear)
.def("zeroExtend", &InterpolatedSpectrum::zeroExtend);
void (Bitmap::*accumulate_1)(const Bitmap *bitmap, Point2i sourceOffset, Point2i targetOffset, Vector2i size) = &Bitmap::accumulate;
void (Bitmap::*accumulate_2)(const Bitmap *bitmap, Point2i targetOffset) = &Bitmap::accumulate;
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("clone", &Bitmap::clone, BP_RETURN_VALUE)
.def("clear", &Bitmap::clear)
.def("separateChannel", &Bitmap::separateChannel, BP_RETURN_VALUE)
.def("expand", &Bitmap::expand, BP_RETURN_VALUE)
.def("flipVertically", &Bitmap::flipVertically)
.def("crop", &Bitmap::crop)
.def("accumulate", &Bitmap::accumulate)
.def("clear", &Bitmap::clear)
.def("write", &Bitmap::write)
.def("applyMatrix", &bitmap_applyMatrix)
.def("colorBalance", &Bitmap::colorBalance)
.def("accumulate", accumulate_1)
.def("accumulate", accumulate_2)
.def("write", &bitmap_write)
.def("setString", &Bitmap::setString)
.def("getString", &Bitmap::getString, BP_RETURN_VALUE)
.def("setGamma", &Bitmap::setGamma)
@ -732,9 +782,18 @@ void export_core() {
.def("getBitsPerComponent", &Bitmap::getBitsPerComponent)
.def("getBytesPerComponent", &Bitmap::getBytesPerComponent)
.def("getBytesPerPixel", &Bitmap::getBytesPerPixel)
.def("getBufferSize", &Bitmap::getBufferSize)
.def("getPixel", &Bitmap::getPixel, BP_RETURN_VALUE)
.def("setPixel", &Bitmap::setPixel)
.def("getSize", &Bitmap::getSize, BP_RETURN_VALUE);
.def("drawHLine", &Bitmap::drawHLine)
.def("drawVLine", &Bitmap::drawVLine)
.def("drawRect", &Bitmap::drawRect)
.def("fillRect", &Bitmap::fillRect)
.def("getSize", &Bitmap::getSize, BP_RETURN_VALUE)
.def("convert", &bitmap_convert_1, BP_RETURN_VALUE)
.def("convert", &bitmap_convert_2, BP_RETURN_VALUE)
.def("convert", &bitmap_convert_3, BP_RETURN_VALUE)
.def("convert", &bitmap_convert_4, BP_RETURN_VALUE);
BP_SETSCOPE(Bitmap_class);
bp::enum_<Bitmap::EPixelFormat>("EPixelFormat")
@ -745,7 +804,8 @@ void export_core() {
.value("ESpectrum", Bitmap::ESpectrum)
.value("ESpectrumAlpha", Bitmap::ESpectrumAlpha)
.value("ESpectrumAlphaWeight", Bitmap::ESpectrumAlphaWeight)
.value("EMultiChannel", Bitmap::EMultiChannel);
.value("EMultiChannel", Bitmap::EMultiChannel)
.export_values();
bp::enum_<Bitmap::EComponentFormat>("EComponentFormat")
.value("EBitmask", Bitmap::EBitmask)
@ -763,10 +823,13 @@ void export_core() {
.value("EPNG", Bitmap::EPNG)
.value("EOpenEXR", Bitmap::EOpenEXR)
.value("ETGA", Bitmap::ETGA)
.value("EPFM", Bitmap::EPFM)
.value("ERGBE", Bitmap::ERGBE)
.value("EBMP", Bitmap::EBMP)
.value("EJPEG", Bitmap::EJPEG)
.value("EAuto", Bitmap::EAuto)
.export_values();
BP_SETSCOPE(coreModule);
BP_CLASS(FileResolver, Object, bp::init<>())
@ -1261,11 +1324,19 @@ void export_core() {
.staticmethod("glOrthographic")
.staticmethod("fromFrame");
Float (*fresnelConductorApprox1)(Float, Float, Float) = &fresnelConductorApprox;
Float (*fresnelConductorExact1)(Float, Float, Float) = &fresnelConductorExact;
Spectrum (*fresnelConductorApprox2)(Float, const Spectrum &, const Spectrum &) = &fresnelConductorApprox;
Spectrum (*fresnelConductorExact2)(Float, const Spectrum &, const Spectrum &) = &fresnelConductorExact;
/* Functions from utility.h */
bp::def("fresnelDielectric", &fresnelDielectric);
bp::def("fresnelDielectricExt", &fresnelDielectricExt1);
bp::def("fresnelDielectricExt", &fresnelDielectricExt2);
bp::def("fresnelConductor", &fresnelConductor, BP_RETURN_VALUE);
bp::def("fresnelConductorApprox", fresnelConductorApprox1, BP_RETURN_VALUE);
bp::def("fresnelConductorApprox", fresnelConductorApprox2, BP_RETURN_VALUE);
bp::def("fresnelConductorExact", fresnelConductorExact1, BP_RETURN_VALUE);
bp::def("fresnelConductorExact", fresnelConductorExact2, BP_RETURN_VALUE);
bp::def("fresnelDiffuseReflectance", &fresnelDiffuseReflectance);
bp::def("reflect", &reflect);
bp::def("refract", &refract1);

View File

@ -47,6 +47,7 @@ Spectrum Texture::getMinimum() const { NotImplementedError("getMinimum"); }
Spectrum Texture::getMaximum() const { NotImplementedError("getMaximum"); }
bool Texture::isConstant() const { NotImplementedError("isConstant"); }
bool Texture::usesRayDifferentials() const { NotImplementedError("usesRayDifferentials"); }
ref<Bitmap> Texture::getBitmap() const { return NULL; }
ref<Texture> Texture::expand() {
return this;

View File

@ -33,9 +33,8 @@ if hasQt:
del qtEnv['CXXFLAGS'][index-1]
index = qtEnv['LINKFLAGS'].index('/SUBSYSTEM:CONSOLE')
del qtEnv['LINKFLAGS'][index]
qtEnv.Append(CXXFLAGS=['/D', '_WINDOWS'])
qtEnv.Append(CXXFLAGS=['/D', '_WINDOWS', '/D', 'MTS_CUSTOM_QTMAIN', '/D', 'MTSGUI_STATIC_QFILEDIALOG=1'])
qtEnv.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
qtEnv.Append(LIBS=['qtmain'])
if hasBreakpad:
qtEnv.Append(CPPPATH=['#dependencies/include/breakpad'])
qtEnv.Append(LIBS=['breakpad_common', 'breakpad_exception_handler', 'breakpad_crash_generation_client',
@ -72,6 +71,10 @@ if hasQt:
qtSources += qtEnv_osx.StaticObject('breakpad.mm')
else:
qtSources = [x for x in qtSources if (not isinstance(x, str) or 'cocoa' not in x)]
if sys.platform == 'win32':
qtSources += qtEnv.StaticObject('qtmain_win.cpp')
mtsgui = qtEnv.Program('mtsgui', qtSources)
if sys.platform == 'darwin':
qtEnv.AddPostAction(mtsgui, 'install_name_tool -change QtGui.framework/Versions/4/QtGui @rpath/QtGui $TARGET')

View File

@ -558,6 +558,8 @@ void MainWindow::on_actionOpen_triggered() {
}
}
void MainWindow::onOpenDialogClose(int reason) { /* unused */ }
#else // MTSGUI_STATIC_QFILEDIALOG
void MainWindow::on_actionOpen_triggered() {
@ -1447,6 +1449,8 @@ void MainWindow::on_actionExportImage_triggered() {
}
}
void MainWindow::onExportDialogClose(int reason) { /* unused */ }
#else // MTSGUI_STATIC_QFILEDIALOG
void MainWindow::on_actionExportImage_triggered() {
@ -1563,6 +1567,8 @@ void MainWindow::on_actionSaveAs_triggered() {
}
}
void MainWindow::onSaveAsDialogClose(int reason) { /* unused */ }
#else // MTSGUI_STATIC_QFILEDIALOG
void MainWindow::on_actionSaveAs_triggered() {

View File

@ -192,11 +192,9 @@ private slots:
void updateUI();
void updateStatus();
void onPreviewSettingsClose();
#if !MTSGUI_STATIC_QFILEDIALOG
void onOpenDialogClose(int reason);
void onExportDialogClose(int reason);
void onSaveAsDialogClose(int reason);
#endif
void onRenderSettingsClose(int reason);
void onImportDialogClose(int reason);
void onSceneInformationClose(int reason);

View File

@ -44,12 +44,12 @@
# error This source file can only be used in Windows builds
#endif
#include <QVector>
#include <QByteArray>
#include <QString>
#include <QtCore/QVector>
#include <QtCore/QByteArray>
#include <QtCore/QString>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <windows.h>
/*
This file contains the code in the qtmain library for Windows.

View File

@ -208,9 +208,9 @@ static int irrOctreeIndex = 0;
* rendered using diffusion theory and radiative transport, respectively.
* The former produces an incorrect result, since the assumption of
* many scattering events breaks down.
* \textbf{(c)}: When the number of irradiance samples is too low, the
* resulting noise becomes visible as ``blotchy'' artifacts in the
* rendering.}
* \textbf{(c)}: When the number of irradiance samples is too low when rendering
* with the dipole model, the resulting noise becomes visible as ``blotchy'' artifacts
* in the rendering.}
* }
*
* \subsubsection*{Typical material setup}

View File

@ -400,6 +400,10 @@ public:
return result;
}
ref<Bitmap> getBitmap() const {
return m_mipmap1.get() ? m_mipmap1->toBitmap() : m_mipmap3->toBitmap();
}
Spectrum eval(const Point2 &uv, const Vector2 &d0, const Vector2 &d1) const {
stats::filteredLookups.incrementBase();
++stats::filteredLookups;

View File

@ -93,7 +93,7 @@ MTS_NAMESPACE_BEGIN
*
* When using this data source to represent floating point density volumes,
* please ensure that the values are all normalized to lie in the
* range $[0, 1]$---otherwise, the Woocock-Tracking integration method in
* range $[0, 1]$---otherwise, the Woodcock-Tracking integration method in
* \pluginref{heterogeneous} will produce incorrect results.
*/
class GridDataSource : public VolumeDataSource {