From 0ebab47ca271f5af97804b15c9891ba447257b80 Mon Sep 17 00:00:00 2001 From: Matthew Wallace Date: Mon, 8 Mar 2021 07:11:39 -0600 Subject: [PATCH 01/25] 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 add165c4a19a77e96017e249b8028c2ff09695c6 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 24 Mar 2021 10:55:40 +0000 Subject: [PATCH 02/25] 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 03/25] 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 3fd865b4bf1a35cfca578c286107e97ecb1cae79 Mon Sep 17 00:00:00 2001 From: Gordon Chapman Date: Wed, 24 Mar 2021 18:10:03 -0700 Subject: [PATCH 04/25] Added Blendshape Support to FBX Export --- code/AssetLib/FBX/FBXExporter.cpp | 109 +++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index ae93cba02..322161411 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -812,6 +812,18 @@ void FBXExporter::WriteDefinitions () // Geometry / FbxMesh // <~~ aiMesh count = mScene->mNumMeshes; + + // Blendshapes are considered Geometry + int32_t bsDeformerCount=0; + for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + aiMesh* m = mScene->mMeshes[mi]; + if (m->mNumAnimMeshes > 0) { + count+=m->mNumAnimMeshes; + bsDeformerCount+=m->mNumAnimMeshes; // One deformer per blendshape + bsDeformerCount++; // Plus one master blendshape deformer + } + } + if (count) { n = FBX::Node("ObjectType", "Geometry"); n.AddChild("Count", count); @@ -978,7 +990,7 @@ void FBXExporter::WriteDefinitions () } // Deformer - count = int32_t(count_deformers(mScene)); + count = int32_t(count_deformers(mScene))+bsDeformerCount; if (count) { n = FBX::Node("ObjectType", "Deformer"); n.AddChild("Count", count); @@ -1363,6 +1375,7 @@ void FBXExporter::WriteObjects () n.End(outstream, binary, indent, true); } + // aiMaterial material_uids.clear(); for (size_t i = 0; i < mScene->mNumMaterials; ++i) { @@ -1697,6 +1710,100 @@ void FBXExporter::WriteObjects () } } + // Blendshapes, if any + for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + const aiMesh* m = mScene->mMeshes[mi]; + if (m->mNumAnimMeshes == 0) { + continue; + } + // make a deformer for this mesh + int64_t deformer_uid = generate_uid(); + FBX::Node dnode("Deformer"); + dnode.AddProperties(deformer_uid, m->mName.data + FBX::SEPARATOR + "Blendshapes", "BlendShape"); + dnode.AddChild("Version", int32_t(101)); + dnode.Dump(outstream, binary, indent); + // connect it + connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]); + std::vector vertex_indices = vVertexIndice[mi]; + + for (unsigned int am = 0; am < m->mNumAnimMeshes; ++am) { + aiAnimMesh *pAnimMesh = m->mAnimMeshes[am]; + std::string blendshape_name = pAnimMesh->mName.data; + + // start the node record + FBX::Node bsnode("Geometry"); + int64_t blendshape_uid = generate_uid(); + mesh_uids.push_back(blendshape_uid); + bsnode.AddProperty(blendshape_uid); + bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape"); + bsnode.AddProperty("Shape"); + bsnode.AddChild("Version", int32_t(100)); + bsnode.Begin(outstream, binary, indent); + bsnode.DumpProperties(outstream, binary, indent); + bsnode.EndProperties(outstream, binary, indent); + bsnode.BeginChildren(outstream, binary, indent); + indent++; + if (pAnimMesh->HasPositions()) { + std::vectorshape_indices; + std::vectorpPositionDiff; + std::vectorpNormalDiff; + + for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) { + aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]); + if(pDiff.Length()>1e-8){ + shape_indices.push_back(vertex_indices[vt]); + pPositionDiff.push_back(pDiff[0]); + pPositionDiff.push_back(pDiff[1]); + pPositionDiff.push_back(pDiff[2]); + + if (pAnimMesh->HasNormals()) { + aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]); + pNormalDiff.push_back(nDiff[0]); + pNormalDiff.push_back(nDiff[1]); + pNormalDiff.push_back(nDiff[2]); + } + } + } + + FBX::Node::WritePropertyNode( + "Indexes", shape_indices, outstream, binary, indent + ); + + FBX::Node::WritePropertyNode( + "Vertices", pPositionDiff, outstream, binary, indent + ); + + if (pNormalDiff.size()>0) { + FBX::Node::WritePropertyNode( + "Normals", pNormalDiff, outstream, binary, indent + ); + } + } + indent--; + bsnode.End(outstream, binary, indent, true); + + // Add blendshape Channel Deformer + FBX::Node sdnode("Deformer"); + const int64_t blendchannel_uid = generate_uid(); + sdnode.AddProperties( + blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel" + ); + sdnode.AddChild("Version", int32_t(100)); + sdnode.AddChild("DeformPercent", int32_t(100)); + FBX::Node p("Properties70"); + p.AddP70numberA("DeformPercent", 100.); + sdnode.AddChild(p); + // TODO: Normally just one weight per channel, adding stub for later development + std::vectorfFullWeights; + fFullWeights.push_back(0.); + sdnode.AddChild("FullWeights", fFullWeights); + sdnode.Dump(outstream, binary, indent); + + connections.emplace_back("C", "OO", blendchannel_uid, deformer_uid); + connections.emplace_back("C", "OO", blendshape_uid, blendchannel_uid); + } + } + // bones. // // output structure: From 0bd938c0247b7c3c3380a003f8b00c13cd26967b Mon Sep 17 00:00:00 2001 From: Elias Daler Date: Mon, 29 Mar 2021 02:26:03 +0300 Subject: [PATCH 05/25] 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 09d3266250fd266cb6c0c9c7ff0b1b8f52bf80a7 Mon Sep 17 00:00:00 2001 From: Bernold Kraft Date: Mon, 29 Mar 2021 15:31:08 +0200 Subject: [PATCH 06/25] Fixing 3DS import for CHUNK_TRMATRIX translation vector. --- code/AssetLib/3DS/3DSLoader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index 3dabf9da1..0a64f6870 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -981,9 +981,9 @@ void Discreet3DSImporter::ParseMeshChunk() { mMesh.mMat.a3 = stream->GetF4(); mMesh.mMat.b3 = stream->GetF4(); mMesh.mMat.c3 = stream->GetF4(); - mMesh.mMat.a4 = stream->GetF4(); - mMesh.mMat.b4 = stream->GetF4(); - mMesh.mMat.c4 = stream->GetF4(); + mMesh.mMat.d1 = stream->GetF4(); + mMesh.mMat.d2 = stream->GetF4(); + mMesh.mMat.d3 = stream->GetF4(); } break; case Discreet3DS::CHUNK_MAPLIST: { From 8e589221d7cd1e49769671219c2179af9e4ab66f Mon Sep 17 00:00:00 2001 From: Clement Jacob Date: Wed, 10 Mar 2021 09:48:12 +0100 Subject: [PATCH 07/25] [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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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 31e80420714949395e1d971e73bab8f9e97e6954 Mon Sep 17 00:00:00 2001 From: Scott Baldric Date: Mon, 5 Apr 2021 09:59:22 -0500 Subject: [PATCH 24/25] 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 25/25] 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");