Merge with default

metadata
Edgar Velazquez-Armendariz 2012-10-12 17:54:44 -04:00
commit a26272344c
44 changed files with 2670 additions and 136 deletions

View File

@ -104,7 +104,7 @@ if sys.platform == 'win32':
installTargets += env.Install(distDir, '#data/windows/README.txt')
if 'REDIST_PATH' in env:
install(distDir, ['libmmd.dll', 'libiomp5md.dll'], prefix = env['REDIST_PATH'])
install(distDir, ['libmmd.dll', 'libiomp5md.dll', 'svml_dispmd.dll'], prefix = env['REDIST_PATH'])
if hasQt:
install(distDir, ['mtsgui/mtsgui.exe'])

40
build/config-linux-icl.py Normal file
View File

@ -0,0 +1,40 @@
import os, sys
BUILDDIR = '#build/release'
DISTDIR = '#dist'
CXX = 'icpc'
CC = 'icc'
CXXFLAGS = ['-O3', '-Wall', '-g', '-pipe', '-O3', '-ipo', '-no-prec-div', '-xSSE3', '-fp-model', 'fast=2', '-openmp', '-mfpmath=sse', '-march=nocona', '-fno-math-errno', '-fomit-frame-pointer', '-DMTS_DEBUG', '-DSINGLE_PRECISION', '-DSPECTRUM_SAMPLES=3', '-DMTS_SSE', '-DMTS_HAS_COHERENT_RT', '-fopenmp', '-fvisibility=hidden', '-std=c++0x', '-wd2928', '-Qoption,cpp,--rvalue_ctor_is_not_copy_ctor']
LINKFLAGS = []
SHLINKFLAGS = ['-rdynamic', '-shared', '-fPIC', '-lstdc++']
BASEINCLUDE = ['#include']
BASELIB = ['dl', 'pthread', 'iomp5']
EIGENINCLUDE = ['/usr/include/eigen3']
OEXRINCLUDE = ['/usr/include/OpenEXR']
OEXRLIB = ['Half', 'IlmImf', 'z']
PNGLIB = ['png']
JPEGLIB = ['jpeg']
XERCESINCLUDE = []
XERCESLIB = ['xerces-c']
GLLIB = ['GL', 'GLU', 'GLEWmx', 'Xxf86vm', 'X11']
GLFLAGS = ['-DGLEW_MX']
BOOSTLIB = ['boost_system', 'boost_filesystem', 'boost_thread']
COLLADAINCLUDE = ['/usr/include/collada-dom', '/usr/include/collada-dom/1.4']
COLLADALIB = ['collada14dom']
# The following assumes that the Mitsuba bindings should be built for the
# "default" Python version. It is also possible to build bindings for multiple
# versions at the same time by explicitly specifying e.g. PYTHON27INCLUDE,
# PYTHON27LIB, PYTHON27LIBDIR and PYTHON32INCLUDE, PYTHON32LIB, PYTHON32LIBDIR
pyver = os.popen("python --version 2>&1 | grep -oE '([[:digit:]].[[:digit:]])'").read().strip().replace('.', '')
env = locals()
env['PYTHON'+pyver+'INCLUDE'] = []
env['PYTHON'+pyver+'LIB'] = ['boost_python3' if pyver[0] == '3' else 'boost_python']
for entry in os.popen("python-config --cflags --libs").read().split():
if entry[:2] == '-I':
env['PYTHON'+pyver+'INCLUDE'] += [entry[2:]]
if entry[:2] == '-l':
env['PYTHON'+pyver+'LIB'] += [entry[2:]]

View File

@ -1,3 +1,17 @@
mitsuba (0.4.1-1) unstable; urgency=low
* negative pixel values in textures and environment maps are handled more gracefully.
* minor robustness improvements to the OBJ and COLLADA importers.
* fixed the Ubuntu packages so that they don't depend on a specific version of the libjpeg development headers.
* fixed a stack overflow issue in the bidirectional path tracer, as well as some other crash-causing bugs that were found via the Breakpad reports.
* fixed an issue where sun and sky interpreted the combination of a 'toWorld' transform and explicit 'sunDirection' differently, causing misalignment.
* fixed a photon mapper regression involving environment maps.
* Edgar Velázquez-Armendáriz rewrote a piece of initialization code that prevented Mitsuba from running on Windows XP.
* Sean Bell contributed an improved setpath.sh script, which adds ZSH autocompletion on Linux.
* fixed some issues in the bidirectional abstraction layer when dealing with alpha masks.
* fixed a bug where the rectangle shape produced incorrect results when used as an area light.
* on OSX, the python bindings could not be loaded due to invalid library import paths - this now works.
-- Wenzel Jakob <wenzel@cs.cornell.edu> Wed, 10 Oct 2012 00:00:00 -0400
mitsuba (0.4.0-1) unstable; urgency=low
* New bidirectional rendering algorithms: Bidirectional path tracing,
Primary sample space MLT, Path space MLT, Energy redistribution path

View File

