I'm loading a 3D asset into a Away3D scene and I'd like to move the position of the bones in code.
The asset loading all goes well, I grab a pointer to the Mesh
and Skeleton
while loading:
private function onAssetComplete(evt:AssetEvent):void
{
if(evt.asset.assetType == AssetType.SKELETON){
_skeleton = evt.asset as Skeleton;
} else if (evt.asset.assetType == AssetType.MESH) {
_mesh = evt.asset as Mesh;
}
}
After the asset(s) have finished loading, I have a valid Skeleton
and Mesh
instance, the model is also visible in my scene. The next thing I tried is the following.
// create a matrix with the desired joint (bone) position
var pos:Matrix3D = new Matrix3D();
pos.position = new Vector3D(60, 0, 0);
pos.invert();
// get the joint I'd like to modifiy. The bone is named "left"
var joint:SkeletonJoint = _skeleton.jointFromName("left");
// assign joint position
joint.inverseBindPose = pos.rawData;
This code runs without error, but the new position isn't being applied to the visible geometry, eg. the position of the bone doesn't change at all.
Is there an additional step I'm missing here? Do I have to re-assign the skeleton to the Mesh
somehow? Or do I have to explicitly tell the mesh that the bone positions have changed?
This might not be the best way to solve this, but here's what I figured out:
Away3D only applies joint transformations to the geometry when an animation is present. In order to apply your transforms, your geometry must have an animation or you'll have to create an animation in code. Here's how you do that (preferably in your
LoaderEvent.RESOURCE_COMPLETE
handler method:After that initialization step, you can modify your joint poses dynamically (you alter the position by modifying the
translation
property and the rotation by altering theorientation
property). Example:If you don't know the indices of your joints and rather address bones by name, this should work:
If you use the name-lookup frequently (say every frame) and you have a lot of bones in your model, it's advisable to build a
Dictionary
where you can look up bone indices by name. The reason for this is that the implementation ofjointIndexFromName
performs a linear search through all joints which is wasteful if you do this multiple times.