Extract Bone Infos from ASSIMP

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 20, 2012 at 12:26

Hi all,

I’m in the process of extracting bone information using ASSIMP.

I’ve specified the flag aiProcess_LimitBoneWeights but it looks like is not limiting them to 4. Infact they keep being more than 100 !!! Or maybe I’m extracting them in the wrong way.

Btw here is a small snippet of my exporter (it should look for the indices to vertices to reconstruct bone - vertex association):

if(mesh->HasBones()){

            out << "animation_begin" << endl;

            for(unsigned int i=0;i<mesh->mNumBones;++i){
                bone = mesh->mBones[i];
                out << std::string(bone->mName.data) << " ";
                for(unsigned int j = 0;j<bone->mNumWeights;++j){
                    aiVertexWeight vertWeight = bone->mWeights[j];
                    out << "("<< vertWeight.mVertexId << ", " << vertWeight.mWeight << ")" << " ";
                }               


                out << endl;
            }

            out << "animation_end" << endl;
        }

In the end if someone has already went through all of that using ASSIMP, I’ll be more than happy to understand how extract bones for bind pose and how to animate the model.

Thanks a lot in advance

13 Replies

Please log in or register to post a reply.

5000fdaaeeeb9f038be93cf67eb3b130
0
David_Gallagher 102 Jan 20, 2012 at 20:34

I myself havn’t gotten to the animation side of assimp yet, but I found a project that might really help at http://dx11experiments.codeplex.com/ (source code section), I’ve had a quick glance at it and might be useful in sorting this out, probably start looking at his MeshFactory.cpp. Hope it helps as I’m hopeing it will help me :).

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Jan 21, 2012 at 09:15

The aiProcess_LimitBoneWeights specifies how many bones should at most affect a single vertex, but what you are looking at, is how many different vertices each bone is affecting, so you are looking at it backwards :)

If you want to be totally sure, try this (untested) code:

std::vector<unsigned int> vertexBones(pMesh->mNumVertices, 0);
for(unsigned int i=0;i<pMesh->mNumBones;i++) {
  for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
   float w = pMesh->mBones[i]->mWeights[j].mWeight;
   if(w==0.0f) {
    continue;
   }
   unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
   vertexBones[vid]++;
   assert(vertexBones[vid] < 4);
  }
}
Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 31, 2012 at 14:58

@Kenneth Gorking

The aiProcess_LimitBoneWeights specifies how many bones should at most affect a single vertex, but what you are looking at, is how many different vertices each bone is affecting, so you are looking at it backwards :)

If you want to be totally sure, try this (untested) code:

std::vector<unsigned int> vertexBones(pMesh->mNumVertices, 0);
for(unsigned int i=0;i<pMesh->mNumBones;i++) {
  for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
   float w = pMesh->mBones[i]->mWeights[j].mWeight;
   if(w==0.0f) {
    continue;
   }
   unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
   vertexBones[vid]++;
   assert(vertexBones[vid] < 4);
  }
}

Even if with some delay I would like to thank you all for your help.
It got this long because in the meantime I figured it out how to extract data from assimp and I’ve got skinning working.
But I’m not sure about the limit bone weights thing, because I see some artifacts while the animation is playing and I wouldn’t like to think that the approximation that assimp does to limi the weights to, say, 4 is too coarse.

btw the code that I use to reconstruct bone indices into vertex, for me looks like this snippet

//build bones to vertex association
        struct boneIndexToVertex_t{
            unsigned int boneId[4];
            float        weight[4];
            int          currentId;
        };
        boneIndexToVertex_t* boneIndexToVertex = NULL;
        if( mesh->HasBones()  && (optImport & OPT_ANIMATIONS_DATA) ){
            boneIndexToVertex = new boneIndexToVertex_t[mesh->mNumVertices];
            memset(boneIndexToVertex,0,sizeof(boneIndexToVertex_t)*mesh->mNumVertices);
            for(unsigned int k=0;k<mesh->mNumBones;++k){
                const aiBone* pBone = mesh->mBones[k];
                for(unsigned int j=0;j<pBone->mNumWeights;++j){
                    unsigned int boneIndex  = mAnimationMgr.mAiBoneToIdMap[pBone];
                    unsigned int vertexId   = pBone->mWeights[j].mVertexId;
                    float        weight     = pBone->mWeights[j].mWeight;    
                    unsigned int id = boneIndexToVertex[vertexId].currentId++;
                    assert(id<4);
                    boneIndexToVertex[vertexId].boneId[id] = boneIndex;
                    boneIndexToVertex[vertexId].weight[id] = weight;                    
                }       
            }
        }

