Merge pull request #3105 from rudybear/master
Fixed bone splitting with excessive amount of bones with 0 weightpull/3212/head
commit
9f03397f32
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <assimp/TinyFormatter.h>
|
#include <assimp/TinyFormatter.h>
|
||||||
#include <assimp/Exceptional.h>
|
#include <assimp/Exceptional.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
using namespace Assimp::Formatter;
|
using namespace Assimp::Formatter;
|
||||||
|
@ -172,7 +173,15 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||||
const aiBone* bone = pMesh->mBones[a];
|
const aiBone* bone = pMesh->mBones[a];
|
||||||
for( unsigned int b = 0; b < bone->mNumWeights; ++b)
|
for( unsigned int b = 0; b < bone->mNumWeights; ++b)
|
||||||
{
|
{
|
||||||
vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
|
if (bone->mWeights[b].mWeight > 0.0f)
|
||||||
|
{
|
||||||
|
int vertexId = bone->mWeights[b].mVertexId;
|
||||||
|
vertexBones[vertexId].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
|
||||||
|
if (vertexBones[vertexId].size() > mMaxBoneCount)
|
||||||
|
{
|
||||||
|
throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,9 +197,6 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||||
subMeshFaces.reserve( pMesh->mNumFaces);
|
subMeshFaces.reserve( pMesh->mNumFaces);
|
||||||
// accumulated vertex count of all the faces in this submesh
|
// accumulated vertex count of all the faces in this submesh
|
||||||
unsigned int numSubMeshVertices = 0;
|
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
|
// 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)
|
for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
|
||||||
|
@ -200,33 +206,25 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||||
{
|
{
|
||||||
continue;
|
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];
|
const aiFace& face = pMesh->mFaces[a];
|
||||||
// check every vertex if its bones would still fit into the current submesh
|
// check every vertex if its bones would still fit into the current submesh
|
||||||
for( unsigned int b = 0; b < face.mNumIndices; ++b )
|
for( unsigned int b = 0; b < face.mNumIndices; ++b )
|
||||||
{
|
{
|
||||||
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
|
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
|
||||||
for( unsigned int c = 0; c < vb.size(); ++c)
|
for( unsigned int c = 0; c < vb.size(); ++c)
|
||||||
|
{
|
||||||
|
unsigned int boneIndex = vb[c].first;
|
||||||
|
if( !isBoneUsed[boneIndex] )
|
||||||
{
|
{
|
||||||
unsigned int boneIndex = vb[c].first;
|
newBonesAtCurrentFace.insert(boneIndex);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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 )
|
if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
|
||||||
{
|
{
|
||||||
|
@ -234,17 +232,13 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark all new bones as necessary
|
// 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();
|
if (!isBoneUsed[*it])
|
||||||
newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
|
{
|
||||||
if( isBoneUsed[newIndex] )
|
isBoneUsed[*it] = true;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
isBoneUsed[newIndex] = true;
|
|
||||||
numBones++;
|
numBones++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// store the face index and the vertex count
|
// store the face index and the vertex count
|
||||||
|
|
Loading…
Reference in New Issue