From 22311883ce2aca0477f764bb300541f02834645f Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 18:39:40 -0800 Subject: [PATCH 1/2] Fix for #3037 [FATAL] SplitByBoneCountProcess::SplitMesh goes into infinite loop --- code/Common/SplitByBoneCountProcess.cpp | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/code/Common/SplitByBoneCountProcess.cpp b/code/Common/SplitByBoneCountProcess.cpp index b472cb359..e8e216478 100644 --- a/code/Common/SplitByBoneCountProcess.cpp +++ b/code/Common/SplitByBoneCountProcess.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -94,7 +95,10 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) bool isNecessary = false; for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount ) + { isNecessary = true; + break; + } if( !isNecessary ) { @@ -155,7 +159,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones <= mMaxBoneCount ) + { return; + } // necessary optimisation: build a list of all affecting bones for each vertex // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays @@ -165,7 +171,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormBones[a]; for( unsigned int b = 0; b < bone->mNumWeights; ++b) + { vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); + } } unsigned int numFacesHandled = 0; @@ -189,7 +197,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormFaces[a]; // check every vertex if its bones would still fit into the current submesh @@ -201,17 +211,27 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector mMaxBoneCount) + { + throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); + } // leave out the face if the new bones required for this face don't fit the bone count limit anymore if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount ) + { continue; + } // mark all new bones as necessary while( !newBonesAtCurrentFace.empty() ) @@ -219,7 +239,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormName.length > 0 ) + { newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); + } newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; poNewMeshes.push_back( newMesh); @@ -247,7 +271,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumFaces = static_cast(subMeshFaces.size()); newMesh->mVertices = new aiVector3D[newMesh->mNumVertices]; if( pMesh->HasNormals() ) + { newMesh->mNormals = new aiVector3D[newMesh->mNumVertices]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents = new aiVector3D[newMesh->mNumVertices]; @@ -256,13 +282,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( a) ) + { newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices]; + } newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; } for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { if( pMesh->HasVertexColors( a) ) + { newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices]; + } } // and copy over the data, generating faces with linear indices along the way @@ -285,7 +315,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormVertices[nvi] = pMesh->mVertices[srcIndex]; if( pMesh->HasNormals() ) + { newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; @@ -294,12 +326,16 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( c) ) + { newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; + } } for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { if( pMesh->HasVertexColors( c) ) + { newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; + } } nvi++; @@ -316,7 +352,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones; ++a ) { if( !isBoneUsed[a] ) + { continue; + } // create the new bone const aiBone* srcBone = pMesh->mBones[a]; @@ -340,7 +378,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::max() ) + { newMesh->mBones[newBoneIndex]->mNumWeights++; + } } } From 496fcd35c19b8ae4521487ad6d498d5476f69cfa Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 19:17:53 -0800 Subject: [PATCH 2/2] Trimmed trailing whitespaces --- code/Common/SplitByBoneCountProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/SplitByBoneCountProcess.cpp b/code/Common/SplitByBoneCountProcess.cpp index e8e216478..ab7a1fe00 100644 --- a/code/Common/SplitByBoneCountProcess.cpp +++ b/code/Common/SplitByBoneCountProcess.cpp @@ -224,7 +224,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector mMaxBoneCount) - { + { throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); } // leave out the face if the new bones required for this face don't fit the bone count limit anymore