summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerwincoumans <erwincoumans@google.com>2019-08-14 13:37:14 -0700
committerGitHub <noreply@github.com>2019-08-14 13:37:14 -0700
commit75df77611aaa3151ac857c7d8da97bae6bcc8261 (patch)
tree38c34997ae6df6e8378c9eb44af8b566f7ec4fd6
parent3301b46367ea174f866465ce2ff7e1863aaf4a91 (diff)
parenteacebc80d54fdb19152805901f51137b1ae48172 (diff)
downloadbullet3-75df77611aaa3151ac857c7d8da97bae6bcc8261.tar.gz
Merge pull request #2366 from fuchuyuan/tinyObjUpdate
update obj loader
-rw-r--r--Extras/obj2sdf/obj2sdf.cpp41
-rw-r--r--examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp26
-rw-r--r--examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp7
-rw-r--r--examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp14
-rw-r--r--examples/Importers/ImportObjDemo/LoadMeshFromObj.h2
-rw-r--r--examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp103
-rw-r--r--examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h2
-rw-r--r--examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp28
-rw-r--r--examples/SharedMemory/PhysicsServerCommandProcessor.cpp34
-rw-r--r--examples/ThirdPartyLibs/Wavefront/README.md143
-rw-r--r--examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp397
-rw-r--r--examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h43
12 files changed, 475 insertions, 365 deletions
diff --git a/Extras/obj2sdf/obj2sdf.cpp b/Extras/obj2sdf/obj2sdf.cpp
index b6a638c7f..8d3db3955 100644
--- a/Extras/obj2sdf/obj2sdf.cpp
+++ b/Extras/obj2sdf/obj2sdf.cpp
@@ -77,9 +77,10 @@ int main(int argc, char* argv[])
b3FileUtils::extractPath(fileNameWithPath, materialPrefixPath, MAX_PATH_LEN);
std::vector<tinyobj::shape_t> shapes;
+ tinyobj::attrib_t attribute;
b3BulletDefaultFileIO fileIO;
- std::string err = tinyobj::LoadObj(shapes, fileNameWithPath, materialPrefixPath,&fileIO);
+ std::string err = tinyobj::LoadObj(attribute, shapes, fileNameWithPath, materialPrefixPath,&fileIO);
char sdfFileName[MAX_PATH_LEN];
sprintf(sdfFileName, "%s%s.sdf", materialPrefixPath, "newsdf");
@@ -117,20 +118,20 @@ int main(int argc, char* argv[])
int curTexcoords = shapeC->texcoords.size() / 2;
int faceCount = shape.mesh.indices.size();
- int vertexCount = shape.mesh.positions.size();
+ int vertexCount = attribute.vertices.size();
for (int v = 0; v < vertexCount; v++)
{
- shapeC->positions.push_back(shape.mesh.positions[v]);
+ shapeC->positions.push_back(attribute.vertices[v]);
}
- int numNormals = int(shape.mesh.normals.size());
+ int numNormals = int(attribute.normals.size());
for (int vn = 0; vn < numNormals; vn++)
{
- shapeC->normals.push_back(shape.mesh.normals[vn]);
+ shapeC->normals.push_back(attribute.normals[vn]);
}
- int numTexCoords = int(shape.mesh.texcoords.size());
+ int numTexCoords = int(attribute.texcoords.size());
for (int vt = 0; vt < numTexCoords; vt++)
{
- shapeC->texcoords.push_back(shape.mesh.texcoords[vt]);
+ shapeC->texcoords.push_back(attribute.texcoords[vt]);
}
for (int face = 0; face < faceCount; face += 3)
@@ -140,9 +141,9 @@ int main(int argc, char* argv[])
continue;
}
- shapeC->indices.push_back(shape.mesh.indices[face] + curPositions);
- shapeC->indices.push_back(shape.mesh.indices[face + 1] + curPositions);
- shapeC->indices.push_back(shape.mesh.indices[face + 2] + curPositions);
+ shapeC->indices.push_back(shape.mesh.indices[face].vertex_index + curPositions);
+ shapeC->indices.push_back(shape.mesh.indices[face + 1].vertex_index + curPositions);
+ shapeC->indices.push_back(shape.mesh.indices[face + 2].vertex_index + curPositions);
}
}
}
@@ -329,7 +330,7 @@ int main(int argc, char* argv[])
}
int faceCount = shape.mesh.indices.size();
- int vertexCount = shape.mesh.positions.size();
+ int vertexCount = attribute.vertices.size();
tinyobj::material_t mat = shape.material;
if (shape.name.length())
{
@@ -339,7 +340,7 @@ int main(int argc, char* argv[])
}
for (int v = 0; v < vertexCount / 3; v++)
{
- fprintf(f, "v %f %f %f\n", shape.mesh.positions[v * 3 + 0], shape.mesh.positions[v * 3 + 1], shape.mesh.positions[v * 3 + 2]);
+ fprintf(f, "v %f %f %f\n", attribute.vertices[v * 3 + 0], attribute.vertices[v * 3 + 1], attribute.vertices[v * 3 + 2]);
}
if (mat.name.length())
@@ -352,18 +353,18 @@ int main(int argc, char* argv[])
}
fprintf(f, "\n");
- int numNormals = int(shape.mesh.normals.size());
+ int numNormals = int(attribute.normals.size());
for (int vn = 0; vn < numNormals / 3; vn++)
{
- fprintf(f, "vn %f %f %f\n", shape.mesh.normals[vn * 3 + 0], shape.mesh.normals[vn * 3 + 1], shape.mesh.normals[vn * 3 + 2]);
+ fprintf(f, "vn %f %f %f\n", attribute.normals[vn * 3 + 0], attribute.normals[vn * 3 + 1], attribute.normals[vn * 3 + 2]);
}
fprintf(f, "\n");
- int numTexCoords = int(shape.mesh.texcoords.size());
+ int numTexCoords = int(attribute.texcoords.size());
for (int vt = 0; vt < numTexCoords / 2; vt++)
{
- fprintf(f, "vt %f %f\n", shape.mesh.texcoords[vt * 2 + 0], shape.mesh.texcoords[vt * 2 + 1]);
+ fprintf(f, "vt %f %f\n", attribute.texcoords[vt * 2 + 0], attribute.texcoords[vt * 2 + 1]);
}
fprintf(f, "s off\n");
@@ -375,9 +376,9 @@ int main(int argc, char* argv[])
continue;
}
fprintf(f, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
- shape.mesh.indices[face] + 1, shape.mesh.indices[face] + 1, shape.mesh.indices[face] + 1,
- shape.mesh.indices[face + 1] + 1, shape.mesh.indices[face + 1] + 1, shape.mesh.indices[face + 1] + 1,
- shape.mesh.indices[face + 2] + 1, shape.mesh.indices[face + 2] + 1, shape.mesh.indices[face + 2] + 1);
+ shape.mesh.indices[face].vertex_index + 1, shape.mesh.indices[face].vertex_index + 1, shape.mesh.indices[face].vertex_index + 1,
+ shape.mesh.indices[face + 1].vertex_index + 1, shape.mesh.indices[face + 1].vertex_index + 1, shape.mesh.indices[face + 1].vertex_index + 1,
+ shape.mesh.indices[face + 2].vertex_index + 1, shape.mesh.indices[face + 2].vertex_index + 1, shape.mesh.indices[face + 2].vertex_index + 1);
}
fclose(f);
@@ -437,4 +438,4 @@ int main(int argc, char* argv[])
fclose(sdfFile);
return 0;
-} \ No newline at end of file
+}
diff --git a/examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp b/examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp
index d630f8599..f868bcb13 100644
--- a/examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp
+++ b/examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp
@@ -2265,7 +2265,7 @@ int BulletMJCFImporter::getBodyUniqueId() const
return m_data->m_activeBodyUniqueId;
}
-static btCollisionShape* MjcfCreateConvexHullFromShapes(std::vector<tinyobj::shape_t>& shapes, const btVector3& geomScale, btScalar collisionMargin)
+static btCollisionShape* MjcfCreateConvexHullFromShapes(const tinyobj::attrib_t& attribute, std::vector<tinyobj::shape_t>& shapes, const btVector3& geomScale, btScalar collisionMargin)
{
btCompoundShape* compound = new btCompoundShape();
compound->setMargin(collisionMargin);
@@ -2278,25 +2278,26 @@ static btCollisionShape* MjcfCreateConvexHullFromShapes(std::vector<tinyobj::sha
btConvexHullShape* convexHull = new btConvexHullShape();
convexHull->setMargin(collisionMargin);
tinyobj::shape_t& shape = shapes[s];
+
int faceCount = shape.mesh.indices.size();
for (int f = 0; f < faceCount; f += 3)
{
btVector3 pt;
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
}
@@ -2391,10 +2392,11 @@ class btCompoundShape* BulletMJCFImporter::convertLinkCollisionShapes(int linkIn
else
{
std::vector<tinyobj::shape_t> shapes;
- std::string err = tinyobj::LoadObj(shapes, col->m_geometry.m_meshFileName.c_str(),"",m_data->m_fileIO);
+ tinyobj::attrib_t attribute;
+ std::string err = tinyobj::LoadObj(attribute, shapes, col->m_geometry.m_meshFileName.c_str(), "", m_data->m_fileIO);
//create a convex hull for each shape, and store it in a btCompoundShape
- childShape = MjcfCreateConvexHullFromShapes(shapes, col->m_geometry.m_meshScale, m_data->m_globalDefaults.m_defaultCollisionMargin);
+ childShape = MjcfCreateConvexHullFromShapes(attribute, shapes, col->m_geometry.m_meshScale, m_data->m_globalDefaults.m_defaultCollisionMargin);
}
break;
}
diff --git a/examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp b/examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp
index b4e02243d..6f13d86b2 100644
--- a/examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp
+++ b/examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp
@@ -65,13 +65,14 @@ bool b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(const std::string&
btVector3 shift(0, 0, 0);
std::vector<tinyobj::shape_t> shapes;
+ tinyobj::attrib_t attribute;
{
B3_PROFILE("tinyobj::LoadObj");
- std::string err = LoadFromCachedOrFromObj(shapes, relativeFileName, pathPrefix,fileIO);
+ std::string err = LoadFromCachedOrFromObj(attribute, shapes, relativeFileName, pathPrefix, fileIO);
//std::string err = tinyobj::LoadObj(shapes, relativeFileName, pathPrefix);
}
- GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(shapes);
+ GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(attribute, shapes);
{
B3_PROFILE("Load Texture");
//int textureIndex = -1;
@@ -84,7 +85,7 @@ bool b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(const std::string&
meshData.m_rgbaColor[2] = shape.material.diffuse[2];
meshData.m_rgbaColor[3] = shape.material.transparency;
meshData.m_flags |= B3_IMPORT_MESH_HAS_RGBA_COLOR;
-
+
meshData.m_specularColor[0] = shape.material.specular[0];
meshData.m_specularColor[1] = shape.material.specular[1];
meshData.m_specularColor[2] = shape.material.specular[2];
diff --git a/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp b/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
index 566682d0a..e5bd6633c 100644
--- a/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
+++ b/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
@@ -12,6 +12,7 @@ struct CachedObjResult
{
std::string m_msg;
std::vector<tinyobj::shape_t> m_shapes;
+ tinyobj::attrib_t m_attribute;
};
static b3HashMap<b3HashString, CachedObjResult> gCachedObjResults;
@@ -31,24 +32,26 @@ void b3EnableFileCaching(int enable)
}
std::string LoadFromCachedOrFromObj(
+ tinyobj::attrib_t& attribute,
std::vector<tinyobj::shape_t>& shapes, // [output]
const char* filename,
const char* mtl_basepath,
- struct CommonFileIOInterface* fileIO
- )
+ struct CommonFileIOInterface* fileIO)
{
CachedObjResult* resultPtr = gCachedObjResults[filename];
if (resultPtr)
{
const CachedObjResult& result = *resultPtr;
shapes = result.m_shapes;
+ attribute = result.m_attribute;
return result.m_msg;
}
- std::string err = tinyobj::LoadObj(shapes, filename, mtl_basepath,fileIO);
+ std::string err = tinyobj::LoadObj(attribute, shapes, filename, mtl_basepath, fileIO);
CachedObjResult result;
result.m_msg = err;
result.m_shapes = shapes;
+ result.m_attribute = attribute;
if (gEnableFileCaching)
{
gCachedObjResults.insert(filename, result);
@@ -60,14 +63,15 @@ GLInstanceGraphicsShape* LoadMeshFromObj(const char* relativeFileName, const cha
{
B3_PROFILE("LoadMeshFromObj");
std::vector<tinyobj::shape_t> shapes;
+ tinyobj::attrib_t attribute;
{
B3_PROFILE("tinyobj::LoadObj2");
- std::string err = LoadFromCachedOrFromObj(shapes, relativeFileName, materialPrefixPath,fileIO);
+ std::string err = LoadFromCachedOrFromObj(attribute, shapes, relativeFileName, materialPrefixPath, fileIO);
}
{
B3_PROFILE("btgCreateGraphicsShapeFromWavefrontObj");
- GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(shapes);
+ GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(attribute, shapes);
return gfxShape;
}
}
diff --git a/examples/Importers/ImportObjDemo/LoadMeshFromObj.h b/examples/Importers/ImportObjDemo/LoadMeshFromObj.h
index 9b62074c1..54bc66312 100644
--- a/examples/Importers/ImportObjDemo/LoadMeshFromObj.h
+++ b/examples/Importers/ImportObjDemo/LoadMeshFromObj.h
@@ -8,8 +8,8 @@ struct GLInstanceGraphicsShape;
int b3IsFileCachingEnabled();
void b3EnableFileCaching(int enable);
-
std::string LoadFromCachedOrFromObj(
+ tinyobj::attrib_t& attribute,
std::vector<tinyobj::shape_t>& shapes, // [output]
const char* filename,
const char* mtl_basepath,
diff --git a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
index ead2769a0..08fa521ae 100644
--- a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
+++ b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
@@ -9,7 +9,7 @@
#include "../../OpenGLWindow/GLInstancingRenderer.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
-GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes, bool flatShading)
+GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(const tinyobj::attrib_t& attribute, std::vector<tinyobj::shape_t>& shapes, bool flatShading)
{
b3AlignedObjectArray<GLInstanceVertex>* vertices = new b3AlignedObjectArray<GLInstanceVertex>;
{
@@ -36,19 +36,20 @@ GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tiny
}
GLInstanceVertex vtx0;
- vtx0.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f] * 3 + 0];
- vtx0.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f] * 3 + 1];
- vtx0.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f] * 3 + 2];
+ tinyobj::index_t v_0 = shape.mesh.indices[f];
+ vtx0.xyzw[0] = attribute.vertices[3 * v_0.vertex_index];
+ vtx0.xyzw[1] = attribute.vertices[3 * v_0.vertex_index + 1];
+ vtx0.xyzw[2] = attribute.vertices[3 * v_0.vertex_index + 2];
vtx0.xyzw[3] = 0.f;
- if (shape.mesh.texcoords.size())
+ if (attribute.texcoords.size())
{
- int uv0Index = shape.mesh.indices[f] * 2 + 0;
- int uv1Index = shape.mesh.indices[f] * 2 + 1;
- if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < int(shape.mesh.texcoords.size()) && (uv1Index < shape.mesh.texcoords.size())))
+ int uv0Index = 2 * v_0.texcoord_index;
+ int uv1Index = 2 * v_0.texcoord_index + 1;
+ if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < int(attribute.texcoords.size()) && (uv1Index < attribute.texcoords.size())))
{
- vtx0.uv[0] = shape.mesh.texcoords[uv0Index];
- vtx0.uv[1] = shape.mesh.texcoords[uv1Index];
+ vtx0.uv[0] = attribute.texcoords[uv0Index];
+ vtx0.uv[1] = attribute.texcoords[uv1Index];
}
else
{
@@ -64,19 +65,20 @@ GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tiny
}
GLInstanceVertex vtx1;
- vtx1.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 0];
- vtx1.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 1];
- vtx1.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 2];
+ tinyobj::index_t v_1 = shape.mesh.indices[f + 1];
+ vtx1.xyzw[0] = attribute.vertices[3 * v_1.vertex_index];
+ vtx1.xyzw[1] = attribute.vertices[3 * v_1.vertex_index + 1];
+ vtx1.xyzw[2] = attribute.vertices[3 * v_1.vertex_index + 2];
vtx1.xyzw[3] = 0.f;
- if (shape.mesh.texcoords.size())
+ if (attribute.texcoords.size())
{
- int uv0Index = shape.mesh.indices[f + 1] * 2 + 0;
- int uv1Index = shape.mesh.indices[f + 1] * 2 + 1;
- if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < shape.mesh.texcoords.size()) && (uv1Index < shape.mesh.texcoords.size()))
+ int uv0Index = 2 * v_1.texcoord_index;
+ int uv1Index = 2 * v_1.texcoord_index + 1;
+ if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < attribute.texcoords.size()) && (uv1Index < attribute.texcoords.size()))
{
- vtx1.uv[0] = shape.mesh.texcoords[uv0Index];
- vtx1.uv[1] = shape.mesh.texcoords[uv1Index];
+ vtx1.uv[0] = attribute.texcoords[uv0Index];
+ vtx1.uv[1] = attribute.texcoords[uv1Index];
}
else
{
@@ -92,18 +94,20 @@ GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tiny
}
GLInstanceVertex vtx2;
- vtx2.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 0];
- vtx2.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 1];
- vtx2.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 2];
+ tinyobj::index_t v_2 = shape.mesh.indices[f + 2];
+ vtx2.xyzw[0] = attribute.vertices[3 * v_2.vertex_index];
+ vtx2.xyzw[1] = attribute.vertices[3 * v_2.vertex_index + 1];
+ vtx2.xyzw[2] = attribute.vertices[3 * v_2.vertex_index + 2];
vtx2.xyzw[3] = 0.f;
- if (shape.mesh.texcoords.size())
+ if (attribute.texcoords.size())
{
- int uv0Index = shape.mesh.indices[f + 2] * 2 + 0;
- int uv1Index = shape.mesh.indices[f + 2] * 2 + 1;
- if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < shape.mesh.texcoords.size()) && (uv1Index < shape.mesh.texcoords.size()))
+ int uv0Index = 2 * v_2.texcoord_index;
+ int uv1Index = 2 * v_2.texcoord_index + 1;
+
+ if (uv0Index >= 0 && uv1Index >= 0 && (uv0Index < attribute.texcoords.size()) && (uv1Index < attribute.texcoords.size()))
{
- vtx2.uv[0] = shape.mesh.texcoords[uv0Index];
- vtx2.uv[1] = shape.mesh.texcoords[uv1Index];
+ vtx2.uv[0] = attribute.texcoords[uv0Index];
+ vtx2.uv[1] = attribute.texcoords[uv1Index];
}
else
{
@@ -123,16 +127,21 @@ GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tiny
btVector3 v2(vtx2.xyzw[0], vtx2.xyzw[1], vtx2.xyzw[2]);
unsigned int maxIndex = 0;
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f] * 3 + 0);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f] * 3 + 1);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f] * 3 + 2);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 1] * 3 + 0);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 1] * 3 + 1);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 1] * 3 + 2);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 2] * 3 + 0);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 2] * 3 + 1);
- maxIndex = b3Max(maxIndex, shape.mesh.indices[f + 2] * 3 + 2);
- bool hasNormals = (shape.mesh.normals.size() && maxIndex < shape.mesh.normals.size());
+ unsigned n0Index = shape.mesh.indices[f].normal_index;
+ unsigned n1Index = shape.mesh.indices[f + 1].normal_index;
+ unsigned n2Index = shape.mesh.indices[f + 2].normal_index;
+
+ maxIndex = b3Max(maxIndex, 3 * n0Index + 0);
+ maxIndex = b3Max(maxIndex, 3 * n0Index + 1);
+ maxIndex = b3Max(maxIndex, 3 * n0Index + 2);
+ maxIndex = b3Max(maxIndex, 3 * n1Index + 0);
+ maxIndex = b3Max(maxIndex, 3 * n1Index + 1);
+ maxIndex = b3Max(maxIndex, 3 * n1Index + 2);
+ maxIndex = b3Max(maxIndex, 3 * n2Index + 0);
+ maxIndex = b3Max(maxIndex, 3 * n2Index + 1);
+ maxIndex = b3Max(maxIndex, 3 * n2Index + 2);
+
+ bool hasNormals = (attribute.normals.size() && maxIndex < attribute.normals.size());
if (flatShading || !hasNormals)
{
@@ -159,15 +168,15 @@ GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tiny
}
else
{
- vtx0.normal[0] = shape.mesh.normals[shape.mesh.indices[f] * 3 + 0];
- vtx0.normal[1] = shape.mesh.normals[shape.mesh.indices[f] * 3 + 1];
- vtx0.normal[2] = shape.mesh.normals[shape.mesh.indices[f] * 3 + 2]; //shape.mesh.indices[f+1]*3+0
- vtx1.normal[0] = shape.mesh.normals[shape.mesh.indices[f + 1] * 3 + 0];
- vtx1.normal[1] = shape.mesh.normals[shape.mesh.indices[f + 1] * 3 + 1];
- vtx1.normal[2] = shape.mesh.normals[shape.mesh.indices[f + 1] * 3 + 2];
- vtx2.normal[0] = shape.mesh.normals[shape.mesh.indices[f + 2] * 3 + 0];
- vtx2.normal[1] = shape.mesh.normals[shape.mesh.indices[f + 2] * 3 + 1];
- vtx2.normal[2] = shape.mesh.normals[shape.mesh.indices[f + 2] * 3 + 2];
+ vtx0.normal[0] = attribute.normals[3 * n0Index+ 0];
+ vtx0.normal[1] = attribute.normals[3 * n0Index+ 1];
+ vtx0.normal[2] = attribute.normals[3 * n0Index+ 2];
+ vtx1.normal[0] = attribute.normals[3 * n1Index+ 0];
+ vtx1.normal[1] = attribute.normals[3 * n1Index+ 1];
+ vtx1.normal[2] = attribute.normals[3 * n1Index+ 2];
+ vtx2.normal[0] = attribute.normals[3 * n2Index+ 0];
+ vtx2.normal[1] = attribute.normals[3 * n2Index+ 1];
+ vtx2.normal[2] = attribute.normals[3 * n2Index+ 2];
}
vertices->push_back(vtx0);
vertices->push_back(vtx1);
diff --git a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h
index 2840a85d7..4054b4dab 100644
--- a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h
+++ b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h
@@ -4,6 +4,6 @@
#include "../../ThirdPartyLibs/Wavefront/tiny_obj_loader.h"
#include <vector>
-struct GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes, bool flatShading = false);
+struct GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(const tinyobj::attrib_t& attribute, std::vector<tinyobj::shape_t>& shapes, bool flatShading = false);
#endif //WAVEFRONT2GRAPHICS_H
diff --git a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp
index f295458a8..16c85d0b5 100644
--- a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp
+++ b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp
@@ -509,7 +509,7 @@ bool BulletURDFImporter::getRootTransformInWorld(btTransform& rootTransformInWor
return true;
}
-static btCollisionShape* createConvexHullFromShapes(std::vector<tinyobj::shape_t>& shapes, const btVector3& geomScale, int flags)
+static btCollisionShape* createConvexHullFromShapes(const tinyobj::attrib_t& attribute, std::vector<tinyobj::shape_t>& shapes, const btVector3& geomScale, int flags)
{
B3_PROFILE("createConvexHullFromShapes");
btCompoundShape* compound = new btCompoundShape();
@@ -528,20 +528,20 @@ static btCollisionShape* createConvexHullFromShapes(std::vector<tinyobj::shape_t
for (int f = 0; f < faceCount; f += 3)
{
btVector3 pt;
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 2]);
convexHull->addPoint(pt * geomScale, false);
}
@@ -558,8 +558,6 @@ static btCollisionShape* createConvexHullFromShapes(std::vector<tinyobj::shape_t
return compound;
}
-
-
int BulletURDFImporter::getUrdfFromCollisionShape(const btCollisionShape* collisionShape, UrdfCollision& collision) const
{
UrdfCollision* col = m_data->m_bulletCollisionShape2UrdfCollision.find(collisionShape);
@@ -718,10 +716,10 @@ btCollisionShape* BulletURDFImporter::convertURDFToCollisionShape(const UrdfColl
else
{
std::vector<tinyobj::shape_t> shapes;
- std::string err = tinyobj::LoadObj(shapes, collision->m_geometry.m_meshFileName.c_str(),"",m_data->m_fileIO);
+ tinyobj::attrib_t attribute;
+ std::string err = tinyobj::LoadObj(attribute, shapes, collision->m_geometry.m_meshFileName.c_str(), "", m_data->m_fileIO);
//create a convex hull for each shape, and store it in a btCompoundShape
-
- shape = createConvexHullFromShapes(shapes, collision->m_geometry.m_meshScale, m_data->m_flags);
+ shape = createConvexHullFromShapes(attribute, shapes, collision->m_geometry.m_meshScale, m_data->m_flags);
m_data->m_bulletCollisionShape2UrdfCollision.insert(shape, *collision);
return shape;
}
diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
index b8e0275cd..961fc617a 100644
--- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
+++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp
@@ -4764,7 +4764,8 @@ bool PhysicsServerCommandProcessor::processCreateCollisionShapeCommand(const str
else
{
std::vector<tinyobj::shape_t> shapes;
- std::string err = tinyobj::LoadObj(shapes, out_found_filename.c_str(),"",fileIO);
+ tinyobj::attrib_t attribute;
+ std::string err = tinyobj::LoadObj(attribute, shapes, out_found_filename.c_str(), "", fileIO);
//shape = createConvexHullFromShapes(shapes, collision->m_geometry.m_meshScale);
//static btCollisionShape* createConvexHullFromShapes(std::vector<tinyobj::shape_t>& shapes, const btVector3& geomScale)
@@ -4785,20 +4786,20 @@ bool PhysicsServerCommandProcessor::processCreateCollisionShapeCommand(const str
for (int f = 0; f < faceCount; f += 3)
{
btVector3 pt;
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 0].vertex_index + 2]);
convexHull->addPoint(pt * meshScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 1] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 1].vertex_index + 2]);
convexHull->addPoint(pt * meshScale, false);
- pt.setValue(shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 0],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 1],
- shape.mesh.positions[shape.mesh.indices[f + 2] * 3 + 2]);
+ pt.setValue(attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 0],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 1],
+ attribute.vertices[3 * shape.mesh.indices[f + 2].vertex_index + 2]);
convexHull->addPoint(pt * meshScale, false);
}
@@ -7915,23 +7916,24 @@ bool PhysicsServerCommandProcessor::processLoadSoftBodyCommand(const struct Shar
std::string out_found_filename;
int out_type;
- bool foundFile = UrdfFindMeshFile(fileIO,pathPrefix, relativeFileName, error_message_prefix, &out_found_filename, &out_type);
+ bool foundFile = UrdfFindMeshFile(fileIO, pathPrefix, relativeFileName, error_message_prefix, &out_found_filename, &out_type);
std::vector<tinyobj::shape_t> shapes;
- std::string err = tinyobj::LoadObj(shapes, out_found_filename.c_str(),"",fileIO);
+ tinyobj::attrib_t attribute;
+ std::string err = tinyobj::LoadObj(attribute, shapes, out_found_filename.c_str(), "", fileIO);
if (!shapes.empty())
{
const tinyobj::shape_t& shape = shapes[0];
btAlignedObjectArray<btScalar> vertices;
btAlignedObjectArray<int> indices;
- for (int i = 0; i < shape.mesh.positions.size(); i++)
+ for (int i = 0; i < attribute.vertices.size(); i++)
{
- vertices.push_back(shape.mesh.positions[i]);
+ vertices.push_back(attribute.vertices[i]);
}
for (int i = 0; i < shape.mesh.indices.size(); i++)
{
- indices.push_back(shape.mesh.indices[i]);
+ indices.push_back(shape.mesh.indices[i].vertex_index);
}
- int numTris = indices.size() / 3;
+ int numTris = shape.mesh.indices.size() / 3;
if (numTris > 0)
{
btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(m_data->m_dynamicsWorld->getWorldInfo(), &vertices[0], &indices[0], numTris);
diff --git a/examples/ThirdPartyLibs/Wavefront/README.md b/examples/ThirdPartyLibs/Wavefront/README.md
index 6f911e523..de226acd3 100644
--- a/examples/ThirdPartyLibs/Wavefront/README.md
+++ b/examples/ThirdPartyLibs/Wavefront/README.md
@@ -38,51 +38,102 @@ Licensed under 2 clause BSD.
Usage
-----
+Data format
+attrib_t contains single and linear array of vertex data(position, normal and texcoord).
- std::string inputfile = "cornell_box.obj";
- std::vector<tinyobj::shape_t> shapes;
-
- std::string err = tinyobj::LoadObj(shapes, inputfile.c_str());
-
- if (!err.empty()) {
- std::cerr << err << std::endl;
- exit(1);
- }
-
- std::cout << "# of shapes : " << shapes.size() << std::endl;
-
- for (size_t i = 0; i < shapes.size(); i++) {
- printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
- printf("shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
- assert((shapes[i].mesh.indices.size() % 3) == 0);
- for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
- printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
- }
-
- printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
- assert((shapes[i].mesh.positions.size() % 3) == 0);
- for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
- printf(" v[%ld] = (%f, %f, %f)\n", v,
- shapes[i].mesh.positions[3*v+0],
- shapes[i].mesh.positions[3*v+1],
- shapes[i].mesh.positions[3*v+2]);
- }
-
- printf("shape[%ld].material.name = %s\n", i, shapes[i].material.name.c_str());
- printf(" material.Ka = (%f, %f ,%f)\n", shapes[i].material.ambient[0], shapes[i].material.ambient[1], shapes[i].material.ambient[2]);
- printf(" material.Kd = (%f, %f ,%f)\n", shapes[i].material.diffuse[0], shapes[i].material.diffuse[1], shapes[i].material.diffuse[2]);
- printf(" material.Ks = (%f, %f ,%f)\n", shapes[i].material.specular[0], shapes[i].material.specular[1], shapes[i].material.specular[2]);
- printf(" material.Tr = (%f, %f ,%f)\n", shapes[i].material.transmittance[0], shapes[i].material.transmittance[1], shapes[i].material.transmittance[2]);
- printf(" material.Ke = (%f, %f ,%f)\n", shapes[i].material.emission[0], shapes[i].material.emission[1], shapes[i].material.emission[2]);
- printf(" material.Ns = %f\n", shapes[i].material.shininess);
- printf(" material.map_Ka = %s\n", shapes[i].material.ambient_texname.c_str());
- printf(" material.map_Kd = %s\n", shapes[i].material.diffuse_texname.c_str());
- printf(" material.map_Ks = %s\n", shapes[i].material.specular_texname.c_str());
- printf(" material.map_Ns = %s\n", shapes[i].material.normal_texname.c_str());
- std::map<std::string, std::string>::iterator it(shapes[i].material.unknown_parameter.begin());
- std::map<std::string, std::string>::iterator itEnd(shapes[i].material.unknown_parameter.end());
- for (; it != itEnd; it++) {
- printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
- }
- printf("\n");
+attrib_t::vertices => 3 floats per vertex
+
+ v[0] v[1] v[2] v[3] v[n-1]
+ +-----------+-----------+-----------+-----------+ +-----------+
+ | x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+ +-----------+-----------+-----------+-----------+ +-----------+
+
+attrib_t::normals => 3 floats per vertex
+
+ n[0] n[1] n[2] n[3] n[n-1]
+ +-----------+-----------+-----------+-----------+ +-----------+
+ | x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+ +-----------+-----------+-----------+-----------+ +-----------+
+
+attrib_t::texcoords => 2 floats per vertex
+
+ t[0] t[1] t[2] t[3] t[n-1]
+ +-----------+-----------+-----------+-----------+ +-----------+
+ | u | v | u | v | u | v | u | v | .... | u | v |
+ +-----------+-----------+-----------+-----------+ +-----------+
+
+attrib_t::colors => 3 floats per vertex(vertex color. optional)
+
+ c[0] c[1] c[2] c[3] c[n-1]
+ +-----------+-----------+-----------+-----------+ +-----------+
+ | x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+ +-----------+-----------+-----------+-----------+ +-----------+
+
+Each shape_t::mesh_t does not contain vertex data but contains array index to attrib_t. See loader_example.cc for more details.
+
+
+mesh_t::indices => array of vertex indices.
+
+ +----+----+----+----+----+----+----+----+----+----+ +--------+
+ | i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-1) |
+ +----+----+----+----+----+----+----+----+----+----+ +--------+
+
+Each index has an array index to attrib_t::vertices, attrib_t::normals and attrib_t::texcoords.
+
+mesh_t::num_face_vertices => array of the number of vertices per face(e.g. 3 = triangle, 4 = quad , 5 or more = N-gons).
+
+
+ +---+---+---+ +---+
+ | 3 | 4 | 3 | ...... | 3 |
+ +---+---+---+ +---+
+ | | | |
+ | | | +-----------------------------------------+
+ | | | |
+ | | +------------------------------+ |
+ | | | |
+ | +------------------+ | |
+ | | | |
+ |/ |/ |/ |/
+
+ mesh_t::indices
+
+ | face[0] | face[1] | face[2] | | face[n-1] |
+ +----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
+ | i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-3) | i(n-2) | i(n-1) |
+ +----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
+
+```c++
+#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
+#include "tiny_obj_loader.h"
+
+std::string inputfile = "cornell_box.obj";
+tinyobj::attrib_t attrib;
+std::vector<tinyobj::shape_t> shapes;
+
+LoadObj(attrib, shapes, inputfile.c_str());
+
+// Loop over shapes
+for (size_t s = 0; s < shapes.size(); s++) {
+ // Loop over faces(polygon)
+ size_t index_offset = 0;
+ for (size_t f = 0; f < shapes[s].mesh.indices.size(); f++) {
+ int fv = 3;
+ // Loop over vertices in the face.
+ for (size_t v = 0; v < fv; v++) {
+ // access to vertex
+ tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
+ tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
+ tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
+ tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
+ tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
+ tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
+ tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
+ tinyobj::real_t tx = attrib.texcoords[2*idx.texcoord_index+0];
+ tinyobj::real_t ty = attrib.texcoords[2*idx.texcoord_index+1];
}
+ index_offset += fv;
+ }
+}
+
+```
+
diff --git a/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp b/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp
index 9cd2f2092..d1b9c6362 100644
--- a/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp
+++ b/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp
@@ -70,25 +70,6 @@ std::istream& safeGetline(std::istream& is, std::string& t)
}
}
#endif
-struct vertex_index
-{
- int v_idx, vt_idx, vn_idx, dummy;
-};
-struct MyIndices
-{
- int m_offset;
- int m_numIndices;
-};
-
-// for std::map
-static inline bool operator<(const vertex_index& a, const vertex_index& b)
-{
- if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx);
- if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx);
- if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx);
-
- return false;
-}
static inline bool isSpace(const char c)
{
@@ -101,25 +82,33 @@ static inline bool isNewLine(const char c)
}
// Make index zero-base, and also support relative index.
-static inline int fixIndex(int idx, int n)
+static inline bool fixIndex(int idx, int n, int* ret)
{
- int i;
+ if (!ret)
+ {
+ return false;
+ }
if (idx > 0)
{
- i = idx - 1;
+ (*ret) = idx - 1;
+ return true;
}
- else if (idx == 0)
+
+ if (idx == 0)
{
- i = 0;
+ // zero is not allowed according to the spec.
+ return false;
}
- else
- { // negative value = relative
- i = n + idx;
+
+ if (idx < 0)
+ {
+ (*ret) = n + idx; // negative value = relative
+ return true;
}
- return i;
-}
+ return false; // never reach here.
+}
static inline std::string parseString(const char*& token)
{
std::string s;
@@ -156,170 +145,184 @@ static inline void parseFloat3(
z = parseFloat(token);
}
-// Parse triples: i, i/j/k, i//k, i/j
-static vertex_index parseTriple(
- const char*& token,
- int vsize,
- int vnsize,
- int vtsize)
+// Parse triples with index offsets: i, i/j/k, i//k, i/j
+static bool parseTriple(const char** token, int vsize, int vnsize, int vtsize,
+ vertex_index_t* ret)
{
- vertex_index vi;
- vi.vn_idx = -1;
- vi.vt_idx = -1;
- vi.v_idx = -1;
-
- vi.v_idx = fixIndex(atoi(token), vsize);
- token += strcspn(token, "/ \t\r");
- if (token[0] != '/')
+ if (!ret)
{
- return vi;
+ return false;
}
- token++;
- // i//k
- if (token[0] == '/')
+ vertex_index_t vi(-1);
+
+ if (!fixIndex(atoi((*token)), vsize, &(vi.v_idx)))
{
- token++;
- vi.vn_idx = fixIndex(atoi(token), vnsize);
- token += strcspn(token, "/ \t\r");
- return vi;
+ return false;
}
- // i/j/k or i/j
- vi.vt_idx = fixIndex(atoi(token), vtsize);
- token += strcspn(token, "/ \t\r");
- if (token[0] != '/')
+ (*token) += strcspn((*token), "/ \t\r");
+ if ((*token)[0] != '/')
{
- return vi;
+ (*ret) = vi;
+ return true;
}
+ (*token)++;
- // i/j/k
- token++; // skip '/'
- vi.vn_idx = fixIndex(atoi(token), vnsize);
- token += strcspn(token, "/ \t\r");
- return vi;
-}
-
-static unsigned int
-updateVertex(
- std::map<vertex_index, unsigned int>& vertexCache,
- std::vector<float>& positions,
- std::vector<float>& normals,
- std::vector<float>& texcoords,
- const std::vector<float>& in_positions,
- const std::vector<float>& in_normals,
- const std::vector<float>& in_texcoords,
- const vertex_index& i)
-{
- const std::map<vertex_index, unsigned int>::iterator it = vertexCache.find(i);
-
- if (it != vertexCache.end())
+ // i//k
+ if ((*token)[0] == '/')
{
- // found cache
- return it->second;
+ (*token)++;
+ if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx)))
+ {
+ return false;
+ }
+ (*token) += strcspn((*token), "/ \t\r");
+ (*ret) = vi;
+ return true;
}
- assert(static_cast<int>(in_positions.size()) > (3 * i.v_idx + 2));
-
- positions.push_back(in_positions[3 * i.v_idx + 0]);
- positions.push_back(in_positions[3 * i.v_idx + 1]);
- positions.push_back(in_positions[3 * i.v_idx + 2]);
-
- if (i.vn_idx >= 0 && ((3 * i.vn_idx + 2) < in_normals.size()))
+ // i/j/k or i/j
+ if (!fixIndex(atoi((*token)), vtsize, &(vi.vt_idx)))
{
- normals.push_back(in_normals[3 * i.vn_idx + 0]);
- normals.push_back(in_normals[3 * i.vn_idx + 1]);
- normals.push_back(in_normals[3 * i.vn_idx + 2]);
+ return false;
}
- if (i.vt_idx >= 0)
+ (*token) += strcspn((*token), "/ \t\r");
+ if ((*token)[0] != '/')
{
- int numTexCoords = in_texcoords.size();
- int index0 = 2 * i.vt_idx + 0;
- int index1 = 2 * i.vt_idx + 1;
+ (*ret) = vi;
+ return true;
+ }
- if (index0 >= 0 && (index0) < numTexCoords)
- {
- texcoords.push_back(in_texcoords[index0]);
- }
- if (index1 >= 0 && (index1) < numTexCoords)
- {
- texcoords.push_back(in_texcoords[index1]);
- }
+ // i/j/k
+ (*token)++; // skip '/'
+ if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx)))
+ {
+ return false;
}
+ (*token) += strcspn((*token), "/ \t\r");
- unsigned int idx = positions.size() / 3 - 1;
- vertexCache[i] = idx;
+ (*ret) = vi;
- return idx;
+ return true;
}
-static bool
-exportFaceGroupToShape(
- shape_t& shape,
- const std::vector<float>& in_positions,
- const std::vector<float>& in_normals,
- const std::vector<float>& in_texcoords,
- const std::vector<MyIndices>& faceGroup,
- const material_t material,
- const std::string name,
- std::vector<vertex_index>& allIndices)
+static bool exportFaceGroupToShape(shape_t* shape, const std::vector<face_t>& face_group,
+ const material_t material, const std::string& name,
+ const std::vector<float>& v)
{
- if (faceGroup.empty())
+ if (face_group.empty())
{
return false;
}
+ shape->name = name;
// Flattened version of vertex data
- std::vector<float> positions;
- std::vector<float> normals;
- std::vector<float> texcoords;
- std::map<vertex_index, unsigned int> vertexCache;
- std::vector<unsigned int> indices;
// Flatten vertices and indices
- for (size_t i = 0; i < faceGroup.size(); i++)
+ for (size_t i = 0; i < face_group.size(); i++)
{
- const MyIndices& face = faceGroup[i];
+ const face_t& face = face_group[i];
+ size_t npolys = face.size();
+
+ if (npolys < 3)
+ {
+ // Face must have 3+ vertices.
+ continue;
+ }
+ vertex_index_t i0 = face[0];
+ vertex_index_t i1(-1);
+ vertex_index_t i2 = face[1];
- vertex_index i0 = allIndices[face.m_offset];
- vertex_index i1;
- i1.vn_idx = -1;
- i1.vt_idx = -1;
- i1.v_idx = -1;
- vertex_index i2 = allIndices[face.m_offset + 1];
+ face_t remainingFace = face; // copy
+ size_t guess_vert = 0;
+ vertex_index_t ind[3];
- size_t npolys = face.m_numIndices; //.size();
+ // How many iterations can we do without decreasing the remaining
+ // vertices.
+ size_t remainingIterations = face.size();
+ size_t previousRemainingVertices = remainingFace.size();
+ while (remainingFace.size() > 3 && remainingIterations > 0)
{
- // Polygon -> triangle fan conversion
- for (size_t k = 2; k < npolys; k++)
+ npolys = remainingFace.size();
+ if (guess_vert >= npolys)
{
- i1 = i2;
- i2 = allIndices[face.m_offset + k];
-
- unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
- unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
- unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
+ guess_vert -= npolys;
+ }
- indices.push_back(v0);
- indices.push_back(v1);
- indices.push_back(v2);
+ if (previousRemainingVertices != npolys)
+ {
+ // The number of remaining vertices decreased. Reset counters.
+ previousRemainingVertices = npolys;
+ remainingIterations = npolys;
+ }
+ else
+ {
+ // We didn't consume a vertex on previous iteration, reduce the
+ // available iterations.
+ remainingIterations--;
}
- }
- }
- //
- // Construct shape.
- //
- shape.name = name;
- shape.mesh.positions.swap(positions);
- shape.mesh.normals.swap(normals);
- shape.mesh.texcoords.swap(texcoords);
- shape.mesh.indices.swap(indices);
+ for (size_t k = 0; k < 3; k++)
+ {
+ ind[k] = remainingFace[(guess_vert + k) % npolys];
+ size_t vi = size_t(ind[k].v_idx);
+ }
+ // this triangle is an ear
+ {
+ index_t idx0, idx1, idx2;
+ idx0.vertex_index = ind[0].v_idx;
+ idx0.normal_index = ind[0].vn_idx;
+ idx0.texcoord_index = ind[0].vt_idx;
+ idx1.vertex_index = ind[1].v_idx;
+ idx1.normal_index = ind[1].vn_idx;
+ idx1.texcoord_index = ind[1].vt_idx;
+ idx2.vertex_index = ind[2].v_idx;
+ idx2.normal_index = ind[2].vn_idx;
+ idx2.texcoord_index = ind[2].vt_idx;
+
+ shape->mesh.indices.push_back(idx0);
+ shape->mesh.indices.push_back(idx1);
+ shape->mesh.indices.push_back(idx2);
+ }
- shape.material = material;
+ // remove v1 from the list
+ size_t removed_vert_index = (guess_vert + 1) % npolys;
+ while (removed_vert_index + 1 < npolys)
+ {
+ remainingFace[removed_vert_index] =
+ remainingFace[removed_vert_index + 1];
+ removed_vert_index += 1;
+ }
+ remainingFace.pop_back();
+ }
+ if (remainingFace.size() == 3)
+ {
+ i0 = remainingFace[0];
+ i1 = remainingFace[1];
+ i2 = remainingFace[2];
+ {
+ index_t idx0, idx1, idx2;
+ idx0.vertex_index = i0.v_idx;
+ idx0.normal_index = i0.vn_idx;
+ idx0.texcoord_index = i0.vt_idx;
+ idx1.vertex_index = i1.v_idx;
+ idx1.normal_index = i1.vn_idx;
+ idx1.texcoord_index = i1.vt_idx;
+ idx2.vertex_index = i2.v_idx;
+ idx2.normal_index = i2.vn_idx;
+ idx2.texcoord_index = i2.vt_idx;
+
+ shape->mesh.indices.push_back(idx0);
+ shape->mesh.indices.push_back(idx1);
+ shape->mesh.indices.push_back(idx2);
+ }
+ }
+ }
+ shape->material = material;
return true;
}
@@ -329,7 +332,6 @@ void InitMaterial(material_t& material)
material.ambient_texname = "";
material.diffuse_texname = "";
material.specular_texname = "";
- material.normal_texname = "";
for (int i = 0; i < 3; i++)
{
material.ambient[i] = 0.f;
@@ -369,8 +371,8 @@ std::string LoadMtl(
return err.str();
}
#else
- int fileHandle = fileIO->fileOpen(filepath.c_str(),"r");
- if (fileHandle<0)
+ int fileHandle = fileIO->fileOpen(filepath.c_str(), "r");
+ if (fileHandle < 0)
{
err << "Cannot open file [" << filepath << "]" << std::endl;
return err.str();
@@ -396,7 +398,7 @@ std::string LoadMtl(
line = fileIO->readLine(fileHandle, tmpBuf, 1024);
if (line)
{
- linebuf=line;
+ linebuf = line;
}
#endif
@@ -420,7 +422,7 @@ std::string LoadMtl(
// Skip leading space.
const char* token = linebuf.c_str();
token += strspn(token, " \t");
-
+
assert(token);
if (token[0] == '\0') continue; // empty line
@@ -574,12 +576,13 @@ std::string LoadMtl(
}
}
#ifndef USE_STREAM
- while (line);
+ while (line)
+ ;
#endif
// flush last material.
material_map.insert(std::pair<std::string, material_t>(material.name, material));
- if (fileHandle>=0)
+ if (fileHandle >= 0)
{
fileIO->fileClose(fileHandle);
}
@@ -588,11 +591,16 @@ std::string LoadMtl(
std::string
LoadObj(
+ attrib_t& attrib,
std::vector<shape_t>& shapes,
const char* filename,
const char* mtl_basepath,
CommonFileIOInterface* fileIO)
{
+ attrib.vertices.clear();
+ attrib.normals.clear();
+ attrib.texcoords.clear();
+ shapes.clear();
std::string tmp = filename;
if (!mtl_basepath)
{
@@ -604,13 +612,6 @@ LoadObj(
mtl_basepath = tmp.c_str();
//fprintf(stderr, "MTL PATH '%s' orig '%s'\n", mtl_basepath, filename);
}
-
- shapes.resize(0);
- std::vector<vertex_index> allIndices;
- allIndices.reserve(1024 * 1024);
-
- MyIndices face;
-
std::stringstream err;
#ifdef USE_STREAM
std::ifstream ifs(filename);
@@ -620,8 +621,8 @@ LoadObj(
return err.str();
}
#else
- int fileHandle = fileIO->fileOpen(filename,"r");
- if (fileHandle<0)
+ int fileHandle = fileIO->fileOpen(filename, "r");
+ if (fileHandle < 0)
{
err << "Cannot open file [" << filename << "]" << std::endl;
return err.str();
@@ -629,16 +630,15 @@ LoadObj(
#endif
std::vector<float> v;
- v.reserve(1024 * 1024);
std::vector<float> vn;
- vn.reserve(1024 * 1024);
std::vector<float> vt;
- vt.reserve(1024 * 1024);
- //std::vector<std::vector<vertex_index> > faceGroup;
- std::vector<MyIndices> faceGroup;
- faceGroup.reserve(1024 * 1024);
std::string name;
+ int greatest_v_idx = -1;
+ int greatest_vn_idx = -1;
+ int greatest_vt_idx = -1;
+
+ std::vector<face_t> faceGroup;
// material
std::map<std::string, material_t> material_map;
material_t material;
@@ -664,10 +664,9 @@ LoadObj(
line = fileIO->readLine(fileHandle, tmpBuf, 1024);
if (line)
{
- linebuf=line;
+ linebuf = line;
}
#endif
-
// Trim newline '\r\n' or '\r'
if (linebuf.size() > 0)
{
@@ -734,23 +733,34 @@ LoadObj(
token += 2;
token += strspn(token, " \t");
- face.m_offset = allIndices.size();
- face.m_numIndices = 0;
+ face_t face;
+
+ face.reserve(3);
while (!isNewLine(token[0]))
{
- vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2);
- allIndices.push_back(vi);
- face.m_numIndices++;
- int n = strspn(token, " \t\r");
+ vertex_index_t vi;
+ if (!parseTriple(&token, static_cast<int>(v.size() / 3),
+ static_cast<int>(vn.size() / 3),
+ static_cast<int>(vt.size() / 2), &vi))
+ {
+ err << "Failed parse `f' line(e.g. zero value for face index.";
+ return err.str();
+ }
+
+ greatest_v_idx = greatest_v_idx > vi.v_idx ? greatest_v_idx : vi.v_idx;
+ greatest_vn_idx =
+ greatest_vn_idx > vi.vn_idx ? greatest_vn_idx : vi.vn_idx;
+ greatest_vt_idx =
+ greatest_vt_idx > vi.vt_idx ? greatest_vt_idx : vi.vt_idx;
+
+ face.push_back(vi);
+ size_t n = strspn(token, " \t\r");
token += n;
}
-
faceGroup.push_back(face);
-
continue;
}
-
// use mtl
if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6])))
{
@@ -777,10 +787,10 @@ LoadObj(
token += 7;
sscanf(token, "%s", namebuf);
- std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath,fileIO);
+ std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath, fileIO);
if (!err_mtl.empty())
{
- //faceGroup.resize(0); // for safety
+ //face_group.resize(0); // for safety
//return err_mtl;
}
continue;
@@ -791,7 +801,7 @@ LoadObj(
{
// flush previous face group.
shape_t shape;
- bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, allIndices);
+ bool ret = exportFaceGroupToShape(&shape, faceGroup, material, name, v);
if (ret)
{
shapes.push_back(shape);
@@ -827,7 +837,7 @@ LoadObj(
{
// flush previous face group.
shape_t shape;
- bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, allIndices);
+ bool ret = exportFaceGroupToShape(&shape, faceGroup, material, name, v);
if (ret)
{
shapes.push_back(shape);
@@ -847,18 +857,23 @@ LoadObj(
// Ignore unknown command.
}
#ifndef USE_STREAM
- while (line);
+ while (line)
+ ;
#endif
shape_t shape;
- bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, allIndices);
+ bool ret = exportFaceGroupToShape(&shape, faceGroup, material, name, v);
if (ret)
{
shapes.push_back(shape);
}
faceGroup.resize(0); // for safety
- if (fileHandle>=0)
+ attrib.vertices.swap(v);
+ attrib.normals.swap(vn);
+ attrib.texcoords.swap(vt);
+
+ if (fileHandle >= 0)
{
fileIO->fileClose(fileHandle);
}
diff --git a/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h b/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h
index 0319b7c0d..1fb15b34a 100644
--- a/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h
+++ b/examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h
@@ -14,6 +14,17 @@ struct CommonFileIOInterface;
namespace tinyobj
{
+struct vertex_index_t
+{
+ int v_idx, vt_idx, vn_idx;
+ vertex_index_t() : v_idx(-1), vt_idx(-1), vn_idx(-1) {}
+ explicit vertex_index_t(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}
+ vertex_index_t(int vidx, int vtidx, int vnidx)
+ : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {}
+};
+
+typedef std::vector<vertex_index_t> face_t;
+
typedef struct
{
std::string name;
@@ -24,21 +35,27 @@ typedef struct
float transmittance[3];
float emission[3];
float shininess;
- float transparency;
+ float transparency; // 1 == opaque; 0 == fully transparent
- std::string ambient_texname;
- std::string diffuse_texname;
- std::string specular_texname;
+ std::string ambient_texname; // map_Ka
+ std::string diffuse_texname; // map_Kd
+ std::string specular_texname; // map_Ks
std::string normal_texname;
std::map<std::string, std::string> unknown_parameter;
} material_t;
+// Index struct to support different indices for vtx/normal/texcoord.
+// -1 means not used.
typedef struct
{
- std::vector<float> positions;
- std::vector<float> normals;
- std::vector<float> texcoords;
- std::vector<unsigned int> indices;
+ int vertex_index;
+ int normal_index;
+ int texcoord_index;
+} index_t;
+
+typedef struct
+{
+ std::vector<index_t> indices;
} mesh_t;
typedef struct
@@ -48,6 +65,14 @@ typedef struct
mesh_t mesh;
} shape_t;
+// Vertex attributes
+struct attrib_t
+{
+ std::vector<float> vertices; // 'v'(xyz)
+ std::vector<float> normals; // 'vn'
+ std::vector<float> texcoords; // 'vt'(uv)
+ attrib_t() {}
+};
/// Loads .obj from a file.
/// 'shapes' will be filled with parsed shape data
/// The function returns error string.
@@ -55,12 +80,14 @@ typedef struct
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
#ifdef USE_STREAM
std::string LoadObj(
+ attrib_t& attrib,
std::vector<shape_t>& shapes, // [output]
const char* filename,
const char* mtl_basepath = NULL);
#else
std::string
LoadObj(
+ attrib_t& attrib,
std::vector<shape_t>& shapes,
const char* filename,
const char* mtl_basepath,