@ -1,5 +1,5 @@
Name: mitsuba
Version: 0.3.1
Version: 0.4.1
Release: 1%{?dist}
Summary: Mitsuba renderer
Group: Applications/Graphics
@ -7,7 +7,7 @@ License: GPL-3
URL: http://www.mitsuba-renderer.org
Source: %{name}-%{version}.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
BuildRequires: gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel
BuildRequires: gcc-c++ scons boost-devel qt4-devel OpenEXR-devel xerces-c-devel python-devel glew-devel collada-dom-devel eigen3-devel
Requires: boost qt4 OpenEXR-libs xerces-c python libGLEWmx collada-dom
%description
Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased as well as biased techniques and contains heavy optimizations targeted towards current CPU architectures.
@ -24,7 +24,7 @@ building custom plugins and other extensions for Mitsuba.
%prep
%setup -q
%build
cp build/config-linux.py config.py
cat build/config-linux-gcc.py | sed -e "s/\(boost_[^']*\)/\1-mt/g" > config.py
scons
%install
rm -rf $RPM_BUILD_ROOT
@ -36,13 +36,13 @@ mkdir -p $RPM_BUILD_ROOT/usr/share/pixmaps
mkdir -p $RPM_BUILD_ROOT/usr/share/applications
mkdir -p $RPM_BUILD_ROOT/usr/include
strip dist/lib* dist/mtsgui dist/mitsuba dist/mtssrv dist/mtsutil
strip dist/plugins/* dist/python/*
strip dist/plugins/* dist/python/*/*
cp dist/libmitsuba-*.so $RPM_BUILD_ROOT%{_libdir}
cp dist/mtsgui $RPM_BUILD_ROOT%{_bindir}
cp dist/mitsuba $RPM_BUILD_ROOT%{_bindir}
cp dist/mtssrv $RPM_BUILD_ROOT%{_bindir}
cp dist/mtsutil $RPM_BUILD_ROOT%{_bindir}
cp dist/python/mitsuba.so $RPM_BUILD_ROOT%{_libdir}/python2.7/lib-dynload
cp dist/python/2.7/mitsuba.so $RPM_BUILD_ROOT%{_libdir}/python2.7/lib-dynload
cp dist/plugins/* $RPM_BUILD_ROOT/usr/share/mitsuba/plugins
cp -Rdp dist/data $RPM_BUILD_ROOT/usr/share/mitsuba/data
cp src/mtsgui/resources/mitsuba48.png $RPM_BUILD_ROOT/usr/share/pixmaps
@ -62,6 +62,12 @@ rm -rf $RPM_BUILD_ROOT
/usr/include/*
%changelog
* Wed Oct 10 2012 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.1%{?dist}
- Upgrade to version 0.4.1
* Thu Sep 27 2012 Wenzel Jakob <wenzel@cs.cornell.edu> 0.4.0%{?dist}
- Upgrade to version 0.4.0
* Fri Apr 13 2012 Wenzel Jakob <wenzel@cs.cornell.edu> 0.3.1%{?dist}
- Upgrade to version 0.3.1

2251
doc/images/bidir-figures.ai Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -39,7 +39,7 @@
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{3}
\newcommand{\MitsubaVersion}{0.4.0}
\newcommand{\MitsubaVersion}{0.4.1}
\newcommand{\MitsubaYear}{2012}
\typearea[current]{last}

View File

@ -99,6 +99,19 @@ public:
//! @}
// =============================================================
// =============================================================
//! @{ \name Miscellaneous
// =============================================================
/// Initialize the file I/O layer (unicode conversions etc.)
static void staticInitialization();
/// Release resources taken up by staticInitialization()
static void staticShutdown();
//! @}
// =============================================================
MTS_DECLARE_CLASS()
protected:
/** \brief Virtual destructor

View File

@ -124,8 +124,15 @@ public:
inline size_t sample(Float sampleValue) const {
std::vector<Float>::const_iterator entry =
std::lower_bound(m_cdf.begin(), m_cdf.end(), sampleValue);
size_t index = (size_t) std::max((ptrdiff_t) 0, entry - m_cdf.begin() - 1);
return std::min(index, m_cdf.size()-2);
size_t index = std::min(m_cdf.size()-2,
(size_t) std::max((ptrdiff_t) 0, entry - m_cdf.begin() - 1));
/* Handle a rare corner-case where a entry has probability 0
but is sampled nonetheless */
while (operator[](index) == 0 && index < m_cdf.size()-1)
++index;
return index;
}
/**

View File

@ -26,7 +26,7 @@ MTS_NAMESPACE_BEGIN
* \brief Current release of Mitsuba
* \ingroup libcore
*/
#define MTS_VERSION "0.4.0"
#define MTS_VERSION "0.4.1"
/**
* \brief Year of the current release

View File

@ -219,6 +219,17 @@ public:
m_pyramid[0].cleanup();
m_pyramid[0].init((Value *) bitmap->getData(), m_minimum, m_maximum, m_average);
if (m_minimum.min() < 0) {
Log(EWarn, "The texture contains negative pixel values! These will be clamped!");
Value *value = (Value *) bitmap->getData();
for (size_t i=0, count=bitmap->getPixelCount(); i<count; ++i)
(*value++).clampNegative();
m_pyramid[0].init((Value *) bitmap->getData(), m_minimum, m_maximum, m_average);
}
m_sizeRatio[0] = Vector2(1, 1);
/* 3. Progressively downsample until only a 1x1 image is left */

