From a56134ba330775415dd6148d8667e9a3c7ce2537 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 09:05:09 +0100 Subject: [PATCH 01/11] Drop faces when indices are out of range. --- code/AssetLib/glTF2/glTF2Importer.cpp | 117 +++++++++++++++----------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 4d740d8c1..1c32b48e2 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -298,25 +298,37 @@ void glTF2Importer::ImportMaterials(glTF2::Asset &r) { } } -static inline void SetFace(aiFace &face, int a) { - face.mNumIndices = 1; - face.mIndices = new unsigned int[1]; - face.mIndices[0] = a; +static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a) { + if (a >= numVertices) { + return; + } + face->mNumIndices = 1; + face->mIndices = new unsigned int[1]; + face->mIndices[0] = a; + ++face; } -static inline void SetFace(aiFace &face, int a, int b) { - face.mNumIndices = 2; - face.mIndices = new unsigned int[2]; - face.mIndices[0] = a; - face.mIndices[1] = b; +static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b) { + if ((a >= numVertices) || (b >= numVertices)) { + return; + } + face->mNumIndices = 2; + face->mIndices = new unsigned int[2]; + face->mIndices[0] = a; + face->mIndices[1] = b; + ++face; } -static inline void SetFace(aiFace &face, int a, int b, int c) { - face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; - face.mIndices[0] = a; - face.mIndices[1] = b; - face.mIndices[2] = c; +static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b, unsigned int c) { + if ((a >= numVertices) || (b >= numVertices) || (c >= numVertices)) { + return; + } + face->mNumIndices = 3; + face->mIndices = new unsigned int[3]; + face->mIndices[0] = a; + face->mIndices[1] = b; + face->mIndices[2] = c; + ++face; } #ifdef ASSIMP_BUILD_DEBUG @@ -486,6 +498,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } aiFace *faces = nullptr; + aiFace *facePtr = nullptr; size_t nFaces = 0; if (prim.indices) { @@ -497,9 +510,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], data.GetUInt(i)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i)); } break; } @@ -510,9 +523,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); count = nFaces * 2; } - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1)); } break; } @@ -520,13 +533,13 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } @@ -537,33 +550,33 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); count = nFaces * 3; } - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < nFaces; ++i) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i + 1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); } else { //For odd n, vertices n, n+1, and n+2 define triangle n - SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance(facePtr, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 1; i < nFaces; ++i) { - SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); } break; } @@ -575,9 +588,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], i); + SetFaceAndAdvance(facePtr, aim->mNumVertices, i); } break; } @@ -588,9 +601,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); count = (unsigned int)nFaces * 2; } - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], i, i + 1); + SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1); } break; } @@ -598,13 +611,13 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], 0, 1); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance(facePtr, aim->mNumVertices, 0, 1); for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], i); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], i); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } @@ -615,42 +628,46 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); count = (unsigned int)nFaces * 3; } - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], i, i + 1, i + 2); + SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1, i + 2); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; - faces = new aiFace[nFaces]; + facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < nFaces; ++i) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i + 1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFace(faces[i], i + 1, i, i + 2); + SetFaceAndAdvance(facePtr, aim->mNumVertices, i + 1, i, i + 2); } else { //For odd n, vertices n, n+1, and n+2 define triangle n - SetFace(faces[i], i, i + 1, i + 2); + SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1, i + 2); } } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], 0, 1, 2); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance(facePtr, aim->mNumVertices, 0, 1, 2); for (unsigned int i = 1; i < nFaces; ++i) { - SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); + SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); } break; } } - if (nullptr != faces) { + if (faces) { aim->mFaces = faces; - aim->mNumFaces = static_cast(nFaces); - ai_assert(CheckValidFacesIndices(faces, static_cast(nFaces), aim->mNumVertices)); + const unsigned int actualNumFaces = facePtr - faces; + if (actualNumFaces < nFaces) { + ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped."); + } + aim->mNumFaces = actualNumFaces; + ai_assert(CheckValidFacesIndices(faces, actualNumFaces, aim->mNumVertices)); } if (prim.material) { From c0d978786e3714aaeb2934540b6c425823509c13 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 09:12:52 +0100 Subject: [PATCH 02/11] Fix warning --- code/AssetLib/glTF2/glTF2Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 1c32b48e2..9ce488cbd 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -662,7 +662,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (faces) { aim->mFaces = faces; - const unsigned int actualNumFaces = facePtr - faces; + const unsigned int actualNumFaces = static_cast(facePtr - faces); if (actualNumFaces < nFaces) { ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped."); } From 7e7161852ae2a724e1f44667294b048a3281f670 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 11:19:10 +0100 Subject: [PATCH 03/11] Add a unit test. --- .../glTF2/IndexOutOfRange/IndexOutOfRange.bin | Bin 0 -> 648 bytes .../IndexOutOfRange/IndexOutOfRange.gltf | 142 ++++++++++++++++++ test/unit/utglTF2ImportExport.cpp | 28 ++++ 3 files changed, 170 insertions(+) create mode 100644 test/models/glTF2/IndexOutOfRange/IndexOutOfRange.bin create mode 100644 test/models/glTF2/IndexOutOfRange/IndexOutOfRange.gltf diff --git a/test/models/glTF2/IndexOutOfRange/IndexOutOfRange.bin b/test/models/glTF2/IndexOutOfRange/IndexOutOfRange.bin new file mode 100644 index 0000000000000000000000000000000000000000..b7cfe377b9cdabc5bc9ed9879730941916b3946e GIT binary patch literal 648 zcmb7;0Sbap5JaDqm6es1bsVqe%{p4`2t&(9kc7v~?hM}rf8$^WOMZN(?t))>OE2Y4 zIp=K7|8vXl>iFlv-P0ZFm?6B-oYniRxnr+fzC`YAz-dW4cdufTg sR^{^3{GnpSI;hxCvt<|5>}fb~3>r?foVf%oS2}LogN_G1PhLUK7moElJ^%m! literal 0 HcmV?d00001 diff --git a/test/models/glTF2/IndexOutOfRange/IndexOutOfRange.gltf b/test/models/glTF2/IndexOutOfRange/IndexOutOfRange.gltf new file mode 100644 index 000000000..67561c591 --- /dev/null +++ b/test/models/glTF2/IndexOutOfRange/IndexOutOfRange.gltf @@ -0,0 +1,142 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 255 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "name": "Red" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 648, + "uri": "IndexOutOfRange.bin" + } + ] +} diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 6791d5f89..8bc20e950 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -541,3 +541,31 @@ TEST_F(utglTF2ImportExport, norootnode_issue_3269) { const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/issue_3269/texcoord_crash.gltf", aiProcess_ValidateDataStructure); ASSERT_EQ(scene, nullptr); } + +#include +#include + +TEST_F(utglTF2ImportExport, indexOutOfRange) { + // The contents of an asset should not lead to an assert. + Assimp::Importer importer; + + struct WarningObserver : Assimp::LogStream + { + bool m_observedWarning = false; + void write(const char *message) override + { + m_observedWarning = m_observedWarning || std::strstr(message, "faces were dropped"); + } + }; + WarningObserver warningObserver; + + DefaultLogger::get()->attachStream(&warningObserver); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/IndexOutOfRange/IndexOutOfRange.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_NE(scene->mRootNode, nullptr); + ASSERT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 11); + DefaultLogger::get()->detachStream(&warningObserver); + EXPECT_TRUE(warningObserver.m_observedWarning); +} + From 212903e935d64e8d0d3f20c68603744ddbc213f9 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 12:19:00 +0100 Subject: [PATCH 04/11] Unit test for all indices out of range, and fix. --- code/AssetLib/glTF2/glTF2Importer.cpp | 8 ++++++-- test/unit/utglTF2ImportExport.cpp | 25 ++++++++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 9ce488cbd..0b784e0d4 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -574,7 +574,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance(facePtr, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 1; i < nFaces; ++i) { SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); } @@ -664,7 +664,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { aim->mFaces = faces; const unsigned int actualNumFaces = static_cast(facePtr - faces); if (actualNumFaces < nFaces) { - ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped."); + ASSIMP_LOG_WARN("Some faces in mesh had out-of-range indices. Those faces were dropped."); + } + if (actualNumFaces == 0) + { + throw DeadlyImportError(std::string("Mesh \"") + aim->mName.C_Str() + "\" has no faces"); } aim->mNumFaces = actualNumFaces; ai_assert(CheckValidFacesIndices(faces, actualNumFaces, aim->mNumVertices)); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 8bc20e950..c3ad2d994 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -46,11 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include + #include #include - using namespace Assimp; class utglTF2ImportExport : public AbstractImportExportBase { @@ -542,14 +544,11 @@ TEST_F(utglTF2ImportExport, norootnode_issue_3269) { ASSERT_EQ(scene, nullptr); } -#include -#include - TEST_F(utglTF2ImportExport, indexOutOfRange) { // The contents of an asset should not lead to an assert. Assimp::Importer importer; - struct WarningObserver : Assimp::LogStream + struct LogObserver : Assimp::LogStream { bool m_observedWarning = false; void write(const char *message) override @@ -557,15 +556,23 @@ TEST_F(utglTF2ImportExport, indexOutOfRange) { m_observedWarning = m_observedWarning || std::strstr(message, "faces were dropped"); } }; - WarningObserver warningObserver; + LogObserver logObserver; - DefaultLogger::get()->attachStream(&warningObserver); + DefaultLogger::get()->attachStream(&logObserver); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/IndexOutOfRange/IndexOutOfRange.gltf", aiProcess_ValidateDataStructure); ASSERT_NE(scene, nullptr); ASSERT_NE(scene->mRootNode, nullptr); ASSERT_EQ(scene->mNumMeshes, 1); EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 11); - DefaultLogger::get()->detachStream(&warningObserver); - EXPECT_TRUE(warningObserver.m_observedWarning); + DefaultLogger::get()->detachStream(&logObserver); + EXPECT_TRUE(logObserver.m_observedWarning); } +TEST_F(utglTF2ImportExport, allIndicesOutOfRange) { + // The contents of an asset should not lead to an assert. + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/IndexOutOfRange/AllIndicesOutOfRange.gltf", aiProcess_ValidateDataStructure); + ASSERT_EQ(scene, nullptr); + std::string error = importer.GetErrorString(); + ASSERT_NE(error.find("Mesh \"Mesh\" has no faces"), std::string::npos); +} From fff6396e3c997b2a4368e597511495967e1eca82 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 12:22:28 +0100 Subject: [PATCH 05/11] Rename to avoid overloading problems. --- code/AssetLib/glTF2/glTF2Importer.cpp | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 0b784e0d4..fae87a990 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -298,7 +298,7 @@ void glTF2Importer::ImportMaterials(glTF2::Asset &r) { } } -static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a) { +static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, unsigned int a) { if (a >= numVertices) { return; } @@ -308,7 +308,7 @@ static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, un ++face; } -static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b) { +static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b) { if ((a >= numVertices) || (b >= numVertices)) { return; } @@ -319,7 +319,7 @@ static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, un ++face; } -static inline void SetFaceAndAdvance(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b, unsigned int c) { +static inline void SetFaceAndAdvance3(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b, unsigned int c) { if ((a >= numVertices) || (b >= numVertices) || (c >= numVertices)) { return; } @@ -512,7 +512,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { nFaces = count; facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i)); + SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i)); } break; } @@ -525,7 +525,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1)); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1)); } break; } @@ -534,12 +534,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], data.GetUInt(i)); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } @@ -552,7 +552,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } @@ -563,10 +563,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i + 1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); } else { //For odd n, vertices n, n+1, and n+2 define triangle n - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } } break; @@ -574,9 +574,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); } break; } @@ -590,7 +590,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { nFaces = count; facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, i); + SetFaceAndAdvance1(facePtr, aim->mNumVertices, i); } break; } @@ -603,7 +603,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1); } break; } @@ -612,12 +612,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance(facePtr, aim->mNumVertices, 0, 1); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1); for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], i); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], i); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } @@ -630,7 +630,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } facePtr = faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1, i + 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2); } break; } @@ -641,10 +641,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i + 1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFaceAndAdvance(facePtr, aim->mNumVertices, i + 1, i, i + 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2); } else { //For odd n, vertices n, n+1, and n+2 define triangle n - SetFaceAndAdvance(facePtr, aim->mNumVertices, i, i + 1, i + 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2); } } break; @@ -652,9 +652,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance(facePtr, aim->mNumVertices, 0, 1, 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2); for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); } break; } From d4f5f29b44d64f3dd44b5e68e90e6d395f528f5b Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 12:22:39 +0100 Subject: [PATCH 06/11] Add missing asset --- .../IndexOutOfRange/AllIndicesOutOfRange.bin | Bin 0 -> 648 bytes .../IndexOutOfRange/AllIndicesOutOfRange.gltf | 142 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.bin create mode 100644 test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.gltf diff --git a/test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.bin b/test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.bin new file mode 100644 index 0000000000000000000000000000000000000000..8fef5c7c04bc230c538c8bf7aed41e73d302acb9 GIT binary patch literal 648 zcmb`BfeFAc2n5|Mt7Wr}*5(37MFLW2;Q7-RV}x%GDWcg4dQ@1NcSS)YSh literal 0 HcmV?d00001 diff --git a/test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.gltf b/test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.gltf new file mode 100644 index 000000000..3dbb6efe4 --- /dev/null +++ b/test/models/glTF2/IndexOutOfRange/AllIndicesOutOfRange.gltf @@ -0,0 +1,142 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 255 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "name": "Red" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 648, + "uri": "AllIndicesOutOfRange.bin" + } + ] +} From f3170a96ba48b6938ff455d6ea5a2cfd5919c884 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 12:36:48 +0100 Subject: [PATCH 07/11] Ensure data does not depend on faces we may not have created. --- code/AssetLib/glTF2/glTF2Importer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index fae87a990..566e48a69 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -536,10 +536,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { facePtr = faces = new aiFace[nFaces]; SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], data.GetUInt(i)); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast(count) - 1), faces[0].mIndices[0]); } break; } @@ -576,7 +576,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { facePtr = faces = new aiFace[nFaces]; SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance3(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } @@ -614,10 +614,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { facePtr = faces = new aiFace[nFaces]; SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1); for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[i - 2].mIndices[1], i); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance2(facePtr, aim->mNumVertices, faces[count - 2].mIndices[1], faces[0].mIndices[0]); + SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0); } break; } @@ -654,7 +654,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { facePtr = faces = new aiFace[nFaces]; SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2); for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance3(facePtr, aim->mNumVertices, faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); + SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2); } break; } From 37e1fb9cd7a85e0716cc17175ac914f403cf25e2 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 14:19:13 +0100 Subject: [PATCH 08/11] Fix message --- code/AssetLib/glTF2/glTF2Importer.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 566e48a69..441219feb 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -299,9 +299,9 @@ void glTF2Importer::ImportMaterials(glTF2::Asset &r) { } static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, unsigned int a) { - if (a >= numVertices) { - return; - } + if (a >= numVertices) { + return; + } face->mNumIndices = 1; face->mIndices = new unsigned int[1]; face->mIndices[0] = a; @@ -309,14 +309,14 @@ static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, u } static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b) { - if ((a >= numVertices) || (b >= numVertices)) { - return; - } + if ((a >= numVertices) || (b >= numVertices)) { + return; + } face->mNumIndices = 2; face->mIndices = new unsigned int[2]; face->mIndices[0] = a; face->mIndices[1] = b; - ++face; + ++face; } static inline void SetFaceAndAdvance3(aiFace*& face, unsigned int numVertices, unsigned int a, unsigned int b, unsigned int c) { @@ -328,7 +328,7 @@ static inline void SetFaceAndAdvance3(aiFace*& face, unsigned int numVertices, u face->mIndices[0] = a; face->mIndices[1] = b; face->mIndices[2] = c; - ++face; + ++face; } #ifdef ASSIMP_BUILD_DEBUG @@ -498,7 +498,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } aiFace *faces = nullptr; - aiFace *facePtr = nullptr; + aiFace *facePtr = nullptr; size_t nFaces = 0; if (prim.indices) { @@ -664,7 +664,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { aim->mFaces = faces; const unsigned int actualNumFaces = static_cast(facePtr - faces); if (actualNumFaces < nFaces) { - ASSIMP_LOG_WARN("Some faces in mesh had out-of-range indices. Those faces were dropped."); + ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped."); } if (actualNumFaces == 0) { From e1bab44e19d797a9372669a3d3dd333784e26000 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 15:02:27 +0100 Subject: [PATCH 09/11] Exception safety --- code/AssetLib/glTF2/glTF2Importer.cpp | 6 +++--- include/assimp/BaseImporter.h | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 441219feb..18c95d42b 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -347,7 +347,7 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign void glTF2Importer::ImportMeshes(glTF2::Asset &r) { ASSIMP_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes"); - std::vector meshes; + std::vector> meshes; unsigned int k = 0; meshOffsets.clear(); @@ -361,8 +361,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive &prim = mesh.primitives[p]; - aiMesh *aim = new aiMesh(); - meshes.push_back(aim); + meshes.emplace_back(std::make_unique()); + aiMesh *aim = meshes.back().get(); aim->mName = mesh.name.empty() ? mesh.id : mesh.name; diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index ed146168d..cc14f2f03 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include struct aiScene; struct aiImporterDesc; @@ -391,6 +392,24 @@ public: // static utilities } } + // ------------------------------------------------------------------- + /** Utility function to move a std::vector of unique_ptrs into a aiScene array + * @param vec The vector of unique_ptrs to be moved + * @param out The output pointer to the allocated array. + * @param numOut The output count of elements copied. */ + template + AI_FORCE_INLINE static void CopyVector( + std::vector> &vec, + T **&out, + unsigned int &outLength) { + outLength = unsigned(vec.size()); + if (outLength) { + out = new T*[outLength]; + T** outPtr = out; + std::for_each(vec.begin(), vec.end(), [&outPtr](auto& uPtr){*outPtr = uPtr.release(); ++outPtr; }); + } + } + protected: /// Error description in case there was one. std::string m_ErrorText; From e51e07982d3ae6056f84a9881d6ab3a1d34f935e Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 15:05:42 +0100 Subject: [PATCH 10/11] Remove generic lambda usage. --- include/assimp/BaseImporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index cc14f2f03..e6ff2e68d 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -406,7 +406,7 @@ public: // static utilities if (outLength) { out = new T*[outLength]; T** outPtr = out; - std::for_each(vec.begin(), vec.end(), [&outPtr](auto& uPtr){*outPtr = uPtr.release(); ++outPtr; }); + std::for_each(vec.begin(), vec.end(), [&outPtr](std::unique_ptr& uPtr){*outPtr = uPtr.release(); ++outPtr; }); } } From 04df5f8b1e585fbe74a0934b07308cb9784fa9c6 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 15 Jul 2020 15:47:25 +0100 Subject: [PATCH 11/11] Don't use make_unique --- code/AssetLib/glTF2/glTF2Importer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 18c95d42b..23d42ba97 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -361,8 +361,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive &prim = mesh.primitives[p]; - meshes.emplace_back(std::make_unique()); - aiMesh *aim = meshes.back().get(); + aiMesh *aim = new aiMesh(); + meshes.push_back(std::unique_ptr(aim)); aim->mName = mesh.name.empty() ? mesh.id : mesh.name;