Merge with upstream
commit
d49e89fb94
|
@ -1,5 +1,6 @@
|
|||
#!/bin/bash
|
||||
cp /opt/intel/composer_xe_*/compiler/lib/libiomp5.dylib Mitsuba.app/Contents/Frameworks
|
||||
install_name_tool -id @rpath/libiomp5.dylib Mitsuba.app/Contents/Frameworks/libiomp5.dylib
|
||||
find Mitsuba.app/Contents/MacOS/ Mitsuba.app/plugins -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
|
||||
find Mitsuba.app/Contents/Frameworks/libmitsuba-* -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
|
||||
find Mitsuba.app/python -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib
|
||||
|
|
|
@ -472,7 +472,7 @@ public:
|
|||
template <typename T> void readArray(T *array, size_t count);
|
||||
|
||||
/**
|
||||
* \brief Read a known-size array from the stream (uses partial template
|
||||
* \brief Read a known-size array from the stream (uses partial template
|
||||
* specialization to select a method appropriate to the data type)
|
||||
*/
|
||||
template <typename T, size_t N> inline void readArray(T (&arr)[N]) {
|
||||
|
@ -484,9 +484,9 @@ public:
|
|||
* specialization to select a method appropriate to the data type)
|
||||
*/
|
||||
template <typename T> void writeArray(const T *array, size_t count);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Write a known-size array to the stream (uses partial template
|
||||
* \brief Write a known-size array to the stream (uses partial template
|
||||
* specialization to select a method appropriate to the data type)
|
||||
*/
|
||||
template <typename T, size_t N> inline void writeArray(const T (&arr)[N]) {
|
||||
|
|
|
@ -141,7 +141,8 @@ protected:
|
|||
}
|
||||
|
||||
inline static void destruct(void *data) {
|
||||
delete static_cast<ValueType *>(data);
|
||||
if (data)
|
||||
delete static_cast<ValueType *>(data);
|
||||
}
|
||||
protected:
|
||||
detail::ThreadLocalBase m_base;
|
||||
|
|
|
@ -189,6 +189,13 @@ template <typename T> inline TVector1<T> normalize(const TVector1<T> &v) {
|
|||
return v / v.length();
|
||||
}
|
||||
|
||||
template <typename T> inline TVector1<T> normalizeStrict(const TVector1<T> &v, const char *errMsg) {
|
||||
Float length = v.length();
|
||||
if (length == 0)
|
||||
SLog(EError, "normalizeStrict(): %s", errMsg);
|
||||
return v / length;
|
||||
}
|
||||
|
||||
template <> inline TVector1<int> TVector1<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
|
@ -380,6 +387,13 @@ template <typename T> inline TVector2<T> normalize(const TVector2<T> &v) {
|
|||
return v / v.length();
|
||||
}
|
||||
|
||||
template <typename T> inline TVector2<T> normalizeStrict(const TVector2<T> &v, const char *errMsg) {
|
||||
Float length = v.length();
|
||||
if (length == 0)
|
||||
SLog(EError, "normalizeStrict(): %s", errMsg);
|
||||
return v / length;
|
||||
}
|
||||
|
||||
template <> inline TVector2<int> TVector2<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
|
@ -582,6 +596,13 @@ template <typename T> inline TVector3<T> normalize(const TVector3<T> &v) {
|
|||
return v / v.length();
|
||||
}
|
||||
|
||||
template <typename T> inline TVector3<T> normalizeStrict(const TVector3<T> &v, const char *errMsg) {
|
||||
Float length = v.length();
|
||||
if (length == 0)
|
||||
SLog(EError, "normalizeStrict(): %s", errMsg);
|
||||
return v / length;
|
||||
}
|
||||
|
||||
template <> inline TVector3<int> TVector3<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
|
@ -781,6 +802,13 @@ template <typename T> inline TVector4<T> normalize(const TVector4<T> &v) {
|
|||
return v / v.length();
|
||||
}
|
||||
|
||||
template <typename T> inline TVector4<T> normalizeStrict(const TVector4<T> &v, const char *errMsg) {
|
||||
Float length = v.length();
|
||||
if (length == 0)
|
||||
SLog(EError, "normalizeStrict(): %s", errMsg);
|
||||
return v / length;
|
||||
}
|
||||
|
||||
template <> inline TVector4<int> TVector4<int>::operator/(int s) const {
|
||||
#ifdef MTS_DEBUG
|
||||
if (s == 0)
|
||||
|
|
|
@ -101,6 +101,9 @@ public:
|
|||
/// Free the memory taken up by staticInitialization()
|
||||
static void staticShutdown();
|
||||
|
||||
/// Push a cleanup handler to be executed after loading the scene is done
|
||||
static void pushCleanupHandler(void (*cleanup)());
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implementation of the SAX DocumentHandler interface
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
@ -312,9 +312,10 @@ protected:
|
|||
|
||||
/**
|
||||
* \brief Reads the header information of a compressed file, returning
|
||||
* the version ID. This function assumes the stream is at the beginning
|
||||
* of the compressed file and leaves the stream located right after the
|
||||
* header.
|
||||
* the version ID.
|
||||
*
|
||||
* This function assumes the stream is at the beginning of the compressed
|
||||
* file and leaves the stream located right after the header.
|
||||
*/
|
||||
static short readHeader(Stream *stream);
|
||||
|
||||
|
|
|
@ -318,11 +318,11 @@ public:
|
|||
|
||||
Point2 sample(_sample);
|
||||
if (sampleSpecular && sampleNested) {
|
||||
if (sample.x > probSpecular) {
|
||||
if (sample.x < probSpecular) {
|
||||
sample.x /= probSpecular;
|
||||
} else {
|
||||
sample.x = (sample.x - probSpecular) / (1 - probSpecular);
|
||||
choseSpecular = false;
|
||||
} else {
|
||||
sample.x /= probSpecular;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -321,7 +321,7 @@ public:
|
|||
(1-Fi) * (1-m_specularSamplingWeight));
|
||||
|
||||
/* Importance sample wrt. the Fresnel reflectance */
|
||||
if (sample.x <= probSpecular) {
|
||||
if (sample.x < probSpecular) {
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDeltaReflection;
|
||||
bRec.wo = reflect(bRec.wi);
|
||||
|
@ -384,7 +384,7 @@ public:
|
|||
(1-Fi) * (1-m_specularSamplingWeight));
|
||||
|
||||
/* Importance sample wrt. the Fresnel reflectance */
|
||||
if (sample.x <= probSpecular) {
|
||||
if (sample.x < probSpecular) {
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDeltaReflection;
|
||||
bRec.wo = reflect(bRec.wi);
|
||||
|
|
|
@ -391,7 +391,7 @@ public:
|
|||
(probSpecular*m_specularSamplingWeight +
|
||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||
|
||||
if (sample.y <= probSpecular) {
|
||||
if (sample.y < probSpecular) {
|
||||
sample.y /= probSpecular;
|
||||
} else {
|
||||
sample.y = (sample.y - probSpecular) / (1 - probSpecular);
|
||||
|
|
|
@ -254,7 +254,7 @@ public:
|
|||
if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) {
|
||||
if (name == "reflectance" || name == "diffuseReflectance")
|
||||
m_reflectance = static_cast<Texture *>(child);
|
||||
if (name == "alpha")
|
||||
else if (name == "alpha")
|
||||
m_alpha = static_cast<Texture *>(child);
|
||||
else
|
||||
BSDF::addChild(name, child);
|
||||
|
|
|
@ -447,7 +447,7 @@ public:
|
|||
(probSpecular*m_specularSamplingWeight +
|
||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||
|
||||
if (sample.y <= probSpecular) {
|
||||
if (sample.y < probSpecular) {
|
||||
sample.y /= probSpecular;
|
||||
} else {
|
||||
sample.y = (sample.y - probSpecular) / (1 - probSpecular);
|
||||
|
|
|
@ -50,7 +50,7 @@ void PSSMLTSampler::serialize(Stream *stream, InstanceManager *manager) const {
|
|||
}
|
||||
|
||||
void PSSMLTSampler::configure() {
|
||||
m_logRatio = -std::log(m_s2/m_s1);
|
||||
m_logRatio = -math::fastlog(m_s2/m_s1);
|
||||
m_time = 0;
|
||||
m_largeStepTime = 0;
|
||||
m_largeStep = false;
|
||||
|
|
|
@ -133,22 +133,24 @@ struct ThreadLocalBase::ThreadLocalPrivate {
|
|||
/// Look up a TLS entry. The goal is to make this operation very fast!
|
||||
std::pair<void *, bool> get() {
|
||||
bool existed = true;
|
||||
void *data;
|
||||
|
||||
#if defined(__OSX__)
|
||||
PerThreadData *ptd = (PerThreadData *) pthread_getspecific(ptdLocal);
|
||||
#else
|
||||
PerThreadData *ptd = ptdLocal;
|
||||
#endif
|
||||
if(EXPECT_NOT_TAKEN(!ptd)) {
|
||||
throw std::runtime_error("null per-thread data");
|
||||
}
|
||||
if (EXPECT_NOT_TAKEN(!ptd))
|
||||
throw std::runtime_error("Internal error: call to ThreadLocalPrivate::get() "
|
||||
" precedes the construction of thread-specific data structures!");
|
||||
|
||||
void *data;
|
||||
/* This is an uncontended thread-local lock (i.e. not to worry) */
|
||||
boost::lock_guard<boost::recursive_mutex> guard(ptd->mutex);
|
||||
PerThreadData::key_iterator it = ptd->map.find(this);
|
||||
if (EXPECT_TAKEN(it != ptd->map.end())) {
|
||||
data = it->second.data;
|
||||
} else {
|
||||
/* This is the first access from this thread */
|
||||
TLSEntry entry;
|
||||
entry.data = data = constructFunctor();
|
||||
entry.destructFunctor = destructFunctor;
|
||||
|
|
|
@ -189,8 +189,8 @@ Transform Transform::glOrthographic(Float clipLeft, Float clipRight,
|
|||
}
|
||||
|
||||
Transform Transform::lookAt(const Point &p, const Point &t, const Vector &up) {
|
||||
Vector dir = normalize(t-p);
|
||||
Vector left = normalize(cross(up, dir));
|
||||
Vector dir = normalizeStrict(t-p, "lookAt(): 'origin' and 'target' coincide!");
|
||||
Vector left = normalizeStrict(cross(up, dir), "lookAt(): the forward and upward direction must be linearly independent!");
|
||||
Vector newUp = cross(dir, left);
|
||||
|
||||
Matrix4x4 result, inverse;
|
||||
|
|
|
@ -137,7 +137,7 @@ Point2 Warp::squareToStdNormal(const Point2 &sample) {
|
|||
}
|
||||
|
||||
Float Warp::squareToStdNormalPdf(const Point2 &pos) {
|
||||
return INV_TWOPI * std::exp(-(pos.x*pos.x + pos.y*pos.y)/2.0f);
|
||||
return INV_TWOPI * math::fastexp(-(pos.x*pos.x + pos.y*pos.y)/2.0f);
|
||||
}
|
||||
|
||||
static Float intervalToTent(Float sample) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/render/scene.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
@ -46,6 +47,10 @@ XERCES_CPP_NAMESPACE_USE
|
|||
level, NULL, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
typedef void (*CleanupFun) ();
|
||||
typedef boost::unordered_set<CleanupFun> CleanupSet;
|
||||
static PrimitiveThreadLocal<CleanupSet> __cleanup_tls;
|
||||
|
||||
SceneHandler::SceneHandler(const SAXParser *parser,
|
||||
const ParameterMap ¶ms, NamedObjectMap *namedObjects,
|
||||
bool isIncludedFile) : m_parser(parser), m_params(params),
|
||||
|
@ -155,6 +160,13 @@ void SceneHandler::startDocument() {
|
|||
|
||||
void SceneHandler::endDocument() {
|
||||
SAssert(m_scene != NULL);
|
||||
|
||||
/* Call cleanup handlers */
|
||||
CleanupSet &cleanup = __cleanup_tls.get();
|
||||
for (CleanupSet::iterator it = cleanup.begin();
|
||||
it != cleanup.end(); ++it)
|
||||
(*it)();
|
||||
cleanup.clear();
|
||||
}
|
||||
|
||||
void SceneHandler::characters(const XMLCh* const name,
|
||||
|
@ -247,6 +259,10 @@ void SceneHandler::startElement(const XMLCh* const xmlName,
|
|||
m_context.push(context);
|
||||
}
|
||||
|
||||
void SceneHandler::pushCleanupHandler(void (*cleanup)()) {
|
||||
__cleanup_tls.get().insert(cleanup);
|
||||
}
|
||||
|
||||
void SceneHandler::endElement(const XMLCh* const xmlName) {
|
||||
std::string name = transcode(xmlName);
|
||||
ParseContext &context = m_context.top();
|
||||
|
|
|
@ -260,6 +260,7 @@ void PerspectiveCamera::configure() {
|
|||
SLog(EError, "Could not parse the focal length (must be of the form "
|
||||
"<x>mm, where <x> is a positive integer)!");
|
||||
|
||||
m_properties.removeProperty("focalLength");
|
||||
setDiagonalFov(2 * 180/M_PI* std::atan(std::sqrt((Float) (36*36+24*24)) / (2*value)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ void TriMesh::loadCompressed(Stream *_stream, int index) {
|
|||
|
||||
if (stream->getByteOrder() != Stream::ELittleEndian)
|
||||
Log(EError, "Tried to unserialize a shape from a stream, "
|
||||
"which was not previously set to little endian byte order!");
|
||||
"which was not previously set to little endian byte order!");
|
||||
|
||||
const short version = readHeader(stream);
|
||||
|
||||
|
@ -305,7 +305,7 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version,
|
|||
+ sizeof(char) // Name
|
||||
+ 2*sizeof(uint64_t) // Number of vertices and triangles
|
||||
+ 3*sizeof(float) // One vertex
|
||||
+ 3*sizeof(uint32_t)); // One triange
|
||||
+ 3*sizeof(uint32_t)); // One triangle
|
||||
|
||||
if (streamSize >= minSize) {
|
||||
outOffsets.resize(count);
|
||||
|
@ -314,9 +314,8 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version,
|
|||
if (typeid(size_t) == typeid(uint64_t)) {
|
||||
stream->readArray(&outOffsets[0], count);
|
||||
} else {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
outOffsets[i] = static_cast<size_t>(stream->readSize());
|
||||
}
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
outOffsets[i] = stream->readSize();
|
||||
}
|
||||
} else {
|
||||
stream->seek(stream->getSize() - sizeof(uint32_t) * (count + 1));
|
||||
|
@ -325,7 +324,7 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version,
|
|||
stream->readArray(&outOffsets[0], count);
|
||||
} else {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
outOffsets[i] = stream->readUInt();
|
||||
outOffsets[i] = (size_t) stream->readUInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ public:
|
|||
Float eval(Float x) const {
|
||||
Float alpha = -1.0f / (2.0f * m_stddev*m_stddev);
|
||||
return std::max((Float) 0.0f,
|
||||
std::exp(alpha * x * x) -
|
||||
std::exp(alpha * m_radius * m_radius));
|
||||
math::fastexp(alpha * x * x) -
|
||||
math::fastexp(alpha * m_radius * m_radius));
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/render/scenehandler.h>
|
||||
#include <mitsuba/core/properties.h>
|
||||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
|
@ -211,16 +212,15 @@ public:
|
|||
private:
|
||||
|
||||
/**
|
||||
* Helper class for loading serialized meshes from the same file
|
||||
* Helper class for loading serialized meshes from the same file
|
||||
* repeatedly: it is common for scene to load multiple meshes from the same
|
||||
* file, most times even in ascending order. This class loads the mesh
|
||||
* file, most times even in ascending order. This class loads the mesh
|
||||
* offsets dictionary only once and keeps the stream open.
|
||||
*
|
||||
* Instances of this class are not thread safe.
|
||||
*/
|
||||
class MeshLoader {
|
||||
public:
|
||||
|
||||
MeshLoader(const fs::path& filePath) {
|
||||
m_fstream = new FileStream(filePath, FileStream::EReadOnly);
|
||||
m_fstream->setByteOrder(Stream::ELittleEndian);
|
||||
|
@ -264,6 +264,11 @@ private:
|
|||
&boost::make_shared<MeshLoader, const fs::path&>) {}
|
||||
};
|
||||
|
||||
/// Release all currently held offset caches / file streams
|
||||
static void flushCache() {
|
||||
m_cache.set(NULL);
|
||||
}
|
||||
|
||||
/// Loads the mesh from the thread-local file stream cache
|
||||
void loadCompressed(const fs::path& filePath, const int idx) {
|
||||
if (EXPECT_NOT_TAKEN(idx < 0)) {
|
||||
|
@ -276,6 +281,7 @@ private:
|
|||
if (EXPECT_NOT_TAKEN(cache == NULL)) {
|
||||
cache = new FileStreamCache();
|
||||
m_cache.set(cache);
|
||||
SceneHandler::pushCleanupHandler(&SerializedMesh::flushCache);
|
||||
}
|
||||
|
||||
boost::shared_ptr<MeshLoader> meshLoader = cache->get(filePath);
|
||||
|
@ -288,7 +294,6 @@ private:
|
|||
|
||||
ThreadLocal<SerializedMesh::FileStreamCache> SerializedMesh::m_cache;
|
||||
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(SerializedMesh, false, TriMesh)
|
||||
MTS_EXPORT_PLUGIN(SerializedMesh, "Serialized mesh loader");
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
|
||||
if (m_type == Properties::EFloat)
|
||||
m_float = props.getFloat("value");
|
||||
else if (m_type == Properties::EPoint)
|
||||
else if (m_type == Properties::EVector)
|
||||
m_vector = props.getVector("value");
|
||||
else if (m_type == Properties::ESpectrum)
|
||||
m_spectrum = props.getSpectrum("value");
|
||||
|
@ -72,7 +72,7 @@ public:
|
|||
m_type = stream->readInt();
|
||||
if (m_type == Properties::EFloat)
|
||||
m_float = stream->readFloat();
|
||||
else if (m_type == Properties::EPoint)
|
||||
else if (m_type == Properties::EVector)
|
||||
m_vector = Vector(stream);
|
||||
else if (m_type == Properties::ESpectrum)
|
||||
m_spectrum = Spectrum(stream);
|
||||
|
|
Loading…
Reference in New Issue