Sign in to follow this  

skeletal / bone animation with matrices: Need help with understanding

Recommended Posts

I'm having difficulties understanding how the implementation lined out in this article is meant to work.

 

http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/skinned-mesh-animation-using-matrices-r3577

 

 

1) I don't quite understand what the different types of matrices are used for. As I understand it, a bone -in this implementation- does not have a position vertex, but a matrix, which stores it's position in world coordinates, right? Would that be the "offset matrix", the article speaks about?

 

2) The "ToParent" matrix of a bone, as I understand it, stores the position of a bone, in its parent bone's space right?

 

3) The "ToRoot" matrix does the same for a bone, with respect to the root-bone space correct?

 

4) The offset matrix does the same for a bone, encoding its position in world space?

 

5) The Transformation matrix, stores the current changes, for animation purposes?

 

6) This transformation is encoded in bone space, correct?

 

7) What exactly is the MeshFrame.ToRoot matrix? And what is it needed for. It seems that the article uses "frame" and "bone" interchangeably, But in the later parts of the article it talks about an animation "frame" too, which I think means a different concept (a point in time during an animation sequence), but I'm confused and not sure....   quoted from the article: // Note: MeshFrame.ToRoot is the transform for moving the mesh into root-frame space.

So my question really is, what do I need MeshFrame.ToRoot for, is it somehow different from all the other ToRoot matrices?

 

8) How is the world position of the root bone stored? Would that be its offset matrix?  In the article: offsetMatrix[ 0 ]  ?

 

[attachment=34233:torso-2.png]

 

9) Let's assume we have a mesh, as shown in the picture. 

"root-bone" has a child bone called "shoulder-bone", which again has a child bone "elbow-bone".

Let's also assume root-bone has no influence on any vertices of the mesh, apart from indirect influence on all its children, via parent to child propagation. Shoulder-bone has direct influence on the vertices of the upper arm and shoulder sub-set of vertices and finally, elbow-bone influences all vertices of the lower arm.

 

Now I'd like the bones to effectively have world space coordinates as shown in the picture. So here's my question: would root-bone's offsetMatrix then ( using "column-vector" matrices) be:

 

(1, 0, 0, 0)

(0, 1, 0, 1)

(0, 0, 1, 0)

(0, 0, 0, 1)

 

Or else, in which Matrix would that information for root bone be stored?

 

10) Would the root-bone's toParent be the Identity matrix?

 

11) With all the assumptions made in (9), what would the to MeshFrame.ToRoot matrix look like? Would it be:

 

( 1, 0, 0, 0 )

( 0, 1, 0,-1 )

( 0, 0, 1, 0 )

( 0, 0, 0, 1 )

 

12) Would the "ToParent" matrix of shoulder-bone be:

 

( 1, 0, 0, 0.3 )

( 0, 1, 0, 1.0 )

( 0, 0, 1, 0.0 )

( 0, 0, 0, 1.0 )

 

13) and the ToParent of elbow Bone would be:

 

( 1, 0, 0, 0.01 )

( 0, 1, 0,-0.50 )

( 0, 0, 1, 0.00 )

( 0, 0, 0, 1.00 )

 
sorry if some of this is repetitive.. Just needed some clarity with concrete examples.

 

 

Share this post


Link to post
Share on other sites
4) The offset matrix does the same for a bone, encoding its position in world space?

 

from the article:

 

"The transformation for a vertex to bone-space in "pose" position is called the "offset" matrix."

 

 

skinned meshes are one of the "thicker" 3d topics out there. it might take a while to figure it out.

 

try this for an example of fully working code:

 

http://www.gamedev.net/blog/1729/entry-2261223-skinned-mesh-code-part-1-low-level-microsoft-code/

Edited by Norman Barrows

Share this post


Link to post
Share on other sites

try this for an example of fully working code:  

 

 

thanks, had a look at it.. wow looks pretty involved code. When I get more time, I'll inspect it more.

 

Using my assumptions about the matrices I got to a spot where all the bone-connected vertices are transformed to be positioned at (0,0,0) in World space. Like so:

 

[attachment=34253:torso-3.png]

 

it seems like at this position they are just ready to be transformed according to animation, and then they need to be placed back "where they belong".

 

But: I followed the description, outlined in that article, to the iota (in my perception at least), so it seems, at render time, the bones should be already transformed back to where they belong. Why are they persisting to stay at world origin.. No dice. There must be a bug.

Share this post


Link to post
Share on other sites

I got it to work now.

 

Mainly where I got stuck was... I didn't realise that for each bone, it's TransformationMatrix needs to encode not only the bone's rotation relative to its parent, but also its translation, relative to its parent.

 

Somehow I had thought that its translation was already given by its toParent Matrix, which was wrong.

Not wrong per se.. but basically the toParent matrices yield the toRoot matrices which again are used to calculate the offset matrices. They bring the bones to their local spaces. Now animated state can be applied to them. This includes not only rotation, but also translation relative to parent bone.

 

On the whole, implementing this was quite tough and took me a while, because there were so many concepts in play that needed to be understood. At first I tried hacking through it, trying to get it to work without really understanding it. But looking back, poking the system, also helped me understand it better bit by bit, until finally I felt everything falling into place.

 

If you attempt this, using this article remember that the order of matrices is indeed important, and that you need to encode the rotation AND the translation (in that order) inside each bones TransformationMatrix. And don't despair, you'll get through it, in time. :-) 

 

[attachment=34301:torso-4.jpg]

Share this post


Link to post
Share on other sites

When tackling the subject of skinned animation like this, it's helpful to master rigid animation first. Skinned animation is basically the same thing, just much more complex.

 

