Sign in to follow this  
easyBob0101

Matrix troubles (skinning the bones)

Recommended Posts

easyBob0101    122
I've written an exporter for Blender that exports all the data I need to do a simple skeletal animation. The structure is like this: The mesh has it's own world space matrix and all verts are local to it. Each vert knows which bones influence it and by how much (smooth skinning ready, but currently trying simple skinning). Rendering a static mesh properly is no problem. The bonetree(armature) has it's own world space matrix as well. Each bone gets it's local and world space matrix calculated after each call to slerp. Rendering the animated bone structure is no problem either. I can render the bone tree correctly using either local(concat) or world matrixs(push/pop). The problem I have is how to apply those bone rotations/translations to the mesh. During the render step for the mesh, I have the bones local and world matrixs that effect the current vert, and also the meshes world matrix...Basicly, I have all the stuff I should have to be able to rotate and translate the verts... But I can't seem to find the right way to apply all the data to rotate and transform the vert based on the bone data, and it's driving me nuts. So, simply, how do I apply the bone data to the vert to rot/trans it correctly? Thanks in advance, -Chris Again, the data available during the render step is: for each face: for each vert in face: -Bone local matrix -Bone world matrix -Bonetree world matrix -vert (xyz) local coord -mesh world matrix EDIT: The closest I've come to making it look right is by taking the bone worldspace matrix and multipling it by the inverse bonetree world matrix, then multipling the vertex by that new matrix. The root bone effects the mesh correctly but all it's child bones seem to stretch out everything they are connected to. [Edited by - easyBob0101 on March 20, 2007 5:38:19 AM]

Share this post


Link to post
Share on other sites
JohnBolton    1372
Here is a summary. First, you have the model space locations of the vertices in the "bind" pose. Then to animate a vertex, for each bone that modifies it -- you transform it into that bone's space (inverse of the bone's bind pose transform), transform it back into model space using the animated bone transform, then weight it and accumulate it.

Share this post


Link to post
Share on other sites
easyBob0101    122
Quote:
Original post by JohnBolton
Here is a summary. First, you have the model space locations of the vertices in the "bind" pose. Then to animate a vertex, for each bone that modifies it -- you transform it into that bone's space (inverse of the bone's bind pose transform), transform it back into model space using the animated bone transform, then weight it and accumulate it.


Thanks John!

It's closer than it has ever been. It still is incorrect, but I now think it has to do with the data I'm exporting from blender...How blender keeps all it's bone data is kinda funky to me (bone space->armature space->pose space->world space).

I'm exporting the bones armature space data when I think I should export the bones armature space * armature mat to get the world space data for the bind pose (I'm not used to using 'bind' as a term...kinda new to this).

Anyways, thanks again!
-Chris

EDIT: Here is how bones are rendered (this draws my supposed "bind pose"/no animation) from local space data:
void EXLoader::RenderBones (Armature a)
{
glPushMatrix ();
glMultMatrixf ( glSpace.to16 () );
for(int r=0;r<a.numRoots;r++)
{
glPushMatrix ();

// apply the armatures world matrix
glMultMatrixf ( a.WorldSpaceDQuat.getMat ().to16 () );

RenderBone (a, a.RootNodes[r]);
glPopMatrix ();
}
glPopMatrix ();
}

void EXLoader::RenderBone (Armature a, int b)
{
glPushMatrix ();
// apply the bones local matrix
glMultMatrixf ( a.Bones[b].boneLocal.to16 () );

glDisable (GL_LIGHTING);


glColor3d (0,0,1);

glBegin (GL_LINES);
glVertex3d (0,0,0);
glVertex3d (0,a.Bones[b].bLength,0);
glEnd ();

glEnable (GL_LIGHTING);

for(int t=0;t<a.Bones[b].numChildren;t++)
RenderBone (a, a.Bones[b].ChildList[t]);
glPopMatrix ();
}










And this is how I render the armature space data:

glDisable (GL_LIGHTING);
// convert from left hand to right hand system
glMultMatrixf ( glSpace.to16 () );

// bring bones into world space
glMultMatrixf ( BModel.MArm.WorldSpaceDQuat.getMat ().to16 () );
//
// testing
for(int k=0;k<BModel.MArm.BoneCount;k++)
{

glPushMatrix ();

// apply the bones armature space matrix
mat4x4 temp = BModel.MArm.Bones[k].boneWorld;

glMultMatrixf ( temp.to16 () );

glColor3d ( 1,0,0 );
glBegin (GL_LINES);
glVertex3d (0,0,0);
glVertex3d (0,BModel.MArm.Bones[k].bLength,0 );
glEnd ();
glPopMatrix ();
}
glEnable(GL_LIGHTING);










I'm a little worried that my bone data is not really in the proper space to transform the verts...I did a search for "bone pose" to see what it is about, and didn't find anything. Is the bone pose data in world space, or local to something like how I have my bone data stored (local to the armature object)? Same question for the mesh data...Are the verts supposed to be in world space when in the bind pose? Because just like the bones, the vert data is local to the mesh object.

[Edited by - easyBob0101 on March 24, 2007 11:55:38 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this