View File

@ -31,10 +31,11 @@
XERCES_CPP_NAMESPACE_BEGIN
class SAXParser;
class XMLTranscoder;
XERCES_CPP_NAMESPACE_END
XERCES_CPP_NAMESPACE_USE
MTS_NAMESPACE_BEGIN
namespace xercesc = XERCES_CPP_NAMESPACE;
#ifdef _MSC_VER
// Disable warning 4275: non dll-interface used as base for dll-interface class
@ -76,13 +77,14 @@ private:
* \ingroup librender
* \ingroup libpython
*/
class MTS_EXPORT_RENDER SceneHandler : public HandlerBase {
class MTS_EXPORT_RENDER SceneHandler : public xercesc::HandlerBase {
public:
typedef std::map<std::string, ConfigurableObject *> NamedObjectMap;
typedef std::map<std::string, std::string, SimpleStringOrdering> ParameterMap;
SceneHandler(const SAXParser *parser, const ParameterMap &params,
NamedObjectMap *objects = NULL, bool isIncludedFile = false);
SceneHandler(const xercesc::SAXParser *parser,
const ParameterMap &params, NamedObjectMap *objects = NULL,
bool isIncludedFile = false);
virtual ~SceneHandler();
/// Convenience method -- load a scene from a given filename
@ -106,7 +108,7 @@ public:
virtual void endDocument();
virtual void startElement(
const XMLCh* const name,
AttributeList& attributes
xercesc::AttributeList& attributes
);
virtual void endElement(const XMLCh* const name);
virtual void characters(const XMLCh* const chars, const XMLSize_t length);
@ -117,16 +119,12 @@ public:
// -----------------------------------------------------------------------
// Implementation of the SAX ErrorHandler interface
// -----------------------------------------------------------------------
void warning(const SAXParseException& exc);
void error(const SAXParseException& exc);
void fatalError(const SAXParseException& exc);
void warning(const xercesc::SAXParseException& exc);
void error(const xercesc::SAXParseException& exc);
void fatalError(const xercesc::SAXParseException& exc);
protected:
inline std::string transcode(const XMLCh * const xmlName) const {
char *value = XMLString::transcode(xmlName);
std::string result(value);
XMLString::release(&value);
return result;
}
std::string transcode(const XMLCh * input) const;
Float parseFloat(const std::string &name, const std::string &str,
Float defVal = -1) const;
@ -163,7 +161,8 @@ private:
typedef std::pair<ETag, const Class *> TagEntry;
typedef boost::unordered_map<std::string, TagEntry> TagMap;
const SAXParser *m_parser;
const xercesc::SAXParser *m_parser;
xercesc::XMLTranscoder* m_transcoder;
ref<Scene> m_scene;
ParameterMap m_params;
NamedObjectMap *m_namedObjects;

View File

@ -261,6 +261,12 @@ public:
}
}
Float getRoughness(const Intersection &its, int component) const {
int bsdfIndex = m_indices[component].first;
component = m_indices[component].second;
return m_bsdfs[bsdfIndex]->getRoughness(its, component);
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) {
BSDF *bsdf = static_cast<BSDF *>(child);

View File

@ -230,6 +230,10 @@ public:
return result;
}
Float getRoughness(const Intersection &its, int component) const {
return m_nested->getRoughness(its, component);
}
std::string toString() const {
std::ostringstream oss;
oss << "BumpMap[" << endl

View File

@ -379,6 +379,11 @@ public:
return SmoothCoating::sample(bRec, pdf, sample);
}
Float getRoughness(const Intersection &its, int component) const {
return component < (int) m_components.size()
? m_nested->getRoughness(its, component) : (Float) 0;
}
std::string toString() const {
std::ostringstream oss;
oss << "SmoothCoating[" << endl

View File

@ -408,6 +408,12 @@ public:
}
}
Float getRoughness(const Intersection &its, int component) const {
/* For lack of a better value, treat this material as diffuse
in Manifold Exploration */
return std::numeric_limits<Float>::infinity();
}
std::string toString() const {
std::ostringstream oss;
oss << "HanrahanKrueger[" << endl

View File

@ -614,6 +614,12 @@ public:
return al / (4.0f * M_PI) * c1 * c2 / (c1 + c2);
}
Float getRoughness(const Intersection &its, int component) const {
/* For lack of a better value, treat this material as diffuse
in Manifold Exploration */
return std::numeric_limits<Float>::infinity();
}
std::string toString() const {
std::ostringstream oss;
oss << "IrawanClothBRDF[" << endl

View File

@ -218,6 +218,10 @@ public:
return result;
}
Float getRoughness(const Intersection &its, int component) const {
return m_nestedBSDF->getRoughness(its, component);
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "opacity")
m_opacity = static_cast<Texture *>(child);

