portal luminaire, support for adjustments when importing from COLLADA, bugfixes
parent
b8ff508576
commit
fa1789be6d
|
@ -409,7 +409,7 @@ if hasCollada:
|
|||
if env.has_key('COLLADALIB'):
|
||||
colladaEnv.Append(LIBS=env['COLLADALIB'])
|
||||
colladaConverter = colladaEnv.StaticObject('src/collada/converter.cpp')
|
||||
colladaEnv.Program('mtsimport', darwinStub + ['src/collada/main.cpp', colladaConverter])
|
||||
colladaEnv.Program('mtsimport', darwinStub + ['src/collada/main.cpp', colladaConverter] + resources)
|
||||
|
||||
if hasQt:
|
||||
qtEnv = mainEnv.Clone()
|
||||
|
@ -529,6 +529,7 @@ plugins += env.SharedLibrary('plugins/spot', ['src/luminaires/spot.cpp'])
|
|||
plugins += env.SharedLibrary('plugins/point', ['src/luminaires/point.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/collimated', ['src/luminaires/collimated.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/directional', ['src/luminaires/directional.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/portal', ['src/luminaires/portal.cpp'])
|
||||
|
||||
# Integrators
|
||||
plugins += env.SharedLibrary('plugins/direct', ['src/integrators/direct/direct.cpp'])
|
||||
|
|
|
@ -133,10 +133,11 @@ Passing strings is very straightforward:
|
|||
\end{xml}
|
||||
\subsubsection{Color spectra}
|
||||
There are several different ways of passing color spectra to objects, which can be used interchangeably.
|
||||
The most basic one is to supply linear RGB values as floating-point triplets or hex values
|
||||
The most basic one is to supply linear RGB or sRGB values as floating-point triplets or hex values
|
||||
\begin{xml}
|
||||
<rgb name="spectrumProperty" value="0.2, 0.8, 0.4"/>
|
||||
<rgb name="spectrumProperty" value="#f9aa34"/>
|
||||
<srgb name="spectrumProperty" value="0.4, 0.3, 0.2"/>
|
||||
<srgb name="spectrumProperty" value="#f9aa34"/>
|
||||
\end{xml}
|
||||
When Mitsuba is compiled with the default settings, it internally uses linear RGB to represent colors, so
|
||||
these values are directly used. The renderer can also be configured to sample the color spectrum using a specified
|
||||
|
|
|
@ -216,7 +216,7 @@ public:
|
|||
* will be stored in <tt>eRec</tt>.
|
||||
*/
|
||||
void sampleEmissionArea(EmissionRecord &lRec, Point2 &sample) const;
|
||||
|
||||
|
||||
/**
|
||||
* As above, but handles only the directional part. Must be called *after*
|
||||
* sampleEmissionArea(). The return value is to be understood as a BRDF,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<xsd:element name="string" type="string"/>
|
||||
<xsd:element name="spectrum" type="string"/>
|
||||
<xsd:element name="rgb" type="string"/>
|
||||
<xsd:element name="srgb" type="string"/>
|
||||
<xsd:element name="blackbody" type="blackbody"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
@ -40,6 +41,7 @@
|
|||
<xsd:element name="string" type="string"/>
|
||||
<xsd:element name="spectrum" type="string"/>
|
||||
<xsd:element name="rgb" type="string"/>
|
||||
<xsd:element name="srgb" type="string"/>
|
||||
<xsd:element name="blackbody" type="blackbody"/>
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="type" type="xsd:string" use="required"/>
|
||||
|
@ -83,6 +85,7 @@
|
|||
<xsd:extension base="object">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="texture" type="object"/>
|
||||
<xsd:element name="luminaire" type="luminaire"/>
|
||||
</xsd:choice>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
|
@ -97,7 +100,7 @@
|
|||
<xsd:element name="bsdf" type="bsdf"/>
|
||||
<xsd:element name="subsurface" type="object"/>
|
||||
<xsd:element name="ref" type="reference"/>
|
||||
<xsd:element name="luminaire" type="object"/>
|
||||
<xsd:element name="luminaire" type="luminaire"/>
|
||||
</xsd:choice>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
|
|
|
@ -231,6 +231,18 @@ public:
|
|||
|
||||
return Spectrum(0.0f);
|
||||
}
|
||||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseReflectance") {
|
||||
m_diffuseReflectance = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
|
||||
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularReflectance") {
|
||||
m_specularReflectance = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
|
||||
} else {
|
||||
BSDF::addChild(name, child);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||
BSDF::serialize(stream, manager);
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
#define BOOST_FILESYSTEM_NO_LIB
|
||||
#define BOOST_SYSTEM_NO_LIB
|
||||
|
||||
#include <xercesc/dom/DOM.hpp>
|
||||
#include <xercesc/dom/DOMDocument.hpp>
|
||||
#include <xercesc/dom/DOMDocumentType.hpp>
|
||||
#include <xercesc/dom/DOMElement.hpp>
|
||||
#include <xercesc/dom/DOMImplementation.hpp>
|
||||
#include <xercesc/dom/DOMImplementationLS.hpp>
|
||||
#include <xercesc/dom/DOMNodeIterator.hpp>
|
||||
#include <xercesc/dom/DOMNodeList.hpp>
|
||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
#include <xercesc/framework/MemBufInputSource.hpp>
|
||||
#include <xercesc/framework/Wrapper4DOMInputSource.hpp>
|
||||
#include <xercesc/framework/Wrapper4InputSource.hpp>
|
||||
#include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||
#include <xercesc/util/XMLUni.hpp>
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <mitsuba/render/trimesh.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
|
@ -19,6 +33,8 @@
|
|||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
#include "converter.h"
|
||||
|
||||
typedef std::map<std::string, std::string> StringMap;
|
||||
|
@ -80,7 +96,87 @@ struct VertexData {
|
|||
delete[] glPos;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ImporterDOMErrorHandler : public DOMErrorHandler {
|
||||
public:
|
||||
inline ImporterDOMErrorHandler() { }
|
||||
|
||||
bool handleError(const DOMError& domError) {
|
||||
ELogLevel logLevel;
|
||||
|
||||
if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING)
|
||||
logLevel = EWarn;
|
||||
else
|
||||
logLevel = EError;
|
||||
|
||||
SLog(logLevel, "%s (line %i, char %i): %s",
|
||||
XMLString::transcode(domError.getLocation()->getURI()),
|
||||
domError.getLocation()->getLineNumber(),
|
||||
domError.getLocation()->getColumnNumber(),
|
||||
XMLString::transcode(domError.getMessage()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void findRemovals(DOMNode *node, std::set<std::string> &removals) {
|
||||
if (node) {
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE && node->hasAttributes()) {
|
||||
DOMNamedNodeMap *attributes = node->getAttributes();
|
||||
for (size_t i=0; i<attributes->getLength(); ++i) {
|
||||
DOMAttr *attribute = (DOMAttr*) attributes->item(i);
|
||||
char *name = XMLString::transcode(attribute->getName());
|
||||
char *value = XMLString::transcode(attribute->getValue());
|
||||
|
||||
if (strcmp(name, "id") == 0)
|
||||
removals.insert(value);
|
||||
|
||||
XMLString::release(&name);
|
||||
XMLString::release(&value);
|
||||
}
|
||||
}
|
||||
for (DOMNode *child = node->getFirstChild(); child != 0; child=child->getNextSibling())
|
||||
findRemovals(child, removals);
|
||||
}
|
||||
}
|
||||
|
||||
bool cleanupPass(DOMNode *node, const std::set<std::string> &removals) {
|
||||
if (node) {
|
||||
char *nodeName = XMLString::transcode(node->getNodeName());
|
||||
if (strcmp(nodeName, "ref") == 0) {
|
||||
XMLString::release(&nodeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE && node->hasAttributes()) {
|
||||
DOMNamedNodeMap *attributes = node->getAttributes();
|
||||
for (size_t i=0; i<attributes->getLength(); ++i) {
|
||||
DOMAttr *attribute = (DOMAttr*) attributes->item(i);
|
||||
char *name = XMLString::transcode(attribute->getName());
|
||||
char *value = XMLString::transcode(attribute->getValue());
|
||||
|
||||
if (strcmp(name, "id") == 0 && removals.find(value) != removals.end()) {
|
||||
XMLString::release(&name);
|
||||
XMLString::release(&value);
|
||||
return true; /* Remove this node */
|
||||
}
|
||||
|
||||
XMLString::release(&name);
|
||||
XMLString::release(&value);
|
||||
}
|
||||
XMLString::release(&nodeName);
|
||||
}
|
||||
DOMNode *child = node->getFirstChild();
|
||||
while (child) {
|
||||
DOMNode *next = child->getNextSibling();
|
||||
bool doRemove = cleanupPass(child, removals);
|
||||
if (doRemove)
|
||||
node->removeChild(child);
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This code is not thread-safe for now */
|
||||
GLUtesselator *tess = NULL;
|
||||
std::vector<domUint> tess_data;
|
||||
|
@ -383,7 +479,7 @@ void loadGeometry(std::string nodeName, Transform transform, std::ostream &os, d
|
|||
}
|
||||
}
|
||||
|
||||
void loadMaterialParam(std::ostream &os, const std::string &name, StringMap &idToTexture,
|
||||
void loadMaterialParam(ColladaConverter *cvt, std::ostream &os, const std::string &name, StringMap &idToTexture,
|
||||
domCommon_color_or_texture_type *value, bool handleRefs) {
|
||||
if (!value)
|
||||
return;
|
||||
|
@ -393,8 +489,11 @@ void loadMaterialParam(std::ostream &os, const std::string &name, StringMap &idT
|
|||
value->getTexture().cast();
|
||||
if (color && !handleRefs) {
|
||||
domFloat4 &colValue = color->getValue();
|
||||
os << "\t\t<rgb name=\"" << name << "\" value=\""
|
||||
<< colValue.get(0) << " " << colValue.get(1) << " "
|
||||
if (cvt->m_srgb)
|
||||
os << "\t\t<srgb name=\"" << name << "\" value=\"";
|
||||
else
|
||||
os << "\t\t<rgb name=\"" << name << "\" value=\"";
|
||||
os << colValue.get(0) << " " << colValue.get(1) << " "
|
||||
<< colValue.get(2) << "\"/>" << endl;
|
||||
} else if (texture && handleRefs) {
|
||||
if (idToTexture.find(texture->getTexture()) == idToTexture.end()) {
|
||||
|
@ -406,7 +505,7 @@ void loadMaterialParam(std::ostream &os, const std::string &name, StringMap &idT
|
|||
}
|
||||
}
|
||||
|
||||
void loadMaterialParam(std::ostream &os, const std::string &name, StringMap &,
|
||||
void loadMaterialParam(ColladaConverter *cvt, std::ostream &os, const std::string &name, StringMap &,
|
||||
domCommon_float_or_param_type *value, bool handleRef) {
|
||||
if (!value)
|
||||
return;
|
||||
|
@ -417,7 +516,7 @@ void loadMaterialParam(std::ostream &os, const std::string &name, StringMap &,
|
|||
}
|
||||
}
|
||||
|
||||
void loadMaterial(std::ostream &os, domMaterial &mat, StringMap &_idToTexture) {
|
||||
void loadMaterial(ColladaConverter *cvt, std::ostream &os, domMaterial &mat, StringMap &_idToTexture) {
|
||||
SLog(EInfo, "Converting material \"%s\" ..", mat.getName());
|
||||
StringMap idToTexture = _idToTexture;
|
||||
|
||||
|
@ -485,24 +584,24 @@ void loadMaterial(std::ostream &os, domMaterial &mat, StringMap &_idToTexture) {
|
|||
}
|
||||
if (isDiffuse) {
|
||||
os << "\t<bsdf id=\"" << mat.getId() << "\" type=\"lambertian\">" << endl;
|
||||
loadMaterialParam(os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(os, "reflectance", idToTexture, diffuse, true);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
} else {
|
||||
os << "\t<bsdf id=\"" << mat.getId() << "\" type=\"phong\">" << endl;
|
||||
loadMaterialParam(os, "diffuseReflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(os, "specularReflectance", idToTexture, specular, false);
|
||||
loadMaterialParam(os, "exponent", idToTexture, shininess, false);
|
||||
loadMaterialParam(os, "diffuseReflectance", idToTexture, diffuse, true);
|
||||
loadMaterialParam(os, "specularReflectance", idToTexture, specular, true);
|
||||
loadMaterialParam(os, "exponent", idToTexture, shininess, true);
|
||||
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, false);
|
||||
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, false);
|
||||
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, true);
|
||||
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, true);
|
||||
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
}
|
||||
} else if (lambert) {
|
||||
domCommon_color_or_texture_type* diffuse = lambert->getDiffuse();
|
||||
os << "\t<bsdf id=\"" << mat.getId() << "\" type=\"lambertian\">" << endl;
|
||||
loadMaterialParam(os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(os, "reflectance", idToTexture, diffuse, true);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "reflectance", idToTexture, diffuse, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
} else {
|
||||
SLog(EError, "Material type not supported! (must be Lambertian/Phong)");
|
||||
|
@ -670,8 +769,9 @@ void loadCamera(Transform transform, std::ostream &os, domCamera &camera) {
|
|||
os << "\t\t<transform name=\"toWorld\">" << endl;
|
||||
os << "\t\t\t<matrix value=\"" << matrixValues.substr(0, matrixValues.length()-1) << "\"/>" << endl;
|
||||
os << "\t\t</transform>" << endl << endl;
|
||||
|
||||
os << "\t\t<sampler type=\"stratified\"/>" << endl << endl;
|
||||
os << "\t\t<sampler type=\"ldsampler\">" << endl;
|
||||
os << "\t\t\t<integer name=\"sampleCount\" value=\"8\"/>" << endl;
|
||||
os << "\t\t</sampler>" << endl << endl;
|
||||
os << "\t\t<film type=\"exrfilm\">" << endl;
|
||||
os << "\t\t\t<integer name=\"width\" value=\"" << xres << "\"/>" << endl;
|
||||
os << "\t\t\t<integer name=\"height\" value=\"" << (int) (xres/aspect) << "\"/>" << endl;
|
||||
|
@ -876,8 +976,8 @@ void ColladaConverter::convert(const std::string &inputFile,
|
|||
|
||||
domNode_Array &nodes = visualScene->getNode_array();
|
||||
os << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl << endl;
|
||||
os << "<!--" << endl;
|
||||
os << "\tAutomatically converted from COLLADA" << endl;
|
||||
os << "<!--" << endl << endl;
|
||||
os << "\tAutomatically converted from COLLADA" << endl << endl;
|
||||
os << "-->" << endl << endl;
|
||||
os << "<scene>" << endl;
|
||||
os << "\t<integrator type=\"direct\"/>" << endl << endl;
|
||||
|
@ -896,7 +996,7 @@ void ColladaConverter::convert(const std::string &inputFile,
|
|||
for (size_t i=0; i<libraryMaterials.getCount(); ++i) {
|
||||
domMaterial_Array &materials = libraryMaterials[i]->getMaterial_array();
|
||||
for (size_t j=0; j<materials.getCount(); ++j)
|
||||
loadMaterial(os, *materials.get(j), idToTexture);
|
||||
loadMaterial(this, os, *materials.get(j), idToTexture);
|
||||
}
|
||||
|
||||
for (size_t i=0; i<nodes.getCount(); ++i)
|
||||
|
@ -906,11 +1006,72 @@ void ColladaConverter::convert(const std::string &inputFile,
|
|||
|
||||
gluDeleteTess(tess);
|
||||
delete dae;
|
||||
|
||||
if (adjustmentFile != "") {
|
||||
SLog(EInfo, "Applying adjustments ..");
|
||||
static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
|
||||
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
|
||||
DOMBuilder *parser = ((DOMImplementationLS*) impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
|
||||
|
||||
ImporterDOMErrorHandler errorHandler;
|
||||
parser->setErrorHandler(&errorHandler);
|
||||
|
||||
std::string xmlString = os.str();
|
||||
MemBufInputSource* memBufIS = new MemBufInputSource((const XMLByte*) xmlString.c_str(),
|
||||
xmlString.length(), "bufID", false);
|
||||
Wrapper4InputSource *wrapper = new Wrapper4InputSource(memBufIS, false);
|
||||
DOMDocument *doc = parser->parse(*wrapper);
|
||||
DOMDocument *adj = parser->parseURI(adjustmentFile.c_str());
|
||||
|
||||
std::ofstream ofile(outputFile.c_str());
|
||||
if (ofile.fail())
|
||||
SLog(EError, "Could not write to \"%s\"!", outputFile.c_str());
|
||||
ofile << os.str();
|
||||
ofile.close();
|
||||
std::set<std::string> removals;
|
||||
findRemovals(adj, removals);
|
||||
cleanupPass(doc, removals);
|
||||
|
||||
DOMElement *docRoot = doc->getDocumentElement();
|
||||
DOMElement *adjRoot = adj->getDocumentElement();
|
||||
|
||||
DOMNode *insertBeforeNode = NULL;
|
||||
for (DOMNode *child = docRoot->getFirstChild(); child != 0; child=child->getNextSibling()) {
|
||||
char *name = XMLString::transcode(child->getNodeName());
|
||||
if (strcmp(name, "shape") == 0) {
|
||||
insertBeforeNode = child;
|
||||
break;
|
||||
}
|
||||
XMLString::release(&name);
|
||||
}
|
||||
|
||||
if (insertBeforeNode == NULL) {
|
||||
/* No shape node found, use the camera node instead */
|
||||
for (DOMNode *child = docRoot->getFirstChild(); child != 0; child=child->getNextSibling()) {
|
||||
char *name = XMLString::transcode(child->getNodeName());
|
||||
if (strcmp(name, "camera") == 0) {
|
||||
insertBeforeNode = child;
|
||||
break;
|
||||
}
|
||||
XMLString::release(&name);
|
||||
}
|
||||
SAssertEx(insertBeforeNode != NULL, "Internal error while applying adjustments: cannot find shape/camera node");
|
||||
}
|
||||
|
||||
for (DOMNode *child = adjRoot->getFirstChild(); child != 0; child=child->getNextSibling())
|
||||
docRoot->insertBefore(doc->importNode(child, true), insertBeforeNode);
|
||||
|
||||
DOMWriter *serializer = ((DOMImplementationLS*)impl)->createDOMWriter();
|
||||
serializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
|
||||
serializer->setErrorHandler(&errorHandler);
|
||||
XMLFormatTarget *target = new LocalFileFormatTarget(outputFile.c_str());
|
||||
serializer->writeNode(target, *doc);
|
||||
|
||||
delete wrapper;
|
||||
delete memBufIS;
|
||||
delete serializer;
|
||||
parser->release();
|
||||
} else {
|
||||
std::ofstream ofile(outputFile.c_str());
|
||||
if (ofile.fail())
|
||||
SLog(EError, "Could not write to \"%s\"!", outputFile.c_str());
|
||||
ofile << os.str();
|
||||
ofile.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ using namespace mitsuba;
|
|||
|
||||
class ColladaConverter {
|
||||
public:
|
||||
inline ColladaConverter() { }
|
||||
inline ColladaConverter() {
|
||||
m_srgb = false;
|
||||
}
|
||||
|
||||
void convert(const std::string &inputFile,
|
||||
const std::string &outputDirectory,
|
||||
|
@ -12,4 +14,8 @@ public:
|
|||
const std::string &adjustmentFile);
|
||||
|
||||
virtual std::string locateResource(const std::string &resource) = 0;
|
||||
|
||||
void setSRGB(bool srgb) { m_srgb = srgb; }
|
||||
public:
|
||||
bool m_srgb;
|
||||
};
|
||||
|
|
|
@ -29,10 +29,14 @@
|
|||
* (e.g. using Lighting/shading -> Batch bake in Maya).
|
||||
*/
|
||||
|
||||
#include <xercesc/parsers/SAXParser.hpp>
|
||||
#include <xercesc/dom/DOMException.hpp>
|
||||
#include "converter.h"
|
||||
#include <mitsuba/hw/glrenderer.h>
|
||||
#include <mitsuba/core/fresolver.h>
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
class ConsoleColladaConverter : public ColladaConverter {
|
||||
public:
|
||||
inline ConsoleColladaConverter() {
|
||||
|
@ -43,21 +47,57 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void help() {
|
||||
cout << "COLLADA 1.4 Importer, Version " MTS_VERSION ", Copyright (c) " MTS_YEAR " Wenzel Jakob" << endl
|
||||
<< "Syntax: mtsimport [options] <DAE source file> <XML destination file> [Adjustment file]" << endl
|
||||
<< "Options/Arguments:" << endl
|
||||
<< " -h Display this help text" << endl << endl
|
||||
<< " -s Assume that colors are in sRGB space." << endl << endl
|
||||
<< "Please see the documentation for more information." << endl;
|
||||
}
|
||||
|
||||
int colladaMain(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
cout << "Syntax: mtsimport <DAE source file URL> <XML destination file> [Adjustment file]" << endl
|
||||
<< "Please see the documentation for more information." << endl;
|
||||
bool srgb = false;
|
||||
char optchar;
|
||||
|
||||
optind = 1;
|
||||
|
||||
while ((optchar = getopt(argc, argv, "sh")) != -1) {
|
||||
switch (optchar) {
|
||||
case 's':
|
||||
srgb = true;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
if (argc-optind < 2) {
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ConsoleColladaConverter converter;
|
||||
converter.convert(argv[1], "", argv[2], argc > 3 ? argv[3] : "");
|
||||
converter.setSRGB(srgb);
|
||||
converter.convert(argv[optind], "", argv[optind+1], argc > optind+2 ? argv[optind+2] : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ubi_main(int argc, char **argv) {
|
||||
int retval;
|
||||
|
||||
/* Initialize Xerces-C */
|
||||
try {
|
||||
XMLPlatformUtils::Initialize();
|
||||
} catch(const XMLException &toCatch) {
|
||||
fprintf(stderr, "Error during Xerces initialization: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize the core framework */
|
||||
Class::staticInitialization();
|
||||
Statistics::staticInitialization();
|
||||
|
@ -112,10 +152,20 @@ int ubi_main(int argc, char **argv) {
|
|||
} catch (const std::exception &e) {
|
||||
std::cerr << "Caught a critical exeption: " << e.what() << std::endl;
|
||||
retval = -1;
|
||||
} catch(const XMLException &toCatch) {
|
||||
SLog(EError, "Caught a Xerces exception: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
retval = -1;
|
||||
} catch(const DOMException &toCatch) {
|
||||
SLog(EError, "Caught a Xerces exception: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
retval = -1;
|
||||
} catch (...) {
|
||||
std::cerr << "Caught a critical exeption of unknown type!" << endl;
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
XMLPlatformUtils::Terminate();
|
||||
|
||||
/* Shutdown the core framework */
|
||||
Spectrum::staticShutdown();
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#include <mitsuba/render/scene.h>
|
||||
#include <mitsuba/hw/gpuprogram.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Portal luminaire -- can be used to turn a surface into a
|
||||
* portal that exposes luminaires behind it, such as an
|
||||
* environment map. This is often necessary to make interior
|
||||
* lighting work efficiently enough when using algorithms like
|
||||
* path tracing or photon mapping.
|
||||
*/
|
||||
class PortalLuminaire : public Luminaire {
|
||||
public:
|
||||
PortalLuminaire(const Properties &props) : Luminaire(props), m_shape(NULL) {
|
||||
AssertEx(m_luminaireToWorld.isIdentity(), "Error: non-identity transformation found. "
|
||||
"Portal luminaires inherit their transformation from the associated shape!");
|
||||
m_type = EDiffuseDirection | EOnSurface;
|
||||
m_intersectable = true;
|
||||
}
|
||||
|
||||
virtual ~PortalLuminaire() {
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
||||
m_luminaires[i]->decRef();
|
||||
}
|
||||
|
||||
PortalLuminaire(Stream *stream, InstanceManager *manager)
|
||||
: Luminaire(stream, manager) {
|
||||
m_shape = static_cast<Shape *>(manager->getInstance(stream));
|
||||
int luminaireCount = stream->readInt();
|
||||
for (int i=0; i<luminaireCount; ++i)
|
||||
addChild("", static_cast<Luminaire *>(manager->getInstance(stream)));
|
||||
configure();
|
||||
}
|
||||
|
||||
void preprocess(const Scene *scene) {
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
||||
m_luminaires[i]->preprocess(scene);
|
||||
configure();
|
||||
}
|
||||
|
||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||
Luminaire::serialize(stream, manager);
|
||||
|
||||
manager->serialize(stream, m_shape);
|
||||
stream->writeInt((int) m_luminaires.size());
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
||||
manager->serialize(stream, m_luminaires[i]);
|
||||
}
|
||||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
const Class *cClass = child->getClass();
|
||||
if (cClass->derivesFrom(Luminaire::m_theClass)) {
|
||||
Luminaire *luminaire = static_cast<Luminaire *>(child);
|
||||
m_luminaires.push_back(luminaire);
|
||||
luminaire->incRef();
|
||||
} else {
|
||||
Luminaire::addChild(name, child);
|
||||
}
|
||||
}
|
||||
|
||||
void setParent(ConfigurableObject *parent) {
|
||||
ConfigurableObject::setParent(parent);
|
||||
|
||||
if (parent->getClass()->derivesFrom(Shape::m_theClass)) {
|
||||
m_shape = static_cast<Shape *>(parent);
|
||||
parent->configure();
|
||||
m_surfaceArea = m_shape->getSurfaceArea();
|
||||
} else {
|
||||
Log(EError, "An portal light source must be child of a shape instance");
|
||||
}
|
||||
}
|
||||
|
||||
void configure() {
|
||||
m_power = Spectrum(0.0f);
|
||||
if (m_luminaires.size() == 0)
|
||||
Log(EError, "Portal luminaire must have one or more child luminaires!");
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i) {
|
||||
m_luminaires[i]->configure();
|
||||
m_power += m_luminaires[i]->getPower();
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum getPower() const {
|
||||
return m_power;
|
||||
}
|
||||
|
||||
Spectrum Le(const EmissionRecord &eRec) const {
|
||||
Spectrum result(0.0f);
|
||||
|
||||
if (dot(eRec.d, eRec.sRec.n) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
||||
result += m_luminaires[i]->Le(Ray(eRec.sRec.p, -eRec.d));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Spectrum Le(const LuminaireSamplingRecord &lRec) const {
|
||||
Spectrum result(0.0f);
|
||||
|
||||
if (dot(lRec.d, lRec.sRec.n) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
||||
result += m_luminaires[i]->Le(Ray(lRec.sRec.p, -lRec.d));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void sample(const Point &p, LuminaireSamplingRecord &lRec,
|
||||
const Point2 &sample) const {
|
||||
lRec.pdf = m_shape->sampleSolidAngle(lRec.sRec, p, sample);
|
||||
lRec.d = p - lRec.sRec.p;
|
||||
|
||||
if (EXPECT_TAKEN(lRec.pdf > 0 && dot(lRec.d, lRec.sRec.n) > 0)) {
|
||||
lRec.d = normalize(lRec.d);
|
||||
lRec.Le = Le(lRec);
|
||||
} else {
|
||||
lRec.pdf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void sample(const Intersection &its, LuminaireSamplingRecord &lRec,
|
||||
const Point2 &sample) const {
|
||||
PortalLuminaire::sample(its.p, lRec, sample);
|
||||
}
|
||||
|
||||
inline Float pdf(const Point &p, const LuminaireSamplingRecord &lRec) const {
|
||||
return m_shape->pdfSolidAngle(lRec.sRec, p);
|
||||
}
|
||||
|
||||
Float pdf(const Intersection &its, const LuminaireSamplingRecord &lRec) const {
|
||||
return pdf(its.p, lRec);
|
||||
}
|
||||
|
||||
void sampleEmission(EmissionRecord &eRec,
|
||||
const Point2 &sample1, const Point2 &sample2) const {
|
||||
eRec.pdfArea = m_shape->sampleArea(eRec.sRec, sample1);
|
||||
Vector wo = squareToHemispherePSA(sample2);
|
||||
eRec.pdfDir = Frame::cosTheta(wo) * INV_PI;
|
||||
eRec.d = Frame(eRec.sRec.n).toWorld(wo);
|
||||
eRec.P = Le(eRec);
|
||||
}
|
||||
|
||||
void sampleEmissionArea(EmissionRecord &eRec, const Point2 &sample) const {
|
||||
eRec.pdfArea = m_shape->sampleArea(eRec.sRec, sample);
|
||||
eRec.P = 1.0f;
|
||||
}
|
||||
|
||||
Spectrum fArea(const EmissionRecord &eRec) const {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
||||
Vector wo = squareToHemispherePSA(sample);
|
||||
eRec.d = Frame(eRec.sRec.n).toWorld(wo);
|
||||
eRec.pdfDir = Frame::cosTheta(wo) * INV_PI;
|
||||
return Le(eRec);
|
||||
}
|
||||
|
||||
Spectrum f(const EmissionRecord &eRec) const {
|
||||
Float dp = dot(eRec.sRec.n, eRec.d);
|
||||
if (dp > 0)
|
||||
return Le(eRec);
|
||||
else
|
||||
return Spectrum(0.0f);
|
||||
}
|
||||
|
||||
void pdfEmission(EmissionRecord &eRec) const {
|
||||
Float dp = dot(eRec.sRec.n, eRec.d);
|
||||
if (dp > 0)
|
||||
eRec.pdfDir = dp * INV_PI;
|
||||
else {
|
||||
eRec.pdfDir = 0;
|
||||
}
|
||||
eRec.pdfArea = m_shape->pdfArea(eRec.sRec);
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
return "PortalLuminaire[]";
|
||||
}
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
const Shape *m_shape;
|
||||
Spectrum m_power;
|
||||
std::vector<Luminaire *> m_luminaires;
|
||||
};
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(PortalLuminaire, false, Luminaire)
|
||||
MTS_EXPORT_PLUGIN(PortalLuminaire, "Portal luminaire");
|
||||
MTS_NAMESPACE_END
|
|
@ -236,6 +236,29 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
|||
specValue.fromLinearRGB(value[0], value[1], value[2]);
|
||||
context.parent->properties.setSpectrum(context.attributes["name"],
|
||||
specValue);
|
||||
} else if (name == "srgb") {
|
||||
std::string valueStr = context.attributes["value"];
|
||||
std::vector<std::string> tokens = tokenize(valueStr, ", ");
|
||||
Float value[3];
|
||||
if (tokens.size() == 1 && tokens[0].length() == 7 && tokens[0][0] == '#') {
|
||||
char *end_ptr = NULL;
|
||||
/* Parse HTML-style hexadecimal colors */
|
||||
int encoded = strtol(tokens[0].c_str()+1, &end_ptr, 16);
|
||||
if (*end_ptr != '\0')
|
||||
SLog(EError, "Invalid sRGB value specified (in <%s>)", context.attributes["name"].c_str());
|
||||
value[0] = ((encoded & 0xFF0000) >> 16) / 255.0f;
|
||||
value[1] = ((encoded & 0x00FF00) >> 8) / 255.0f;
|
||||
value[2] = (encoded & 0x0000FF) / 255.0f;
|
||||
} else {
|
||||
if (tokens.size() != 3)
|
||||
SLog(EError, "Invalid RGB value specified");
|
||||
for (int i=0; i<3; i++)
|
||||
value[i] = parseFloat(name, tokens[i]);
|
||||
}
|
||||
Spectrum specValue;
|
||||
specValue.fromSRGB(value[0], value[1], value[2]);
|
||||
context.parent->properties.setSpectrum(context.attributes["name"],
|
||||
specValue);
|
||||
} else if (name == "blackbody") {
|
||||
Float temperature = parseFloat(name, context.attributes["temperature"]);
|
||||
BlackBodySpectrum *spec = new BlackBodySpectrum(temperature);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <QtGui/QtGui>
|
||||
#include <xercesc/parsers/SAXParser.hpp>
|
||||
#include <QtGui/QtGui>
|
||||
#include <mitsuba/core/shvector.h>
|
||||
#include <mitsuba/core/sched.h>
|
||||
#if defined(__OSX__)
|
||||
|
|
Loading…
Reference in New Issue