diff options
author | Andy Nichols <andy.nichols@qt.io> | 2025-06-10 12:58:18 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2025-06-10 12:59:03 +0200 |
commit | 488a2f7af2920295ada886f113a0d563dab79b8d (patch) | |
tree | 60618a0947d45081caf6c5038cee9706e4af4ae0 /code/PostProcessing | |
parent | 647f94648c0ae24b9c6684383a9dbbc0e2fc23b7 (diff) | |
parent | fb375dd8c0a032106a2122815fb18dffe0283721 (diff) |
Merge tag 'v6.0.2' into qt6_assimpqt6_assimp
Change-Id: I70ab8ef899f760cfa3ef8406419ecdb976d6ffc3
Diffstat (limited to 'code/PostProcessing')
62 files changed, 269 insertions, 412 deletions
diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index fa524a7fd..90e1523f4 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -81,7 +81,7 @@ void ArmaturePopulate::Execute(aiScene *out) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; ASSIMP_LOG_VERBOSE_DEBUG("active node lookup: ", bone->mName.C_Str()); - + // lcl transform grab - done in generate_nodes :) aiNode *armature = GetArmatureRoot(bone_node, bones); diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index af1792fb0..939d3cb3a 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/CalcTangentsProcess.cpp b/code/PostProcessing/CalcTangentsProcess.cpp index 8fd063260..314907972 100644 --- a/code/PostProcessing/CalcTangentsProcess.cpp +++ b/code/PostProcessing/CalcTangentsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team @@ -200,7 +200,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) { localBitangent.NormalizeSafe(); // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. - bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z) + bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z) || (-0.5f < localTangent.x && localTangent.x < 0.5f && -0.5f < localTangent.y && localTangent.y < 0.5f && -0.5f < localTangent.z && localTangent.z < 0.5f); bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z) || (-0.5f < localBitangent.x && localBitangent.x < 0.5f && -0.5f < localBitangent.y && localBitangent.y < 0.5f && -0.5f < localBitangent.z && localBitangent.z < 0.5f); diff --git a/code/PostProcessing/CalcTangentsProcess.h b/code/PostProcessing/CalcTangentsProcess.h index 3d7bb2a5e..708f3b492 100644 --- a/code/PostProcessing/CalcTangentsProcess.h +++ b/code/PostProcessing/CalcTangentsProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ComputeUVMappingProcess.cpp b/code/PostProcessing/ComputeUVMappingProcess.cpp index cac51e8d0..c3d2e2b62 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.cpp +++ b/code/PostProcessing/ComputeUVMappingProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ComputeUVMappingProcess.h b/code/PostProcessing/ComputeUVMappingProcess.h index 2a40a15b1..663b4686f 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.h +++ b/code/PostProcessing/ComputeUVMappingProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 77c7cb853..224c8df15 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ConvertToLHProcess.h b/code/PostProcessing/ConvertToLHProcess.h index e5ef19a8d..f6f876ef6 100644 --- a/code/PostProcessing/ConvertToLHProcess.h +++ b/code/PostProcessing/ConvertToLHProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -60,7 +60,7 @@ struct aiNode; struct aiMaterial; struct aiCamera; -namespace Assimp { +namespace Assimp { // ----------------------------------------------------------------------------------- /** @brief The MakeLeftHandedProcess converts all imported data to a left-handed diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index 1ae79ee30..33ef2afbc 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -187,7 +187,7 @@ bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh) { } } else { vertexBones[vid] = i; - } + } } if(!isBoneNecessary[i]) { diff --git a/code/PostProcessing/DeboneProcess.h b/code/PostProcessing/DeboneProcess.h index cc2d43cb7..a7fb13cd4 100644 --- a/code/PostProcessing/DeboneProcess.h +++ b/code/PostProcessing/DeboneProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/DropFaceNormalsProcess.cpp b/code/PostProcessing/DropFaceNormalsProcess.cpp index 29967b74b..b252547b4 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.cpp +++ b/code/PostProcessing/DropFaceNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team diff --git a/code/PostProcessing/DropFaceNormalsProcess.h b/code/PostProcessing/DropFaceNormalsProcess.h index 84f9dbe83..859ac9c05 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.h +++ b/code/PostProcessing/DropFaceNormalsProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index 568031d8f..c39187391 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ProcessHelper.h" #include <fstream> +#include <algorithm> using namespace Assimp; @@ -91,25 +92,47 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { ASSIMP_LOG_INFO("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); } +std::string EmbedTexturesProcess::tryToFindValidPath(const std::string &imagePath) const +{ + // Test path directly + if (mIOHandler->Exists(imagePath)) { + return imagePath; + } + ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); + + // Test path in root path + std::string testPath = mRootPath + imagePath; + if (mIOHandler->Exists(testPath)) { + return testPath; + } + + // Test path basename in root path + testPath = mRootPath + imagePath.substr(imagePath.find_last_of("\\/") + 1u); + if (mIOHandler->Exists(testPath)) { + return testPath; + } + + // In unix systems, '\' is a valid file name character, but some files may use \ as a directory separator. + // Try replacing '\' by '/'. + if (mIOHandler->getOsSeparator() != '\\' && imagePath.find('\\') != std::string::npos) { + ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image '", imagePath, "' in root folder. Will try replacing directory separators."); + testPath = imagePath; + std::replace(testPath.begin(), testPath.end(), '\\', mIOHandler->getOsSeparator()); + return tryToFindValidPath(testPath); + } + + ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", imagePath, "."); + return {}; +} + bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path) const { std::streampos imageSize = 0; - std::string imagePath = path; + std::string imagePath = tryToFindValidPath(path); - // Test path directly - if (!mIOHandler->Exists(imagePath)) { - ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); - - // Test path in root path - imagePath = mRootPath + path; - if (!mIOHandler->Exists(imagePath)) { - // Test path basename in root path - imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); - if (!mIOHandler->Exists(imagePath)) { - ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); - return false; - } - } + if (imagePath.empty()) { + return false; } + IOStream* pFile = mIOHandler->Open(imagePath); if (pFile == nullptr) { ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); diff --git a/code/PostProcessing/EmbedTexturesProcess.h b/code/PostProcessing/EmbedTexturesProcess.h index 8210eec96..5fbc440ab 100644 --- a/code/PostProcessing/EmbedTexturesProcess.h +++ b/code/PostProcessing/EmbedTexturesProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -74,9 +73,11 @@ public: void SetupProperties(const Importer* pImp) override; /// Overwritten, @see BaseProcess - virtual void Execute(aiScene* pScene) override; + void Execute(aiScene* pScene) override; private: + // Try several ways to attempt to resolve the image path + std::string tryToFindValidPath(const std::string &imagePath) const; // Resolve the path and add the file content to the scene as a texture. bool addTexture(aiScene *pScene, const std::string &path) const; diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index 7401ea0e7..5006d41dd 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/FindDegenerates.h b/code/PostProcessing/FindDegenerates.h index 0d046df2d..0548da0e3 100644 --- a/code/PostProcessing/FindDegenerates.h +++ b/code/PostProcessing/FindDegenerates.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/mesh.h> class FindDegeneratesProcessTest; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- diff --git a/code/PostProcessing/FindInstancesProcess.cpp b/code/PostProcessing/FindInstancesProcess.cpp index 9186dd3dd..35a687773 100644 --- a/code/PostProcessing/FindInstancesProcess.cpp +++ b/code/PostProcessing/FindInstancesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team diff --git a/code/PostProcessing/FindInstancesProcess.h b/code/PostProcessing/FindInstancesProcess.h index 63e988abf..fd1bbb2d9 100644 --- a/code/PostProcessing/FindInstancesProcess.h +++ b/code/PostProcessing/FindInstancesProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 12f345407..fa4160aca 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/FindInvalidDataProcess.h b/code/PostProcessing/FindInvalidDataProcess.h index 516db4272..d6fa573e8 100644 --- a/code/PostProcessing/FindInvalidDataProcess.h +++ b/code/PostProcessing/FindInvalidDataProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/FixNormalsStep.cpp b/code/PostProcessing/FixNormalsStep.cpp index 2bf85430f..5dcb00d32 100644 --- a/code/PostProcessing/FixNormalsStep.cpp +++ b/code/PostProcessing/FixNormalsStep.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team diff --git a/code/PostProcessing/FixNormalsStep.h b/code/PostProcessing/FixNormalsStep.h index b25d92282..62933e40c 100644 --- a/code/PostProcessing/FixNormalsStep.h +++ b/code/PostProcessing/FixNormalsStep.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/GenBoundingBoxesProcess.cpp b/code/PostProcessing/GenBoundingBoxesProcess.cpp index da9fd7137..7f67593f8 100644 --- a/code/PostProcessing/GenBoundingBoxesProcess.cpp +++ b/code/PostProcessing/GenBoundingBoxesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/GenBoundingBoxesProcess.h b/code/PostProcessing/GenBoundingBoxesProcess.h index c24009dc9..3efb7e6cf 100644 --- a/code/PostProcessing/GenBoundingBoxesProcess.h +++ b/code/PostProcessing/GenBoundingBoxesProcess.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -19,7 +19,7 @@ conditions are met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -s + * 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 @@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -/** +/** * @brief Post-processing process to find axis-aligned bounding volumes for amm meshes * used in a scene. */ diff --git a/code/PostProcessing/GenFaceNormalsProcess.cpp b/code/PostProcessing/GenFaceNormalsProcess.cpp index 79a30ca24..5bf5c0e75 100644 --- a/code/PostProcessing/GenFaceNormalsProcess.cpp +++ b/code/PostProcessing/GenFaceNormalsProcess.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -41,9 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file Implementation of the post processing step to generate face -* normals for all imported faces. -*/ +/** + * @file Implementation of the post-processing step to generate face + * normals for all imported faces. + */ #include "GenFaceNormalsProcess.h" #include <assimp/Exceptional.h> @@ -55,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. +// Returns whether the processing step is in the given flag field. bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const { force_ = (pFlags & aiProcess_ForceGenNormals) != 0; flippedWindingOrder_ = (pFlags & aiProcess_FlipWindingOrder) != 0; @@ -64,7 +63,7 @@ bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const { } // ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. +// Executes the post-processing step on the given imported data. void GenFaceNormalsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin"); @@ -88,7 +87,7 @@ void GenFaceNormalsProcess::Execute(aiScene *pScene) { } // ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. +// Executes the post-processing step on the given imported data. bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) { if (nullptr != pMesh->mNormals) { if (force_) { @@ -107,8 +106,27 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) { } // allocate an array to hold the output normals - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - const float qnan = get_qnan(); + std::vector<aiVector3D> normals; + normals.resize(pMesh->mNumVertices); + + // mask to indicate if a vertex was already referenced and needs to be duplicated + std::vector<bool> alreadyReferenced; + alreadyReferenced.resize(pMesh->mNumVertices, false); + std::vector<aiVector3D> duplicatedVertices; + + auto storeNormalSplitVertex = [&](unsigned int index, const aiVector3D& normal) { + if (!alreadyReferenced[index]) { + normals[index] = normal; + alreadyReferenced[index] = true; + } else { + duplicatedVertices.push_back(pMesh->mVertices[index]); + normals.push_back(normal); + index = pMesh->mNumVertices + static_cast<unsigned int>(duplicatedVertices.size() - 1); + } + return index; + }; + + const aiVector3D undefinedNormal = aiVector3D(get_qnan()); // iterate through all faces and compute per-face normals but store them per-vertex. for (unsigned int a = 0; a < pMesh->mNumFaces; a++) { @@ -116,7 +134,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) { if (face.mNumIndices < 3) { // either a point or a line -> no well-defined normal vector for (unsigned int i = 0; i < face.mNumIndices; ++i) { - pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan); + face.mIndices[i] = storeNormalSplitVertex(face.mIndices[i], undefinedNormal); } continue; } @@ -124,15 +142,29 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) { const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]]; - // Boolean XOR - if either but not both of these flags is set, then the winding order has - // changed and the cross product to calculate the normal needs to be reversed - if (flippedWindingOrder_ != leftHanded_) + // Boolean XOR - if either but not both of these flags are set, then the winding order has + // changed and the cross-product to calculate the normal needs to be reversed + if (flippedWindingOrder_ != leftHanded_) std::swap(pV2, pV3); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); for (unsigned int i = 0; i < face.mNumIndices; ++i) { - pMesh->mNormals[face.mIndices[i]] = vNor; + face.mIndices[i] = storeNormalSplitVertex(face.mIndices[i], vNor); } } + + // store normals (and additional vertices) back into the mesh + if (!duplicatedVertices.empty()) { + const aiVector3D * oldVertices = pMesh->mVertices; + auto oldNumVertices = pMesh->mNumVertices; + pMesh->mNumVertices += static_cast<unsigned int>(duplicatedVertices.size()); + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + memcpy(pMesh->mVertices, oldVertices, oldNumVertices * sizeof(aiVector3D)); + memcpy(pMesh->mVertices + oldNumVertices, duplicatedVertices.data(), duplicatedVertices.size() * sizeof(aiVector3D)); + delete[] oldVertices; + } + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + memcpy(pMesh->mNormals, normals.data(), normals.size() * sizeof(aiVector3D)); + return true; } diff --git a/code/PostProcessing/GenFaceNormalsProcess.h b/code/PostProcessing/GenFaceNormalsProcess.h index a5aad13d1..a33d68df6 100644 --- a/code/PostProcessing/GenFaceNormalsProcess.h +++ b/code/PostProcessing/GenFaceNormalsProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { // --------------------------------------------------------------------------- -/** +/** * @brief The GenFaceNormalsProcess computes face normals for all faces of all meshes */ class ASSIMP_API_WINONLY GenFaceNormalsProcess : public BaseProcess { diff --git a/code/PostProcessing/GenVertexNormalsProcess.cpp b/code/PostProcessing/GenVertexNormalsProcess.cpp index f7fef6bc4..7cfb6594d 100644 --- a/code/PostProcessing/GenVertexNormalsProcess.cpp +++ b/code/PostProcessing/GenVertexNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/GenVertexNormalsProcess.h b/code/PostProcessing/GenVertexNormalsProcess.h index 677c06a43..6be1fae74 100644 --- a/code/PostProcessing/GenVertexNormalsProcess.h +++ b/code/PostProcessing/GenVertexNormalsProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ImproveCacheLocality.cpp b/code/PostProcessing/ImproveCacheLocality.cpp index e108354b1..0445920d6 100644 --- a/code/PostProcessing/ImproveCacheLocality.cpp +++ b/code/PostProcessing/ImproveCacheLocality.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ImproveCacheLocality.h b/code/PostProcessing/ImproveCacheLocality.h index 30fa59608..1cb081dec 100644 --- a/code/PostProcessing/ImproveCacheLocality.h +++ b/code/PostProcessing/ImproveCacheLocality.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index f4c623c98..19c3b47e9 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <unordered_set> #include <unordered_map> #include <memory> +#include <map> using namespace Assimp; @@ -99,52 +100,6 @@ void JoinVerticesProcess::Execute( aiScene* pScene) { namespace { -bool areVerticesEqual( - const Vertex &lhs, - const Vertex &rhs, - unsigned numUVChannels, - unsigned numColorChannels) { - // A little helper to find locally close vertices faster. - // Try to reuse the lookup table from the last step. - const static float epsilon = 1e-5f; - // Squared because we check against squared length of the vector difference - static const float squareEpsilon = epsilon * epsilon; - - // Square compare is useful for animeshes vertices compare - if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) { - return false; - } - - // We just test the other attributes even if they're not present in the mesh. - // In this case they're initialized to 0 so the comparison succeeds. - // By this method the non-present attributes are effectively ignored in the comparison. - if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) { - return false; - } - - if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) { - return false; - } - - if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) { - return false; - } - - for (unsigned i = 0; i < numUVChannels; i++) { - if ((lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) { - return false; - } - } - - for (unsigned i = 0; i < numColorChannels; i++) { - if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) { - return false; - } - } - - return true; -} - template<class XMesh> void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) { // replace vertex data with the unique data sets @@ -157,7 +112,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) { // ---------------------------------------------------------------------------- // Position, if present (check made for aiAnimMesh) - if (pMesh->mVertices) { + if (pMesh->mVertices) { std::unique_ptr<aiVector3D[]> oldVertices(pMesh->mVertices); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; for (unsigned int a = 0; a < pMesh->mNumVertices; a++) @@ -204,41 +159,6 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) { } // namespace // ------------------------------------------------------------------------------------------------ -// Unites identical vertices in the given mesh -// combine hashes -inline void hash_combine(std::size_t &) { - // empty -} - -template <typename T, typename... Rest> -inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { - std::hash<T> hasher; - seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); - hash_combine(seed, rest...); -} -//template specialization for std::hash for Vertex -template<> -struct std::hash<Vertex> { - std::size_t operator()(Vertex const& v) const noexcept { - size_t seed = 0; - hash_combine(seed, v.position.x ,v.position.y,v.position.z); - return seed; - } -}; -//template specialization for std::equal_to for Vertex -template<> -struct std::equal_to<Vertex> { - equal_to(unsigned numUVChannels, unsigned numColorChannels) : - mNumUVChannels(numUVChannels), - mNumColorChannels(numColorChannels) {} - bool operator()(const Vertex &lhs, const Vertex &rhs) const { - return areVerticesEqual(lhs, rhs, mNumUVChannels, mNumColorChannels); - } - -private: - unsigned mNumUVChannels; - unsigned mNumColorChannels; -}; static constexpr size_t JOINED_VERTICES_MARK = 0x80000000u; @@ -266,7 +186,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { // We'll never have more vertices afterwards. std::vector<int> uniqueVertices; - uniqueVertices.reserve( pMesh->mNumVertices); // For each vertex the index of the vertex it was replaced by. // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark @@ -276,31 +195,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff"); std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff); - // float posEpsilonSqr; - SpatialSort *vertexFinder = nullptr; - SpatialSort _vertexFinder; - - typedef std::pair<SpatialSort,float> SpatPair; - if (shared) { - std::vector<SpatPair >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) { - SpatPair& blubb = (*avf)[meshIndex]; - vertexFinder = &blubb.first; - // posEpsilonSqr = blubb.second; - } - } - if (!vertexFinder) { - // bad, need to compute it. - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); - vertexFinder = &_vertexFinder; - // posEpsilonSqr = ComputePositionEpsilon(pMesh); - } - - // Again, better waste some bytes than a realloc ... - std::vector<unsigned int> verticesFound; - verticesFound.reserve(10); - // Run an optimized code path if we don't have multiple UVs or vertex colors. // This should yield false in more than 99% of all imports ... const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0; @@ -314,14 +208,8 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { } } // a map that maps a vertex to its new index - const auto numBuckets = pMesh->mNumVertices; - const auto hasher = std::hash<Vertex>(); - const auto comparator = std::equal_to<Vertex>( - pMesh->GetNumUVChannels(), - pMesh->GetNumColorChannels()); - std::unordered_map<Vertex, int> vertex2Index(numBuckets, hasher, comparator); + std::map<Vertex, int> vertex2Index = {}; // we can not end up with more vertices than we started with - vertex2Index.reserve(pMesh->mNumVertices); // Now check each vertex if it brings something new to the table int newIndex = 0; for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { @@ -336,8 +224,8 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { // if the vertex is not in the map then it is a new vertex add it. if (it == vertex2Index.end()) { // this is a new vertex give it a new index - vertex2Index[v] = newIndex; - //keep track of its index and increment 1 + vertex2Index.emplace(v, newIndex); + // keep track of its index and increment 1 replaceIndex[a] = newIndex++; // add the vertex to the unique vertices uniqueVertices.push_back(a); diff --git a/code/PostProcessing/JoinVerticesProcess.h b/code/PostProcessing/JoinVerticesProcess.h index 60630dae3..ea72ac330 100644 --- a/code/PostProcessing/JoinVerticesProcess.h +++ b/code/PostProcessing/JoinVerticesProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -65,7 +64,7 @@ class ASSIMP_API JoinVerticesProcess : public BaseProcess { public: // ------------------------------------------------------------------- /// The default class constructor / destructor. - JoinVerticesProcess() = default; + JoinVerticesProcess() = default; ~JoinVerticesProcess() override = default; // ------------------------------------------------------------------- diff --git a/code/PostProcessing/LimitBoneWeightsProcess.cpp b/code/PostProcessing/LimitBoneWeightsProcess.cpp index 71b6f9ec6..33f466894 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.cpp +++ b/code/PostProcessing/LimitBoneWeightsProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -68,7 +68,7 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const { // Executes the post processing step on the given imported data. void LimitBoneWeightsProcess::Execute( aiScene* pScene) { ai_assert(pScene != nullptr); - + ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin"); for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) { @@ -88,7 +88,7 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) { // ------------------------------------------------------------------------------------------------ static unsigned int removeEmptyBones(aiMesh *pMesh) { ai_assert(pMesh != nullptr); - + unsigned int writeBone = 0; for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) { aiBone* bone = pMesh->mBones[readBone]; @@ -98,7 +98,7 @@ static unsigned int removeEmptyBones(aiMesh *pMesh) { delete bone; } } - + return writeBone; } diff --git a/code/PostProcessing/LimitBoneWeightsProcess.h b/code/PostProcessing/LimitBoneWeightsProcess.h index b2612c313..edb713853 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.h +++ b/code/PostProcessing/LimitBoneWeightsProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/MakeVerboseFormat.cpp b/code/PostProcessing/MakeVerboseFormat.cpp index d0c5693e7..837511b9c 100644 --- a/code/PostProcessing/MakeVerboseFormat.cpp +++ b/code/PostProcessing/MakeVerboseFormat.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team diff --git a/code/PostProcessing/MakeVerboseFormat.h b/code/PostProcessing/MakeVerboseFormat.h index 02fe21fa7..569c22495 100644 --- a/code/PostProcessing/MakeVerboseFormat.h +++ b/code/PostProcessing/MakeVerboseFormat.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiMesh; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** MakeVerboseFormatProcess: Class to convert an asset to the verbose diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index 01f6fca14..7323e3f04 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/OptimizeGraph.h b/code/PostProcessing/OptimizeGraph.h index c32748d7f..34ebafe2b 100644 --- a/code/PostProcessing/OptimizeGraph.h +++ b/code/PostProcessing/OptimizeGraph.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -58,7 +57,7 @@ struct aiMesh; class OptimizeGraphProcessTest; -namespace Assimp { +namespace Assimp { // ----------------------------------------------------------------------------- /** @brief Postprocessing step to optimize the scenegraph diff --git a/code/PostProcessing/OptimizeMeshes.cpp b/code/PostProcessing/OptimizeMeshes.cpp index 44792420c..0d9c26f6b 100644 --- a/code/PostProcessing/OptimizeMeshes.cpp +++ b/code/PostProcessing/OptimizeMeshes.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team diff --git a/code/PostProcessing/OptimizeMeshes.h b/code/PostProcessing/OptimizeMeshes.h index e424ae24a..e0fac3c41 100644 --- a/code/PostProcessing/OptimizeMeshes.h +++ b/code/PostProcessing/OptimizeMeshes.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -56,7 +55,7 @@ struct aiMesh; struct aiNode; class OptimizeMeshesProcessTest; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** @brief Postprocessing step to optimize mesh usage diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 0203ac211..0f96318e2 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -348,7 +348,7 @@ void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **i mesh->mBones = reinterpret_cast<aiBone **>(&node->mTransformation); mesh->mNumBones = UINT_MAX; continue; - } + } // try to find us in the list of newly created meshes for (unsigned int n = 0; n < out.size(); ++n) { diff --git a/code/PostProcessing/PretransformVertices.h b/code/PostProcessing/PretransformVertices.h index 74c886488..7f2f3db68 100644 --- a/code/PostProcessing/PretransformVertices.h +++ b/code/PostProcessing/PretransformVertices.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index cfbac3e80..526382578 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 273b122ae..69c45ff3c 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index 111c233b1..6343bd710 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -78,7 +78,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) { if (pScene->mNumMaterials == 0) { return; } - + // Find out which materials are referenced by meshes std::vector<bool> abReferenced(pScene->mNumMaterials,false); for (unsigned int i = 0;i < pScene->mNumMeshes;++i) { diff --git a/code/PostProcessing/RemoveRedundantMaterials.h b/code/PostProcessing/RemoveRedundantMaterials.h index 107de0daa..e317496c7 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.h +++ b/code/PostProcessing/RemoveRedundantMaterials.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -51,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class RemoveRedundantMatsTest; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** RemoveRedundantMatsProcess: Post-processing step to remove redundant diff --git a/code/PostProcessing/RemoveVCProcess.cpp b/code/PostProcessing/RemoveVCProcess.cpp index 13ef81e23..5ef3c04b8 100644 --- a/code/PostProcessing/RemoveVCProcess.cpp +++ b/code/PostProcessing/RemoveVCProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/RemoveVCProcess.h b/code/PostProcessing/RemoveVCProcess.h index 8d9b5167a..27d80eec9 100644 --- a/code/PostProcessing/RemoveVCProcess.h +++ b/code/PostProcessing/RemoveVCProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -83,7 +82,7 @@ public: * The function is a request to the process to update its configuration * basing on the Importer's configuration property list. */ - virtual void SetupProperties(const Importer* pImp) override; + void SetupProperties(const Importer* pImp) override; // ------------------------------------------------------------------- /** Manually setup the configuration flags for the step diff --git a/code/PostProcessing/ScaleProcess.cpp b/code/PostProcessing/ScaleProcess.cpp index 5cd7eea6e..3e28f746a 100644 --- a/code/PostProcessing/ScaleProcess.cpp +++ b/code/PostProcessing/ScaleProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ScaleProcess.h b/code/PostProcessing/ScaleProcess.h index 2887c7221..6faa38dd2 100644 --- a/code/PostProcessing/ScaleProcess.h +++ b/code/PostProcessing/ScaleProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -74,13 +73,13 @@ public: ai_real getScale() const; /// Overwritten, @see BaseProcess - virtual bool IsActive( unsigned int pFlags ) const override; + bool IsActive( unsigned int pFlags ) const override; /// Overwritten, @see BaseProcess - virtual void SetupProperties( const Importer* pImp ) override; + void SetupProperties( const Importer* pImp ) override; /// Overwritten, @see BaseProcess - virtual void Execute( aiScene* pScene ) override; + void Execute( aiScene* pScene ) override; private: void traverseNodes( aiNode *currentNode, unsigned int nested_node_id = 0 ); diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 48ebbc573..162ddab6f 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -66,36 +66,46 @@ void SortByPTypeProcess::SetupProperties(const Importer *pImp) { } // ------------------------------------------------------------------------------------------------ +static void clearMeshesInNode(aiNode *node) { + delete[] node->mMeshes; + node->mNumMeshes = 0; + node->mMeshes = nullptr; +} + +// ------------------------------------------------------------------------------------------------ // Update changed meshes in all nodes void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) { + ai_assert(node != nullptr); + if (node->mNumMeshes) { unsigned int newSize = 0; for (unsigned int m = 0; m < node->mNumMeshes; ++m) { unsigned int add = node->mMeshes[m] << 2; for (unsigned int i = 0; i < 4; ++i) { - if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize; + if (UINT_MAX != replaceMeshIndex[add + i]) { + ++newSize; + } } } - if (!newSize) { - delete[] node->mMeshes; - node->mNumMeshes = 0; - node->mMeshes = nullptr; - } else { - // Try to reuse the old array if possible - unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes); - - for (unsigned int m = 0; m < node->mNumMeshes; ++m) { - unsigned int add = node->mMeshes[m] << 2; - for (unsigned int i = 0; i < 4; ++i) { - if (UINT_MAX != replaceMeshIndex[add + i]) - *newMeshes++ = replaceMeshIndex[add + i]; + if (newSize == 0) { + clearMeshesInNode(node); + return; + } + + // Try to reuse the old array if possible + unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes); + for (unsigned int m = 0; m < node->mNumMeshes; ++m) { + unsigned int add = node->mMeshes[m] << 2; + for (unsigned int i = 0; i < 4; ++i) { + if (UINT_MAX != replaceMeshIndex[add + i]) { + *newMeshes++ = replaceMeshIndex[add + i]; } } - if (newSize > node->mNumMeshes) - delete[] node->mMeshes; - - node->mMeshes = newMeshes - (node->mNumMeshes = newSize); } + if (newSize > node->mNumMeshes) { + clearMeshesInNode(node); + } + node->mMeshes = newMeshes - (node->mNumMeshes = newSize); } // call all subnodes recursively @@ -126,6 +136,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh *const mesh = pScene->mMeshes[i]; if (mesh->mPrimitiveTypes == 0) { + for (size_t idx = 0; idx < outMeshes.size(); ++idx) { + delete outMeshes[idx]; + } throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str()); } @@ -167,6 +180,10 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { // with the largest number of primitives unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 }; aiFace *pFirstFace = mesh->mFaces; + if (pFirstFace == nullptr) { + continue; + } + aiFace *const pLastFace = pFirstFace + mesh->mNumFaces; unsigned int numPolyVerts = 0; @@ -308,7 +325,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { if (vert) { *vert++ = mesh->mVertices[idx]; } - if (nor) + if (nor) *nor++ = mesh->mNormals[idx]; if (tan) { *tan++ = mesh->mTangents[idx]; @@ -316,13 +333,13 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { } for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) { - if (!uv[pp]) + if (!uv[pp]) break; *uv[pp]++ = mesh->mTextureCoords[pp][idx]; } for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) { - if (!cols[pp]) + if (!cols[pp]) break; *cols[pp]++ = mesh->mColors[pp][idx]; } diff --git a/code/PostProcessing/SortByPTypeProcess.h b/code/PostProcessing/SortByPTypeProcess.h index aa7774d7f..d966d8522 100644 --- a/code/PostProcessing/SortByPTypeProcess.h +++ b/code/PostProcessing/SortByPTypeProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class SortByPTypeProcessTest; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index f63478767..e2500fe8a 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/SplitByBoneCountProcess.h b/code/PostProcessing/SplitByBoneCountProcess.h index c90661cb5..c41e435a3 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.h +++ b/code/PostProcessing/SplitByBoneCountProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -74,7 +74,7 @@ public: /// @brief Called prior to ExecuteOnScene(). /// The function is a request to the process to update its configuration /// basing on the Importer's configuration property list. - virtual void SetupProperties(const Importer* pImp) override; + void SetupProperties(const Importer* pImp) override; /// @brief Will return the maximal number of bones. /// @return The maximal number of bones. diff --git a/code/PostProcessing/SplitLargeMeshes.cpp b/code/PostProcessing/SplitLargeMeshes.cpp index 3bee28521..7d6d038e9 100644 --- a/code/PostProcessing/SplitLargeMeshes.cpp +++ b/code/PostProcessing/SplitLargeMeshes.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -100,6 +100,11 @@ void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) { // ------------------------------------------------------------------------------------------------ // Update a node after some meshes have been split void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& avList) { + if (pcNode == nullptr) { + ASSIMP_LOG_WARN("UpdateNode skipped, nullptr detected."); + return; + } + // for every index in out list build a new entry std::vector<unsigned int> aiEntries; aiEntries.reserve(pcNode->mNumMeshes + 1); diff --git a/code/PostProcessing/SplitLargeMeshes.h b/code/PostProcessing/SplitLargeMeshes.h index 25bf300d5..42133122b 100644 --- a/code/PostProcessing/SplitLargeMeshes.h +++ b/code/PostProcessing/SplitLargeMeshes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index 228e97e42..321479c21 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/TextureTransform.h b/code/PostProcessing/TextureTransform.h index 7c0addf09..2d491e319 100644 --- a/code/PostProcessing/TextureTransform.h +++ b/code/PostProcessing/TextureTransform.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -53,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiNode; struct aiMaterial; -namespace Assimp { +namespace Assimp { #define AI_TT_UV_IDX_LOCK_TBD 0xffffffff #define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee @@ -220,7 +219,7 @@ protected: private: unsigned int configFlags; }; - + } // namespace Assimp #endif //! AI_TEXTURE_TRANSFORM_H_INCLUDED diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index c0ffffd6b..e58f5fa98 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "PostProcessing/TriangulateProcess.h" #include "PostProcessing/ProcessHelper.h" #include "Common/PolyTools.h" +#include "contrib/earcut-hpp/earcut.hpp" #include <memory> #include <cstdint> @@ -74,6 +75,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define POLY_GRID_XPAD 20 #define POLY_OUTPUT_FILE "assimp_polygons_debug.txt" +namespace mapbox::util { + +template <> +struct nth<0, aiVector2D> { + inline static auto get(const aiVector2D& t) { + return t.x; + } +}; +template <> +struct nth<1, aiVector2D> { + inline static auto get(const aiVector2D& t) { + return t.y; + } +}; + +} // namespace mapbox::util + using namespace Assimp; namespace { @@ -225,7 +243,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { ASSIMP_LOG_ERROR( "Invalidation detected in the number of indices: does not fit to the primitive type." ); return false; } - + aiVector3D *nor_out = nullptr; // if we don't have normals yet, but expect them to be a cheap side @@ -244,7 +262,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { aiFace* out = new aiFace[numOut](), *curOut = out; std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */ - std::vector<aiVector2D> temp_verts(max_out+2); + std::vector<std::vector<aiVector2D>> temp_poly(1); /* temporary storage for earcut.hpp */ + std::vector<aiVector2D>& temp_verts = temp_poly[0]; + temp_verts.reserve(max_out + 2); NGONEncoder ngonEncoder; @@ -264,13 +284,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { const aiVector3D* verts = pMesh->mVertices; - // use std::unique_ptr to avoid slow std::vector<bool> specialiations - std::unique_ptr<bool[]> done(new bool[max_out]); for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { aiFace& face = pMesh->mFaces[a]; unsigned int* idx = face.mIndices; - int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num; + unsigned int num = face.mNumIndices; // Apply vertex colors to represent the face winding? #ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING @@ -363,16 +381,16 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { // 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 (unsigned int tmp = 0; tmp < num; ++tmp) { temp_verts3d[tmp] = verts[idx[tmp]]; } // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh aiVector3D n; - NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z); + NewellNormal<3, 3, 3>(n, num, &temp_verts3d.front().x, &temp_verts3d.front().y, &temp_verts3d.front().z); if (nor_out) { - for (tmp = 0; tmp < max; ++tmp) - nor_out[idx[tmp]] = n; + for (unsigned int tmp = 0; tmp < num; ++tmp) + nor_out[idx[tmp]] = n; } // Select largest normal coordinate to ignore for projection @@ -398,10 +416,20 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { std::swap(ac,bc); } - for (tmp =0; tmp < max; ++tmp) { + temp_verts.resize(num); + for (unsigned int tmp = 0; tmp < num; ++tmp) { temp_verts[tmp].x = verts[idx[tmp]][ac]; temp_verts[tmp].y = verts[idx[tmp]][bc]; - done[tmp] = false; + } + + auto indices = mapbox::earcut(temp_poly); + for (size_t i = 0; i < indices.size(); i += 3) { + aiFace& nface = *curOut++; + nface.mIndices = new unsigned int[3]; + nface.mNumIndices = 3; + nface.mIndices[0] = indices[i]; + nface.mIndices[1] = indices[i + 1]; + nface.mIndices[2] = indices[i + 2]; } #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS @@ -431,120 +459,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { fprintf(fout,"\ntriangulation sequence: "); #endif - - // - // FIXME: currently this is the slow O(kn) variant with a worst case - // complexity of O(n^2) (I think). Can be done in O(n). - while (num > 3) { - - // Find the next ear of the polygon - int num_found = 0; - for (ear = next;;prev = ear,ear = next) { - - // break after we looped two times without a positive match - for (next=ear+1;done[(next>=max?next=0:next)];++next); - if (next < ear) { - if (++num_found == 2) { - break; - } - } - const aiVector2D* pnt1 = &temp_verts[ear], - *pnt0 = &temp_verts[prev], - *pnt2 = &temp_verts[next]; - - // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1. - if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1) == 1) { - continue; - } - - // Skip when three point is in a line - aiVector2D left = *pnt0 - *pnt1; - aiVector2D right = *pnt2 - *pnt1; - - left.Normalize(); - right.Normalize(); - auto mul = left * right; - - // if the angle is 0 or 180 - if (std::abs(mul - 1.f) < ai_epsilon || std::abs(mul + 1.f) < ai_epsilon) { - // skip this ear - ASSIMP_LOG_WARN("Skip a ear, due to its angle is near 0 or 180."); - continue; - } - - // and no other point may be contained in this triangle - for ( tmp = 0; tmp < max; ++tmp) { - - // We need to compare the actual values because it's possible that multiple indexes in - // the polygon are referring to the same position. concave_polygon.obj is a sample - // - // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in - // PointInTriangle() I'm guessing that it's actually possible to construct - // input data that would cause us to end up with no ears. The problem is, - // which epsilon? If we chose a too large value, we'd get wrong results - const aiVector2D& vtmp = temp_verts[tmp]; - if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) { - break; - } - } - if (tmp != max) { - continue; - } - - // this vertex is an ear - break; - } - if (num_found == 2) { - - // Due to the 'two ear theorem', every simple polygon with more than three points must - // have 2 'ears'. Here's definitely something wrong ... but we don't give up yet. - // - - // Instead we're continuing with the standard tri-fanning algorithm which we'd - // use if we had only convex polygons. That's life. - ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?"); - -#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS - fprintf(fout,"critical error here, no ear found! "); -#endif - num = 0; - break; - } - - aiFace& nface = *curOut++; - nface.mNumIndices = 3; - - if (!nface.mIndices) { - nface.mIndices = new unsigned int[3]; - } - - // setup indices for the new triangle ... - nface.mIndices[0] = prev; - nface.mIndices[1] = ear; - nface.mIndices[2] = next; - - // exclude the ear from most further processing - done[ear] = true; - --num; - } - if (num > 0) { - // We have three indices forming the last 'ear' remaining. Collect them. - aiFace& nface = *curOut++; - nface.mNumIndices = 3; - if (!nface.mIndices) { - nface.mIndices = new unsigned int[3]; - } - - for (tmp = 0; done[tmp]; ++tmp); - nface.mIndices[0] = tmp; - - for (++tmp; done[tmp]; ++tmp); - nface.mIndices[1] = tmp; - - for (++tmp; done[tmp]; ++tmp); - nface.mIndices[2] = tmp; - - } } #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS diff --git a/code/PostProcessing/TriangulateProcess.h b/code/PostProcessing/TriangulateProcess.h index e17a10e33..485b59433 100644 --- a/code/PostProcessing/TriangulateProcess.h +++ b/code/PostProcessing/TriangulateProcess.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 8441b48be..fd977886c 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -134,7 +134,7 @@ inline void ValidateDSProcess::DoValidationEx(T **parray, unsigned int size, if (size == 0) { return; } - + if (!parray) { ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", firstName, secondName, size); @@ -447,7 +447,7 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) { ReportError("aiBone::mWeights[%i].mVertexId is out of range", i); } else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) { - ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value", i); + ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value %i. Value must be greater than zero and less than 1.", i, pBone->mWeights[i].mWeight); } afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight; } @@ -891,6 +891,9 @@ void ValidateDSProcess::Validate(const aiNode *pNode) { ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName); } } + } else if (pNode->mChildren) { + ReportError("aiNode::mChildren is not nullptr for empty node %s (aiNode::mNumChildren is %i)", + nodeName, pNode->mNumChildren); } } diff --git a/code/PostProcessing/ValidateDataStructure.h b/code/PostProcessing/ValidateDataStructure.h index 8bc13e60d..a6f2780f1 100644 --- a/code/PostProcessing/ValidateDataStructure.h +++ b/code/PostProcessing/ValidateDataStructure.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2024, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -63,7 +62,7 @@ struct aiString; struct aiCamera; struct aiLight; -namespace Assimp { +namespace Assimp { // -------------------------------------------------------------------------------------- /** Validates the whole ASSIMP scene data structure for correctness. |