View File

@ -285,6 +285,12 @@ public:
BSDF::addChild(name, child);
}
}
Float getRoughness(const Intersection &its, int component) const {
int bsdfIndex = m_indices[component].first;
component = m_indices[component].second;
return m_bsdfs[bsdfIndex]->getRoughness(its, component);
}
std::string toString() const {
std::ostringstream oss;
@ -418,7 +424,6 @@ public:
}
}
MTS_DECLARE_CLASS()
private:
std::vector<Shader *> m_bsdfShader;

View File

@ -263,6 +263,15 @@ public:
manager->serialize(stream, m_exponent.get());
}
Float getRoughness(const Intersection &its, int component) const {
Assert(component == 0 || component == 1);
/* Find the Beckmann-equivalent roughness */
if (component == 0)
return std::sqrt(2 / (2+m_exponent->eval(its).average()));
else
return std::numeric_limits<Float>::infinity();
}
std::string toString() const {
std::ostringstream oss;
oss << "Phong[" << endl

View File

@ -437,6 +437,12 @@ public:
return RoughCoating::sample(bRec, pdf, sample);
}
Float getRoughness(const Intersection &its, int component) const {
return component < (int) m_components.size()
? m_nested->getRoughness(its, component)
: m_alpha->eval(its).average();
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) {
if (m_nested != NULL)

View File

@ -505,7 +505,7 @@ public:
Assert(component == 0 || component == 1);
if (component == 0)
return m_alpha->getAverage().average();
return m_alpha->eval(its).average();
else
return std::numeric_limits<Float>::infinity();
}

View File

