diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index ed9b1ca85..428763798 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -467,7 +467,15 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive &prim = mesh.primitives[p]; - // extract used vertices: + Mesh::Primitive::Attributes &attr = prim.attributes; + + // Find out the maximum number of vertices: + size_t numAllVertices = 0; + if (!attr.position.empty() && attr.position[0]) { + numAllVertices = attr.position[0]->count; + } + + // Extract used vertices: bool useIndexBuffer = prim.indices; std::vector* vertexRemappingTable = nullptr; if (useIndexBuffer) { @@ -487,6 +495,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { const unsigned int unusedIndex = ~0u; for (unsigned int i = 0; i < count; ++i) { unsigned int index = data.GetUInt(i); + if (index >= numAllVertices) { + // Out-of-range indices will be filtered out when adding the faces and then lead to a warning. At this stage, we just keep them. + indexBuffer[i] = index; + continue; + } if (index >= reverseMappingIndices.size()) { reverseMappingIndices.resize(index + 1, unusedIndex); } @@ -527,12 +540,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { break; } - Mesh::Primitive::Attributes &attr = prim.attributes; - - size_t numAllVertices = 0; if (!attr.position.empty() && attr.position[0]) { - numAllVertices = attr.position[0]->count; - aim->mNumVertices = static_cast(attr.position[0]->ExtractData(aim->mVertices, vertexRemappingTable)); + aim->mNumVertices = static_cast(attr.position[0]->ExtractData(aim->mVertices, vertexRemappingTable)); } if (!attr.normal.empty() && attr.normal[0]) { diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index ef3fc4137..957a94b15 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -380,7 +380,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) { const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); - std::array l1 = { { 0u, 3u, 2u, 1u, 0u } }; + std::array l1 = { { 0u, 1u, 2u, 3u, 0u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u); for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); @@ -394,7 +394,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) { const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); - std::array l1 = { { 0, 3u, 2u, 1u, 0u } }; + std::array l1 = { { 0, 1u, 2u, 3u, 0u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u); for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); @@ -408,7 +408,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) { const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); - std::array l1 = { { 0u, 3u, 2u, 1u, 0u } }; + std::array l1 = { { 0u, 1u, 2u, 3u, 0u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u); for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]); @@ -423,13 +423,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) { EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); - std::array f1 = { { 0u, 3u, 1u } }; + std::array f1 = { { 0u, 1u, 2u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); } - std::array f2 = { { 1u, 3u, 2u } }; + std::array f2 = { { 2u, 1u, 3u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]); @@ -443,13 +443,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) { EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u); - std::array f1 = { { 0u, 3u, 2u } }; + std::array f1 = { { 0u, 1u, 2u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]); } - std::array f2 = { { 0u, 2u, 1u } }; + std::array f2 = { { 0u, 2u, 3u } }; EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);