   Skeletal Animation: "Bonespace"
  I've been working for a couple days trying to get my head around all of the theory behind skeletal animation, and I think I've got the basic idea, but there's still a few things that are confusing me.Been working mostly with blender through its Python API, to write an exporter, but I would assume this is similar across any animation package.Basically what I think I need so far is two matrices for every bone:M1) A matrix that converts from model space to bone spaceM2) A matrix that converts from the bone's parent space to the bone space.and to rotate a bone I need an M3M3) A matrix that defines a rotation to a bone in that bone's spaceAssume I have a bone chain such that bone 0 is the root and parent of bone 1, bone 1 is the parent of bone 2, etc. Then when I want to say, bend bone 3 by 45 degrees, I'll do something like this for all the vertices 'v' attached to bone 3 (ignoring verts attached to other bones for now)v; //v is in model spaceV1 = bone3.M1 * v; //V1 is in bone3 spaceV2 = (bone3.M3) * V1; //V2 is in bone3 space (now posed)V3 = (bone3.M2) * V2; //V3 is in bone2 space V4 = (bone2.M2) * V3; //V4 is in bone1 spaceV5 = (bone1.M2) * V4; //V5 is in bone0 spaceV6 = (bone0.M2) * V5; //V6 is in armature spaceV7 = armature.matrix * V6 //V7 is in world spaceThen if I want to say, rotate bone1 as well, I'll throw a bone1.M3 into the chain, which will rotate bone1 and all of the bones downstream, and allow all bones to rotate independently of each other.Now I'm working in blender and trying to build all of these matrices, but it is not making it easy, which is why I think I might have a wrong idea somewhere. I thought I understood a bonespace matrix is a conversion from a parent's space into a bone's space, but the documentation describes it as follows:Quote:'BONESPACE' - the matrix of the bone in relation to itself What could this mean, "in relation to itself"?Also I find it odd that it only defines a 3x3 matrix, don't I need a 4x4 matrix so that it can include the translation from the parent's origin to itself?Also the matrix it defines for the root bone I can't understand:[1,0,0][0,0,1][0,-1,0]The bone is aligned to the armature with no rotation that I can tell, so wouldn't this be identity?I know there's a lot of topics out on this already, but I haven't found anything that specifically answers my questions so I was thinking someone could tell me if I'm on the right track.Thanks!   
  This is something I've just figured out myself and is very fresh in my mind so perhaps if I pour out my thoughts it might help - you'll know most of it but it'll also help me to understand it better by writing everything down.I had lots of terminology issues, so in order to aid that, here's a 'key' as to what I perceive the terminology to be:Local Bind Pose Matrix - this is a matrix/transformation that represents a bone transformation in local bone space.  As it's part of the 'bind pose', this matrix represents the local transform of bones whilst the character is in the familiar 'T' bind pose.World Transform Bind Pose Matrix - this is a matrix/transformation that represents the bone transformations in world space.  In order for it to be in world space, it is a product of this Local Bind Pose Matrix (LBPM) and all of its parent World Transform Bind Pose Matrices (WTBPM), so currentBone->WTBPM = currentBone->LBPM * parentBone->WTBPM.Inverse Bind Pose Matrix - this is the important one.  This matrix is the inverse of the World Transform Bind Pose Matrix (WTBPM).  So at any level in the skeleton hiearchy, multiplying any bone's World Transform Bind Pose Matrix (WTBPM) by its Inverse Bind Pose Matrix (IBPM) will move into its bone's local bone space.Each bone in the skeleton then will have 3 matrices.  One Local Bind Pose Matrix, one Inverse Bind Pose Matrix and a new one - an Animation Current Frame Matrix.  The Animation Current Frame Matrix is the matrix we use when calculating a particular animation pose and also the one and only matrix that gets sent to the vertex shader (or the one that is used to transform vertices if doing CPU skinning).  All the other matrices remain intact throughout the whole application.  The reason we don't need the World Transform Bind Pose Matrix is because that's only really used at startup to give us the Inverse Bind Pose Matrix.  If you can import the Inverse Bind Pose Matrix with your skeleton data, you can omit it entirely.The skeleton is then made up of a number of these bones, each with any number of child bones as necessary.So the process of skinning to an animation pose (after a new acronym!) is:World Transform Bind Pose With Animation Matrix (WTBPWAM!) - This is essentially constructed in the same fashion as the World Transform Bind Pose Matrix above, but also includes any animation data for the current animation pose.  To calculate this matrix, you have:WTBPWAM = (currentBone->LBPM * localAnimationTransformForThisBone) * parent bone's WTBPWAM.  You don't really have to store this WTBPWAM matrix on the bone itself (or you could do if you like), you can simply pass it down the hierarchy.  It gets overwritten every frame anyway.So now we're all set to create the actual matrix used for the skinning, the Animation Current Frame Matrix.  To create this, immediately after the above creation of the WTBPWAM matrix, you do this:currentBone->ACFM = currentBone->IBPM * currentBone->WTBPWAMAnd that's it.  Pass the ACFM to the shader, multiply the vertex by it and it'll move to the correct position.The reason it works (which is what I had real issues grasping), is because when you multiply the vertex by the ACFM, the IBPM part of the transform first moves the vertex to the bone's local space (so any rotation would effectively be around the joint rather than world origin), then transforms it by the WTBPWAM which is the bind pose combined with any animation data.Hope that helps.  Perhaps you could apply it to your issue.   ;  I saw you had a similar post and I had been following it, I also appreciate you taking the time to write out everything so clearly. I do think that we are mostly on the same page theory wise.I guess what I'm hanging up on the most is exporting the Local Bind Pose Matrix. I believe that this is what I'm referring to as the Blender BONESPACE matrix. Am I right that the Local Bind Pose Matrix is the position and rotation of a bone in it's parent's space? Such that if a bone has no rotation from its parent and is just an extension of its parent by one unit in the Z direction it will look something like this? (I'm using Blender's coordinate system, so don't worry about RH/LH matrices at this point)[1,0,0,0][0,1,0,0][0,0,1,0][0,0,1,1]I'm just confused now why blender only uses 3x3 matrices for its bonespace matrix, which therefore contains no translation and only a rotation. What good is having the rotation only without a translation? I'm thinking that I have to build my own LBPM from this 3x3 rotation matrix (R), and the position (P) of the parent's tail in the parent's bonespace.[R,R,R,0][R,R,R,0][R,R,R,0][P,P,P,1]Usually I find the blender API to be pretty intelligently designed, so I'm just a little worried I'm missing something that I'm trying to hack together this matrix that they don't expose.Also I'm still confused why my bone with no rotation (only an extension in the parent's Z direction) has a non-identity bonespace rotation matrix, unless this blender matrix refers to some other kind of transformation, which is why I was confused that it said "the matrix in relation to itself".   ;Quote:I guess what I'm hanging up on the most is exporting the Local Bind Pose Matrix. I believe that this is what I'm referring to as the Blender BONESPACE matrix. Am I right that the Local Bind Pose Matrix is the position and rotation of a bone in it's parent's space? Such that if a bone has no rotation from its parent and is just an extension of its parent by one unit in the Z direction it will look something like this? (I'm using Blender's coordinate system, so don't worry about RH/LH matrices at this point)That's correct as far as I'm aware.Quote:I'm thinking that I have to build my own LBPM from this 3x3 rotation matrix (R), and the position (P) of the parent's tail in the parent's bonespace.A 3x3 LBPM doesn't sound right at all. How would you know the position of the parent's tail if the parent doesn't have a translation either?Could you maybe post up the bits of interest from your exported file?   ;  Well I don't have anything exported yet, I'm merely looking for the right variables in the API to export. This is what it exposes for each bone:The matrix values look kind of like what I want, although ARMATURESPACE is 4x4, while BONESPACE is a 3x3 matrix. Quote:headThis Bone's "head" ending position when in rest state. Keys are:    * 'ARMATURESPACE' - this head position in relation to the armature    * 'BONESPACE' - the head position in relation to itself.Type:    DictionarylengthThe length of the bone. This cannot be set.Type:    FloatmatrixThis Bone's matrix. This cannot be set. Keys are:    * 'ARMATURESPACE' - this matrix of the bone in relation to the armature    * 'BONESPACE' - the matrix of the bone in relation to itselfType:    Matrix ObjectrollThis Bone's roll value. Keys are:    * 'ARMATURESPACE' - this roll in relation to the armature    * 'BONESPACE' - the roll in relation to itselfType:    DictionarytailThis Bone's "tail" ending position when in rest state. Keys are:    * 'ARMATURESPACE' - this tail position in relation to the armature    * 'BONESPACE' - the tail position in relation to itselfType:    Dictionary ;  I think it looks like they just represent their bones slightly differently, they make break out the concept of a joint and a bone as two separate entities, one for the rotation (the 3x3 matrix), and the other for the length and perhaps scale? If you haven't already, I would create a very simple bone setup (just 2 bones) in blender and retreve the values from the api and you should be able to either calculate the values you're after or perhaps see it in a different light.   ;  Maybe the easiest way to calculate the bonespace matrix would be using the given armature matrices, I've looked at these values and they seem correct.If I'm looking for matrix "Bone1.bonespace" that converts from bone0 space to bone1 space, and I have two matrices Bone0.armaturespace and Bone1.armaturespace that convert from that bonespace to armaturespace, then I should be able to calculate Bone1.bonespace by:Bone1.bonespace = B0.armaturespace * (B1.armaturespace)^-1I'll try this out later when I get a chance. The problem with the given bonespace matrix is just that I've looked at the values and they just don't seem like what I expect them to be.   ;  Have you seen this?Might be worth a look at the link that someone has suggested on that thread, sounds like the OP is having a similar issue to yourself.Good luck   