With rigid animation, you take several objects (meshes) and link them together. You have a parent and a child and they in turn can have their own children. To make two objects parented together, you multiply their world/object matrices together in order to get the world/object matrix of the child that will actually be used.

 

That's a bit confusing, so let me try to state the same thing a little more clearly. You have the parent's matrix to position and orient the parent in the 3D world. The child has it's own matrix, but you don't actually use it, not directly anyway. Instead, you multiply the parent's matrix times the child's matrix and use the result as if it is the child's world/object matrix.

 

Now, anything the parent does will affect the child, yet the child can rotate and even translate (move) independently of the parent. So, if the parent is a car body and the child is a wheel, the wheels will move when you move the car body through the scene and stay attached to the car. Furthermore, you can rotate the wheels without affecting the orientation of the car body.

 

What about a grand-child? What if the wheels have a ring of spikes that is a separate mesh attached to the wheel that rotate in the opposite direction the wheel rotates when you press a button on the controller? Things still work the same for the car body parent and the child wheel. But now the wheel has it's own child. So, to get the world/object matrix of the grand-child you multiply the car body matrix times the wheel matrix times the spike ring matrix to get the world/object matrix of the spike ring. In doing so, the spike ring will stay attached to the wheel, which stays attached to the body of the car, but when it can rotate independently of the car body or the wheel.

 

When playing with this, start with basic meshes if it helps. You can take 4 cubes and link them together in a chain this way, for example.

 

Rigid animation is very easy to implement in code.

 

Skinned animation takes this same concept except instead of the matrix controlling an entire mesh, it controls a bone of the model's armature. You may only have 1 mesh with many bones. In a humanoid, you may have a torso bone as a parent of a neck bone that is a parent of a head bone. And the "bones" are attached to the vertices of the model in a process known as "skinning". So, the matrices here are moving vertices of a single mesh.

 

Another thing to be careful of is that the matrices are offset from one another because a bone has a position of one end of the bone, an orientation of the bone, and a length of the bone where the other matrix (bone) is supposed to be attached to.

 

In an animation, the armature has a pose called a "frame". Technically, a frame is the pose of the armature for each time you draw the screen or each iteration of the game loop. By interpolating (averaging position and orientation) between two poses you can fill in all the frames that morph one pose into the next. That is how animation is done: you set poses called "key frames" and your code morphs one pose into the next by interpolating between the matrix values of one pose to the next as a weighted average. When you are 0% of the way between the two poses, it uses 100% of the first pose. When you are 100% of the way between the two poses, it uses 100% of the second pose and 0% of the first. Any percentage between the two gets a weighted average, so that 60% of the way between the two poses (time wise) will use 60% of the second pose and 40% of the first pose.

 

I believe this requires SLERP. I haven't coded this in probably over a year now and so my memory of it is getting a bit rusty. But I seem to recall that matrices are really terrible at this kind of interpolation, which is why people use quaternions in basically the same way although a quaternion requires you to store the position separately because it can only store orientation on it's own (possibly you need to store scale separately as well). I'm sure there's a way to decompose the matrices and interpolate them, but it's pretty certainly going to be easier and more efficient to use quaternions for this. It's the one time that I think quaternions are better than matrices and the one place I would recommend not using matrices. Still, getting the concept down using rigid animation and matrices first should help the learning process. You'll be doing the same thing with quaternions, it's just that it's better to use them for SLERP (Spherical Linear Interpolation) (that's: circular weighted averages in human speak). And you need to SLERP between every key frame pose to produce your animations for your armature.

 

Once you get your armature moving properly according to the animation file, you can then attach the vertices of the model to the bones(matrices - or in this case quaternions).

 

Another thing to be aware of is that the humanoid model is probably modeled in what is called a "T-pose". That's where the arms are out straight like a letter t or they can be angled down somewhat. It's done this way largely so that the artist can see the torso underneath from the sides, but also to reduce the amount of stretch needed during animation. But the big thing to be aware of is that this pose is your "zero". This T-pose is basically like all of your matrices as identity matrices. Every pose is related back to this pose.

 

If you think about it, it has to be this way. If all of your matrices in the armature are identity matrices, they would all be on top of one another at the origin and you no longer have an armature. They all have to be spread out in the T-pose and contain non-identity values to have your neutral "just standing there" pose. So, any new pose is going to be related back to the neutral T-pose. A slight rotation of the head is not relative to an identity matrix, but rather relative to the T-pose. So, you have to take that into account.

 

Anyway, frame and bone are not the same thing. A frame again is an iteration of your animation or game loop. A bone is a matrix or similar construct such as a quaternion that you can imagine as a line oriented and positioned in 3D space and a child of any parent bone it is attached to. Your bones can move each frame in the animation. A pose is the positioning of these bones in any one given frame. The animation file will contain poses for specific frames and you have to interpolate the poses between the key frames that are given poses.

 

Edit: After quickly glancing over the article you are referencing, I can see the author does indeed call a bone a "frame". He means "frame of reference" as he explains and seems to get this idea from mathematics. That's kind of confusing, because animation and game programming uses the word frame to mean something entirely different which is: a slice of time which is one iteration of the animation or game loop where an armature will have a specific pose. No big deal, as long as you understand that the word frame there is being used to mean two completely different things, both related to the same subject of animation. Hence the reason we call them bones and not frames. A critical concept in animation is understand "key frames" and those have nothing to do with bones, but rather are a point in time, except that you pose the bones into a specific pose at every key frame. It's rather confusing to say instead that you "pose the frames into a specific pose at every key frame".

Edited by BBeck

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