@ -1056,6 +1056,11 @@ void loadImage(ColladaContext &ctx, domImage &image) {
SLog(EDebug, "Converting texture \"%s\" ..", identifier.c_str());
std::string filename = cdom::uriToFilePath(image.getInit_from()->getValue().str());
/* Prevent Linux/OSX fs::path handling issues for DAE files created on Windows */
for (size_t i=0; i<filename.length(); ++i) {
if (filename[i] == '\\')
filename[i] = '/';
}
if (ctx.fileToId.find(filename) != ctx.fileToId.end()) {
ctx.idToTexture[identifier] = ctx.fileToId[filename];
return;
@ -1174,10 +1179,10 @@ void loadCamera(ColladaContext &ctx, Transform transform, domCamera &camera) {
ctx.os << "\t\t<transform name=\"toWorld\">" << endl;
ctx.os << "\t\t\t<matrix value=\"" << matrixValues.substr(0, matrixValues.length()-1) << "\"/>" << endl;
ctx.os << "\t\t</transform>" << endl << endl;
ctx.os << "\t\t<sampler id=\"sampler\" type=\"ldsampler\">" << endl;
ctx.os << "\t\t<sampler id=\"" << identifier << "_sampler\" type=\"ldsampler\">" << endl;
ctx.os << "\t\t\t<integer name=\"sampleCount\" value=\"4\"/>" << endl;
ctx.os << "\t\t</sampler>" << endl << endl;
ctx.os << "\t\t<film id=\"film\" type=\"" << ctx.cvt->m_filmType << "\">" << endl;
ctx.os << "\t\t<film id=\"" << identifier << "_film\" type=\"" << ctx.cvt->m_filmType << "\">" << endl;
ctx.os << "\t\t\t<integer name=\"width\" value=\"" << xres << "\"/>" << endl;
ctx.os << "\t\t\t<integer name=\"height\" value=\"" << (int) (xres/aspect) << "\"/>" << endl;
ctx.os << "\t\t\t<rfilter type=\"gaussian\"/>" << endl;

View File

@ -30,6 +30,12 @@ std::set<std::string> availableTextures;
void referenceTexture(GeometryConverter *cvt, std::ostream &os, const std::string &parameter,
const std::string &indent, const fs::path &textureDir, std::string filename) {
/* Prevent Linux/OSX fs::path handling issues for OBJ files created on Windows */
for (size_t i=0; i<filename.length(); ++i) {
if (filename[i] == '\\')
filename[i] = '/';
}
fs::path path = fs::path(filename);
fs::path targetPath = textureDir / path.filename();
std::string textureName = targetPath.filename().string();
@ -75,7 +81,7 @@ void addMaterial(GeometryConverter *cvt, std::ostream &os, const std::string &mt
const std::string &diffuseMap, const std::string maskMap) {
if (mtlName == "")
return;
SLog(EInfo, "Copying material \"%s\" ..", mtlName.c_str());
SLog(EInfo, "Importing material \"%s\" ..", mtlName.c_str());
std::string indent = "";
if (maskMap != "") {

View File

@ -178,7 +178,7 @@ public:
Spectrum *target = (Spectrum *) bitmap->getFloatData();
Spectrum value =
m_radiance * (2 * M_PI * (1-std::cos(m_theta))) *
static_cast<Float>(bitmap->getWidth() * bitmap->getHeight())
static_cast<Float>(bitmap->getWidth() * bitmap->getHeight())
/ (2 * M_PI * M_PI * nSamples);
for (size_t i=0; i<nSamples; ++i) {
@ -192,7 +192,7 @@ public:
std::min(std::max(0, (int) (sphCoords.azimuth * factor.x)), bitmap->getWidth()-1),
std::min(std::max(0, (int) (sphCoords.elevation * factor.y)), bitmap->getHeight()-1));
target[pos.x + pos.y * bitmap->getWidth()] += value / sinTheta;
target[pos.x + pos.y * bitmap->getWidth()] += value / std::max(1e-3f, sinTheta);
}
/* Instantiate a nested envmap plugin */

View File

@ -177,7 +177,7 @@ public:
Spectrum value =
sunRadiance * (2 * M_PI * (1-std::cos(theta))) *
static_cast<Float>(bitmap->getWidth() * bitmap->getHeight())
static_cast<Float>(bitmap->getWidth() * bitmap->getHeight())
/ (2 * M_PI * M_PI * nSamples);
for (size_t i=0; i<nSamples; ++i) {
@ -191,7 +191,7 @@ public:
std::min(std::max(0, (int) (sphCoords.azimuth * factor.x)), bitmap->getWidth()-1),
std::min(std::max(0, (int) (sphCoords.elevation * factor.y)), bitmap->getHeight()-1));
data[pos.x + pos.y * bitmap->getWidth()] += value / sinTheta;
data[pos.x + pos.y * bitmap->getWidth()] += value / std::max(1e-3f, sinTheta);
}
Log(EDebug, "Done (took %i ms)", timer->getMilliseconds());

View File

@ -204,6 +204,7 @@ public:
if (suitabilities.normalize() == 0) {
/* No mutator can handle this path -- give up */
accumulatedWeight += m_config.chainLength - it;
break;
}
mutatorIdx = (int) suitabilities.sample(m_indepSampler->next1D());

View File

@ -289,13 +289,15 @@ Float Path::miWeight(const Scene *scene, const Path &emitterSubpath,
for (int i=0; i<=s; ++i) {
const PathVertex *v = emitterSubpath.vertex(i);
connectable[pos] = v->isConnectable();
isNull[pos++] = v->isNullInteraction();
isNull[pos] = v->isNullInteraction() && !connectable[pos];
pos++;
}
for (int i=t; i>=0; --i) {
const PathVertex *v = sensorSubpath.vertex(i);
connectable[pos] = v->isConnectable();
isNull[pos++] = v->isNullInteraction();
isNull[pos] = v->isNullInteraction() && !connectable[pos];
pos++;
}
if (k <= 3)

View File

@ -41,11 +41,15 @@ StreamAppender::StreamAppender(const std::string &filename)
void StreamAppender::readLog(std::string &target) {
Assert(m_isFile);
std::fstream &stream = * ((std::fstream *) m_stream);
if (!stream.good()) {
target = "";
return;
}
stream.flush();
stream.seekg(0, std::ios::end);
std::streamoff size = stream.tellg();
if (size == 0) {
target.clear();
if (stream.fail() || size == 0) {
target = "";
return;
}
target.resize((size_t) size);
@ -62,7 +66,7 @@ void StreamAppender::readLog(std::string &target) {
void StreamAppender::append(ELogLevel level, const std::string &text) {
/* Insert a newline if the last message was a progress message */
if (m_lastMessageWasProgress && !m_isFile)
std::cout << endl;
(*m_stream) << endl;
(*m_stream) << text << endl;
m_lastMessageWasProgress = false;
}
@ -70,8 +74,8 @@ void StreamAppender::append(ELogLevel level, const std::string &text) {
void StreamAppender::logProgress(Float progress, const std::string &name,
const std::string &formatted, const std::string &eta, const void *ptr) {
if (!m_isFile) {
std::cout << formatted;
std::cout.flush();
(*m_stream) << formatted;
m_stream->flush();
}
m_lastMessageWasProgress = true;
}

View File

@ -23,6 +23,7 @@
# include <unistd.h>
#else
# include <windows.h>
# include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
#endif
MTS_NAMESPACE_BEGIN
@ -359,5 +360,28 @@ bool FileStream::canWrite() const {
return d->write;
}
#if defined(__WINDOWS__)
static boost::filesystem::detail::utf8_codecvt_facet *__facet = NULL;
#endif
void FileStream::staticInitialization() {
#if defined(__WINDOWS__)
/* On Linux + MacOS, strings are assumed to be in UTF-8. On
Windows, they still are, but fs::path is UTF-16. So we need
a codecvt_facet to take care of the necessary conversions */
std::locale global_loc = std::locale();
__facet = new boost::filesystem::detail::utf8_codecvt_facet();
std::locale locale(global_loc, __facet);
boost::filesystem::path::imbue(locale);
#endif
}
void FileStream::staticShutdown() {
#if defined(__WINDOWS__)
boost::filesystem::path::imbue(std::locale());
/* Can't delete __facet unfortunately, or we risk a crash .. oh well.. */
#endif
}
MTS_IMPLEMENT_CLASS(FileStream, false, Stream)
MTS_NAMESPACE_END

View File

@ -23,14 +23,19 @@
#if defined(Assert)
# undef Assert
#endif
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/util/TransService.hpp>
#include <mitsuba/render/scenehandler.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/render/scene.h>
#include <boost/algorithm/string.hpp>
MTS_NAMESPACE_BEGIN
XERCES_CPP_NAMESPACE_USE
#define TRANSCODE_BLOCKSIZE 2048
#if !defined(__OSX__)
#define XMLLog(level, fmt, ...) Thread::getThread()->getLogger()->log(\
@ -94,9 +99,15 @@ SceneHandler::SceneHandler(const SAXParser *parser,
m_tags["transform"] = TagEntry(ETransform, (Class *) NULL);
m_tags["include"] = TagEntry(EInclude, (Class *) NULL);
m_tags["alias"] = TagEntry(EAlias, (Class *) NULL);
XMLTransService::Codes failReason;
m_transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
"UTF-8", failReason, TRANSCODE_BLOCKSIZE);
}
SceneHandler::~SceneHandler() {
delete m_transcoder;
clear();
if (!m_isIncludedFile)
delete m_namedObjects;
@ -112,6 +123,28 @@ void SceneHandler::clear() {
}
}
std::string SceneHandler::transcode(const XMLCh * input) const {
XMLSize_t charsToBeConsumed = XMLString::stringLen(input);
char output[TRANSCODE_BLOCKSIZE + 4];
XMLSize_t totalCharsConsumed = 0;
std::string result;
while (totalCharsConsumed < charsToBeConsumed) {
XMLSize_t charsConsumed = 0;
XMLSize_t charsProduced = m_transcoder->transcodeTo(input,
std::min((XMLSize_t) 2048, charsToBeConsumed - totalCharsConsumed),
(XMLByte *) output, TRANSCODE_BLOCKSIZE, charsConsumed,
XMLTranscoder::UnRep_RepChar);
totalCharsConsumed += charsConsumed;
output[charsProduced] = '\0';
input += charsConsumed;
result += output;
}
return result;
}
// -----------------------------------------------------------------------
// Implementation of the SAX DocumentHandler interface
// -----------------------------------------------------------------------

View File

@ -46,8 +46,6 @@ void Subsurface::setParent(ConfigurableObject *parent) {
if (std::find(m_shapes.begin(), m_shapes.end(), shape) == m_shapes.end()) {
m_shapes.push_back(shape);
}
} else {
Log(EError, "IsotropicDipole: Invalid child node!");
}
}

View File

@ -27,6 +27,7 @@
#include <mitsuba/core/sched_remote.h>
#include <mitsuba/core/sstream.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/appender.h>
#include <mitsuba/core/sshstream.h>
#include <mitsuba/core/shvector.h>
@ -43,6 +44,8 @@
#include <signal.h>
#endif
XERCES_CPP_NAMESPACE_USE
using namespace mitsuba;
void help() {
@ -402,6 +405,7 @@ int main(int argc, char **argv) {
Statistics::staticInitialization();
Thread::staticInitialization();
Logger::staticInitialization();
FileStream::staticInitialization();
Spectrum::staticInitialization();
Bitmap::staticInitialization();
Scheduler::staticInitialization();
@ -430,6 +434,7 @@ int main(int argc, char **argv) {
Scheduler::staticShutdown();
Bitmap::staticShutdown();
Spectrum::staticShutdown();
FileStream::staticShutdown();
Logger::staticShutdown();
Thread::staticShutdown();
Statistics::staticShutdown();

View File

@ -21,6 +21,7 @@
#include <mitsuba/core/sstream.h>
#include <mitsuba/core/statistics.h>
#include <mitsuba/core/sshstream.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/shvector.h>
#include <mitsuba/core/appender.h>
#include <mitsuba/core/version.h>
@ -389,6 +390,7 @@ int main(int argc, char **argv) {
Statistics::staticInitialization();
Thread::staticInitialization();
Logger::staticInitialization();
FileStream::staticInitialization();
Spectrum::staticInitialization();
Bitmap::staticInitialization();
Scheduler::staticInitialization();
@ -414,6 +416,7 @@ int main(int argc, char **argv) {
Scheduler::staticShutdown();
Bitmap::staticShutdown();
Spectrum::staticShutdown();
FileStream::staticShutdown();
Logger::staticShutdown();
Thread::staticShutdown();
Statistics::staticShutdown();

View File

@ -30,6 +30,7 @@
#include <mitsuba/core/shvector.h>
#include <mitsuba/core/statistics.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/version.h>
#include <mitsuba/core/appender.h>
#include <mitsuba/render/util.h>
@ -390,6 +391,7 @@ int mts_main(int argc, char **argv) {
Statistics::staticInitialization();
Thread::staticInitialization();
Logger::staticInitialization();
FileStream::staticInitialization();
Spectrum::staticInitialization();
Bitmap::staticInitialization();
Scheduler::staticInitialization();
@ -418,6 +420,7 @@ int mts_main(int argc, char **argv) {
Scheduler::staticShutdown();
Bitmap::staticShutdown();
Spectrum::staticShutdown();
FileStream::staticShutdown();
Logger::staticShutdown();
Thread::staticShutdown();
Statistics::staticShutdown();

View File

@ -81,7 +81,7 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;About Mitsuba&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Version MTS_VERSION&lt;br /&gt;Configuration flags: &lt;span style=&quot; font-family:'Courier New,courier';&quot;&gt;CONFIG_FLAGS&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased as well as biased techniques and contains heavy optimizations targeted towards current CPU architectures.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Copyright © 2010 Wenzel Jakob &amp;lt;&lt;a href=&quot;mailto:wenzel@cs.cornell.edu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;wenzel@cs.cornell.edu&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Copyright © 2012 Wenzel Jakob &amp;lt;&lt;a href=&quot;mailto:wenzel@cs.cornell.edu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;wenzel@cs.cornell.edu&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Licensed under the &lt;a href=&quot;http://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;GNU GPL, Version 3&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">

View File

@ -230,6 +230,8 @@ public:
}
};
#define QStringToUTF8(str) str.toUtf8().data()
inline QString fromFsPath(const fs::path &path) {
#if defined(__WINDOWS__)
# if defined(_MSC_VER) && _MSC_VER >= 1600
@ -237,7 +239,7 @@ inline QString fromFsPath(const fs::path &path) {
# endif
return QString(reinterpret_cast<const QChar*>(path.c_str()));
#else
return QString(path.c_str());
return QString::fromUtf8(path.c_str());
#endif
}
@ -245,7 +247,7 @@ inline fs::path toFsPath(const QString &str) {
#if defined(__WINDOWS__)
return fs::path(reinterpret_cast<const fs::path::value_type*>(str.constData()));
#else
return fs::path(qPrintable(str));
return fs::path(QStringToUTF8(str));
#endif
}

View File

@ -886,7 +886,7 @@ void GLWidget::paintGL() {
m_renderer->setDepthMask(true);
if (m_context == NULL) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
m_renderer->clear();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_renderer->setBlendMode(Renderer::EBlendAlpha);
m_renderer->blitTexture(m_logoTexture);
m_renderer->setBlendMode(Renderer::EBlendNone);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>353</width>
<height>273</height>
<width>358</width>
<height>282</height>
</rect>
</property>
<property name="windowTitle">
@ -234,9 +234,9 @@
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="linearButton">
<widget class="QRadioButton" name="sRGBButton">
<property name="text">
<string>Linear</string>
<string>sRGB</string>
</property>
<property name="checked">
<bool>true</bool>
@ -244,9 +244,12 @@
</widget>
</item>
<item>
<widget class="QRadioButton" name="sRGBButton">
<widget class="QRadioButton" name="linearButton">
<property name="text">
<string>sRGB</string>
<string>Linear</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>

View File

@ -37,7 +37,7 @@ public:
void append(ELogLevel level, const std::string &message) {
if (!m_ignoreMessages) {
emit textMessage(level, QString::fromLatin1(message.c_str()));
emit textMessage(level, QString::fromUtf8(message.c_str()));
if (level >= EWarn)
floodCheck();
}
@ -47,8 +47,8 @@ public:
const std::string &formatted, const std::string &eta,
const void *ptr) {
emit progressMessage((RenderJob *) ptr,
QString::fromLatin1(name.c_str()), (float) progress,
QString::fromLatin1(eta.c_str()));
QString::fromUtf8(name.c_str()), (float) progress,
QString::fromUtf8(eta.c_str()));
}
void floodCheck() {

View File

@ -23,6 +23,7 @@
#include <mitsuba/core/sched.h>
#include <mitsuba/core/plugin.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/appender.h>
#include <mitsuba/core/statistics.h>
#include <mitsuba/render/scenehandler.h>
@ -168,6 +169,7 @@ int main(int argc, char *argv[]) {
Statistics::staticInitialization();
Thread::staticInitialization();
Logger::staticInitialization();
FileStream::staticInitialization();
Thread::initializeOpenMP(getCoreCount());
Spectrum::staticInitialization();
Bitmap::staticInitialization();
@ -312,6 +314,7 @@ int main(int argc, char *argv[]) {
Scheduler::staticShutdown();
Bitmap::staticShutdown();
Spectrum::staticShutdown();
FileStream::staticShutdown();
Logger::staticShutdown();
Thread::staticShutdown();
Statistics::staticShutdown();

View File

@ -29,6 +29,8 @@
#include <mitsuba/core/fstream.h>
#include <boost/algorithm/string.hpp>
XERCES_CPP_NAMESPACE_USE
SceneLoader::SceneLoader(FileResolver *resolver, const fs::path &filename,
const std::map<std::string, std::string, SimpleStringOrdering> &parameters)
: Thread("load"), m_resolver(resolver), m_filename(fromFsPath(filename)),
@ -100,11 +102,11 @@ void SceneLoader::run() {
filePath = fs::absolute(filename).parent_path(),
baseName = filename.stem();
SLog(EInfo, "Parsing scene description from \"%s\" ..", qPrintable(m_filename));
SLog(EInfo, "Parsing scene description from \"%s\" ..", filename.string().c_str());
if (!fs::exists(filename))
SLog(EError, "Unable to load scene \"%s\": file not found!",
qPrintable(m_filename));
filename.string().c_str());
try {
parser->parse(filename.c_str());
@ -134,7 +136,7 @@ void SceneLoader::run() {
/* Also generate a DOM representation for the Qt-based GUI */
QFile file(m_filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
Log(EError, "Unable to open the file \"%s\"", qPrintable(m_filename));
Log(EError, "Unable to open the file \"%s\"", filename.string().c_str());
QString errorMsg;
int line, column;
if (!m_result->doc.setContent(&file, &errorMsg, &line, &column))

View File

@ -86,7 +86,7 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
if (backupFilename.endsWith(".xml", Qt::CaseInsensitive))
backupFilename.replace(backupFilename.length()-4, 4, ".bak");
SLog(EInfo, "Saving a backup copy of \"%s\" as \"%s\"",
qPrintable(filename), qPrintable(backupFilename));
QStringToUTF8(filename), QStringToUTF8(backupFilename));
QFile file(filename), backupFile(backupFilename);
if (backupFile.exists())
@ -97,7 +97,7 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
if (!file.open(QIODevice::ReadOnly))
SLog(EError, "Unable to open \"%s\" with read access -- stopping "
"the upgrade operation.", qPrintable(filename));
"the upgrade operation.", QStringToUTF8(filename));
QByteArray inputArray = file.readAll(), outputArray;
file.close();
@ -119,7 +119,7 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
QFile trafoFile(trafoFilename);
if (!trafoFile.open(QIODevice::ReadOnly | QIODevice::Text))
SLog(EError, "Unable to open the stylesheet \"%s\" -- stopping "
"the upgrade operation.", qPrintable(trafoFilename));
"the upgrade operation.", QStringToUTF8(trafoFilename));
QXmlQuery query(QXmlQuery::XSLT20);
query.setMessageHandler(&handler);
@ -127,7 +127,7 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
query.setQuery(&trafoFile);
if (!query.isValid())
SLog(EError, "Unable to parse the stylesheet \"%s\" -- stopping "
"the upgrade operation.", qPrintable(trafoFilename));
"the upgrade operation.", QStringToUTF8(trafoFilename));
SLog(EInfo, "Transformation is ready, running it now..");
QXmlFormatter formatter(query, &outputBuffer);
@ -152,11 +152,11 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
/* Done, write back to disk */
SLog(EInfo, "Successfully applied %i transformations, writing the result "
"to \"%s\" ..", nTransformations, qPrintable(filename));
"to \"%s\" ..", nTransformations, QStringToUTF8(filename));
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
SLog(EError, "Unable to open \"%s\" with write access -- stopping "
"the upgrade operation.", qPrintable(filename));
"the upgrade operation.", QStringToUTF8(filename));
}
int line, column;
@ -164,7 +164,7 @@ void UpgradeManager::performUpgrade(const QString &filename, const Version &vers
QDomDocument doc;
if (!doc.setContent(inputArray, &errorMsg, &line, &column))
SLog(EError, "Unable to parse file: error %s at line %i, colum %i",
qPrintable(errorMsg), line, column);
QStringToUTF8(errorMsg), line, column);
QDomElement root = doc.documentElement();
/* Search for include nodes */

View File

@ -377,13 +377,25 @@ public:
Texture *loadTexture(const FileResolver *fileResolver,
std::map<std::string, Texture *> &cache,
const fs::path &mtlPath, const std::string &filename) {
const fs::path &mtlPath, std::string filename) {
/* Prevent Linux/OSX fs::path handling issues for DAE files created on Windows */
for (size_t i=0; i<filename.length(); ++i) {
if (filename[i] == '\\')
filename[i] = '/';
}
if (cache.find(filename) != cache.end())
return cache[filename];
fs::path path = fileResolver->resolve(filename);
if (!fs::exists(path))
Log(EError, "Unable to find texture \"%s\" referenced from \"%s\"!",
path.string().c_str(), mtlPath.string().c_str());
if (!fs::exists(path)) {
path = fileResolver->resolve(fs::path(filename).filename());
if (!fs::exists(path)) {
Log(EWarn, "Unable to find texture \"%s\" referenced from \"%s\"!",
path.string().c_str(), mtlPath.string().c_str());
return new ConstantSpectrumTexture(Spectrum(0.0f));
}
}
Properties props("bitmap");
props.setString("filename", path.string());
ref<Texture> texture = static_cast<Texture *> (PluginManager::getInstance()->
@ -424,7 +436,7 @@ public:
if (mtlName != "")
addMaterial(mtlName, diffuse, specular, exponent, bump, mask, illum);
mtlName = trim(line.substr(7, line.length()-7));
mtlName = trim(line.substr(6, line.length()-6));
specular = new ConstantSpectrumTexture(Spectrum(0.0f));
diffuse = new ConstantSpectrumTexture(Spectrum(0.0f));