Bone Manipulation

Dec 8, 2008 at 4:42 PM
I was wondering if it was possible to change the position/orientation of individual bones.

I've been trying to do this for a while today, but I can't seem to get it done, mostly because the ModelData.SkeletonData.Transform[] is only accessible through a ReadOnlyArrayCollection. That was probably intentional :P

Maybe this is not the right data to use to reposition/orient models... anybody have a way to do it?


Coordinator
Dec 9, 2008 at 2:17 AM
Edited Dec 9, 2008 at 2:32 AM

Hello.

Unfortunately this isn't currently supported. It's on the todo list though (along with some other refactoring of the animation system). Animation is fairly complex, so I've yet to get round to those changes.

>> Maybe this is not the right data to use to reposition/orient models... anybody have a way to do it?

If you simply want to position the entire model, then the best way is to use the world matrix. If you want to position meshes within the model, then that also isn't supported - although it could be done with the ModelInstanceShaderProvider class, by pushing a new world matrix in the BeginMesh method (the method must be overridden - you'd also need to override EndMesh).

If you simply want to put in a work around that does allow setting individual bones, then there are a few places/ways it could be done.

The most important place in the code is ProcessAnimation method in the AnimationController class. The very last line of this method is:

modelData.skeleton.TransformHierarchy(transformedBones);

The transformedBones array stores the bone transforms in their own local space. The TransformHierarchy method recursively transforms the bones into world space (starting at the parent, going through the tree).

If you want to modify a bone, before or after this last line would be the place to do it (depending if you want a world space change, or a bone space change).

You would need to put in some of your own code to do this. As I say, I plan to add this ability (hopefully in the next update) but that won't be out until the new year.

The other option, is to simply have animations representing the transforms you want to apply, and then weight them accordingly. It's an ugly solution but it can work surprisingly well in some limited situations (eg, a 'look left' animation could be used to have a character look left and right). 

Be aware of a potential problem with this, models in xen store bounding boxes that are animated with the model. If you are changing values too significantly, you may find your models getting culled prematurely.

Thankyou ! :-)

Dec 9, 2008 at 7:04 AM
Edited Dec 9, 2008 at 7:34 AM
Ah sweet. I had already tried adding some code but I was looking in the wrong place. Thanks for the pointer.

I'll add the hack until you put it in :)

EDIT:

I've been looking at the code of the animation controller, and I think it's pretty essential to know exactly how the transformedBones Transform[] is built up in order to replace it.

How is the Transform[] constructed (roughly)? I understand it is a set of local bone transforms, so that just means a position and an orientation relative to the model's origin? Or other data as well?
Coordinator
Dec 9, 2008 at 10:28 PM
Edited Dec 9, 2008 at 10:39 PM

It's actually fairly complex. (surprise! :)

The bones are stored in relation to the default pose of the model. And the bone transforms are stored as 'bone-local' transforms, as you guess. So a change to the root bone before the hierarchy transform will change the entire model.

The 'gotcha' in all this, is the first bit. The bones are in relation to the model for their world-transform. So the default pose will have *all* identity transforms (for both local and hierarchy transformed bones - the transforms sent to the video card will all be identity). Any local transform you make may have unexpected results if you just send in a world matrix.

The advantage is that the transforms are fairly simple, and compress really well.

To get a bone transform from local space, into game world space, then you need to do something similar to tutorial 12. In this case, the heirachy transformed bone is multiplied by the transform in Skeleton.BoneWorldTransforms. This last bit is quite important. If you wish to set a bone to an exact world matrix, you will need to apply the inverse of this transform. (does that make sense?).

To make things even more complex, the bones are decoded from the compressed streams as they are needed. This is why the code may look a bit scary. It's to keep memory usage down (although they are decoded into buffers that currently waste too much memory :) I haven't touched the animation code since the very first release, and it's something I want to clean up a bit soon.

I'm hope I've explained it correctly...

Dec 10, 2008 at 2:13 PM
I think I understand. So there are 2 things that are important

1. Transforms are relative to base-pose (in the tiny_anim4 model the arms outstretch standing up pose)
2. Transforms are relative to parent bones throughout the hierarchy.

The second one is the most tricky to deal with, but can be done pretty easily by parsing the hierarchy and pushing/popping the transforms as you pass through the hierarchy.
Coordinator
Dec 10, 2008 at 8:10 PM

Yes that is correct.

The second one can be dealt with by modifying the bones after the hierarchy transform. However you will only be modifying one bone at a time then (for instance, if you just wanted to rotate the head, that would be fine - assuming there are no bones attached to the head).