From 5d841ec9a5889f910fe0ed906056616babefe6cf Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Apr 2023 18:20:14 +0200 Subject: [PATCH 1/5] Refactoring: Cleanup post-processing steps. --- code/AssetLib/3DS/3DSHelper.h | 4 -- code/AssetLib/X3D/X3DExporter.hpp | 2 - code/Geometry/GeometryUtils.cpp | 13 ++++ code/Geometry/GeometryUtils.h | 2 + code/PostProcessing/ArmaturePopulate.cpp | 27 +++------ code/PostProcessing/ArmaturePopulate.h | 8 +-- .../ComputeUVMappingProcess.cpp | 37 ++++-------- code/PostProcessing/ConvertToLHProcess.cpp | 9 --- code/PostProcessing/DeboneProcess.cpp | 12 ++-- code/PostProcessing/FindDegenerates.cpp | 3 +- code/PostProcessing/RemoveVCProcess.cpp | 59 ------------------- code/PostProcessing/ScaleProcess.cpp | 8 +-- code/PostProcessing/SortByPTypeProcess.cpp | 21 +++---- .../SplitByBoneCountProcess.cpp | 18 +++--- code/PostProcessing/SplitByBoneCountProcess.h | 13 +++- include/assimp/Vertex.h | 2 +- 16 files changed, 75 insertions(+), 163 deletions(-) diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 06c36bfeb..2279d105c 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -397,10 +397,6 @@ struct Material { Material(const Material &other) = default; - Material(Material &&other) AI_NO_EXCEPT = default; - - Material &operator=(Material &&other) AI_NO_EXCEPT = default; - virtual ~Material() = default; //! Name of the material diff --git a/code/AssetLib/X3D/X3DExporter.hpp b/code/AssetLib/X3D/X3DExporter.hpp index e77aa6877..babf552dd 100644 --- a/code/AssetLib/X3D/X3DExporter.hpp +++ b/code/AssetLib/X3D/X3DExporter.hpp @@ -58,8 +58,6 @@ class X3DExporter { Value(value) { // empty } - - SAttribute(SAttribute &&rhs) AI_NO_EXCEPT = default; }; /***********************************************/ diff --git a/code/Geometry/GeometryUtils.cpp b/code/Geometry/GeometryUtils.cpp index ab735aa6e..92a3aa853 100644 --- a/code/Geometry/GeometryUtils.cpp +++ b/code/Geometry/GeometryUtils.cpp @@ -76,4 +76,17 @@ ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh return area; } +// ------------------------------------------------------------------------------------------------ +// Check whether a ray intersects a plane and find the intersection point +bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, + const aiVector3D& planeNormal, aiVector3D& pos) { + const ai_real b = planeNormal * (planePos - ray.pos); + ai_real h = ray.dir * planeNormal; + if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0) + return false; + + pos = ray.pos + (ray.dir * h); + return true; +} + } // namespace Assimp diff --git a/code/Geometry/GeometryUtils.h b/code/Geometry/GeometryUtils.h index ab49380de..bd2038f78 100644 --- a/code/Geometry/GeometryUtils.h +++ b/code/Geometry/GeometryUtils.h @@ -62,6 +62,8 @@ public: /// @param mesh The mesh containing the face /// @return The area. static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ); + + static bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, const aiVector3D& planeNormal, aiVector3D& pos); }; } // namespace Assimp diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index a05cd91e9..a29735205 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -47,11 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -/// The default class constructor. -ArmaturePopulate::ArmaturePopulate() = default; +static bool IsBoneNode(const aiString &bone_name, std::vector &bones) { + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } + } -/// The class destructor. -ArmaturePopulate::~ArmaturePopulate() = default; + return false; +} bool ArmaturePopulate::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_PopulateArmatureData) != 0; @@ -78,9 +82,8 @@ 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 :) - - // bone->mOffsetMatrix = bone_node->mTransformation; aiNode *armature = GetArmatureRoot(bone_node, bones); ai_assert(armature); @@ -212,18 +215,6 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, return nullptr; } -// Simple IsBoneNode check if this could be a bone -bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, - std::vector &bones) { - for (aiBone *bone : bones) { - if (bone->mName == bone_name) { - return true; - } - } - - return false; -} - // Pop this node by name from the stack if found // Used in multiple armature situations with duplicate node / bone names // Known flaw: cannot have nodes with bone names, will be fixed in later release diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index 530932f48..83cbf8cf7 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -69,10 +69,10 @@ namespace Assimp { class ASSIMP_API ArmaturePopulate : public BaseProcess { public: /// The default class constructor. - ArmaturePopulate(); + ArmaturePopulate() = default; /// The class destructor. - virtual ~ArmaturePopulate(); + virtual ~ArmaturePopulate() = default; /// Overwritten, @see BaseProcess virtual bool IsActive( unsigned int pFlags ) const; @@ -86,9 +86,6 @@ public: static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector &bone_list); - static bool IsBoneNode(const aiString &bone_name, - std::vector &bones); - static aiNode *GetNodeFromStack(const aiString &node_name, std::vector &nodes); @@ -108,5 +105,4 @@ public: } // Namespace Assimp - #endif // SCALE_PROCESS_H_ diff --git a/code/PostProcessing/ComputeUVMappingProcess.cpp b/code/PostProcessing/ComputeUVMappingProcess.cpp index a5472668b..e81f63d42 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.cpp +++ b/code/PostProcessing/ComputeUVMappingProcess.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,10 +41,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file GenUVCoords step */ - #include "ComputeUVMappingProcess.h" #include "ProcessHelper.h" #include +#include "Geometry/GeometryUtils.h" using namespace Assimp; @@ -59,31 +58,17 @@ namespace { // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const -{ +bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_GenUVCoords) != 0; } -// ------------------------------------------------------------------------------------------------ -// Check whether a ray intersects a plane and find the intersection point -inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, - const aiVector3D& planeNormal, aiVector3D& pos) -{ - const ai_real b = planeNormal * (planePos - ray.pos); - ai_real h = ray.dir * planeNormal; - if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0) - return false; - - pos = ray.pos + (ray.dir * h); - return true; -} - // ------------------------------------------------------------------------------------------------ // Find the first empty UV channel in a mesh -inline unsigned int FindEmptyUVChannel (aiMesh* mesh) -{ +inline unsigned int FindEmptyUVChannel (aiMesh* mesh) { for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) - if (!mesh->mTextureCoords[m])return m; + if (!mesh->mTextureCoords[m]) { + return m; + } ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found"); return UINT_MAX; @@ -91,8 +76,7 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh) // ------------------------------------------------------------------------------------------------ // Try to remove UV seams -void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) -{ +void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { // TODO: just a very rough algorithm. I think it could be done // much easier, but I don't know how and am currently too tired to // to think about a better solution. @@ -103,10 +87,11 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) const static ai_real LOWER_EPSILON = ai_real( 10e-3 ); const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 ); - for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) - { + for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) { const aiFace& face = mesh->mFaces[fidx]; - if (face.mNumIndices < 3) continue; // triangles and polygons only, please + if (face.mNumIndices < 3) { + continue; // triangles and polygons only, please + } unsigned int smallV = face.mNumIndices, large = smallV; bool zero = false, one = false, round_to_zero = false; diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 08e3fe48a..e67bf030f 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -219,13 +217,6 @@ void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) { // rotation keys for (unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) { - /* That's the safe version, but the float errors add up. So we try the short version instead - aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix(); - rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3; - rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2; - aiQuaternion rotquat( rotmat); - pAnim->mRotationKeys[a].mValue = rotquat; - */ pAnim->mRotationKeys[a].mValue.x *= -1.0f; pAnim->mRotationKeys[a].mValue.y *= -1.0f; } diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index 2a8499dc5..e91196ce2 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -87,7 +86,7 @@ void DeboneProcess::Execute( aiScene* pScene) { if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) { for(unsigned int a = 0; a < pScene->mNumMeshes; a++) { if(splitList[a]) { - numSplits++; + ++numSplits; } } } @@ -119,8 +118,8 @@ void DeboneProcess::Execute( aiScene* pScene) { aiNode *theNode = find ? pScene->mRootNode->FindNode(*find) : nullptr; std::pair push_pair(static_cast(meshes.size()),theNode); - mSubMeshIndices[a].push_back(push_pair); - meshes.push_back(newMeshes[b].first); + mSubMeshIndices[a].emplace_back(push_pair); + meshes.emplace_back(newMeshes[b].first); out+=newMeshes[b].first->mNumBones; } @@ -360,9 +359,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const { unsigned int m = static_cast(pNode->mNumMeshes), n = static_cast(mSubMeshIndices.size()); // first pass, look for meshes which have not moved - for(unsigned int a=0;amMeshes[a]; const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex]; unsigned int nSubmeshes = static_cast(subMeshes.size()); @@ -376,8 +373,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const { // second pass, collect deboned meshes - for(unsigned int a=0;a > &subMeshes = mSubMeshIndices[a]; unsigned int nSubmeshes = static_cast(subMeshes.size()); diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index 5874c17d2..87ee75601 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -236,8 +236,7 @@ evil_jump_outside: face_src.mNumIndices = 0; face_src.mIndices = nullptr; } - } - else { + } else { // Otherwise delete it if we don't need this face delete[] face_src.mIndices; face_src.mIndices = nullptr; diff --git a/code/PostProcessing/RemoveVCProcess.cpp b/code/PostProcessing/RemoveVCProcess.cpp index 35047dc0a..bcad65423 100644 --- a/code/PostProcessing/RemoveVCProcess.cpp +++ b/code/PostProcessing/RemoveVCProcess.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -74,63 +72,6 @@ inline void ArrayDelete(T **&in, unsigned int &num) { num = 0; } -#if 0 -// ------------------------------------------------------------------------------------------------ -// Updates the node graph - removes all nodes which have the "remove" flag set and the -// "don't remove" flag not set. Nodes with meshes are never deleted. -bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) -{ - bool b = false; - - std::list mine; - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - if(UpdateNodeGraph(node->mChildren[i],mine,false)) - b = true; - } - - // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set, - // so we can do a simple comparison against MSB here - if (!root && AI_RC_UINT_MSB == node->mNumMeshes ) - { - // this node needs to be removed - if(node->mNumChildren) - { - childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end()); - - // set all children to nullptr to make sure they are not deleted when we delete ourself - for (unsigned int i = 0; i < node->mNumChildren;++i) - node->mChildren[i] = nullptr; - } - b = true; - delete node; - } - else - { - AI_RC_UNMASK(node->mNumMeshes); - childsOfParent.push_back(node); - - if (b) - { - // reallocate the array of our children here - node->mNumChildren = (unsigned int)mine.size(); - aiNode** const children = new aiNode*[mine.size()]; - aiNode** ptr = children; - - for (std::list::iterator it = mine.begin(), end = mine.end(); - it != end; ++it) - { - *ptr++ = *it; - } - delete[] node->mChildren; - node->mChildren = children; - return false; - } - } - return b; -} -#endif - // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. void RemoveVCProcess::Execute(aiScene *pScene) { diff --git a/code/PostProcessing/ScaleProcess.cpp b/code/PostProcessing/ScaleProcess.cpp index 665f28a7e..00df07090 100644 --- a/code/PostProcessing/ScaleProcess.cpp +++ b/code/PostProcessing/ScaleProcess.cpp @@ -86,9 +86,9 @@ void ScaleProcess::Execute( aiScene* pScene ) { return; // nothing to scale } - ai_assert( mScale != 0 ); - ai_assert( nullptr != pScene ); - ai_assert( nullptr != pScene->mRootNode ); + ai_assert(mScale != 0 ); + ai_assert(nullptr != pScene ); + ai_assert(nullptr != pScene->mRootNode ); if ( nullptr == pScene ) { return; @@ -140,7 +140,7 @@ void ScaleProcess::Execute( aiScene* pScene ) { aiMatrix4x4 scaling; aiMatrix4x4::Scaling( aiVector3D(scale), scaling ); - aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix()); + const aiMatrix4x4 RotMatrix = aiMatrix4x4(rotation.GetMatrix()); bone->mOffsetMatrix = translation * RotMatrix * scaling; } diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 1be75fc48..394ef15c8 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,10 +52,7 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -SortByPTypeProcess::SortByPTypeProcess() : - mConfigRemoveMeshes(0) { - // empty -} +SortByPTypeProcess::SortByPTypeProcess() : mConfigRemoveMeshes(0) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. @@ -155,7 +150,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { if (1 == num) { if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) { *meshIdx = static_cast(outMeshes.size()); - outMeshes.push_back(mesh); + outMeshes.emplace_back(mesh); } else { delete mesh; pScene->mMeshes[i] = nullptr; @@ -311,21 +306,23 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { if (vert) { *vert++ = mesh->mVertices[idx]; - //mesh->mVertices[idx].x = get_qnan(); } - if (nor) *nor++ = mesh->mNormals[idx]; + if (nor) + *nor++ = mesh->mNormals[idx]; if (tan) { *tan++ = mesh->mTangents[idx]; *bit++ = mesh->mBitangents[idx]; } for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) { - if (!uv[pp]) break; + 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]) break; + if (!cols[pp]) + break; *cols[pp]++ = mesh->mColors[pp][idx]; } @@ -351,7 +348,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { } } if (pp == mesh->mNumAnimMeshes) - amIdx++; + ++amIdx; in.mIndices[q] = outIdx++; } diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 5324160d4..e44a55979 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -166,7 +165,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector isBoneUsed( pMesh->mNumBones, false); // indices of the faces which are going to go into this submesh - std::vector subMeshFaces; + IndexArray subMeshFaces; subMeshFaces.reserve( pMesh->mNumFaces); // accumulated vertex count of all the faces in this submesh unsigned int numSubMeshVertices = 0; @@ -202,7 +201,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it) { if (!isBoneUsed[*it]) { isBoneUsed[*it] = true; - numBones++; + ++numBones; } } @@ -212,18 +211,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormName.length > 0 ) - { + if( pMesh->mName.length > 0 ) { newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); } newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; - poNewMeshes.push_back( newMesh); + poNewMeshes.emplace_back( newMesh); // create all the arrays for this mesh if the old mesh contained them newMesh->mNumVertices = numSubMeshVertices; @@ -251,7 +249,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormFaces = new aiFace[subMeshFaces.size()]; unsigned int nvi = 0; // next vertex index - std::vector previousVertexIndices( numSubMeshVertices, std::numeric_limits::max()); // per new vertex: its index in the source mesh + IndexArray previousVertexIndices( numSubMeshVertices, std::numeric_limits::max()); // per new vertex: its index in the source mesh for( unsigned int a = 0; a < subMeshFaces.size(); ++a ) { const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]]; aiFace& dstFace = newMesh->mFaces[a]; @@ -399,10 +397,10 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumMeshes == 0 ) { - std::vector newMeshList; + IndexArray newMeshList; for( unsigned int a = 0; a < pNode->mNumMeshes; ++a) { unsigned int srcIndex = pNode->mMeshes[a]; - const std::vector& replaceMeshes = mSubMeshIndices[srcIndex]; + const IndexArray& replaceMeshes = mSubMeshIndices[srcIndex]; newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end()); } diff --git a/code/PostProcessing/SplitByBoneCountProcess.h b/code/PostProcessing/SplitByBoneCountProcess.h index 625019e0c..efe85824f 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.h +++ b/code/PostProcessing/SplitByBoneCountProcess.h @@ -76,6 +76,10 @@ public: /// basing on the Importer's configuration property list. virtual void SetupProperties(const Importer* pImp) override; + /// @brief Will return the maximal number of bones. + /// @return The maximal number of bones. + size_t getMaxNumberOfBones() const; + protected: /// Executes the post processing step on the given imported data. /// At the moment a process is not supposed to fail. @@ -90,14 +94,19 @@ protected: /// Recursively updates the node's mesh list to account for the changed mesh list void UpdateNode( aiNode* pNode) const; -public: +private: /// Max bone count. Splitting occurs if a mesh has more than that number of bones. size_t mMaxBoneCount; /// Per mesh index: Array of indices of the new submeshes. - std::vector< std::vector > mSubMeshIndices; + using IndexArray = std::vector; + std::vector mSubMeshIndices; }; +inline size_t SplitByBoneCountProcess::getMaxNumberOfBones() const { + return mMaxBoneCount; +} + } // end of namespace Assimp #endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index fd7eb037e..b4aa1dd2d 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -105,7 +105,7 @@ class Vertex { friend Vertex operator * (ai_real, const Vertex&); public: - Vertex() {} + Vertex() = default; // ---------------------------------------------------------------------------- /** Extract a particular vertex from a mesh and interleave all components */ From d58201a579759305cec8330cdcc908d954d2b970 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 4 May 2023 00:00:52 +0200 Subject: [PATCH 2/5] Refactoring: Reuse code from GeometryUtils --- code/Geometry/GeometryUtils.cpp | 8 + code/Geometry/GeometryUtils.h | 14 +- .../ComputeUVMappingProcess.cpp | 289 ++++++++--------- .../PostProcessing/DropFaceNormalsProcess.cpp | 25 +- code/PostProcessing/FindDegenerates.cpp | 80 +++-- code/PostProcessing/PretransformVertices.cpp | 293 +++++++++--------- code/PostProcessing/PretransformVertices.h | 18 +- code/PostProcessing/ProcessHelper.cpp | 7 +- .../RemoveRedundantMaterials.cpp | 33 +- code/PostProcessing/ScaleProcess.cpp | 1 - code/PostProcessing/SortByPTypeProcess.cpp | 3 +- .../SplitByBoneCountProcess.cpp | 4 +- code/PostProcessing/SplitLargeMeshes.cpp | 36 +-- code/PostProcessing/TextureTransform.cpp | 6 +- code/PostProcessing/TriangulateProcess.cpp | 45 +-- code/PostProcessing/ValidateDataStructure.cpp | 83 +++-- include/assimp/StreamWriter.h | 5 +- include/assimp/Vertex.h | 25 +- test/CMakeLists.txt | 18 +- test/unit/Geometry/utGeometryUtils.cpp | 68 ++++ 20 files changed, 526 insertions(+), 535 deletions(-) create mode 100644 test/unit/Geometry/utGeometryUtils.cpp diff --git a/code/Geometry/GeometryUtils.cpp b/code/Geometry/GeometryUtils.cpp index 92a3aa853..ad99f2224 100644 --- a/code/Geometry/GeometryUtils.cpp +++ b/code/Geometry/GeometryUtils.cpp @@ -89,4 +89,12 @@ bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, return true; } +// ------------------------------------------------------------------------------------------------ +void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, + size_t numVectors) { + for (size_t i=0; i -#include "Geometry/GeometryUtils.h" using namespace Assimp; namespace { - const static aiVector3D base_axis_y(0.0,1.0,0.0); - const static aiVector3D base_axis_x(1.0,0.0,0.0); - const static aiVector3D base_axis_z(0.0,0.0,1.0); - const static ai_real angle_epsilon = ai_real( 0.95 ); -} +const static aiVector3D base_axis_y(0.0, 1.0, 0.0); +const static aiVector3D base_axis_x(1.0, 0.0, 0.0); +const static aiVector3D base_axis_z(0.0, 0.0, 1.0); +const static ai_real angle_epsilon = ai_real(0.95); +} // namespace // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const { - return (pFlags & aiProcess_GenUVCoords) != 0; +bool ComputeUVMappingProcess::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_GenUVCoords) != 0; } // ------------------------------------------------------------------------------------------------ // Find the first empty UV channel in a mesh -inline unsigned int FindEmptyUVChannel (aiMesh* mesh) { - for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) +inline unsigned int FindEmptyUVChannel(aiMesh *mesh) { + for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++m) if (!mesh->mTextureCoords[m]) { return m; } @@ -76,19 +76,19 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh) { // ------------------------------------------------------------------------------------------------ // Try to remove UV seams -void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { +void RemoveUVSeams(aiMesh *mesh, aiVector3D *out) { // TODO: just a very rough algorithm. I think it could be done // much easier, but I don't know how and am currently too tired to // to think about a better solution. - const static ai_real LOWER_LIMIT = ai_real( 0.1 ); - const static ai_real UPPER_LIMIT = ai_real( 0.9 ); + const static ai_real LOWER_LIMIT = ai_real(0.1); + const static ai_real UPPER_LIMIT = ai_real(0.9); - const static ai_real LOWER_EPSILON = ai_real( 10e-3 ); - const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 ); + const static ai_real LOWER_EPSILON = ai_real(10e-3); + const static ai_real UPPER_EPSILON = ai_real(1.0 - 10e-3); - for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) { - const aiFace& face = mesh->mFaces[fidx]; + for (unsigned int fidx = 0; fidx < mesh->mNumFaces; ++fidx) { + const aiFace &face = mesh->mFaces[fidx]; if (face.mNumIndices < 3) { continue; // triangles and polygons only, please } @@ -100,20 +100,18 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { // but the assumption that a face with at least one very small // on the one side and one very large U coord on the other side // lies on a UV seam should work for most cases. - for (unsigned int n = 0; n < face.mNumIndices;++n) - { - if (out[face.mIndices[n]].x < LOWER_LIMIT) - { + for (unsigned int n = 0; n < face.mNumIndices; ++n) { + if (out[face.mIndices[n]].x < LOWER_LIMIT) { smallV = n; // If we have a U value very close to 0 we can't // round the others to 0, too. if (out[face.mIndices[n]].x <= LOWER_EPSILON) zero = true; - else round_to_zero = true; + else + round_to_zero = true; } - if (out[face.mIndices[n]].x > UPPER_LIMIT) - { + if (out[face.mIndices[n]].x > UPPER_LIMIT) { large = n; // If we have a U value very close to 1 we can't @@ -122,10 +120,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { one = true; } } - if (smallV != face.mNumIndices && large != face.mNumIndices) - { - for (unsigned int n = 0; n < face.mNumIndices;++n) - { + if (smallV != face.mNumIndices && large != face.mNumIndices) { + for (unsigned int n = 0; n < face.mNumIndices; ++n) { // If the u value is over the upper limit and no other u // value of that face is 0, round it to 0 if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero) @@ -141,9 +137,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { // Due to numerical inaccuracies one U coord becomes 0, the // other 1. But we do still have a third UV coord to determine // to which side we must round to. - else if (one && zero) - { - if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) + else if (one && zero) { + if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) out[face.mIndices[n]].x = 0.0; else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON) out[face.mIndices[n]].x = 1.0; @@ -154,8 +149,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) { } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ +void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { aiVector3D center, min, max; FindMeshCenter(mesh, center, min, max); @@ -163,7 +157,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { // For each point get a normalized projection vector in the sphere, // get its longitude and latitude and map them to their respective @@ -177,58 +171,54 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D // Thus we can derive: // lat = arcsin (z) // lon = arctan (y/x) - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } } // slower code path in case the mapping axis is not one of the coordinate system axes - else { + else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = ((mTrafo * mesh->mVertices[pnt]) - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } } - // Now find and remove UV seams. A seam occurs if a face has a tcoord // close to zero on the one side, and a tcoord close to one on the // other side. - RemoveUVSeams(mesh,out); + RemoveUVSeams(mesh, out); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ +void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { aiVector3D center, min, max; // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.x - min.x; @@ -236,116 +226,110 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector // directly to the texture V axis. The other axis is derived from // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where // 'c' is the center point of the mesh. - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.x - min.x) / diff; - uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.z - center.z, pos.y - center.y) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.y - min.y; // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.y - min.y) / diff; - uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.z - min.z; // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.z - min.z) / diff; - uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.y - center.y, pos.x - center.x) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } } // slower code path in case the mapping axis is not one of the coordinate system axes else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); + FindMeshCenterTransformed(mesh, center, min, max, mTrafo); const ai_real diff = max.y - min.y; // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){ - const aiVector3D pos = mTrafo* mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.y - min.y) / diff; - uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } } // Now find and remove UV seams. A seam occurs if a face has a tcoord // close to zero on the one side, and a tcoord close to one on the // other side. - RemoveUVSeams(mesh,out); + RemoveUVSeams(mesh, out); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ - ai_real diffu,diffv; +void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { + ai_real diffu, diffv; aiVector3D center, min, max; // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.z - min.z; diffv = max.y - min.y; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.z - min.z) / diffu, (pos.y - min.y) / diffv, 0.0); } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.x - min.x; diffv = max.z - min.z; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0); } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.x - min.x; diffv = max.y - min.y; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.x - min.x) / diffu, (pos.y - min.y) / diffv, 0.0); } } // slower code path in case the mapping axis is not one of the coordinate system axes - else - { + else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); + FindMeshCenterTransformed(mesh, center, min, max, mTrafo); diffu = max.x - min.x; diffv = max.z - min.z; // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0); + out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0); } } @@ -353,14 +337,12 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* ) -{ +void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh *, aiVector3D *) { ASSIMP_LOG_ERROR("Mapping type currently not implemented"); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::Execute( aiScene* pScene) -{ +void ComputeUVMappingProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin"); char buffer[1024]; @@ -371,23 +353,18 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) /* Iterate through all materials and search for non-UV mapped textures */ - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { mappingStack.clear(); - aiMaterial* mat = pScene->mMaterials[i]; - for (unsigned int a = 0; a < mat->mNumProperties;++a) - { - aiMaterialProperty* prop = mat->mProperties[a]; - if (!::strcmp( prop->mKey.data, "$tex.mapping")) - { - aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData); - if (aiTextureMapping_UV != mapping) - { - if (!DefaultLogger::isNullLogger()) - { + aiMaterial *mat = pScene->mMaterials[i]; + for (unsigned int a = 0; a < mat->mNumProperties; ++a) { + aiMaterialProperty *prop = mat->mProperties[a]; + if (!::strcmp(prop->mKey.data, "$tex.mapping")) { + aiTextureMapping &mapping = *((aiTextureMapping *)prop->mData); + if (aiTextureMapping_UV != mapping) { + if (!DefaultLogger::isNullLogger()) { ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s", - aiTextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex, - MappingTypeToString(mapping)); + aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex, + MappingTypeToString(mapping)); ASSIMP_LOG_INFO(buffer); } @@ -395,70 +372,62 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) if (aiTextureMapping_OTHER == mapping) continue; - MappingInfo info (mapping); + MappingInfo info(mapping); // Get further properties - currently only the major axis - for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) - { - aiMaterialProperty* prop2 = mat->mProperties[a2]; + for (unsigned int a2 = 0; a2 < mat->mNumProperties; ++a2) { + aiMaterialProperty *prop2 = mat->mProperties[a2]; if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) continue; - if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) { - info.axis = *((aiVector3D*)prop2->mData); + if (!::strcmp(prop2->mKey.data, "$tex.mapaxis")) { + info.axis = *((aiVector3D *)prop2->mData); break; } } - unsigned int idx( 99999999 ); + unsigned int idx(99999999); // Check whether we have this mapping mode already - std::list::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info); - if (mappingStack.end() != it) - { + std::list::iterator it = std::find(mappingStack.begin(), mappingStack.end(), info); + if (mappingStack.end() != it) { idx = (*it).uv; - } - else - { + } else { /* We have found a non-UV mapped texture. Now - * we need to find all meshes using this material - * that we can compute UV channels for them. - */ - for (unsigned int m = 0; m < pScene->mNumMeshes;++m) - { - aiMesh* mesh = pScene->mMeshes[m]; + * we need to find all meshes using this material + * that we can compute UV channels for them. + */ + for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) { + aiMesh *mesh = pScene->mMeshes[m]; unsigned int outIdx = 0; - if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX || - !mesh->mNumVertices) - { + if (mesh->mMaterialIndex != i || (outIdx = FindEmptyUVChannel(mesh)) == UINT_MAX || + !mesh->mNumVertices) { continue; } // Allocate output storage - aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; + aiVector3D *p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; - switch (mapping) - { + switch (mapping) { case aiTextureMapping_SPHERE: - ComputeSphereMapping(mesh,info.axis,p); + ComputeSphereMapping(mesh, info.axis, p); break; case aiTextureMapping_CYLINDER: - ComputeCylinderMapping(mesh,info.axis,p); + ComputeCylinderMapping(mesh, info.axis, p); break; case aiTextureMapping_PLANE: - ComputePlaneMapping(mesh,info.axis,p); + ComputePlaneMapping(mesh, info.axis, p); break; case aiTextureMapping_BOX: - ComputeBoxMapping(mesh,p); + ComputeBoxMapping(mesh, p); break; default: ai_assert(false); } - if (m && idx != outIdx) - { + if (m && idx != outIdx) { ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to " - "this material have equal numbers of UV channels. The UV index stored in " - "the material structure does therefore not apply for all meshes. "); + "this material have equal numbers of UV channels. The UV index stored in " + "the material structure does therefore not apply for all meshes. "); } idx = outIdx; } @@ -468,7 +437,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) // Update the material property list mapping = aiTextureMapping_UV; - ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex)); + ((aiMaterial *)mat)->AddProperty(&idx, 1, AI_MATKEY_UVWSRC(prop->mSemantic, prop->mIndex)); } } } diff --git a/code/PostProcessing/DropFaceNormalsProcess.cpp b/code/PostProcessing/DropFaceNormalsProcess.cpp index 223482374..c5f6333e0 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.cpp +++ b/code/PostProcessing/DropFaceNormalsProcess.cpp @@ -42,27 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Implementation of the post processing step to drop face -* normals for all imported faces. -*/ - + * normals for all imported faces. + */ #include "DropFaceNormalsProcess.h" +#include #include #include #include -#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool DropFaceNormalsProcess::IsActive( unsigned int pFlags) const { - return (pFlags & aiProcess_DropNormals) != 0; +bool DropFaceNormalsProcess::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_DropNormals) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void DropFaceNormalsProcess::Execute( aiScene* pScene) { +void DropFaceNormalsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("DropFaceNormalsProcess begin"); if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { @@ -70,21 +69,21 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) { } bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - bHas |= this->DropMeshFaceNormals( pScene->mMeshes[a]); + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + bHas |= this->DropMeshFaceNormals(pScene->mMeshes[a]); } - if (bHas) { + if (bHas) { ASSIMP_LOG_INFO("DropFaceNormalsProcess finished. " - "Face normals have been removed"); + "Face normals have been removed"); } else { ASSIMP_LOG_DEBUG("DropFaceNormalsProcess finished. " - "No normals were present"); + "No normals were present"); } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) { +bool DropFaceNormalsProcess::DropMeshFaceNormals(aiMesh *mesh) { ai_assert(nullptr != mesh); if (nullptr == mesh->mNormals) { diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index 87ee75601..d9c14425c 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file FindDegenerates.cpp * @brief Implementation of the FindDegenerates post-process step. -*/ + */ -#include "ProcessHelper.h" #include "FindDegenerates.h" #include "Geometry/GeometryUtils.h" +#include "ProcessHelper.h" #include @@ -54,35 +54,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // Correct node indices to meshes and remove references to deleted mesh -static void updateSceneGraph(aiNode* pNode, const std::unordered_map& meshMap); +static void updateSceneGraph(aiNode *pNode, const std::unordered_map &meshMap); // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() : - mConfigRemoveDegenerates( false ), - mConfigCheckAreaOfTriangle( false ){ + mConfigRemoveDegenerates(false), + mConfigCheckAreaOfTriangle(false) { // empty } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const { +bool FindDegeneratesProcess::IsActive(unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindDegenerates); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { +void FindDegeneratesProcess::SetupProperties(const Importer *pImp) { // Get the current value of AI_CONFIG_PP_FD_REMOVE - mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); - mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) ); + mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE, 0)); + mConfigCheckAreaOfTriangle = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA)); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindDegeneratesProcess::Execute( aiScene* pScene) { +void FindDegeneratesProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin"); - if ( nullptr == pScene) { + if (nullptr == pScene) { return; } @@ -112,7 +112,7 @@ void FindDegeneratesProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished"); } -static void updateSceneGraph(aiNode* pNode, const std::unordered_map& meshMap) { +static void updateSceneGraph(aiNode *pNode, const std::unordered_map &meshMap) { unsigned int targetIndex = 0; for (unsigned i = 0; i < pNode->mNumMeshes; ++i) { const unsigned int sourceMeshIndex = pNode->mMeshes[i]; @@ -123,7 +123,7 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_mapmNumMeshes = targetIndex; - //recurse to all children + // recurse to all children for (unsigned i = 0; i < pNode->mNumChildren; ++i) { updateSceneGraph(pNode->mChildren[i], meshMap); } @@ -131,17 +131,17 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_mapmPrimitiveTypes = 0; std::vector remove_me; if (mConfigRemoveDegenerates) { - remove_me.resize( mesh->mNumFaces, false ); + remove_me.resize(mesh->mNumFaces, false); } unsigned int deg = 0, limit; - for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) { - aiFace& face = mesh->mFaces[a]; + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + aiFace &face = mesh->mFaces[a]; bool first = true; // check whether the face contains degenerated entries @@ -151,43 +151,43 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { // double points may not come directly after another. limit = face.mNumIndices; if (face.mNumIndices > 4) { - limit = std::min( limit, i+2 ); + limit = std::min(limit, i + 2); } - for (unsigned int t = i+1; t < limit; ++t) { - if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) { + for (unsigned int t = i + 1; t < limit; ++t) { + if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) { // we have found a matching vertex position // remove the corresponding index from the array --face.mNumIndices; --limit; for (unsigned int m = t; m < face.mNumIndices; ++m) { - face.mIndices[ m ] = face.mIndices[ m+1 ]; + face.mIndices[m] = face.mIndices[m + 1]; } --t; // NOTE: we set the removed vertex index to an unique value // to make sure the developer gets notified when his // application attempts to access this data. - face.mIndices[ face.mNumIndices ] = 0xdeadbeef; + face.mIndices[face.mNumIndices] = 0xdeadbeef; - if(first) { + if (first) { ++deg; first = false; } - if ( mConfigRemoveDegenerates ) { - remove_me[ a ] = true; + if (mConfigRemoveDegenerates) { + remove_me[a] = true; goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! } } } - if ( mConfigCheckAreaOfTriangle ) { - if ( face.mNumIndices == 3 ) { - ai_real area = GeometryUtils::calculateAreaOfTriangle( face, mesh ); + if (mConfigCheckAreaOfTriangle) { + if (face.mNumIndices == 3) { + ai_real area = GeometryUtils::calculateAreaOfTriangle(face, mesh); if (area < ai_epsilon) { - if ( mConfigRemoveDegenerates ) { - remove_me[ a ] = true; + if (mConfigRemoveDegenerates) { + remove_me[a] = true; ++deg; goto evil_jump_outside; } @@ -199,8 +199,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { } // We need to update the primitive flags array of the mesh. - switch (face.mNumIndices) - { + switch (face.mNumIndices) { case 1u: mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; break; @@ -214,22 +213,21 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; break; }; -evil_jump_outside: + evil_jump_outside: continue; } // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import if (mConfigRemoveDegenerates && deg) { unsigned int n = 0; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { - aiFace& face_src = mesh->mFaces[a]; + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + aiFace &face_src = mesh->mFaces[a]; if (!remove_me[a]) { - aiFace& face_dest = mesh->mFaces[n++]; + aiFace &face_dest = mesh->mFaces[n++]; // Do a manual copy, keep the index array face_dest.mNumIndices = face_src.mNumIndices; - face_dest.mIndices = face_src.mIndices; + face_dest.mIndices = face_src.mIndices; if (&face_src != &face_dest) { // clear source @@ -246,15 +244,15 @@ evil_jump_outside: // Just leave the rest of the array unreferenced, we don't care for now mesh->mNumFaces = n; if (!mesh->mNumFaces) { - //The whole mesh consists of degenerated faces - //signal upward, that this mesh should be deleted. + // The whole mesh consists of degenerated faces + // signal upward, that this mesh should be deleted. ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives"); return true; } } if (deg && !DefaultLogger::isNullLogger()) { - ASSIMP_LOG_WARN( "Found ", deg, " degenerated primitives"); + ASSIMP_LOG_WARN("Found ", deg, " degenerated primitives"); } return false; } diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index b6bb6155e..ff066a1d3 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file PretransformVertices.cpp - * @brief Implementation of the "PretransformVertices" post processing step -*/ +/// @file PretransformVertices.cpp +/// @brief Implementation of the "PretransformVertices" post processing step #include "PretransformVertices.h" #include "ConvertToLHProcess.h" @@ -57,16 +54,44 @@ using namespace Assimp; #define AI_PTVS_VERTEX 0x0 #define AI_PTVS_FACE 0x1 +namespace { + +// Get a bitwise combination identifying the vertex format of a mesh +static unsigned int GetMeshVFormat(aiMesh *pcMesh) { + // the vertex format is stored in aiMesh::mBones for later retrieval. + // there isn't a good reason to compute it a few hundred times + // from scratch. The pointer is unused as animations are lost + // during PretransformVertices. + if (pcMesh->mBones) + return (unsigned int)(uint64_t)pcMesh->mBones; + + const unsigned int iRet = GetMeshVFormatUnique(pcMesh); + + // store the value for later use + pcMesh->mBones = (aiBone **)(uint64_t)iRet; + return iRet; +} + +// Get a list of all vertex formats that occur for a given material index +// The output list contains duplicate elements +static void GetVFormatList(const aiScene *pcScene, unsigned int iMat, std::list &aiOut) { + for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { + aiMesh *pcMesh = pcScene->mMeshes[i]; + if (iMat == pcMesh->mMaterialIndex) { + aiOut.push_back(GetMeshVFormat(pcMesh)); + } + } +} + +} // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PretransformVertices::PretransformVertices() : - configKeepHierarchy(false), - configNormalize(false), - configTransform(false), - configTransformation(), - mConfigPointCloud(false) { - // empty -} + mConfigKeepHierarchy(false), + mConfigNormalize(false), + mConfigTransform(false), + mConfigTransformation(), + mConfigPointCloud(false) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. @@ -79,11 +104,11 @@ bool PretransformVertices::IsActive(unsigned int pFlags) const { void PretransformVertices::SetupProperties(const Importer *pImp) { // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE, // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION - configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0)); - configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0)); - configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0)); + mConfigKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0)); + mConfigNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0)); + mConfigTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0)); - configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); + mConfigTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); } @@ -99,25 +124,7 @@ unsigned int PretransformVertices::CountNodes(const aiNode *pcNode) const { } // ------------------------------------------------------------------------------------------------ -// Get a bitwise combination identifying the vertex format of a mesh -unsigned int PretransformVertices::GetMeshVFormat(aiMesh *pcMesh) const { - // the vertex format is stored in aiMesh::mBones for later retrieval. - // there isn't a good reason to compute it a few hundred times - // from scratch. The pointer is unused as animations are lost - // during PretransformVertices. - if (pcMesh->mBones) - return (unsigned int)(uint64_t)pcMesh->mBones; - - const unsigned int iRet = GetMeshVFormatUnique(pcMesh); - - // store the value for later use - pcMesh->mBones = (aiBone **)(uint64_t)iRet; - return iRet; -} - -// ------------------------------------------------------------------------------------------------ -// Count the number of vertices in the whole scene and a given -// material index +// Count the number of vertices in the whole scene and a given material index void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode, unsigned int iMat, unsigned int iVFormat, unsigned int *piFaces, unsigned int *piVertices) const { for (unsigned int i = 0; i < pcNode->mNumMeshes; ++i) { @@ -128,8 +135,7 @@ void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const a } } for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { - CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, - iVFormat, piFaces, piVertices); + CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, iVFormat, piFaces, piVertices); } } @@ -272,19 +278,6 @@ void PretransformVertices::CollectData(const aiScene *pcScene, const aiNode *pcN } } -// ------------------------------------------------------------------------------------------------ -// Get a list of all vertex formats that occur for a given material index -// The output list contains duplicate elements -void PretransformVertices::GetVFormatList(const aiScene *pcScene, unsigned int iMat, - std::list &aiOut) const { - for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { - aiMesh *pcMesh = pcScene->mMeshes[i]; - if (iMat == pcMesh->mMaterialIndex) { - aiOut.push_back(GetMeshVFormat(pcMesh)); - } - } -} - // ------------------------------------------------------------------------------------------------ // Compute the absolute transformation matrices of each node void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { @@ -297,39 +290,44 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { } } +static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) { + for (size_t i=0; iHasFaces() && mat.Determinant() < 0) { - // Reverse the mesh face winding order - FlipWindingOrderProcess::ProcessMesh(mesh); + // Check for odd negative scale (mirror) + if (mesh->HasFaces() && mat.Determinant() < 0) { + // Reverse the mesh face winding order + FlipWindingOrderProcess::ProcessMesh(mesh); + } + + // Update positions + if (mesh->HasPositions()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mVertices[i] = mat * mesh->mVertices[i]; } + } - // Update positions - if (mesh->HasPositions()) { + // Update normals and tangents + if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { + const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); + + if (mesh->HasNormals()) { + normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); + } + if (mesh->HasTangentsAndBitangents()) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mVertices[i] = mat * mesh->mVertices[i]; - } - } - - // Update normals and tangents - if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { - const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); - - if (mesh->HasNormals()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); - } - } - if (mesh->HasTangentsAndBitangents()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); - mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); - } + mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); + mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); } } } @@ -352,40 +350,41 @@ void PretransformVertices::BuildWCSMeshes(std::vector &out, aiMesh **i // yes, we can. mesh->mBones = reinterpret_cast(&node->mTransformation); mesh->mNumBones = UINT_MAX; - } else { + continue; + } - // try to find us in the list of newly created meshes - for (unsigned int n = 0; n < out.size(); ++n) { - aiMesh *ctz = out[n]; - if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { + // try to find us in the list of newly created meshes + for (unsigned int n = 0; n < out.size(); ++n) { + aiMesh *ctz = out[n]; + if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { - // ok, use this one. Update node mesh index - node->mMeshes[i] = numIn + n; - } + // ok, use this one. Update node mesh index + node->mMeshes[i] = numIn + n; } - if (node->mMeshes[i] < numIn) { - // Worst case. Need to operate on a full copy of the mesh - ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); - aiMesh *ntz; + } + if (node->mMeshes[i] < numIn) { + // Worst case. Need to operate on a full copy of the mesh + ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); + aiMesh *ntz; - const unsigned int tmp = mesh->mNumBones; // - mesh->mNumBones = 0; - SceneCombiner::Copy(&ntz, mesh); - mesh->mNumBones = tmp; + const unsigned int cacheNumBones = mesh->mNumBones; // + mesh->mNumBones = 0; + SceneCombiner::Copy(&ntz, mesh); + mesh->mNumBones = cacheNumBones; - ntz->mNumBones = node->mMeshes[i]; - ntz->mBones = reinterpret_cast(&node->mTransformation); + ntz->mNumBones = node->mMeshes[i]; + ntz->mBones = reinterpret_cast(&node->mTransformation); - out.push_back(ntz); + out.push_back(ntz); - node->mMeshes[i] = static_cast(numIn + out.size() - 1); - } + node->mMeshes[i] = static_cast(numIn + out.size() - 1); } } // call children - for (unsigned int i = 0; i < node->mNumChildren; ++i) + for (unsigned int i = 0; i < node->mNumChildren; ++i) { BuildWCSMeshes(out, in, numIn, node->mChildren[i]); + } } // ------------------------------------------------------------------------------------------------ @@ -394,8 +393,9 @@ void PretransformVertices::MakeIdentityTransform(aiNode *nd) const { nd->mTransformation = aiMatrix4x4(); // call children - for (unsigned int i = 0; i < nd->mNumChildren; ++i) + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { MakeIdentityTransform(nd->mChildren[i]); + } } // ------------------------------------------------------------------------------------------------ @@ -405,8 +405,27 @@ void PretransformVertices::BuildMeshRefCountArray(const aiNode *nd, unsigned int refs[nd->mMeshes[i]]++; // call children - for (unsigned int i = 0; i < nd->mNumChildren; ++i) + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { BuildMeshRefCountArray(nd->mChildren[i], refs); + } +} + +// ------------------------------------------------------------------------------------------------ +static void appendNewMeshesToScene(aiScene *pScene, std::vector &apcOutMeshes) { + ai_assert(pScene != nullptr); + + if (apcOutMeshes.empty()) { + return; + } + + aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()]; + + ::memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes); + ::memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size()); + + pScene->mNumMeshes += static_cast(apcOutMeshes.size()); + delete[] pScene->mMeshes; + pScene->mMeshes = npp; } // ------------------------------------------------------------------------------------------------ @@ -418,12 +437,12 @@ void PretransformVertices::Execute(aiScene *pScene) { if (!pScene->mNumMeshes) return; - const unsigned int iOldMeshes = pScene->mNumMeshes; - const unsigned int iOldAnimationChannels = pScene->mNumAnimations; - const unsigned int iOldNodes = CountNodes(pScene->mRootNode); + const unsigned int oldMeshes = pScene->mNumMeshes; + const unsigned int oldAnimationChannels = pScene->mNumAnimations; + const unsigned int oldNodes = CountNodes(pScene->mRootNode); - if (configTransform) { - pScene->mRootNode->mTransformation = configTransformation * pScene->mRootNode->mTransformation; + if (mConfigTransform) { + pScene->mRootNode->mTransformation = mConfigTransformation * pScene->mRootNode->mTransformation; } // first compute absolute transformation matrices for all nodes @@ -449,22 +468,13 @@ void PretransformVertices::Execute(aiScene *pScene) { // we go on and transform all meshes, if one is referenced by nodes // with different absolute transformations a depth copy of the mesh // is required. - if (configKeepHierarchy) { + if (mConfigKeepHierarchy) { // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones BuildWCSMeshes(apcOutMeshes, pScene->mMeshes, pScene->mNumMeshes, pScene->mRootNode); // ... if new meshes have been generated, append them to the end of the scene - if (apcOutMeshes.size() > 0) { - aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()]; - - memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes); - memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size()); - - pScene->mNumMeshes += static_cast(apcOutMeshes.size()); - delete[] pScene->mMeshes; - pScene->mMeshes = npp; - } + appendNewMeshesToScene(pScene, apcOutMeshes); // now iterate through all meshes and transform them to world-space for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { @@ -488,34 +498,35 @@ void PretransformVertices::Execute(aiScene *pScene) { aiVFormats.sort(); aiVFormats.unique(); for (std::list::const_iterator j = aiVFormats.begin(); j != aiVFormats.end(); ++j) { - unsigned int iVertices = 0; - unsigned int iFaces = 0; - CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &iFaces, &iVertices); - if (0 != iFaces && 0 != iVertices) { + unsigned int numVertices = 0u; + unsigned int numFaces = 0u; + CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &numFaces, &numVertices); + if (0 != numFaces && 0 != numVertices) { apcOutMeshes.push_back(new aiMesh()); aiMesh *pcMesh = apcOutMeshes.back(); - pcMesh->mNumFaces = iFaces; - pcMesh->mNumVertices = iVertices; - pcMesh->mFaces = new aiFace[iFaces]; - pcMesh->mVertices = new aiVector3D[iVertices]; + pcMesh->mNumFaces = numFaces; + pcMesh->mNumVertices = numVertices; + pcMesh->mFaces = new aiFace[numFaces]; + pcMesh->mVertices = new aiVector3D[numVertices]; pcMesh->mMaterialIndex = i; - if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[iVertices]; + if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[numVertices]; if ((*j) & 0x4) { - pcMesh->mTangents = new aiVector3D[iVertices]; - pcMesh->mBitangents = new aiVector3D[iVertices]; + pcMesh->mTangents = new aiVector3D[numVertices]; + pcMesh->mBitangents = new aiVector3D[numVertices]; } - iFaces = 0; - while ((*j) & (0x100 << iFaces)) { - pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; - if ((*j) & (0x10000 << iFaces)) - pcMesh->mNumUVComponents[iFaces] = 3; - else - pcMesh->mNumUVComponents[iFaces] = 2; - iFaces++; + numFaces = 0; + while ((*j) & (0x100 << numFaces)) { + pcMesh->mTextureCoords[numFaces] = new aiVector3D[numVertices]; + if ((*j) & (0x10000 << numFaces)) { + pcMesh->mNumUVComponents[numFaces] = 3; + } else { + pcMesh->mNumUVComponents[numFaces] = 2; + } + ++numFaces; } - iFaces = 0; - while ((*j) & (0x1000000 << iFaces)) - pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; + numFaces = 0; + while ((*j) & (0x1000000 << numFaces)) + pcMesh->mColors[numFaces++] = new aiColor4D[numVertices]; // fill the mesh ... unsigned int aiTemp[2] = { 0, 0 }; @@ -593,7 +604,7 @@ void PretransformVertices::Execute(aiScene *pScene) { l->mUp = aiMatrix3x3(nd->mTransformation) * l->mUp; } - if (!configKeepHierarchy) { + if (!mConfigKeepHierarchy) { // now delete all nodes in the scene and build a new // flat node graph with a root node and some level 1 children @@ -644,7 +655,7 @@ void PretransformVertices::Execute(aiScene *pScene) { MakeIdentityTransform(pScene->mRootNode); } - if (configNormalize) { + if (mConfigNormalize) { // compute the boundary of all meshes aiVector3D min, max; MinMaxChooser()(min, max); @@ -674,9 +685,9 @@ void PretransformVertices::Execute(aiScene *pScene) { if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); - ASSIMP_LOG_INFO("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", + ASSIMP_LOG_INFO("Removed ", oldNodes, " nodes and ", oldAnimationChannels, " animation channels (", CountNodes(pScene->mRootNode), " output nodes)"); ASSIMP_LOG_INFO("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras."); - ASSIMP_LOG_INFO("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); + ASSIMP_LOG_INFO("Moved ", oldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); } } diff --git a/code/PostProcessing/PretransformVertices.h b/code/PostProcessing/PretransformVertices.h index 7c2b5e99e..69d3d8400 100644 --- a/code/PostProcessing/PretransformVertices.h +++ b/code/PostProcessing/PretransformVertices.h @@ -90,7 +90,7 @@ public: * @param keep true for keep configuration. */ void KeepHierarchy(bool keep) { - configKeepHierarchy = keep; + mConfigKeepHierarchy = keep; } // ------------------------------------------------------------------- @@ -98,7 +98,7 @@ public: * @return ... */ bool IsHierarchyKept() const { - return configKeepHierarchy; + return mConfigKeepHierarchy; } private: @@ -108,7 +108,7 @@ private: // ------------------------------------------------------------------- // Get a bitwise combination identifying the vertex format of a mesh - unsigned int GetMeshVFormat(aiMesh *pcMesh) const; + //unsigned int GetMeshVFormat(aiMesh *pcMesh) const; // ------------------------------------------------------------------- // Count the number of vertices in the whole scene and a given @@ -131,8 +131,8 @@ private: // ------------------------------------------------------------------- // Get a list of all vertex formats that occur for a given material // The output list contains duplicate elements - void GetVFormatList(const aiScene *pcScene, unsigned int iMat, - std::list &aiOut) const; + /*void GetVFormatList(const aiScene *pcScene, unsigned int iMat, + std::list &aiOut) const;*/ // ------------------------------------------------------------------- // Compute the absolute transformation matrices of each node @@ -156,10 +156,10 @@ private: void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const; //! Configuration option: keep scene hierarchy as long as possible - bool configKeepHierarchy; - bool configNormalize; - bool configTransform; - aiMatrix4x4 configTransformation; + bool mConfigKeepHierarchy; + bool mConfigNormalize; + bool mConfigTransform; + aiMatrix4x4 mConfigTransformation; bool mConfigPointCloud; }; diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index 15f01676c..e55c17648 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -175,10 +175,9 @@ unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) { // tangents and bitangents if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4; -#ifdef BOOST_STATIC_ASSERT - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); -#endif + + static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); + static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); // texture coordinates unsigned int p = 0; diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index dbc3c8822..ea8d154dc 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // internal headers - #include "RemoveRedundantMaterials.h" #include #include "ProcessHelper.h" @@ -57,35 +54,28 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() -: mConfigFixedMaterials() { - // nothing to do here -} +RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() : mConfigFixedMaterials() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const -{ +bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_RemoveRedundantMaterials) != 0; } // ------------------------------------------------------------------------------------------------ // Setup import properties -void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) -{ +void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) { // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST mConfigFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,""); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void RemoveRedundantMatsProcess::Execute( aiScene* pScene) -{ +void RemoveRedundantMatsProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin"); unsigned int redundantRemoved = 0, unreferencedRemoved = 0; - if (pScene->mNumMaterials) - { + if (pScene->mNumMaterials) { // Find out which materials are referenced by meshes std::vector abReferenced(pScene->mNumMaterials,false); for (unsigned int i = 0;i < pScene->mNumMeshes;++i) @@ -134,8 +124,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // we do already have a specific hash. This allows us to // determine which materials are identical. uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { + for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { // No mesh is referencing this material, remove it. if (!abReferenced[i]) { ++unreferencedRemoved; @@ -147,8 +136,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // Check all previously mapped materials for a matching hash. // On a match we can delete this material and just make it ref to the same index. uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]); - for (unsigned int a = 0; a < i;++a) - { + for (unsigned int a = 0; a < i;++a) { if (abReferenced[a] && me == aiHashes[a]) { ++redundantRemoved; me = 0; @@ -205,12 +193,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) delete[] aiHashes; delete[] aiMappingTable; } - if (redundantRemoved == 0 && unreferencedRemoved == 0) - { + if (redundantRemoved == 0 && unreferencedRemoved == 0) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished "); - } - else - { + } else { ASSIMP_LOG_INFO("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ", unreferencedRemoved, " unused materials."); } diff --git a/code/PostProcessing/ScaleProcess.cpp b/code/PostProcessing/ScaleProcess.cpp index 00df07090..1bb9196f1 100644 --- a/code/PostProcessing/ScaleProcess.cpp +++ b/code/PostProcessing/ScaleProcess.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 394ef15c8..47633dce5 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -99,8 +99,9 @@ void UpdateNodes(const std::vector &replaceMeshIndex, aiNode *node } // call all subnodes recursively - for (unsigned int m = 0; m < node->mNumChildren; ++m) + for (unsigned int m = 0; m < node->mNumChildren; ++m) { UpdateNodes(replaceMeshIndex, node->mChildren[m]); + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index e44a55979..969146fee 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -57,9 +57,7 @@ using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ // Constructor -SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) { - // empty -} +SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag. diff --git a/code/PostProcessing/SplitLargeMeshes.cpp b/code/PostProcessing/SplitLargeMeshes.cpp index 73e0cc5d8..b6e5b772a 100644 --- a/code/PostProcessing/SplitLargeMeshes.cpp +++ b/code/PostProcessing/SplitLargeMeshes.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,9 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** - * @file Implementation of the SplitLargeMeshes postprocessing step - */ + /// @file Implementation of the SplitLargeMeshes postprocessing step // internal headers of the post-processing framework #include "SplitLargeMeshes.h" @@ -75,22 +72,22 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) { this->SplitMesh(a, pScene->mMeshes[a],avList); } - if (avList.size() != pScene->mNumMeshes) { - // it seems something has been split. rebuild the mesh list - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) { - pScene->mMeshes[i] = avList[i].first; - } - - // now we need to update all nodes - this->UpdateNode(pScene->mRootNode,avList); - ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); - } else { + if (avList.size() == pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); } + + // it seems something has been split. rebuild the mesh list + delete[] pScene->mMeshes; + pScene->mNumMeshes = (unsigned int)avList.size(); + pScene->mMeshes = new aiMesh*[avList.size()]; + + for (unsigned int i = 0; i < avList.size();++i) { + pScene->mMeshes[i] = avList[i].first; + } + + // now we need to update all nodes + this->UpdateNode(pScene->mRootNode,avList); + ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); } // ------------------------------------------------------------------------------------------------ @@ -102,8 +99,7 @@ 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 >& avList) { +void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector >& avList) { // for every index in out list build a new entry std::vector aiEntries; aiEntries.reserve(pcNode->mNumMeshes + 1); diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index 2ed17f390..3de357c17 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file A helper class that processes texture transformations */ - - #include #include #include @@ -494,8 +491,9 @@ void TextureTransformStep::Execute( aiScene* pScene) { ai_assert(nullptr != src); // Copy the data to the destination array - if (dest != src) + if (dest != src) { ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices); + } end = dest + mesh->mNumVertices; diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 52cfa66bf..b4c66b41e 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -158,15 +158,13 @@ namespace { // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool TriangulateProcess::IsActive( unsigned int pFlags) const -{ +bool TriangulateProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_Triangulate) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void TriangulateProcess::Execute( aiScene* pScene) -{ +void TriangulateProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("TriangulateProcess begin"); bool bHas = false; @@ -187,8 +185,7 @@ void TriangulateProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Triangulates the given mesh. -bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) -{ +bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases if (!pMesh->mPrimitiveTypes) { bool bNeed = false; @@ -218,8 +215,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) if( face.mNumIndices <= 3) { numOut++; - } - else { + } else { numOut += face.mNumIndices-2; max_out = std::max(max_out,face.mNumIndices); } @@ -511,22 +507,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) #endif num = 0; break; - - /*curOut -= (max-num); // undo all previous work - for (tmp = 0; tmp < max-2; ++tmp) { - aiFace& nface = *curOut++; - - nface.mNumIndices = 3; - if (!nface.mIndices) - nface.mIndices = new unsigned int[3]; - - nface.mIndices[0] = 0; - nface.mIndices[1] = tmp+1; - nface.mIndices[2] = tmp+2; - - } - num = 0; - break;*/ } aiFace& nface = *curOut++; @@ -580,23 +560,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) for(aiFace* f = last_face; f != curOut; ) { unsigned int* i = f->mIndices; - // drop dumb 0-area triangles - deactivated for now: - //FindDegenerates post processing step can do the same thing - //if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) { - // ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0"); - // --curOut; - - // delete[] f->mIndices; - // f->mIndices = nullptr; - - // for(aiFace* ff = f; ff != curOut; ++ff) { - // ff->mNumIndices = (ff+1)->mNumIndices; - // ff->mIndices = (ff+1)->mIndices; - // (ff+1)->mIndices = nullptr; - // } - // continue; - //} - i[0] = idx[i[0]]; i[1] = idx[i[1]]; i[2] = idx[i[2]]; diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index cae35b895..af4ff788e 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -110,18 +108,21 @@ inline int HasNameMatch(const aiString &in, aiNode *node) { template inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) { // validate all entries - if (size) { - if (!parray) { - ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", - firstName, secondName, size); - } - for (unsigned int i = 0; i < size; ++i) { - if (!parray[i]) { - ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)", - firstName, i, secondName, size); - } - Validate(parray[i]); + if (size == 0) { + return; + } + + if (!parray) { + ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", + firstName, secondName, size); + } + + for (unsigned int i = 0; i < size; ++i) { + if (!parray[i]) { + ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)", + firstName, i, secondName, size); } + Validate(parray[i]); } } @@ -130,25 +131,27 @@ template inline void ValidateDSProcess::DoValidationEx(T **parray, unsigned int size, const char *firstName, const char *secondName) { // validate all entries - if (size) { - if (!parray) { - ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", - firstName, secondName, size); + if (size == 0) { + return; + } + + if (!parray) { + ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", + firstName, secondName, size); + } + for (unsigned int i = 0; i < size; ++i) { + if (!parray[i]) { + ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)", + firstName, i, secondName, size); } - for (unsigned int i = 0; i < size; ++i) { - if (!parray[i]) { - ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)", - firstName, i, secondName, size); - } - Validate(parray[i]); + Validate(parray[i]); - // check whether there are duplicate names - for (unsigned int a = i + 1; a < size; ++a) { - if (parray[i]->mName == parray[a]->mName) { - ReportError("aiScene::%s[%u] has the same name as " - "aiScene::%s[%u]", - firstName, i, secondName, a); - } + // check whether there are duplicate names + for (unsigned int a = i + 1; a < size; ++a) { + if (parray[i]->mName == parray[a]->mName) { + ReportError("aiScene::%s[%u] has the same name as " + "aiScene::%s[%u]", + firstName, i, secondName, a); } } } @@ -229,12 +232,6 @@ void ValidateDSProcess::Execute(aiScene *pScene) { if (pScene->mNumMaterials) { DoValidation(pScene->mMaterials, pScene->mNumMaterials, "mMaterials", "mNumMaterials"); } -#if 0 - // NOTE: ScenePreprocessor generates a default material if none is there - else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - ReportError("aiScene::mNumMaterials is 0. At least one material must be there"); - } -#endif else if (pScene->mMaterials) { ReportError("aiScene::mMaterials is non-null although there are no materials"); } @@ -267,8 +264,7 @@ void ValidateDSProcess::Validate(const aiCamera *pCamera) { if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear) ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear"); - // FIX: there are many 3ds files with invalid FOVs. No reason to - // reject them at all ... a warning is appropriate. + // There are many 3ds files with invalid FOVs. No reason to reject them at all ... a warning is appropriate. if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI) ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV", pCamera->mHorizontalFOV); } @@ -362,15 +358,6 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) { if (face.mIndices[a] >= pMesh->mNumVertices) { ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range", i, a); } - // the MSB flag is temporarily used by the extra verbose - // mode to tell us that the JoinVerticesProcess might have - // been executed already. - /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) && - abRefList[face.mIndices[a]]) - { - ReportError("aiMesh::mVertices[%i] is referenced twice - second " - "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a); - }*/ abRefList[face.mIndices[a]] = true; } } @@ -466,7 +453,7 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float this->Validate(&pBone->mName); if (!pBone->mNumWeights) { - //ReportError("aiBone::mNumWeights is zero"); + ReportWarning("aiBone::mNumWeights is zero"); } // check whether all vertices affected by this bone are valid diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 1bdfcc650..50e28447c 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -68,8 +66,7 @@ namespace Assimp { */ // -------------------------------------------------------------------------------------------- template -class StreamWriter -{ +class StreamWriter { enum { INITIAL_CAPACITY = 1024 }; diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index b4aa1dd2d..3fc974504 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -97,14 +97,20 @@ namespace Assimp { * to *all* vertex components equally. This is useful for stuff like interpolation * or subdivision, but won't work if special handling is required for some vertex components. */ // ------------------------------------------------------------------------------------------------ -class Vertex { +struct Vertex { friend Vertex operator + (const Vertex&,const Vertex&); friend Vertex operator - (const Vertex&,const Vertex&); friend Vertex operator * (const Vertex&,ai_real); friend Vertex operator / (const Vertex&,ai_real); friend Vertex operator * (ai_real, const Vertex&); -public: + aiVector3D position; + aiVector3D normal; + aiVector3D tangent, bitangent; + + aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS]; + Vertex() = default; // ---------------------------------------------------------------------------- @@ -178,7 +184,7 @@ public: } // ---------------------------------------------------------------------------- - /** Convert back to non-interleaved storage */ + /// Convert back to non-interleaved storage void SortBack(aiMesh* out, unsigned int idx) const { ai_assert(idxmNumVertices); out->mVertices[idx] = position; @@ -204,7 +210,7 @@ public: private: // ---------------------------------------------------------------------------- - /** Construct from two operands and a binary operation to combine them */ + /// Construct from two operands and a binary operation to combine them template