Sometimes one wishes to procedurally take control of a model's joint. For example, if you wish to force a character model's eyes to follow the mouse, you will need to procedurally take control of the neck and head. To achieve this, use controlJoint. Caution: the behavior of controlJoint is not entirely straightforward, so be sure to read this entire section.
myNodePath = actor.controlJoint(None,"modelRoot","Joint Name")
|
This creates a dummy node. Every frame, the transform is copied from the dummy node into the joint. By setting the transform of the dummy node, you can control the joint. Normally, one would want to use setHpr to rotate the joint without moving it. The dummy node is initialized in such a way that the joint is in its default location, the one specified in the model's egg file.
You must store a local (not global) transform in the dummy node. In other words, the transform is relative to the joint's parent bone. If you are controlling the forearm of a model, for instance, the transform will be relative to the upperarm.
The string "modelRoot" represents the name of the model node - the string "modelRoot" is usually the correct value.
The string "Joint Name" represents the name of the joint. Typically it would be something like "Femur", or "Neck", or "L Finger1". This is usually set inside the modeling package. For example, in MAX, each object in the scene has a name, including the bones. If necessary, you can determine the joint names by scanning the egg file for strings like <Joint> Femur . Beginning in Panda3D version 1.2, you can also use the call actor.listJoints() to show the complete hierarchy of joints.
Cautions and limitations
- controlJoint only works when an animation is playing on the joint. The animation of the controlled joint is completely overridden. However, the animated movement of other joints continues normally. In other words, you have to create an animation for the model, and the animation must manipulate the joint you wish to control. If the animation ends, the control stops as well. If the animation is restarted, you regain control.
- controlJoint works by setting up some internal structures that must be in place before a given animation has been started the first time. Thus, it is important to make all of your controlJoint() calls for a particular model before you make the first call to play(), loop(), or pose().
- controlJoint cannot be undone. Once you call controlJoint, the joint in question is forever under application control; the animation channels no longer affect the joint. If you need to restore animation control to a joint in your application, one strategy would be to load two copies of the Actor, and only call controlJoint on one of them. When you want to restore animation control, swap in the other Actor. A different strategy might be to create a new, dummy joint in your character that doesn't have any animation on it anyway, and only call controlJoint on that dummy joint.
These limitations are due to the implementation of the animation subsystem. Eventually, we hope to remove the these quirks in controlJoint.
|