瀏覽代碼

Fixed bone splitting with excessive amount of bones with 0 weight

Alexey Medvedev 5 年之前
父節點
當前提交
5e93b9ea8b
共有 1 個文件被更改,包括 15 次插入33 次删除
  1. 15 33
      code/PostProcessing/SplitByBoneCountProcess.cpp

+ 15 - 33
code/PostProcessing/SplitByBoneCountProcess.cpp

@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <limits>
 #include <assimp/TinyFormatter.h>
 #include <assimp/Exceptional.h>
+#include <set>
 
 using namespace Assimp;
 using namespace Assimp::Formatter;
@@ -188,9 +189,6 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         subMeshFaces.reserve( pMesh->mNumFaces);
         // accumulated vertex count of all the faces in this submesh
         unsigned int numSubMeshVertices = 0;
-        // a small local array of new bones for the current face. State of all used bones for that face
-        // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
-        std::vector<unsigned int> newBonesAtCurrentFace;
 
         // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
         for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
@@ -200,33 +198,21 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
             {
                 continue;
             }
-
+            // a small local set of new bones for the current face. State of all used bones for that face
+            // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
+            std::set<unsigned int> newBonesAtCurrentFace;
+          
             const aiFace& face = pMesh->mFaces[a];
             // check every vertex if its bones would still fit into the current submesh
             for( unsigned int b = 0; b < face.mNumIndices; ++b )
             {
-                const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
-                for( unsigned int c = 0; c < vb.size(); ++c)
-                {
-                    unsigned int boneIndex = vb[c].first;
-                    // if the bone is already used in this submesh, it's ok
-                    if( isBoneUsed[boneIndex] )
-                    {
-                        continue;
-                    }
-
-                    // if it's not used, yet, we would need to add it. Store its bone index
-                    if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
-                    {
-                        newBonesAtCurrentFace.push_back( boneIndex);
-                    }
-                }
+              const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
+              for( unsigned int c = 0; c < vb.size(); ++c)
+              {
+                newBonesAtCurrentFace.insert(vb[c].first);
+              }
             }
 
-            if (newBonesAtCurrentFace.size() > 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 )
             {
@@ -234,17 +220,13 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
             }
 
             // mark all new bones as necessary
-            while( !newBonesAtCurrentFace.empty() )
+            for (std::set<unsigned int>::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it)
             {
-                unsigned int newIndex = newBonesAtCurrentFace.back();
-                newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
-                if( isBoneUsed[newIndex] )
-                {
-                    continue;
-                }
-
-                isBoneUsed[newIndex] = true;
+              if (!isBoneUsed[*it])
+              {
+                isBoneUsed[*it] = true;
                 numBones++;
+              }
             }
 
             // store the face index and the vertex count