From 0ebab47ca271f5af97804b15c9891ba447257b80 Mon Sep 17 00:00:00 2001 From: Matthew Wallace Date: Mon, 8 Mar 2021 07:11:39 -0600 Subject: [PATCH 01/37] updated MIN_IOS_VERSION to 10.0 --- .gitignore | 3 +++ port/iOS/build.sh | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f9c1a490f..0a999d3aa 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,6 @@ tools/assimp_qt_viewer/moc_glview.cpp_parameters tools/assimp_qt_viewer/moc_mainwindow.cpp tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters tools/assimp_qt_viewer/ui_mainwindow.h + +#Generated directory +generated/* \ No newline at end of file diff --git a/port/iOS/build.sh b/port/iOS/build.sh index f118c45c1..335b450d1 100755 --- a/port/iOS/build.sh +++ b/port/iOS/build.sh @@ -22,7 +22,7 @@ BUILD_TYPE=Release ################################################ # Minimum iOS deployment target version ################################################ -MIN_IOS_VERSION="6.0" +MIN_IOS_VERSION="10.0" IOS_SDK_TARGET=$MIN_IOS_VERSION XCODE_ROOT_DIR=$(xcode-select --print-path) @@ -60,8 +60,8 @@ build_arch() unset DEVROOT SDKROOT CFLAGS LDFLAGS CPPFLAGS CXXFLAGS CMAKE_CLI_INPUT - #export CC="$(xcrun -sdk iphoneos -find clang)" - #export CPP="$CC -E" + export CC="$(xcrun -sdk iphoneos -find clang)" + export CPP="$CC -E" export DEVROOT=$XCODE_ROOT_DIR/Platforms/$IOS_SDK_DEVICE.platform/Developer export SDKROOT=$DEVROOT/SDKs/$IOS_SDK_DEVICE$IOS_SDK_VERSION.sdk export CFLAGS="-arch $1 -pipe -no-cpp-precomp -stdlib=$CPP_STD_LIB -isysroot $SDKROOT -I$SDKROOT/usr/include/ -miphoneos-version-min=$IOS_SDK_TARGET" From cc7e229c3c1ed78a7e2ca2371ffbaad041fe06f5 Mon Sep 17 00:00:00 2001 From: Urs Hanselmann Date: Fri, 12 Mar 2021 08:55:11 +0100 Subject: [PATCH 02/37] disable size check --- code/AssetLib/FBX/FBXMeshGeometry.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp index f2f19d0b1..0a5074fb4 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.cpp +++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp @@ -508,11 +508,11 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); - if (uvIndices.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") - << uvIndices.size() << ", expected " << vertex_count); - return; - } + // if (uvIndices.size() != vertex_count) { + // FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") + // << uvIndices.size() << ", expected " << vertex_count); + // return; + // } data_out.resize(vertex_count); From c0c7e6a0de94c450275775d8a94582f7a6457871 Mon Sep 17 00:00:00 2001 From: Urs Hanselmann Date: Fri, 12 Mar 2021 14:48:38 +0100 Subject: [PATCH 03/37] trim uvIndices to fix import of Cheetah3D generated fbx files --- code/AssetLib/FBX/FBXMeshGeometry.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp index 0a5074fb4..fd8a0ff98 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.cpp +++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp @@ -508,11 +508,17 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); - // if (uvIndices.size() != vertex_count) { - // FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") - // << uvIndices.size() << ", expected " << vertex_count); - // return; - // } + if (uvIndices.size() > vertex_count) { + FBXImporter::LogWarn(Formatter::format("trimming length of input array for ByPolygonVertex mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + uvIndices.resize(vertex_count); + } + + if (uvIndices.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + return; + } data_out.resize(vertex_count); From add165c4a19a77e96017e249b8028c2ff09695c6 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 24 Mar 2021 10:55:40 +0000 Subject: [PATCH 04/37] Check target sizes to avoid reading beyond allocation --- code/AssetLib/glTF2/glTF2Importer.cpp | 52 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 8442c4958..0574c25da 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -536,35 +536,47 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { Mesh::Primitive::Target &target = targets[i]; if (needPositions) { - aiVector3D *positionDiff = nullptr; - target.position[0]->ExtractData(positionDiff); - for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { - aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId]; + if (target.position[0]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Positions of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + } else { + aiVector3D *positionDiff = nullptr; + target.position[0]->ExtractData(positionDiff); + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { + aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId]; + } + delete[] positionDiff; } - delete[] positionDiff; } if (needNormals) { - aiVector3D *normalDiff = nullptr; - target.normal[0]->ExtractData(normalDiff); - for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { - aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId]; + if (target.normal[0]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Normals of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + } else { + aiVector3D *normalDiff = nullptr; + target.normal[0]->ExtractData(normalDiff); + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { + aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId]; + } + delete[] normalDiff; } - delete[] normalDiff; } if (needTangents) { - Tangent *tangent = nullptr; - attr.tangent[0]->ExtractData(tangent); + if (target.tangent[0]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Tangents of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + } else { + Tangent *tangent = nullptr; + attr.tangent[0]->ExtractData(tangent); - aiVector3D *tangentDiff = nullptr; - target.tangent[0]->ExtractData(tangentDiff); + aiVector3D *tangentDiff = nullptr; + target.tangent[0]->ExtractData(tangentDiff); - for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) { - tangent[vertexId].xyz += tangentDiff[vertexId]; - aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz; - aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w; + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) { + tangent[vertexId].xyz += tangentDiff[vertexId]; + aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz; + aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w; + } + delete[] tangent; + delete[] tangentDiff; } - delete[] tangent; - delete[] tangentDiff; } if (mesh.weights.size() > i) { aiAnimMesh.mWeight = mesh.weights[i]; From d94ddd32b1a902bf2fbbd3bd546b02cb89cfc166 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 24 Mar 2021 11:04:39 +0000 Subject: [PATCH 05/37] Extra check. Better logging. --- code/AssetLib/glTF2/glTF2Importer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 0574c25da..dca6fcb2d 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -527,8 +527,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { std::fill(aim->mAnimMeshes, aim->mAnimMeshes + aim->mNumAnimMeshes, nullptr); for (size_t i = 0; i < targets.size(); i++) { bool needPositions = targets[i].position.size() > 0; - bool needNormals = targets[i].normal.size() > 0; - bool needTangents = targets[i].tangent.size() > 0; + bool needNormals = (targets[i].normal.size() > 0) && aim->HasNormals(); + bool needTangents = (targets[i].tangent.size() > 0) && aim->HasTangentsAndBitangents(); // GLTF morph does not support colors and texCoords aim->mAnimMeshes[i] = aiCreateAnimMesh(aim, needPositions, needNormals, needTangents, false, false); @@ -537,7 +537,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (needPositions) { if (target.position[0]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Positions of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + ASSIMP_LOG_WARN_F("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { aiVector3D *positionDiff = nullptr; target.position[0]->ExtractData(positionDiff); @@ -549,7 +549,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } if (needNormals) { if (target.normal[0]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Normals of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + ASSIMP_LOG_WARN_F("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { aiVector3D *normalDiff = nullptr; target.normal[0]->ExtractData(normalDiff); @@ -561,7 +561,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } if (needTangents) { if (target.tangent[0]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Tangents of target in mesh \"" + mesh.name + "\" does not match the vertex count"); + ASSIMP_LOG_WARN_F("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { Tangent *tangent = nullptr; attr.tangent[0]->ExtractData(tangent); From 0bd938c0247b7c3c3380a003f8b00c13cd26967b Mon Sep 17 00:00:00 2001 From: Elias Daler Date: Mon, 29 Mar 2021 02:26:03 +0300 Subject: [PATCH 06/37] Add zlibstatic to the list of exported targets --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6d9b3977..97a3641f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,7 +454,7 @@ IF(ASSIMP_HUNTER_ENABLED) ELSE() # If the zlib is already found outside, add an export in case assimpTargets can't find it. IF( ZLIB_FOUND ) - INSTALL( TARGETS zlib + INSTALL( TARGETS zlib zlibstatic EXPORT "${TARGETS_EXPORT_NAME}") ENDIF() From 8e589221d7cd1e49769671219c2179af9e4ab66f Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Wed, 10 Mar 2021 09:48:12 +0100 Subject: [PATCH 07/37] [gltf2-exporter] Adding FB_ngon_encoding support --- code/AssetLib/glTF2/glTF2Asset.h | 1 + code/AssetLib/glTF2/glTF2AssetWriter.inl | 17 +++++++++++++++++ code/AssetLib/glTF2/glTF2Exporter.cpp | 3 +++ code/PostProcessing/TriangulateProcess.cpp | 11 +++++++++++ 4 files changed, 32 insertions(+) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 0e4ba6eda..37aacd2fb 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -1108,6 +1108,7 @@ public: bool KHR_materials_clearcoat; bool KHR_materials_transmission; bool KHR_draco_mesh_compression; + bool FB_ngon_encoding; } extensionsUsed; //! Keeps info about the required extensions diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 166eada0f..aae96d0f7 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -507,6 +507,19 @@ namespace glTF2 { Mesh::Primitive& p = m.primitives[i]; Value prim; prim.SetObject(); + + // Extensions + { + Value exts; + exts.SetObject(); + + Value FB_ngon_encoding; + FB_ngon_encoding.SetObject(); + + exts.AddMember(StringRef("FB_ngon_encoding"), FB_ngon_encoding, w.mAl); + prim.AddMember("extensions", exts, w.mAl); + } + { prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl); @@ -874,6 +887,10 @@ namespace glTF2 { if (this->mAsset.extensionsUsed.KHR_materials_transmission) { exts.PushBack(StringRef("KHR_materials_transmission"), mAl); } + + if (this->mAsset.extensionsUsed.FB_ngon_encoding) { + exts.PushBack(StringRef("FB_ngon_encoding"), mAl); + } } if (!exts.Empty()) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index aa89e96da..d244e19f5 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -97,6 +97,9 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai mAsset.reset( new Asset( pIOSystem ) ); + // Always on as our triangulation process is aware of this type of encoding + mAsset->extensionsUsed.FB_ngon_encoding = true; + if (isBinary) { mAsset->SetAsBinary(); } diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index e971bf85f..f8e63c304 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -217,10 +217,21 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // if it's a simple point,line or triangle: just copy it if( face.mNumIndices <= 3) { + // ngon encoding: making sure that triangles are not recognized as false ngons. + // To do so, we make sure the first indice is not the same as previous triangle emitted. + unsigned int prev_first_indice = (unsigned int)-1; + if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0]; + aiFace& nface = *curOut++; nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; + if (nface.mIndices[0] == prev_first_indice) { + // rotate indices to avoid ngon encoding false ngons + std::swap(nface.mIndices[0], nface.mIndices[2]); + std::swap(nface.mIndices[1], nface.mIndices[2]); + } + face.mIndices = nullptr; continue; } From 6d1a0c60546d79d65cd2042a34406b2c76fbd883 Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Mon, 29 Mar 2021 15:20:40 +0200 Subject: [PATCH 08/37] Adding quad proper handling --- code/PostProcessing/TriangulateProcess.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index f8e63c304..e5b3dbdf3 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -214,14 +214,14 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) aiFace* const last_face = curOut; + // ngon encoding: making sure that triangles are not recognized as false ngons. + // To do so, we make sure the first indice is not the same as previous triangle emitted. + unsigned int prev_first_indice = (unsigned int)-1; + if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0]; + // if it's a simple point,line or triangle: just copy it if( face.mNumIndices <= 3) { - // ngon encoding: making sure that triangles are not recognized as false ngons. - // To do so, we make sure the first indice is not the same as previous triangle emitted. - unsigned int prev_first_indice = (unsigned int)-1; - if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0]; - aiFace& nface = *curOut++; nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; @@ -241,6 +241,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // quads can have at maximum one concave vertex. Determine // this vertex (if it exists) and start tri-fanning from // it. + // + // Due to ngon encoding, if this concave vertex is the same as the previously + // emitted triangle, we use the opposite vertex which also happens to work + // for tri-fanning a concave quad. + // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 unsigned int start_vertex = 0; for (unsigned int i = 0; i < 4; ++i) { const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]]; @@ -259,8 +264,10 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) const float angle = std::acos(left*diag) + std::acos(right*diag); if (angle > AI_MATH_PI_F) { - // this is the concave point - start_vertex = i; + // i is the concave point + // ngon encoding: if the concave vertex is same as last triangle first index, + // then we chose the opposite vertex. + start_vertex = (face.mIndices[i] != prev_first_indice) ? i : ((i+2) % 4); break; } } From 81019d5e589833d86686acdf4c42a36d6aad622e Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Mon, 29 Mar 2021 15:31:48 +0200 Subject: [PATCH 09/37] Fixing quad encoding --- code/PostProcessing/TriangulateProcess.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index e5b3dbdf3..00a55e35d 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -246,6 +246,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // emitted triangle, we use the opposite vertex which also happens to work // for tri-fanning a concave quad. // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 + unsigned int start_vertex = 0; for (unsigned int i = 0; i < 4; ++i) { const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]]; @@ -265,13 +266,16 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) const float angle = std::acos(left*diag) + std::acos(right*diag); if (angle > AI_MATH_PI_F) { // i is the concave point - // ngon encoding: if the concave vertex is same as last triangle first index, - // then we chose the opposite vertex. - start_vertex = (face.mIndices[i] != prev_first_indice) ? i : ((i+2) % 4); + start_vertex = i; break; } } + // ngon encoding: if vertex is same as last triangle first index, + // then we chose the opposite vertex (works for both concave & convex quad). + if (face.mIndices[start_vertex] == prev_first_indice) + start_vertex = (start_vertex+2) % 4; + const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]}; aiFace& nface = *curOut++; From 596001c89c672f2dc559e040693c95a893d6907c Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Mon, 29 Mar 2021 19:03:01 +0200 Subject: [PATCH 10/37] Refactoring the extension --- code/AssetLib/glTF2/glTF2Asset.h | 5 +++ code/AssetLib/glTF2/glTF2AssetWriter.inl | 1 + code/AssetLib/glTF2/glTF2Exporter.cpp | 1 + code/PostProcessing/TriangulateProcess.cpp | 38 +++++++++++++--------- include/assimp/mesh.h | 18 ++++++++++ 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 37aacd2fb..85eff4ac8 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -813,6 +813,11 @@ struct Mesh : public Object { AccessorList position, normal, tangent; }; std::vector targets; + + // extension: FB_ngon_encoding + bool ngonEncoded; + + Primitive(): ngonEncoded(false) {} }; std::vector primitives; diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index aae96d0f7..01a28d4b7 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -509,6 +509,7 @@ namespace glTF2 { prim.SetObject(); // Extensions + if (p.ngonEncoded) { Value exts; exts.SetObject(); diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index d244e19f5..51aef013d 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -958,6 +958,7 @@ void glTF2Exporter::ExportMeshes() m->name = name; p.material = mAsset->materials.Get(aim->mMaterialIndex); + p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0; /******************* Vertices ********************/ Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 00a55e35d..c982d9292 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -195,6 +195,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) const aiVector3D* verts = pMesh->mVertices; + // NGON encoding note: making sure that triangles are not recognized as false ngons. + // To do so, we make sure the first indice of the new emitted triangle is not the same as previous one. + unsigned int prev_first_indice = (unsigned int)-1; + + // The mesh becomes NGON encoded now, during the triangulation process. + pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag; + // use std::unique_ptr to avoid slow std::vector specialiations std::unique_ptr done(new bool[max_out]); for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { @@ -214,24 +221,12 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) aiFace* const last_face = curOut; - // ngon encoding: making sure that triangles are not recognized as false ngons. - // To do so, we make sure the first indice is not the same as previous triangle emitted. - unsigned int prev_first_indice = (unsigned int)-1; - if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0]; - // if it's a simple point,line or triangle: just copy it if( face.mNumIndices <= 3) { aiFace& nface = *curOut++; nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; - - if (nface.mIndices[0] == prev_first_indice) { - // rotate indices to avoid ngon encoding false ngons - std::swap(nface.mIndices[0], nface.mIndices[2]); - std::swap(nface.mIndices[1], nface.mIndices[2]); - } - face.mIndices = nullptr; continue; } @@ -242,7 +237,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // this vertex (if it exists) and start tri-fanning from // it. // - // Due to ngon encoding, if this concave vertex is the same as the previously + // Due to NGON encoding, if this concave vertex is the same as the previously // emitted triangle, we use the opposite vertex which also happens to work // for tri-fanning a concave quad. // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 @@ -265,7 +260,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) const float angle = std::acos(left*diag) + std::acos(right*diag); if (angle > AI_MATH_PI_F) { - // i is the concave point + // this is the concave point start_vertex = i; break; } @@ -306,11 +301,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // modeling suite to make extensive use of highly concave, monster polygons ... // so we need to apply the full 'ear cutting' algorithm to get it right. - // RERQUIREMENT: polygon is expected to be simple and *nearly* planar. + // REQUIREMENT: polygon is expected to be simple and *nearly* planar. // We project it onto a plane to get a 2d triangle. // Collect all vertices of of the polygon. - for (tmp = 0; tmp < max; ++tmp) { + for (tmp = 0; tmp < max; ++tmp) { temp_verts3d[tmp] = verts[idx[tmp]]; } @@ -530,6 +525,17 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) i[0] = idx[i[0]]; i[1] = idx[i[1]]; i[2] = idx[i[2]]; + + // NGON encoding: only quads are supported. + // For everything else, we make sure we don't emit 'false' ngons. We thus avoid having + // 2 consecutive triangles with their first index identical. + if (face.mNumIndices != 4 && i[0] == prev_first_indice) { + // rotate indices + std::swap(i[0], i[2]); + std::swap(i[1], i[2]); + } + + prev_first_indice = i[0]; ++f; } diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 8f17f541d..95651bd17 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -398,6 +398,24 @@ enum aiPrimitiveType { */ aiPrimitiveType_POLYGON = 0x8, + /** + * A flag to determine whether this triangles only mesh is NGON encoded. + * + * NGON encoding is a special encoding that tells whether 2 or more consecutive triangles + * should be considered as a triangle fan. This is identified by looking at the first vertex index. + * 2 consecutive triangles with the same 1st vertex index are part of the same + * NGON. + * + * At the moment, only quads (concave or convex) are supported, meaning that polygons are 'seen' as + * triangles, as usual after a triangulation pass. + * + * To get an NGON encoded mesh, please use the aiProcess_Triangulate post process. + * + * @see aiProcess_Triangulate + * @link https://github.com/KhronosGroup/glTF/pull/1620 + */ + aiPrimitiveType_NGONEncodingFlag = 0x16, + /** This value is not used. It is just here to force the * compiler to map this enum to a 32 Bit integer. */ From 2e90fed5273e89099638b3c400553465cdd0b6a3 Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Tue, 30 Mar 2021 09:06:51 +0200 Subject: [PATCH 11/37] Refactoring and fixing remaining issues in triangulation process --- code/PostProcessing/TriangulateProcess.cpp | 115 ++++++++++++++++----- 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index c982d9292..bc3db799e 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -76,6 +76,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; +namespace { + + /** + * @brief Helper struct used to simplify NGON encoding functions. + */ + struct NGONEncoder { + NGONEncoder(const aiFace * outTriArray, size_t outTriArraySize) + : mOutTriArrayBeg(outTriArray), mOutTriArrayEnd(outTriArray + outTriArraySize) {} + + /** + * @brief Encode the current triangle, and make sure it is recognized as a triangle. + * + * This method will rotate indices in tri if needed in order to avoid tri to be considered + * part of the previous ngon. This method is to be used whenever you want to emit a real triangle, + * and make sure it is seen as a triangle. + * + * @param tri Current triangle, must be in bounds of the outTriArray (= be a cell within the array). + */ + void ngonEncodeTriangle(aiFace * tri) const { + ai_assert(tri >= mOutTriArrayBeg && tri < mOutTriArrayEnd); + ai_assert(tri->mNumIndices == 3); + + // Rotate indices in new triangle to avoid ngon encoding false ngons + // Otherwise, the new triangle would be considered part of the previous NGON. + if (isConsideredSameAsLastNgon(tri)) { + std::swap(tri->mIndices[0], tri->mIndices[2]); + std::swap(tri->mIndices[1], tri->mIndices[2]); + } + } + + /** + * @brief Check whether this triangle would be considered part of the lastly emitted ngon or not. + * + * @param tri Current triangle. + * @return true If used as is, this triangle will be part of last ngon. + * @return false If used as is, this triangle is not considered part of the last ngon. + */ + bool isConsideredSameAsLastNgon(const aiFace * tri) const { + ai_assert(tri >= mOutTriArrayBeg && tri < mOutTriArrayEnd); + ai_assert(tri->mNumIndices == 3); + + // First triangle to be emitted, so no problem here + if (tri == mOutTriArrayBeg) return false; + + const aiFace * prevTri = tri - 1; + return tri->mIndices[0] == prevTri->mIndices[0]; + } + + private: + /** + * @brief Begining of triangulation process out triangles array + */ + const aiFace * mOutTriArrayBeg; + + /** + * @brief End of triangulation process out triangles array (out of bounds, a la C++ iterators). + */ + const aiFace * mOutTriArrayEnd; + }; + +} + + // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer TriangulateProcess::TriangulateProcess() @@ -175,10 +238,15 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON; + // The mesh becomes NGON encoded now, during the triangulation process. + pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag; + aiFace* out = new aiFace[numOut](), *curOut = out; std::vector temp_verts3d(max_out+2); /* temporary storage for vertices */ std::vector temp_verts(max_out+2); + const NGONEncoder ngonEncoder(out, numOut); + // Apply vertex colors to represent the face winding? #ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING if (!pMesh->mColors[0]) @@ -195,13 +263,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) const aiVector3D* verts = pMesh->mVertices; - // NGON encoding note: making sure that triangles are not recognized as false ngons. - // To do so, we make sure the first indice of the new emitted triangle is not the same as previous one. - unsigned int prev_first_indice = (unsigned int)-1; - - // The mesh becomes NGON encoded now, during the triangulation process. - pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag; - // use std::unique_ptr to avoid slow std::vector specialiations std::unique_ptr done(new bool[max_out]); for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { @@ -228,6 +289,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; face.mIndices = nullptr; + ngonEncoder.ngonEncodeTriangle(&nface); continue; } // optimized code for quadrilaterals @@ -236,12 +298,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // quads can have at maximum one concave vertex. Determine // this vertex (if it exists) and start tri-fanning from // it. - // - // Due to NGON encoding, if this concave vertex is the same as the previously - // emitted triangle, we use the opposite vertex which also happens to work - // for tri-fanning a concave quad. - // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 - unsigned int start_vertex = 0; for (unsigned int i = 0; i < 4; ++i) { const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]]; @@ -266,11 +322,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) } } - // ngon encoding: if vertex is same as last triangle first index, - // then we chose the opposite vertex (works for both concave & convex quad). - if (face.mIndices[start_vertex] == prev_first_indice) - start_vertex = (start_vertex+2) % 4; - const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]}; aiFace& nface = *curOut++; @@ -281,6 +332,20 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mIndices[1] = temp[(start_vertex + 1) % 4]; nface.mIndices[2] = temp[(start_vertex + 2) % 4]; + // Due to NGON encoding, if the selected fanning vertex is the same as the previously + // emitted ngon, we use the opposite vertex which also happens to work + // for tri-fanning a concave quad. + // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 + // + // @warning No need to call ngonEncoder.ngonEncodeTriangle() here. We want these 2 faces to be seen as + // a single quad, not 2 separate triangles. This is the whole purpose! + if (ngonEncoder.isConsideredSameAsLastNgon(&nface)) { + start_vertex = (start_vertex+2) % 4; + nface.mIndices[0] = temp[start_vertex]; + nface.mIndices[1] = temp[(start_vertex + 1) % 4]; + nface.mIndices[2] = temp[(start_vertex + 2) % 4]; + } + aiFace& sface = *curOut++; sface.mNumIndices = 3; sface.mIndices = new unsigned int[3]; @@ -526,16 +591,10 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) i[1] = idx[i[1]]; i[2] = idx[i[2]]; - // NGON encoding: only quads are supported. - // For everything else, we make sure we don't emit 'false' ngons. We thus avoid having - // 2 consecutive triangles with their first index identical. - if (face.mNumIndices != 4 && i[0] == prev_first_indice) { - // rotate indices - std::swap(i[0], i[2]); - std::swap(i[1], i[2]); - } - - prev_first_indice = i[0]; + // IMPROVEMENT: Polygons are not supported yet by this ngon encoding + triangulation step. + // So we encode polygons as regular triangles. No way to reconstruct the original + // polygon in this case. + ngonEncoder.ngonEncodeTriangle(f); ++f; } From fc0cf2ea8d29167f330412b817b0619f120cd0a1 Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Tue, 30 Mar 2021 09:19:50 +0200 Subject: [PATCH 12/37] NGON encoding triangles only --- code/PostProcessing/TriangulateProcess.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index bc3db799e..6cc6def4f 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -289,7 +289,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; face.mIndices = nullptr; - ngonEncoder.ngonEncodeTriangle(&nface); + + if (nface.mNumIndices == 3) ngonEncoder.ngonEncodeTriangle(&nface); continue; } // optimized code for quadrilaterals From fc2c12ad6a5ac5995cc79b0ee5d66e65cb9d3383 Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Tue, 30 Mar 2021 09:58:28 +0200 Subject: [PATCH 13/37] Fixing encoding when lines and points are encountered --- code/PostProcessing/TriangulateProcess.cpp | 81 ++++++++++++---------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 6cc6def4f..0f71320b8 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -82,8 +82,7 @@ namespace { * @brief Helper struct used to simplify NGON encoding functions. */ struct NGONEncoder { - NGONEncoder(const aiFace * outTriArray, size_t outTriArraySize) - : mOutTriArrayBeg(outTriArray), mOutTriArrayEnd(outTriArray + outTriArraySize) {} + NGONEncoder() : mLastNGONFirstIndex((unsigned int)-1) {} /** * @brief Encode the current triangle, and make sure it is recognized as a triangle. @@ -92,10 +91,9 @@ namespace { * part of the previous ngon. This method is to be used whenever you want to emit a real triangle, * and make sure it is seen as a triangle. * - * @param tri Current triangle, must be in bounds of the outTriArray (= be a cell within the array). + * @param tri Triangle to encode. */ - void ngonEncodeTriangle(aiFace * tri) const { - ai_assert(tri >= mOutTriArrayBeg && tri < mOutTriArrayEnd); + void ngonEncodeTriangle(aiFace * tri) { ai_assert(tri->mNumIndices == 3); // Rotate indices in new triangle to avoid ngon encoding false ngons @@ -104,6 +102,40 @@ namespace { std::swap(tri->mIndices[0], tri->mIndices[2]); std::swap(tri->mIndices[1], tri->mIndices[2]); } + + mLastNGONFirstIndex = tri->mIndices[0]; + } + + /** + * @brief Encode a quad (2 triangles) in ngon encoding, and make sure they are seen as a single ngon. + * + * @param tri1 First quad triangle + * @param tri2 Second quad triangle + * + * @pre Triangles must be properly fanned from the most appropriate vertex. + */ + void ngonEncodeQuad(aiFace *tri1, aiFace *tri2) { + ai_assert(tri1->mNumIndices == 3); + ai_assert(tri2->mNumIndices == 3); + ai_assert(tri1->mIndices[0] == tri2->mIndices[0]); + + // If the selected fanning vertex is the same as the previously + // emitted ngon, we use the opposite vertex which also happens to work + // for tri-fanning a concave quad. + // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 + if (isConsideredSameAsLastNgon(tri1)) { + // Right-rotate indices for tri1 (index 2 becomes the new fanning vertex) + std::swap(tri1->mIndices[0], tri1->mIndices[2]); + std::swap(tri1->mIndices[1], tri1->mIndices[2]); + + // Left-rotate indices for tri2 (index 2 becomes the new fanning vertex) + std::swap(tri2->mIndices[1], tri2->mIndices[2]); + std::swap(tri2->mIndices[0], tri2->mIndices[2]); + + ai_assert(tri1->mIndices[0] == tri2->mIndices[0]); + } + + mLastNGONFirstIndex = tri1->mIndices[0]; } /** @@ -114,26 +146,12 @@ namespace { * @return false If used as is, this triangle is not considered part of the last ngon. */ bool isConsideredSameAsLastNgon(const aiFace * tri) const { - ai_assert(tri >= mOutTriArrayBeg && tri < mOutTriArrayEnd); ai_assert(tri->mNumIndices == 3); - - // First triangle to be emitted, so no problem here - if (tri == mOutTriArrayBeg) return false; - - const aiFace * prevTri = tri - 1; - return tri->mIndices[0] == prevTri->mIndices[0]; + return tri->mIndices[0] == mLastNGONFirstIndex; } private: - /** - * @brief Begining of triangulation process out triangles array - */ - const aiFace * mOutTriArrayBeg; - - /** - * @brief End of triangulation process out triangles array (out of bounds, a la C++ iterators). - */ - const aiFace * mOutTriArrayEnd; + unsigned int mLastNGONFirstIndex; }; } @@ -245,7 +263,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) std::vector temp_verts3d(max_out+2); /* temporary storage for vertices */ std::vector temp_verts(max_out+2); - const NGONEncoder ngonEncoder(out, numOut); + NGONEncoder ngonEncoder; // Apply vertex colors to represent the face winding? #ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING @@ -290,7 +308,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mIndices = face.mIndices; face.mIndices = nullptr; + // points and lines don't require ngon encoding (and are not supported either!) if (nface.mNumIndices == 3) ngonEncoder.ngonEncodeTriangle(&nface); + continue; } // optimized code for quadrilaterals @@ -333,20 +353,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mIndices[1] = temp[(start_vertex + 1) % 4]; nface.mIndices[2] = temp[(start_vertex + 2) % 4]; - // Due to NGON encoding, if the selected fanning vertex is the same as the previously - // emitted ngon, we use the opposite vertex which also happens to work - // for tri-fanning a concave quad. - // ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760 - // - // @warning No need to call ngonEncoder.ngonEncodeTriangle() here. We want these 2 faces to be seen as - // a single quad, not 2 separate triangles. This is the whole purpose! - if (ngonEncoder.isConsideredSameAsLastNgon(&nface)) { - start_vertex = (start_vertex+2) % 4; - nface.mIndices[0] = temp[start_vertex]; - nface.mIndices[1] = temp[(start_vertex + 1) % 4]; - nface.mIndices[2] = temp[(start_vertex + 2) % 4]; - } - aiFace& sface = *curOut++; sface.mNumIndices = 3; sface.mIndices = new unsigned int[3]; @@ -357,6 +363,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // prevent double deletion of the indices field face.mIndices = nullptr; + + ngonEncoder.ngonEncodeQuad(&nface, &sface); + continue; } else From 5d09105a4991145f4cf30947e9f6dd363e017eb8 Mon Sep 17 00:00:00 2001 From: Clement JACOB Date: Tue, 30 Mar 2021 20:24:03 +0200 Subject: [PATCH 14/37] Update mesh.h Fixing ngon encoding flag value --- include/assimp/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 95651bd17..427dba008 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -414,7 +414,7 @@ enum aiPrimitiveType { * @see aiProcess_Triangulate * @link https://github.com/KhronosGroup/glTF/pull/1620 */ - aiPrimitiveType_NGONEncodingFlag = 0x16, + aiPrimitiveType_NGONEncodingFlag = 0x10, /** This value is not used. It is just here to force the * compiler to map this enum to a 32 Bit integer. From 60794f3743434ae6e7fb03e3f83fcf7412d1fe7e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 1 Apr 2021 17:07:35 +0200 Subject: [PATCH 15/37] Update Readme.md --- Readme.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Readme.md b/Readme.md index 71b3c7f10..51684c4aa 100644 --- a/Readme.md +++ b/Readme.md @@ -76,9 +76,6 @@ For more information, visit [our website](http://assimp.org/). Or check out the If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github. -For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_ - [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) - Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -103,9 +100,6 @@ Become a financial contributor and help us sustain our community. [[Contribute]( -Monthly donations via Patreon: -
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp) - #### Organizations From 658ffe3d2cab7531761357cef8aa580998c39754 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 1 Apr 2021 17:21:12 +0200 Subject: [PATCH 16/37] Update FUNDING.yml Only use OpenCollective. --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 35448d4dc..e1ab13396 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1 @@ -patreon: assimp open_collective: assimp From 89a8f87dae08b6e0c78c4d42185c30b448936afc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 2 Apr 2021 13:10:24 +0200 Subject: [PATCH 17/37] AMF: Remove unused macros --- code/AssetLib/AMF/AMFImporter_Macro.hpp | 113 ------------------------ 1 file changed, 113 deletions(-) diff --git a/code/AssetLib/AMF/AMFImporter_Macro.hpp b/code/AssetLib/AMF/AMFImporter_Macro.hpp index 43dcf76ba..2d44204af 100644 --- a/code/AssetLib/AMF/AMFImporter_Macro.hpp +++ b/code/AssetLib/AMF/AMFImporter_Macro.hpp @@ -48,117 +48,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AMFIMPORTER_MACRO_HPP_INCLUDED #define AMFIMPORTER_MACRO_HPP_INCLUDED -/// \def MACRO_ATTRREAD_LOOPBEG -/// Begin of loop that read attributes values. -#define MACRO_ATTRREAD_LOOPBEG \ - for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \ - { \ - std::string an(mReader->getAttributeName(idx)); - -/// \def MACRO_ATTRREAD_LOOPEND -/// End of loop that read attributes values. -#define MACRO_ATTRREAD_LOOPEND \ - Throw_IncorrectAttr(an); \ - } - -/// \def MACRO_ATTRREAD_LOOPEND_WSKIP -/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but -/// \ref MACRO_ATTRREAD_LOOPEND throw an exception. -#define MACRO_ATTRREAD_LOOPEND_WSKIP \ - continue; \ - } - -/// \def MACRO_ATTRREAD_CHECK_REF -/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then -/// "continue" will called. -/// \param [in] pAttrName - attribute name. -/// \param [out] pVarName - output variable name. -/// \param [in] pFunction - function which read attribute value and write it to pVarName. -#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \ - if(an == pAttrName) \ - { \ - pFunction(idx, pVarName); \ - continue; \ - } - -/// \def MACRO_ATTRREAD_CHECK_RET -/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. -/// If result was read then "continue" will called. -/// \param [in] pAttrName - attribute name. -/// \param [out] pVarName - output variable name. -/// \param [in] pFunction - function which read attribute value and write it to pVarName. -#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \ - if(an == pAttrName) \ - { \ - pVarName = pFunction(idx); \ - continue; \ - } - -/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName) -/// Begin of loop of parsing child nodes. Do not add ';' at end. -/// \param [in] pNodeName - current node name. -#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \ - do { \ - bool close_found = false; \ - \ - while(mReader->read()) \ - { \ - if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \ - { - -/// \def MACRO_NODECHECK_LOOPEND(pNodeName) -/// End of loop of parsing child nodes. -/// \param [in] pNodeName - current node name. -#define MACRO_NODECHECK_LOOPEND(pNodeName) \ - XML_CheckNode_SkipUnsupported(pNodeName); \ - }/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \ - else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \ - { \ - if(XML_CheckNode_NameEqual(pNodeName)) \ - { \ - close_found = true; \ - \ - break; \ - } \ - }/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \ - }/* while(mReader->read()) */ \ - \ - if(!close_found) Throw_CloseNotFound(pNodeName); \ - \ - } while(false) - -/// \def MACRO_NODECHECK_READCOMP_F -/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float". -/// If result was read then "continue" will called. Also check if node data already read then raise exception. -/// \param [in] pNodeName - node name. -/// \param [in, out] pReadFlag - read flag. -/// \param [out] pVarName - output variable name. -#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \ - if(XML_CheckNode_NameEqual(pNodeName)) \ - { \ - /* Check if field already read before. */ \ - if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \ - /* Read color component and assign it to object. */ \ - pVarName = XML_ReadNode_GetVal_AsFloat(); \ - pReadFlag = true; \ - continue; \ - } - -/// \def MACRO_NODECHECK_READCOMP_U32 -/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t". -/// If result was read then "continue" will called. Also check if node data already read then raise exception. -/// \param [in] pNodeName - node name. -/// \param [in, out] pReadFlag - read flag. -/// \param [out] pVarName - output variable name. -#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \ - if(XML_CheckNode_NameEqual(pNodeName)) \ - { \ - /* Check if field already read before. */ \ - if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \ - /* Read color component and assign it to object. */ \ - pVarName = XML_ReadNode_GetVal_AsU32(); \ - pReadFlag = true; \ - continue; \ - } - #endif // AMFIMPORTER_MACRO_HPP_INCLUDED From da0543972ba21304eeb3167e3dae020a1edf7d68 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 3 Apr 2021 10:25:03 +0200 Subject: [PATCH 18/37] Fix parsing for AMF-Files. --- code/AssetLib/AMF/AMFImporter.cpp | 26 ++-- code/AssetLib/AMF/AMFImporter_Geometry.cpp | 62 ++++---- code/AssetLib/AMF/AMFImporter_Macro.hpp | 51 ------- code/AssetLib/AMF/AMFImporter_Material.cpp | 140 +++++++++--------- code/AssetLib/AMF/AMFImporter_Postprocess.cpp | 18 ++- code/AssetLib/Ogre/OgreMaterial.cpp | 4 +- code/AssetLib/Ogre/OgreParsingUtils.h | 2 +- code/AssetLib/Ogre/OgreXmlSerializer.cpp | 4 +- code/AssetLib/STEPParser/STEPFileReader.cpp | 2 +- code/CMakeLists.txt | 1 - code/Common/BaseImporter.cpp | 2 +- code/Common/Importer.cpp | 2 +- code/PostProcessing/EmbedTexturesProcess.cpp | 2 +- include/assimp/StringUtils.h | 2 +- tools/assimp_view/LogWindow.cpp | 2 +- 15 files changed, 136 insertions(+), 184 deletions(-) delete mode 100644 code/AssetLib/AMF/AMFImporter_Macro.hpp diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index 7d6ef2fd0..37756aea0 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -39,16 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/// \file AMFImporter.cpp -/// \brief AMF-format files importer for Assimp: main algorithm implementation. -/// \date 2016 -/// \author smal.root@gmail.com - #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER // Header files, Assimp. #include "AMFImporter.hpp" -#include "AMFImporter_Macro.hpp" #include #include @@ -307,14 +301,14 @@ void AMFImporter::ParseNode_Root() { throw DeadlyImportError("Root node \"amf\" not found."); } XmlNode node = *root; - mUnit = ai_str_tolower(std::string(node.attribute("unit").as_string())); + mUnit = ai_tolower(std::string(node.attribute("unit").as_string())); mVersion = node.attribute("version").as_string(); // Read attributes for node . // Check attributes if (!mUnit.empty()) { - if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) { + if ((mUnit != "inch") && (mUnit != "millimeters") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) { Throw_IncorrectAttrValue("unit", mUnit); } } @@ -409,20 +403,20 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) { if (!node.empty()) { ParseHelper_Node_Enter(ne); - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + for (auto ¤tNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "deltax") { - als.Delta.x = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.x); } else if (currentName == "deltay") { - als.Delta.y = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.y); } else if (currentName == "deltaz") { - als.Delta.z = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.z); } else if (currentName == "rx") { - als.Delta.x = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.x); } else if (currentName == "ry") { - als.Delta.y = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.y); } else if (currentName == "rz") { - als.Delta.z = (ai_real)std::atof(currentNode.value()); + XmlParser::getValueAsFloat(currentNode, als.Delta.z); } } ParseHelper_Node_Exit(); @@ -458,7 +452,7 @@ void AMFImporter::ParseNode_Object(XmlNode &node) { // Check for child nodes if (!node.empty()) { ParseHelper_Node_Enter(ne); - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + for (auto ¤tNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "color") { ParseNode_Color(currentNode); diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 3d50488a2..6b01ecd63 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #include "AMFImporter.hpp" -#include "AMFImporter_Macro.hpp" +//#include "AMFImporter_Macro.hpp" #include @@ -103,17 +103,23 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) { // create new mesh object. ne = new AMFVertices(mNodeElement_Cur); // Check for child nodes - pugi::xml_node vertexNode = node.child("vertex"); - if (!vertexNode.empty()) { - ParseHelper_Node_Enter(ne); - - ParseNode_Vertex(vertexNode); - - ParseHelper_Node_Exit(); - - } else { + if (node.empty()) { mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element - } // if(!mReader->isEmptyElement()) else + return; + } + ParseHelper_Node_Enter(ne); + for (XmlNode ¤tNode : node.children()) { + const std::string ¤tName = currentNode.name(); + if (currentName == "vertex") { + ParseNode_Vertex(currentNode); + } + } + ParseHelper_Node_Exit(); + //pugi::xml_node vertexNode = node.child("vertex"); + //if (!vertexNode.empty()) { + +// } else { +// } // if(!mReader->isEmptyElement()) else mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. } @@ -166,27 +172,25 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) { // X, Y, or Z coordinate, respectively, of a vertex position in space. void AMFImporter::ParseNode_Coordinates(XmlNode &node) { AMFNodeElementBase *ne = nullptr; - - // create new color object. - ne = new AMFCoordinates(mNodeElement_Cur); - - AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience if (!node.empty()) { + ne = new AMFCoordinates(mNodeElement_Cur); ParseHelper_Node_Enter(ne); for (XmlNode ¤tNode : node.children()) { - const std::string ¤tName = currentNode.name(); - if (currentName == "X") { + // create new color object. + AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience + const std::string ¤tName = ai_tolower(currentNode.name()); + if (currentName == "x") { XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); - } else if (currentName == "Y") { + } else if (currentName == "y") { XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); - } else if (currentName == "Z") { + } else if (currentName == "z") { XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); } } - ParseHelper_Node_Exit(); + } else { - mNodeElement_Cur->Child.push_back(ne); + mNodeElement_Cur->Child.push_back(new AMFCoordinates(mNodeElement_Cur)); } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. @@ -216,7 +220,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) { bool col_read = false; if (!node.empty()) { ParseHelper_Node_Enter(ne); - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + for (auto ¤tNode : node.children()) { const std::string currentName = currentNode.name(); if (currentName == "color") { if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for ."); @@ -258,7 +262,8 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) { bool col_read = false; if (!node.empty()) { ParseHelper_Node_Enter(ne); - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + std::string v; + for (auto ¤tNode : node.children()) { const std::string currentName = currentNode.name(); if (currentName == "color") { if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for ."); @@ -269,11 +274,14 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) { } else if (currentName == "map") { ParseNode_TexMap(currentNode, true); } else if (currentName == "v1") { - als.V[0] = std::atoi(currentNode.value()); + XmlParser::getValueAsString(currentNode, v); + als.V[0] = std::atoi(v.c_str()); } else if (currentName == "v2") { - als.V[1] = std::atoi(currentNode.value()); + XmlParser::getValueAsString(currentNode, v); + als.V[1] = std::atoi(v.c_str()); } else if (currentName == "v3") { - als.V[2] = std::atoi(currentNode.value()); + XmlParser::getValueAsString(currentNode, v); + als.V[2] = std::atoi(v.c_str()); } } ParseHelper_Node_Exit(); diff --git a/code/AssetLib/AMF/AMFImporter_Macro.hpp b/code/AssetLib/AMF/AMFImporter_Macro.hpp deleted file mode 100644 index 2d44204af..000000000 --- a/code/AssetLib/AMF/AMFImporter_Macro.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2021, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/// \file AMFImporter_Macro.hpp -/// \brief Useful macrodefines. -/// \date 2016 -/// \author smal.root@gmail.com - -#pragma once -#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED -#define AMFIMPORTER_MACRO_HPP_INCLUDED - -#endif // AMFIMPORTER_MACRO_HPP_INCLUDED diff --git a/code/AssetLib/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp index 1fcc7eed9..6b9300bfa 100644 --- a/code/AssetLib/AMF/AMFImporter_Material.cpp +++ b/code/AssetLib/AMF/AMFImporter_Material.cpp @@ -65,48 +65,45 @@ namespace Assimp { // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // values can be specified as constants, or as a formula depending on the coordinates. void AMFImporter::ParseNode_Color(XmlNode &node) { - std::string profile = node.attribute("profile").as_string(); - - // create new color object. - AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur); - AMFColor& als = *((AMFColor*)ne);// alias for convenience + if (node.empty()) { + return; + } - als.Profile = profile; - if (!node.empty()) { - ParseHelper_Node_Enter(ne); - bool read_flag[4] = { false, false, false, false }; - for (pugi::xml_node &child : node.children()) { - std::string name = child.name(); - if ( name == "r") { - read_flag[0] = true; - XmlParser::getValueAsFloat(child, als.Color.r); - } else if (name == "g") { - read_flag[1] = true; - XmlParser::getValueAsFloat(child, als.Color.g); - } else if (name == "b") { - read_flag[2] = true; - XmlParser::getValueAsFloat(child, als.Color.b); - } else if (name == "a") { - read_flag[3] = true; - XmlParser::getValueAsFloat(child, als.Color.a); - } - ParseHelper_Node_Exit(); + const std::string &profile = node.attribute("profile").as_string(); + bool read_flag[4] = { false, false, false, false }; + AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur); + AMFColor &als = *((AMFColor *)ne); // alias for convenience + ParseHelper_Node_Enter(ne); + for (pugi::xml_node &child : node.children()) { + // create new color object. + als.Profile = profile; + + const std::string &name = child.name(); + if ( name == "r") { + read_flag[0] = true; + XmlParser::getValueAsFloat(child, als.Color.r); + } else if (name == "g") { + read_flag[1] = true; + XmlParser::getValueAsFloat(child, als.Color.g); + } else if (name == "b") { + read_flag[2] = true; + XmlParser::getValueAsFloat(child, als.Color.b); + } else if (name == "a") { + read_flag[3] = true; + XmlParser::getValueAsFloat(child, als.Color.a); } - // check that all components was defined - if (!(read_flag[0] && read_flag[1] && read_flag[2])) { - throw DeadlyImportError("Not all color components are defined."); - } - - // check if is absent. Then manually add "a == 1". - if (!read_flag[3]) { - als.Color.a = 1; - } - } else { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element + // check if is absent. Then manually add "a == 1". + if (!read_flag[3]) { + als.Color.a = 1; + } + } + als.Composed = false; + mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. + ParseHelper_Node_Exit(); + // check that all components was defined + if (!(read_flag[0] && read_flag[1] && read_flag[2])) { + throw DeadlyImportError("Not all color components are defined."); } - - als.Composed = false; - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. } // . void AMFImporter::ParseNode_Texture(XmlNode &node) { - std::string id = node.attribute("id").as_string(); - uint32_t width = node.attribute("width").as_uint(); - uint32_t height = node.attribute("height").as_uint(); - uint32_t depth = node.attribute("depth").as_uint(); - std::string type = node.attribute("type").as_string(); + const std::string id = node.attribute("id").as_string(); + const uint32_t width = node.attribute("width").as_uint(); + const uint32_t height = node.attribute("height").as_uint(); + uint32_t depth = node.attribute("depth").as_uint(); + const std::string type = node.attribute("type").as_string(); bool tiled = node.attribute("tiled").as_bool(); if (node.empty()) { @@ -174,21 +171,22 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) { AMFTexture& als = *((AMFTexture*)ne);// alias for convenience - std::string enc64_data = node.value(); - // Check for child nodes + std::string enc64_data; + XmlParser::getValueAsString(node, enc64_data); + // Check for child nodes // check that all components was defined if (id.empty()) { throw DeadlyImportError("ID for texture must be defined."); } if (width < 1) { - throw DeadlyImportError("INvalid width for texture."); + throw DeadlyImportError("Invalid width for texture."); } if (height < 1) { throw DeadlyImportError("Invalid height for texture."); } if (depth < 1) { - throw DeadlyImportError("Invalid depth for texture."); + // throw DeadlyImportError("Invalid depth for texture."); } if (type != "grayscale") { throw DeadlyImportError("Invalid type for texture."); @@ -203,7 +201,9 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) { als.Depth = depth; als.Tiled = tiled; ParseHelper_Decode_Base64(enc64_data, als.Data); - + if (depth == 0) { + depth = (uint32_t)(als.Data.size() / (width * height)); + } // check data size if ((width * height * depth) != als.Data.size()) { throw DeadlyImportError("Texture has incorrect data size."); @@ -233,20 +233,18 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { AMFTexMap &als = *((AMFTexMap *)ne); // std::string rtexid, gtexid, btexid, atexid; if (!node.empty()) { - ParseHelper_Node_Enter(ne); - for (XmlNode ¤tNode : node.children()) { - const std::string ¤tName = currentNode.name(); - if (currentName == "rtexid") { - XmlParser::getValueAsString(node, rtexid); - } else if (currentName == "gtexid") { - XmlParser::getValueAsString(node, gtexid); - } else if (currentName == "btexid") { - XmlParser::getValueAsString(node, btexid); - } else if (currentName == "atexid") { - XmlParser::getValueAsString(node, atexid); + for (pugi::xml_attribute &attr : node.attributes()) { + const std::string ¤tAttr = attr.name(); + if (currentAttr == "rtexid") { + rtexid = attr.as_string(); + } else if (currentAttr == "gtexid") { + gtexid = attr.as_string(); + } else if (currentAttr == "btexid") { + btexid = attr.as_string(); + } else if (currentAttr == "atexid") { + atexid = attr.as_string(); } } - ParseHelper_Node_Exit(); } // create new texture coordinates object, alias for convenience @@ -256,7 +254,6 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { } // Check for children nodes - //XML_CheckNode_MustHaveChildren(); if (node.children().begin() == node.children().end()) { throw DeadlyImportError("Invalid children definition."); } @@ -264,28 +261,31 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { bool read_flag[6] = { false, false, false, false, false, false }; if (!pUseOldName) { - for (pugi::xml_attribute &attr : node.attributes()) { - const std::string name = attr.name(); + ParseHelper_Node_Enter(ne); + for ( XmlNode ¤tNode : node.children()) { + const std::string &name = currentNode.name(); if (name == "utex1") { read_flag[0] = true; - als.TextureCoordinate[0].x = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x); } else if (name == "utex2") { read_flag[1] = true; - als.TextureCoordinate[1].x = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x); } else if (name == "utex3") { read_flag[2] = true; - als.TextureCoordinate[2].x = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x); } else if (name == "vtex1") { read_flag[3] = true; - als.TextureCoordinate[0].y = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y); } else if (name == "vtex2") { read_flag[4] = true; - als.TextureCoordinate[1].y = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y); } else if (name == "vtex3") { read_flag[5] = true; - als.TextureCoordinate[0].y = attr.as_float(); + XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y); } } + ParseHelper_Node_Exit(); + } else { for (pugi::xml_attribute &attr : node.attributes()) { const std::string name = attr.name(); diff --git a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp index 9bbfc3249..036b647e8 100644 --- a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp +++ b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp @@ -62,12 +62,14 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /* // Check if stored data are supported. if (!Composition.empty()) { throw DeadlyImportError("IME. GetColor for composition"); - } else if (Color->Composed) { - throw DeadlyImportError("IME. GetColor, composed color"); - } else { - tcol = Color->Color; } + if (Color->Composed) { + throw DeadlyImportError("IME. GetColor, composed color"); + } + + tcol = Color->Color; + // Check if default color must be used if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { tcol.r = 0.5f; @@ -79,13 +81,13 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /* return tcol; } -void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector &pVertexCoordinateArray, +void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeElement, std::vector &vertexCoordinateArray, std::vector &pVertexColorArray) const { AMFVertices *vn = nullptr; size_t col_idx; // All data stored in "vertices", search for it. - for (AMFNodeElementBase *ne_child : pNodeElement.Child) { + for (AMFNodeElementBase *ne_child : nodeElement.Child) { if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) { vn = (AMFVertices*)ne_child; } @@ -97,7 +99,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem } // all coordinates stored as child and we need to reserve space for future push_back's. - pVertexCoordinateArray.reserve(vn->Child.size()); + vertexCoordinateArray.reserve(vn->Child.size()); // colors count equal vertices count. pVertexColorArray.resize(vn->Child.size()); @@ -112,7 +114,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem for (AMFNodeElementBase *vtx : vn_child->Child) { if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) { - pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate); + vertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate); continue; } diff --git a/code/AssetLib/Ogre/OgreMaterial.cpp b/code/AssetLib/Ogre/OgreMaterial.cpp index 35a9bf4c5..eced651f6 100644 --- a/code/AssetLib/Ogre/OgreMaterial.cpp +++ b/code/AssetLib/Ogre/OgreMaterial.cpp @@ -419,7 +419,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr size_t posUnderscore = textureRef.find_last_of("_"); if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { - string identifier = ai_str_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); + string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); ASSIMP_LOG_VERBOSE_DEBUG_F("Detecting texture type from filename postfix '", identifier, "'"); if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { @@ -440,7 +440,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr // Detect from texture unit name. This cannot be too broad as // authors might give names like "LightSaber" or "NormalNinja". else { - string unitNameLower = ai_str_tolower(textureUnitName); + string unitNameLower = ai_tolower(textureUnitName); if (unitNameLower.find("normalmap") != string::npos) { textureType = aiTextureType_NORMALS; } else if (unitNameLower.find("specularmap") != string::npos) { diff --git a/code/AssetLib/Ogre/OgreParsingUtils.h b/code/AssetLib/Ogre/OgreParsingUtils.h index 70797a237..0925c0305 100644 --- a/code/AssetLib/Ogre/OgreParsingUtils.h +++ b/code/AssetLib/Ogre/OgreParsingUtils.h @@ -64,7 +64,7 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo } if (!caseSensitive) { - return EndsWith(ai_str_tolower(s), ai_str_tolower(suffix), true); + return EndsWith(ai_tolower(s), ai_tolower(suffix), true); } size_t len = suffix.length(); diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.cpp b/code/AssetLib/Ogre/OgreXmlSerializer.cpp index 99c05a522..938ae48f3 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.cpp +++ b/code/AssetLib/Ogre/OgreXmlSerializer.cpp @@ -120,7 +120,7 @@ std::string OgreXmlSerializer::ReadAttribute(XmlNode &xmlNode, cons template <> bool OgreXmlSerializer::ReadAttribute(XmlNode &xmlNode, const char *name) const { - std::string value = ai_str_tolower(ReadAttribute(xmlNode, name)); + std::string value = ai_tolower(ReadAttribute(xmlNode, name)); if (ASSIMP_stricmp(value, "true") == 0) { return true; } else if (ASSIMP_stricmp(value, "false") == 0) { @@ -545,7 +545,7 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) { // Optional blend mode from root node if (XmlParser::hasAttribute(node, "blendmode")) { - skeleton->blendMode = (ai_str_tolower(ReadAttribute(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE); + skeleton->blendMode = (ai_tolower(ReadAttribute(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE); } for (XmlNode ¤tNode : node.children()) { diff --git a/code/AssetLib/STEPParser/STEPFileReader.cpp b/code/AssetLib/STEPParser/STEPFileReader.cpp index 113b8dd6a..cbf8c07c2 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.cpp +++ b/code/AssetLib/STEPParser/STEPFileReader.cpp @@ -278,7 +278,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, --ne; } while (IsSpace(s.at(ne))); std::string type = s.substr(ns, ne - ns + 1); - type = ai_str_tolower(type); + type = ai_tolower(type); const char* sz = scheme.GetStaticStringForToken(type); if(sz) { const std::string::size_type szLen = n2-n1+1; diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 815d5dd6a..ebc3e0116 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -298,7 +298,6 @@ SET(ASSIMP_EXPORTERS_DISABLED "") # disabled exporters list (used to print) ADD_ASSIMP_IMPORTER( AMF AssetLib/AMF/AMFImporter.hpp - AssetLib/AMF/AMFImporter_Macro.hpp AssetLib/AMF/AMFImporter_Node.hpp AssetLib/AMF/AMFImporter.cpp AssetLib/AMF/AMFImporter_Geometry.cpp diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index cbecbf075..0657216cf 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -276,7 +276,7 @@ std::string BaseImporter::GetExtension(const std::string &file) { // thanks to Andy Maloney for the hint std::string ret = file.substr(pos + 1); - ret = ai_str_tolower(ret); + ret = ai_tolower(ret); return ret; } diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 34953074c..db7fc9e1c 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -982,7 +982,7 @@ size_t Importer::GetImporterIndex (const char* szExtension) const { if (ext.empty()) { return static_cast(-1); } - ext = ai_str_tolower(ext); + ext = ai_tolower(ext); std::set str; for (std::vector::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { str.clear(); diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index b7aadcb23..dc304ff9c 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -137,7 +137,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); - extension = ai_str_tolower(extension); + extension = ai_tolower(extension); if (extension == "jpeg") { extension = "jpg"; } diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index b612a84cc..4afd717cf 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -225,7 +225,7 @@ AI_FORCE_INLINE char_t ai_tolower(char_t in) { /// @param in The incoming string. /// @return The string as lowercase. // --------------------------------------------------------------------------------- -AI_FORCE_INLINE std::string ai_str_tolower(const std::string &in) { +AI_FORCE_INLINE std::string ai_tolower(const std::string &in) { std::string out(in); ai_trim_left(out); ai_trim_right(out); diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index 5397594dc..8a47b259f 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/tools/assimp_view/LogWindow.cpp @@ -105,7 +105,7 @@ void CLogWindow::Init() { // setup the log text this->szText = AI_VIEW_RTF_LOG_HEADER; - ; + this->szPlainText = ""; } From 46e49d0b8352bbd6215b72a821c8e03db854b3a3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 3 Apr 2021 10:27:54 +0200 Subject: [PATCH 19/37] Update AMFImporter_Geometry.cpp --- code/AssetLib/AMF/AMFImporter_Geometry.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 6b01ecd63..7d6023316 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -39,16 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/// \file AMFImporter_Geometry.cpp -/// \brief Parsing data from geometry nodes. -/// \date 2016 -/// \author smal.root@gmail.com - #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #include "AMFImporter.hpp" -//#include "AMFImporter_Macro.hpp" - #include namespace Assimp { From d62c89557ba164be67a1df72302c1f628dc00858 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 3 Apr 2021 10:28:19 +0200 Subject: [PATCH 20/37] Remove dead code --- code/AssetLib/AMF/AMFImporter_Geometry.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 7d6023316..1fd2c49a4 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -108,12 +108,6 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) { } } ParseHelper_Node_Exit(); - //pugi::xml_node vertexNode = node.child("vertex"); - //if (!vertexNode.empty()) { - -// } else { -// } // if(!mReader->isEmptyElement()) else - mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. } From 80fc8538be9098aa7b9d7fb09bdaef5b3aace627 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 3 Apr 2021 10:29:16 +0200 Subject: [PATCH 21/37] Update AMFImporter_Material.cpp --- code/AssetLib/AMF/AMFImporter_Material.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/AssetLib/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp index 6b9300bfa..6d93a43b6 100644 --- a/code/AssetLib/AMF/AMFImporter_Material.cpp +++ b/code/AssetLib/AMF/AMFImporter_Material.cpp @@ -185,9 +185,6 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) { if (height < 1) { throw DeadlyImportError("Invalid height for texture."); } - if (depth < 1) { - // throw DeadlyImportError("Invalid depth for texture."); - } if (type != "grayscale") { throw DeadlyImportError("Invalid type for texture."); } From 7d68eab4a7183d701782a3e86e54be2938440918 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 3 Apr 2021 12:09:23 +0200 Subject: [PATCH 22/37] Update license --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index dc8e24706..acaaf016e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Open Asset Import Library (assimp) -Copyright (c) 2006-2020, assimp team +Copyright (c) 2006-2021, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, From 010c0853ea30b5ea9d74665ea3b6bc0ebf029d0d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 4 Apr 2021 14:40:50 +0200 Subject: [PATCH 23/37] Update INSTALL --- INSTALL | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/INSTALL b/INSTALL index ecec2585b..2cfd38078 100644 --- a/INSTALL +++ b/INSTALL @@ -8,43 +8,10 @@ Getting the documentation ------------------------------ A regularly-updated copy is available at -http://assimp.sourceforge.net/lib_html/index.html - -A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm. -To build the doxygen documentation on your own, follow these steps: - -a) download & install latest doxygen -b) make sure doxygen is in the executable search path -c) navigate to ./doc -d) and run 'doxygen' - -Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice. -Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop' -and configure the path to it in the DOXYFILE first. +https://assimp-docs.readthedocs.io/en/latest/ ------------------------------ Building Assimp ------------------------------ -More detailed build instructions can be found in the documentation, -this section is just for the inpatient among you. - -CMake is the preferred build system for Assimp. The minimum required version -is 2.6. If you don't have it yet, downloads for CMake can be found on -http://www.cmake.org/. - -For Unix: - -1. mkdir build && cd build -2. cmake .. -G 'Unix Makefiles' -3. make -j4 - -For Windows: -1. Open a command prompt -2. mkdir build -3. cd build -4. cmake .. -5. cmake --build . - -For iOS: -Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS +Just check the build-instaructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md From 437d7bf8b82bc048b20653a64efd913799988886 Mon Sep 17 00:00:00 2001 From: Garux Date: Mon, 5 Apr 2021 16:39:41 +0300 Subject: [PATCH 24/37] Fix MDC loader placement new was clearing input buffer by constructor, which was nothing to do with adequate parsing changes are not analyzed in depth, but at least test model and models of Wolf:ET are loading and not crashing --- code/AssetLib/MDC/MDCLoader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 90b88f7da..17a349768 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -250,7 +250,7 @@ void MDCImporter::InternReadFile( // get the number of valid surfaces BE_NCONST MDC::Surface *pcSurface, *pcSurface2; - pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface; + pcSurface = pcSurface2 = reinterpret_cast(mBuffer + pcHeader->ulOffsetSurfaces); unsigned int iNumShaders = 0; for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) { // validate the surface header @@ -260,7 +260,7 @@ void MDCImporter::InternReadFile( ++pScene->mNumMeshes; } iNumShaders += pcSurface2->ulNumShaders; - pcSurface2 = new ((int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface; + pcSurface2 = reinterpret_cast((BE_NCONST int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd); } aszShaders.reserve(iNumShaders); pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; @@ -405,7 +405,7 @@ void MDCImporter::InternReadFile( pcFaceCur->mIndices[2] = iOutIndex + 0; } - pcSurface = new ((int8_t *)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface; + pcSurface = reinterpret_cast((BE_NCONST int8_t *)pcSurface + pcSurface->ulOffsetEnd); } // create a flat node graph with a root node and one child for each surface From 31e80420714949395e1d971e73bab8f9e97e6954 Mon Sep 17 00:00:00 2001 From: Scott Baldric Date: Mon, 5 Apr 2021 09:59:22 -0500 Subject: [PATCH 25/37] Renaming PI to aiPi. --- include/assimp/MathFunctions.h | 4 ++-- test/unit/AssimpAPITest_aiMatrix4x4.cpp | 2 +- test/unit/AssimpAPITest_aiQuaternion.cpp | 6 +++--- test/unit/MathTest.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/assimp/MathFunctions.h b/include/assimp/MathFunctions.h index 1031eab9d..2088c394c 100644 --- a/include/assimp/MathFunctions.h +++ b/include/assimp/MathFunctions.h @@ -87,7 +87,7 @@ inline IntegerType lcm( IntegerType a, IntegerType b ) { } return a / t * b; } -/// @brief Will return the smallest epsilon-value for the requested type. +/// @brief Will return the smallest epsilon-value for the requested type. /// @return The numercical limit epsilon depending on its type. template inline T getEpsilon() { @@ -97,7 +97,7 @@ inline T getEpsilon() { /// @brief Will return the constant PI for the requested type. /// @return Pi template -inline T PI() { +inline T aiPi() { return static_cast(3.14159265358979323846); } diff --git a/test/unit/AssimpAPITest_aiMatrix4x4.cpp b/test/unit/AssimpAPITest_aiMatrix4x4.cpp index c47da877d..d2f57b19d 100644 --- a/test/unit/AssimpAPITest_aiMatrix4x4.cpp +++ b/test/unit/AssimpAPITest_aiMatrix4x4.cpp @@ -57,7 +57,7 @@ protected: aiMatrix4x4 get_predetermined_transformation_matrix_for_decomposition() const { aiMatrix4x4 t, r; aiMatrix4x4::Translation(aiVector3D(14,-25,-8), t); - aiMatrix4x4::Rotation(Math::PI() / 4.0f, aiVector3D(1).Normalize(), r); + aiMatrix4x4::Rotation(Math::aiPi() / 4.0f, aiVector3D(1).Normalize(), r); return t * r; } diff --git a/test/unit/AssimpAPITest_aiQuaternion.cpp b/test/unit/AssimpAPITest_aiQuaternion.cpp index 93c93f674..79f89337e 100644 --- a/test/unit/AssimpAPITest_aiQuaternion.cpp +++ b/test/unit/AssimpAPITest_aiQuaternion.cpp @@ -59,7 +59,7 @@ TEST_F(AssimpAPITest_aiQuaternion, aiCreateQuaternionFromMatrixTest) { // to prevent running into division by zero. aiMatrix3x3 m, r; aiMatrix3x3::Translation(aiVector2D(14,-25), m); - aiMatrix3x3::RotationZ(Math::PI() / 4.0f, r); + aiMatrix3x3::RotationZ(Math::aiPi() / 4.0f, r); m = m * r; result_cpp = aiQuaternion(m); @@ -127,8 +127,8 @@ TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionInterpolateTest) { // Use predetermined quaternions to prevent division by zero // during slerp calculations. const float INTERPOLATION(0.5f); - const auto q1 = aiQuaternion(aiVector3D(-1,1,1).Normalize(), Math::PI() / 4.0f); - const auto q2 = aiQuaternion(aiVector3D(1,2,1).Normalize(), Math::PI() / 2.0f); + const auto q1 = aiQuaternion(aiVector3D(-1,1,1).Normalize(), Math::aiPi() / 4.0f); + const auto q2 = aiQuaternion(aiVector3D(1,2,1).Normalize(), Math::aiPi() / 2.0f); aiQuaternion::Interpolate(result_cpp, q1, q2, INTERPOLATION); aiQuaternionInterpolate(&result_c, &q1, &q2, INTERPOLATION); EXPECT_EQ(result_cpp, result_c); diff --git a/test/unit/MathTest.cpp b/test/unit/MathTest.cpp index 88c95006c..ecc23545c 100644 --- a/test/unit/MathTest.cpp +++ b/test/unit/MathTest.cpp @@ -51,6 +51,6 @@ const float AssimpMathTest::Epsilon = Math::getEpsilon(); RandomUniformFloatGenerator AssimpMathTest::RandNonZero(1.0f, 100.0f); // Initialize with an interval of [-PI,PI] inclusively. -RandomUniformFloatGenerator AssimpMathTest::RandPI(-Math::PI(), Math::PI()); +RandomUniformFloatGenerator AssimpMathTest::RandPI(-Math::aiPi(), Math::aiPi()); } From 7fee91477691df3434a638578607ed5b098d1f32 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 5 Apr 2021 21:24:54 +0200 Subject: [PATCH 26/37] Fix direct leak closes https://github.com/assimp/assimp/issues/3747 --- code/AssetLib/HMP/HMPLoader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/HMP/HMPLoader.cpp b/code/AssetLib/HMP/HMPLoader.cpp index 9151e9d5d..56401f5c9 100644 --- a/code/AssetLib/HMP/HMPLoader.cpp +++ b/code/AssetLib/HMP/HMPLoader.cpp @@ -157,7 +157,10 @@ void HMPImporter::InternReadFile(const std::string &pFile, szBuffer[2] = ((char *)&iMagic)[2]; szBuffer[3] = ((char *)&iMagic)[3]; szBuffer[4] = '\0'; - + + delete[] mBuffer; + mBuffer = nullptr; + // We're definitely unable to load this file throw DeadlyImportError("Unknown HMP subformat ", pFile, ". Magic word (", szBuffer, ") is not known"); From a44ba4141343e18632d159e0f9a9cde8a2d9b224 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 5 Apr 2021 19:14:48 -0700 Subject: [PATCH 27/37] Fix incorrect indices in the MilkShape 3D loader --- code/AssetLib/MS3D/MS3DLoader.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index 10bc17ea3..192bcbe41 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -500,7 +500,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed"); } - TempTriangle& t = triangles[g.triangles[i]]; + TempTriangle& t = triangles[g.triangles[j]]; f.mIndices = new unsigned int[f.mNumIndices=3]; for (unsigned int k = 0; k < 3; ++k,++n) { @@ -508,7 +508,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed"); } - const TempVertex& v = vertices[t.indices[i]]; + const TempVertex& v = vertices[t.indices[k]]; for(unsigned int a = 0; a < 4; ++a) { if (v.bone_id[a] != UINT_MAX) { if (v.bone_id[a] >= joints.size()) { @@ -524,9 +524,9 @@ void MS3DImporter::InternReadFile( const std::string& pFile, // collect vertex components m->mVertices[n] = v.pos; - m->mNormals[n] = t.normals[i]; - m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0); - f.mIndices[i] = n; + m->mNormals[n] = t.normals[k]; + m->mTextureCoords[0][n] = aiVector3D(t.uv[k].x,1.f-t.uv[k].y,0.0); + f.mIndices[k] = n; } } From d1eeb80e1a7f2ff4b585e0911c000e64f508bb84 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Apr 2021 21:05:46 +0200 Subject: [PATCH 28/37] Not resize empty vectors. closes https://github.com/assimp/assimp/issues/3754 --- include/assimp/XmlParser.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index 2f123c54a..ba1f040d6 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +/// @brief Will find a node by its name. struct find_node_by_name_predicate { std::string mName; find_node_by_name_predicate(const std::string &name) : @@ -88,7 +89,11 @@ public: } void clear() { - mData.resize(0); + if(mData.empty() { + mDoc = nullptr; + return; + } + mData.clear(); delete mDoc; mDoc = nullptr; } From a6e4672df1f393b72419269dd1f4419ecdd2b06c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Apr 2021 23:19:00 +0200 Subject: [PATCH 29/37] Fix a typo. --- include/assimp/XmlParser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index ba1f040d6..15c4ff9ff 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -89,7 +89,7 @@ public: } void clear() { - if(mData.empty() { + if(mData.empty()) { mDoc = nullptr; return; } From 4aa52b3af8dcb5df9718a2457bc21a56c49e4810 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Tue, 13 Apr 2021 11:15:52 -0700 Subject: [PATCH 30/37] Flip the check on _MSC_VER for using TR1 containers. --- code/AssetLib/FBX/FBXCompileConfig.h | 12 ++++++------ code/AssetLib/Step/STEPFile.h | 10 +++++----- code/AssetLib/Step/StepExporter.cpp | 10 +++++----- code/AssetLib/glTF/glTFAsset.h | 6 +++--- code/AssetLib/glTF/glTFCommon.h | 6 +++--- code/AssetLib/glTF2/glTF2Asset.h | 8 ++++---- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/code/AssetLib/FBX/FBXCompileConfig.h b/code/AssetLib/FBX/FBXCompileConfig.h index dafa9e7c2..49860b844 100644 --- a/code/AssetLib/FBX/FBXCompileConfig.h +++ b/code/AssetLib/FBX/FBXCompileConfig.h @@ -62,16 +62,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP # include # include -# if _MSC_VER > 1600 -# define fbx_unordered_map unordered_map -# define fbx_unordered_multimap unordered_multimap -# define fbx_unordered_set unordered_set -# define fbx_unordered_multiset unordered_multiset -# else +# if defined(_MSC_VER) && _MSC_VER <= 1600 # define fbx_unordered_map tr1::unordered_map # define fbx_unordered_multimap tr1::unordered_multimap # define fbx_unordered_set tr1::unordered_set # define fbx_unordered_multiset tr1::unordered_multiset +# else +# define fbx_unordered_map unordered_map +# define fbx_unordered_multimap unordered_multimap +# define fbx_unordered_set unordered_set +# define fbx_unordered_multiset unordered_multiset # endif #endif diff --git a/code/AssetLib/Step/STEPFile.h b/code/AssetLib/Step/STEPFile.h index 3f4fe942b..90eaef5f3 100644 --- a/code/AssetLib/Step/STEPFile.h +++ b/code/AssetLib/Step/STEPFile.h @@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable : 4127 4456 4245 4512 ) -#endif // _MSC_VER +#endif // _MSC_VER // #if _MSC_VER > 1500 || (defined __GNUC___) @@ -69,12 +69,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP # include -# if _MSC_VER > 1600 -# define step_unordered_map unordered_map -# define step_unordered_multimap unordered_multimap -# else +# if defined(_MSC_VER) && _MSC_VER <= 1600 # define step_unordered_map tr1::unordered_map # define step_unordered_multimap tr1::unordered_multimap +# else +# define step_unordered_map unordered_map +# define step_unordered_multimap unordered_multimap # endif #endif diff --git a/code/AssetLib/Step/StepExporter.cpp b/code/AssetLib/Step/StepExporter.cpp index b3df3f60b..dfe5bab67 100644 --- a/code/AssetLib/Step/StepExporter.cpp +++ b/code/AssetLib/Step/StepExporter.cpp @@ -75,12 +75,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP # include -# if _MSC_VER > 1600 -# define step_unordered_map unordered_map -# define step_unordered_multimap unordered_multimap -# else +# if defined(_MSC_VER) && _MSC_VER <= 1600 # define step_unordered_map tr1::unordered_map # define step_unordered_multimap tr1::unordered_multimap +# else +# define step_unordered_map unordered_map +# define step_unordered_multimap unordered_multimap # endif #endif @@ -302,7 +302,7 @@ void StepExporter::WriteFile() dv23.Normalize(); dv31.Normalize(); dv13.Normalize(); - + aiVector3D dvY = dv12; aiVector3D dvX = dvY ^ dv13; dvX.Normalize(); diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index d2f8bd20f..1da70832b 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -92,10 +92,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP # include -# if _MSC_VER > 1600 -# define gltf_unordered_map unordered_map -# else +# if defined(_MSC_VER) && _MSC_VER <= 1600 # define gltf_unordered_map tr1::unordered_map +# else +# define gltf_unordered_map unordered_map # endif #endif diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h index 245490df6..d99ffbe86 100644 --- a/code/AssetLib/glTF/glTFCommon.h +++ b/code/AssetLib/glTF/glTFCommon.h @@ -74,10 +74,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP #include -#if _MSC_VER > 1600 -#define gltf_unordered_map unordered_map -#else +#if defined(_MSC_VER) && _MSC_VER <= 1600 #define gltf_unordered_map tr1::unordered_map +#else +#define gltf_unordered_map unordered_map #endif #endif diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 85eff4ac8..53b079117 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -98,12 +98,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP #include #include -#if _MSC_VER > 1600 -#define gltf_unordered_map unordered_map -#define gltf_unordered_set unordered_set -#else +#if defined(_MSC_VER) && _MSC_VER <= 1600 #define gltf_unordered_map tr1::unordered_map #define gltf_unordered_set tr1::unordered_set +#else +#define gltf_unordered_map unordered_map +#define gltf_unordered_set unordered_set #endif #endif From bef2304c5357a0ed761b98e7d5ae725fdf8f2591 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 14 Apr 2021 08:55:55 +0200 Subject: [PATCH 31/37] Update repo for assimp-net --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 51684c4aa..9fecfedf5 100644 --- a/Readme.md +++ b/Readme.md @@ -39,7 +39,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. ### Ports ### * [Android](port/AndroidJNI/README.md) * [Python](port/PyAssimp/README.md) -* [.NET](https://github.com/assimp/assimp-net) +* [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) From 6cbeca5518d8be6f91d4803427f0dd6d670bbd54 Mon Sep 17 00:00:00 2001 From: Krishty Date: Fri, 16 Apr 2021 20:44:40 +0200 Subject: [PATCH 32/37] fixed glTF export stuff being pulled into the EXE even if building with ASSIMP_BUILD_NO_EXPORT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “LazyDictBase::WriteObjects()” in the two glTF implementations is only used for export. Since it’s a virtual method, and many compilers have trouble removing unreferenced virtual methods, glTF export stuff is pulled into the binary even if compiling without exports. This commit removes said virtual function if only compiling for import. This removes 75 KiB of useless code when compiled with Visual Studio for x64. --- code/AssetLib/glTF/glTFAsset.h | 4 ++++ code/AssetLib/glTF/glTFImporter.cpp | 2 ++ code/AssetLib/glTF2/glTF2Asset.h | 4 ++++ code/AssetLib/glTF2/glTF2Importer.cpp | 2 ++ 4 files changed, 12 insertions(+) diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 1da70832b..623f18173 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -954,7 +954,9 @@ namespace glTF virtual void AttachToDocument(Document& doc) = 0; virtual void DetachFromDocument() = 0; +#if !defined(ASSIMP_BUILD_NO_EXPORT) virtual void WriteObjects(AssetWriter& writer) = 0; +#endif }; @@ -986,8 +988,10 @@ namespace glTF void AttachToDocument(Document& doc); void DetachFromDocument(); +#if !defined(ASSIMP_BUILD_NO_EXPORT) void WriteObjects(AssetWriter& writer) { WriteLazyDict(*this, writer); } +#endif Ref Add(T* obj); diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 3335fc109..5e072dd2a 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -43,7 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/glTF/glTFImporter.h" #include "AssetLib/glTF/glTFAsset.h" +#if !defined(ASSIMP_BUILD_NO_EXPORT) #include "AssetLib/glTF/glTFAssetWriter.h" +#endif #include "PostProcessing/MakeVerboseFormat.h" #include diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 53b079117..fad5cba83 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -997,7 +997,9 @@ public: virtual void AttachToDocument(Document &doc) = 0; virtual void DetachFromDocument() = 0; +#if !defined(ASSIMP_BUILD_NO_EXPORT) virtual void WriteObjects(AssetWriter &writer) = 0; +#endif }; template @@ -1030,7 +1032,9 @@ class LazyDict : public LazyDictBase { void AttachToDocument(Document &doc); void DetachFromDocument(); +#if !defined(ASSIMP_BUILD_NO_EXPORT) void WriteObjects(AssetWriter &writer) { WriteLazyDict(*this, writer); } +#endif Ref Add(T *obj); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index dca6fcb2d..ab1f01bf8 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -44,7 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/glTF2/glTF2Importer.h" #include "PostProcessing/MakeVerboseFormat.h" #include "AssetLib/glTF2/glTF2Asset.h" +#if !defined(ASSIMP_BUILD_NO_EXPORT) #include "AssetLib/glTF2/glTF2AssetWriter.h" +#endif #include #include From 3fead344ad06446ce2dca9ea528fcca7b6948e35 Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 07:37:12 +0200 Subject: [PATCH 33/37] updated version string (if anyone cares) --- code/Common/Version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/Version.cpp b/code/Common/Version.cpp index baa83940e..205dde52b 100644 --- a/code/Common/Version.cpp +++ b/code/Common/Version.cpp @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static const char *LEGAL_INFORMATION = "Open Asset Import Library (Assimp).\n" "A free C/C++ library to import various 3D file formats into applications\n\n" - "(c) 2006-2020, assimp team\n" + "(c) 2006-2021, Assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" "https://www.assimp.org\n"; From 930cc25c0e6426ccc6a92fdaab9b5eefe76c2a31 Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 09:51:44 +0200 Subject: [PATCH 34/37] fixed version string test --- test/unit/utVersion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utVersion.cpp b/test/unit/utVersion.cpp index 15d3366fa..0189cd2a9 100644 --- a/test/unit/utVersion.cpp +++ b/test/unit/utVersion.cpp @@ -48,7 +48,7 @@ TEST_F( utVersion, aiGetLegalStringTest ) { EXPECT_NE( lv, nullptr ); std::string text( lv ); - size_t pos( text.find( std::string( "2020" ) ) ); + size_t pos( text.find( std::string( "2021" ) ) ); EXPECT_NE( pos, std::string::npos ); } From 55dd5faafb4b80dd5f58147d56e69cd442eee29f Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 19:33:41 +0200 Subject: [PATCH 35/37] fixed export exceptions on import Ogre and 3MF imports threw DeadlyExportErrors under some circumstances. Bad for people who assumed that they only needed to catch DeadlyImportErrors. Changed them to DeadlyImportErrors. --- code/AssetLib/3MF/D3MFOpcPackage.cpp | 2 +- code/AssetLib/Ogre/OgreBinarySerializer.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index 514e3c2f3..16e659ea3 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -156,7 +156,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : mRootStream = mZipArchive->Open(rootFile.c_str()); ai_assert(mRootStream != nullptr); if (nullptr == mRootStream) { - throw DeadlyExportError("Cannot open root-file in archive : " + rootFile); + throw DeadlyImportError("Cannot open root-file in archive : " + rootFile); } } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index 13bf54e9f..0fc18feb9 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -181,13 +181,13 @@ Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream) { uint16_t id = serializer.ReadHeader(false); if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Mesh file header."); + throw DeadlyImportError("Invalid Ogre Mesh file header."); } /// @todo Check what we can actually support. std::string version = serializer.ReadLine(); if (version != MESH_VERSION_1_8) { - throw DeadlyExportError("Mesh version ", version, " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.", + throw DeadlyImportError("Mesh version ", version, " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.", " Supported versions: ", MESH_VERSION_1_8); } @@ -797,13 +797,13 @@ MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHand void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { uint16_t id = ReadHeader(false); if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Skeleton file header."); + throw DeadlyImportError("Invalid Ogre Skeleton file header."); } // This deserialization supports both versions of the skeleton spec std::string version = ReadLine(); if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) { - throw DeadlyExportError("Skeleton version ", version, " not supported by this importer.", + throw DeadlyImportError("Skeleton version ", version, " not supported by this importer.", " Supported versions: ", SKELETON_VERSION_1_8, " and ", SKELETON_VERSION_1_1); } From 31438a03a6430ee35c686b2bb7b3294fb55588cb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Apr 2021 14:52:31 +0200 Subject: [PATCH 36/37] Add Codacy Badge - Add assimp to codacy - Add batch to readme --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 9fecfedf5..e6c5fdbac 100644 --- a/Readme.md +++ b/Readme.md @@ -8,6 +8,7 @@ A library to import and export various 3d-model-formats including scene-post-pro Coverity Scan Build Status +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") From 4db4e7206da36f80136f85912beb2110866edb0d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Apr 2021 15:14:38 +0200 Subject: [PATCH 37/37] Update Readme.md --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index e6c5fdbac..81fd9fd9d 100644 --- a/Readme.md +++ b/Readme.md @@ -12,7 +12,6 @@ A library to import and export various 3d-model-formats including scene-post-pro [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)