diff --git a/models/quad_plane.obj b/models/quad_plane.obj new file mode 100644 index 00000000..761b16c9 --- /dev/null +++ b/models/quad_plane.obj @@ -0,0 +1,25 @@ +# a 2x2 quad plane +o Plane +v -0.5 0 -0.5 +v 0 0 -0.5 +v 0.5 0 -0.5 +v 0.5 0 0 +v 0.5 0 0.5 +v 0 0 0.5 +v -0.5 0 0.5 +v -0.5 0 0 +v 0 0 0 +vn 0 1 0 +vt 0 1 +vt 0 0.5 +vt 0.5 0.5 +vt 0.5 1 +vt 0 0 +vt 0.5 0 +vt 1 0.5 +vt 1 1 +vt 1 0 +f 1/1/1 8/2/1 9/3/1 2/4/1 +f 8/2/1 7/5/1 6/6/1 9/3/1 +f 2/4/1 9/3/1 4/7/1 3/8/1 +f 9/3/1 6/6/1 5/9/1 4/7/1 diff --git a/models/variable_facevert_count.obj b/models/variable_facevert_count.obj new file mode 100644 index 00000000..2b364980 --- /dev/null +++ b/models/variable_facevert_count.obj @@ -0,0 +1,36 @@ +# three polygonal faces with varying number of vertices. +o Mesh +v -1.04 0 -0.4 +v -1.47301 0 0.35 +v -0.606987 0 0.35 +v -0.5 0 -0.5 +v 0.5 0 -0.5 +v 0.5 0 0.5 +v -0.5 0 0.5 +v 1.15 0 -0.5 +v 0.796447 0 -0.353553 +v 0.65 0 0 +v 0.796447 0 0.353553 +v 1.15 0 0.5 +v 1.50355 0 0.353553 +v 1.65 0 0 +v 1.50355 0 -0.353553 +vn 0 1 0 +vt 0.091042 0.988145 +vt 0.32738 0.578795 +vt 0.563719 0.988145 +vt 0.01 0.5558 +vt 0.01 0.01 +vt 0.5558 0.01 +vt 0.5558 0.5558 +vt 0.99 0.842308 +vt 0.842308 0.99 +vt 0.633439 0.99 +vt 0.485746 0.842308 +vt 0.485746 0.633439 +vt 0.633439 0.485746 +vt 0.842308 0.485746 +vt 0.99 0.633439 +f 1/1/1 2/2/1 3/3/1 +f 4/4/1 7/5/1 6/6/1 5/7/1 +f 8/8/1 9/9/1 10/10/1 11/11/1 12/12/1 13/13/1 14/14/1 15/15/1 diff --git a/source/test/test.cpp b/source/test/test.cpp index 4c94e583..274be996 100644 --- a/source/test/test.cpp +++ b/source/test/test.cpp @@ -71,7 +71,7 @@ bool generateAtlas(const char *filename, bool useUvMesh, AtlasResult *result) std::vector shapes; std::vector materials; std::string err; - if (!tinyobj::LoadObj(shapes, materials, err, filename, NULL, tinyobj::triangulation)) { + if (!tinyobj::LoadObj(shapes, materials, err, filename, NULL, 0)) { logf(" [FAILED]: %s\n", err.c_str()); return false; } @@ -119,6 +119,11 @@ bool generateAtlas(const char *filename, bool useUvMesh, AtlasResult *result) decl.indexCount = (int)objMesh.indices.size(); decl.indexData = objMesh.indices.data(); decl.indexFormat = xatlas::IndexFormat::UInt32; + if (objMesh.num_vertices.size() != objMesh.indices.size() / 3) + { + decl.faceVertexCount = objMesh.num_vertices.data(); + decl.faceCount = (uint32_t)objMesh.num_vertices.size(); + } xatlas::AddMeshError error = xatlas::AddMesh(atlas, decl); if (error != xatlas::AddMeshError::Success) { xatlas::Destroy(atlas); @@ -237,7 +242,7 @@ int main(int argc, char **argv) ASSERT(result.chartCount == 2); } if (generateAtlas(MODEL_PATH "gazebo.obj", false, &result)) { - ASSERT(result.chartCount == 333); + ASSERT(result.chartCount == 332); } if (generateAtlas(MODEL_PATH "zero_area_face.obj", false, &result)) { ASSERT(result.chartCount == 0); @@ -245,6 +250,12 @@ int main(int argc, char **argv) if (generateAtlas(MODEL_PATH "zero_length_edge.obj", false, &result)) { ASSERT(result.chartCount == 1); } + if (generateAtlas(MODEL_PATH "variable_facevert_count.obj", false, &result)) { + ASSERT(result.chartCount == 3); + } + if (generateAtlas(MODEL_PATH "quad_plane.obj", false, &result)) { + ASSERT(result.chartCount == 1); + } } return 0; } diff --git a/source/xatlas/xatlas.cpp b/source/xatlas/xatlas.cpp index 5c5c57ec..1f850ff9 100644 --- a/source/xatlas/xatlas.cpp +++ b/source/xatlas/xatlas.cpp @@ -9083,6 +9083,7 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH meshPolygonMapping->triangleToPolygonMap.reserve(meshDecl.faceCount); meshPolygonMapping->triangleToPolygonIndicesMap.reserve(meshDecl.indexCount); } + uint32_t firstIndex = 0; const uint32_t kMaxWarnings = 50; uint32_t warningCount = 0; internal::Array triIndices; @@ -9093,7 +9094,7 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH uint32_t polygon[UINT8_MAX]; for (uint32_t i = 0; i < faceVertexCount; i++) { if (hasIndices) { - polygon[i] = DecodeIndex(meshDecl.indexFormat, meshDecl.indexData, meshDecl.indexOffset, face * faceVertexCount + i); + polygon[i] = DecodeIndex(meshDecl.indexFormat, meshDecl.indexData, meshDecl.indexOffset, firstIndex + i); // Check if any index is out of range. if (polygon[i] >= meshDecl.vertexCount) { mesh->~Mesh(); @@ -9191,10 +9192,17 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH if (meshPolygonMapping) meshPolygonMapping->triangleToPolygonMap.push_back(face); } + // For each triangle index, store original index location if (meshPolygonMapping) { for (uint32_t i = 0; i < triIndices.size(); i++) - meshPolygonMapping->triangleToPolygonIndicesMap.push_back(triIndices[i]); + { + uint32_t polygonIndex = 0; + for (polygonIndex; polygonIndex < faceVertexCount; polygonIndex++) + if (triIndices[i] == polygon[polygonIndex]) break; + meshPolygonMapping->triangleToPolygonIndicesMap.push_back(firstIndex+polygonIndex); + } } + firstIndex += faceVertexCount; } if (warningCount > kMaxWarnings) XA_PRINT(" %u additional warnings truncated\n", warningCount - kMaxWarnings);