obj.cpp: handle convex n-gons (contributed by Fabrice Rousselle), shapeIndex feature

metadata
Wenzel Jakob 2014-05-19 11:15:14 +02:00
parent 89fd8c1d52
commit 4805fc570e
1 changed files with 30 additions and 25 deletions

View File

@ -52,15 +52,18 @@ MTS_NAMESPACE_BEGIN
* } * }
* \parameter{flipTexCoords}{\Boolean}{ * \parameter{flipTexCoords}{\Boolean}{
* Treat the vertical component of the texture as inverted? Most OBJ files use * Treat the vertical component of the texture as inverted? Most OBJ files use
* this convention. \default{\code{true}, i.e. flip them to get the * this convention. \default{\code{true}}
* correct coordinates}.
* } * }
* \parameter{toWorld}{\Transform\Or\Animation}{ * \parameter{toWorld}{\Transform\Or\Animation}{
* Specifies an optional linear object-to-world transformation. * Specifies an optional linear object-to-world transformation.
* \default{none (i.e. object space $=$ world space)} * \default{none (i.e. object space $=$ world space)}
* } * }
* \parameter{shapeIndex}{\Integer}{
* When the file contains multiple meshes, this parameter can
* be used to select a single one. \default{\code{-1}, \mbox{i.e. load all}}
* }
* \parameter{collapse}{\Boolean}{ * \parameter{collapse}{\Boolean}{
* Collapse all contained meshes into a single object \default{\code{false}} * Collapse all meshes into a single shape \default{\code{false}}
* } * }
* } * }
* \renderings{ * \renderings{
@ -134,7 +137,6 @@ MTS_NAMESPACE_BEGIN
* valid vertex normals). * valid vertex normals).
* *
* \remarks{ * \remarks{
* \item The plugin currently only supports loading meshes constructed from triangles and quadrilaterals.
* \item Importing geometry via OBJ files should only be used as an absolutely * \item Importing geometry via OBJ files should only be used as an absolutely
* last resort. Due to inherent limitations of this format, the files tend to be unreasonably * last resort. Due to inherent limitations of this format, the files tend to be unreasonably
* large, and parsing them requires significant amounts of memory and processing power. What's worse * large, and parsing them requires significant amounts of memory and processing power. What's worse
@ -205,6 +207,9 @@ public:
/* Causes all texture coordinates to be vertically flipped */ /* Causes all texture coordinates to be vertically flipped */
bool flipTexCoords = props.getBoolean("flipTexCoords", true); bool flipTexCoords = props.getBoolean("flipTexCoords", true);
/// When the file contains multiple meshes, this index specifies which one to load
int shapeIndex = props.getInteger("shapeIndex", -1);
/* Object-space -> World-space transformation */ /* Object-space -> World-space transformation */
Transform objectToWorld = props.getTransform("toWorld", Transform()); Transform objectToWorld = props.getTransform("toWorld", Transform());
@ -226,7 +231,7 @@ public:
std::set<std::string> geomNames; std::set<std::string> geomNames;
std::vector<Vertex> vertexBuffer; std::vector<Vertex> vertexBuffer;
fs::path materialLibrary; fs::path materialLibrary;
int geomIdx = 0; int geomIndex = 0;
bool nameBeforeGeometry = false; bool nameBeforeGeometry = false;
std::string materialName; std::string materialName;
@ -260,8 +265,9 @@ public:
if (triangles.size() > 0) { if (triangles.size() > 0) {
/// make sure that we have unique names /// make sure that we have unique names
if (geomNames.find(targetName) != geomNames.end()) if (geomNames.find(targetName) != geomNames.end())
targetName = formatString("%s_%i", targetName.c_str(), geomIdx++); targetName = formatString("%s_%i", targetName.c_str(), geomIndex++);
geomNames.insert(targetName); geomNames.insert(targetName);
if (shapeIndex < 0 || geomIndex-1 == shapeIndex)
createMesh(targetName, vertices, normals, texcoords, createMesh(targetName, vertices, normals, texcoords,
triangles, materialName, objectToWorld, vertexBuffer); triangles, materialName, objectToWorld, vertexBuffer);
triangles.clear(); triangles.clear();
@ -271,11 +277,12 @@ public:
name = newName; name = newName;
} else if (buf == "usemtl") { } else if (buf == "usemtl") {
/* Flush if necessary */ /* Flush if necessary */
if (triangles.size() > 0) { if (triangles.size() > 0 && !m_collapse) {
/// make sure that we have unique names /// make sure that we have unique names
if (geomNames.find(name) != geomNames.end()) if (geomNames.find(name) != geomNames.end())
name = formatString("%s_%i", name.c_str(), geomIdx++); name = formatString("%s_%i", name.c_str(), geomIndex++);
geomNames.insert(name); geomNames.insert(name);
if (shapeIndex < 0 || geomIndex-1 == shapeIndex)
createMesh(name, vertices, normals, texcoords, createMesh(name, vertices, normals, texcoords,
triangles, materialName, objectToWorld, vertexBuffer); triangles, materialName, objectToWorld, vertexBuffer);
triangles.clear(); triangles.clear();
@ -298,25 +305,23 @@ public:
iss >> tmp; parse(t, 1, tmp); iss >> tmp; parse(t, 1, tmp);
iss >> tmp; parse(t, 2, tmp); iss >> tmp; parse(t, 2, tmp);
triangles.push_back(t); triangles.push_back(t);
if (iss >> tmp) { /* Handle n-gons assuming a convex shape */
t.p[1] = t.p[0]; while (iss >> tmp) {
t.uv[1] = t.uv[0]; t.p[1] = t.p[2];
t.n[1] = t.n[0]; t.uv[1] = t.uv[2];
parse(t, 0, tmp); t.n[1] = t.n[2];
parse(t, 2, tmp);
triangles.push_back(t); triangles.push_back(t);
} }
if (iss >> tmp)
Log(EError, "Encountered an n-gon (with n>4)! Only "
"triangles and quads are supported by the OBJ loader.");
} else { } else {
/* Ignore */ /* Ignore */
} }
} }
if (geomNames.find(name) != geomNames.end()) if (geomNames.find(name) != geomNames.end())
/// make sure that we have unique names /// make sure that we have unique names
name = formatString("%s_%i", m_name.c_str(), geomIdx); name = formatString("%s_%i", m_name.c_str(), geomIndex);
if (shapeIndex < 0 || geomIndex-1 == shapeIndex)
createMesh(name, vertices, normals, texcoords, createMesh(name, vertices, normals, texcoords,
triangles, materialName, objectToWorld, vertexBuffer); triangles, materialName, objectToWorld, vertexBuffer);
@ -535,7 +540,7 @@ public:
bsdf->configure(); bsdf->configure();
if (bump) { if (bump) {
props = Properties("bump"); props = Properties("bumpmap");
ref<BSDF> bumpBSDF = static_cast<BSDF *> (PluginManager::getInstance()-> ref<BSDF> bumpBSDF = static_cast<BSDF *> (PluginManager::getInstance()->
createObject(MTS_CLASS(BSDF), props)); createObject(MTS_CLASS(BSDF), props));