Could that depend on the fact that I don’t check if the wieght is 0 (as you do in your code)? But it shouldn’t be a problem I think since that will evaluate the whole thing to 0 in the shader when I’ll perform skinning…

Any thoughts ? If it can help I could try to produce a movie showing the artifacts … they are not terribly bad but something let me think that weights could be skrewed somewhere …

thanks in advance

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Jan 31, 2012 at 15:44

It’s doubtful that the weights are screwed, it is more likely that some weights are being removed which had a significant impact on the vertices movement, and when they were removed, it started looking weird.

Maybe you can try the aiProcess_SplitByBoneCount flag, and see if that helps things. If it doesn’t, you need to manually corect the model in a modeling program :mellow:

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 31, 2012 at 15:52

@Kenneth Gorking

It’s doubtful that the weights are screwed, it is more likely that some weights are being removed which had a significant impact on the vertices movement, and when they were removed, it started looking weird. Maybe you can try the aiProcess_SplitByBoneCount flag, and see if that helps things. If it doesn’t, you need to manually corect the model in a modeling program :mellow:

This sounds strange since everyone wants to do hardware skinning and we know we have to necessarily limit the bone count to 4 in the vertex input layout … So I wouldn’t expect any problem :/ … unless you do skinning on the cpu … which I would avoid to do …
btw I’ll try that flag and I’ll let you know … in the meantime thanks

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 31, 2012 at 15:54

@SuperPixel

This sounds strange since everyone wants to do hardware skinning and we know we have to necessarily limit the bone count to 4 in the vertex input layout … So I wouldn’t expect any problem :/ … unless you do skinning on the cpu … which I would avoid to do …
btw I’ll try that flag and I’ll let you know … in the meantime thanks

aiProcess_SplitByBoneCount doesn’t exist ….

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Jan 31, 2012 at 15:58

It does in mine, and I just did a svn-update to be sure they hadn’t removed it. I’m on revision 1124, and the flag is located in include\aiPostProcess.h. Maybe you need to update your copy?

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 31, 2012 at 16:07

I do not have it under subversion … I have the website version

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Jan 31, 2012 at 16:10

@SuperPixel

I do not have it under subversion … I have the website version

Nevermind I’ve found the repo link for anonimous user and I’ve also checked the aiPostProcess.h header and yes they added it recently … I might have a go with that one

Thanks

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Feb 01, 2012 at 09:54

@Kenneth Gorking

It’s doubtful that the weights are screwed, it is more likely that some weights are being removed which had a significant impact on the vertices movement, and when they were removed, it started looking weird. Maybe you can try the aiProcess_SplitByBoneCount flag, and see if that helps things. If it doesn’t, you need to manually corect the model in a modeling program :mellow:

I’ve tried with that flag, but I’ve got the same problems. I think I should look for a simple animated model with just 4 bones per vertex… do you know about any of them ? It should preferably be a Collada format (*.dae)

thanks

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Feb 01, 2012 at 11:49

@SuperPixel

I’ve tried with that flag, but I’ve got the same problems. I think I should look for a simple animated model with just 4 bones per vertex… do you know about any of them ? It should preferably be a Collada format (*.dae) thanks

I can’t say that I do, but I think there are some test files in assimp. There might be one with animation, if you are lucky.

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Feb 01, 2012 at 17:57

@Kenneth Gorking

I can’t say that I do, but I think there are some test files in assimp. There might be one with animation, if you are lucky.

I debugged a bugged animation frame and I’ve found some bone matrices to have:

-1.#IND000

in all their 16 elements !!!!

for what reason could that happen ?

Cd586a7130b6cb95bed9ae57223fad5c
0
SuperPixel 101 Feb 02, 2012 at 16:52

@Kenneth Gorking

I can’t say that I do, but I think there are some test files in assimp. There might be one with animation, if you are lucky.

Finally I’ve solved ! I wasn’t checking the calculation of the w component of the quaternion that was giving me the sqrt of a negative value that was producing -1.#IND000!