Understanding how animated constraints work in Xsi
Author : David, created in: April 2006, last updated in; March 2010
Note: this article is for the defunct Softimage XSI but constrains could work the same in your 3d package of choice.
I noticed a problem with animated constraints in XSI 5.1. This problem was already in XSI 4.x. After talking with Leith on the Xsi base forum, I understood how animated constraints work, and how they blend with object's transformations and fcurves. In this page you will find links to documents, description of the problem, workarounds to this problem, and an explanation on how do constraints work.
LINKS:
The test scene I am relating to is available here.
Link to the XsiBase forum thread (Note: Xsibase has disappeared since 2 years now).
PROBLEM DESCRIPTION
On this picture: I have a sphere in the middle that is pose constrained (with an offset) to the left cube (cubeleft), and the sphere is also pose constrained on the right cube (cuberight). I animated the blends of the constraints property pages so that at frame 1, the sphere will follow "cubeleft", and at frame 100, the sphere will stick to "cuberight".
Now, on the next picture, I key a translation on cubeleft at its original position at frame 1. At frame 100 I translate it far away, and key it at -10000 in the Z direction.
So when I playback the animation, the sphere will start by following cubeleft. In the middle of the animation, the sphere will not follow the left cube anymore and will start to come back to its constraint on cuberight. So at frame 100, the sphere will be at the same position as frame 1.
Now I want to check if the blending of these 2 constraints is working well. I go back to the first frame, and use the right arrow key of my keyboard to play the animation frame by frame.
When I reach frame 50, I put the mouse over the camera view and press "F" to focus on the sphere. Then I add a memo cam to the viewport. Check the image above.
Now I click randomly in the timeline, once at frame 15 then 72 etc.
After several clicks I go back to frame 50 and here is the problem: the sphere is not there, in the camera view.
If I go back to the first frame and play the animation frame by frame, the sphere will show up in the camera view. But if I go to frame 100, and then backwards to frame 1, frame by frame, the sphere will not show up in the memorized cam at frame 50!
As suggested in the Xsi Base forum, I tried to lower the translation value of cubeleft. Same problem. Cubeleft travels only at -100 (at frame 100). When the scene is played frame by frame from the start, at frame 50, the sphere has a translation value of -17.0626. But when jumping directly to frame 50, it has -13.5744.
Another suggestion were to use the 2 points constraints. It works when you animate the distance percentage slider, but when keying the blend weight slider, you run in the same problem as stated above. Also, sometimes in production, you just need the pose constraint.
WORKAROUNDS:
- Render sequentially.
- Plot the translation (and any other transforms) of the sphere.
- Use a script that will refresh the scene at each frame for render.
QUESTIONS REMAIN:
So my question is: is there a way to avoid these workarounds to play, and RENDER, a constrained animation ?
We had this problem on a production where characters were riding fast vehicules travelling large distances. Sometimes the characters were attached to the vehicules, sometimes they had to be free of the constraints when falling, etc. Some monsters where jumping on and falling from the vehicules. So we had to use animated constraints. The render team had to plot everything.
A LITTLE EXPLANATION ON CONSTRAINTS :
First we need to differentiate 2 things concerning frames. In this article I will tell about "previous timeline frame": if you're on frame 50, the previous timeline frame will be 49. "Previous selected frame" is different: if you jump from frame 75 to frame 50, the previous selected frame is 75.
First let's take simple situations.
If you have an object like this sphere, that has no keyframe on it, and apply on it a pose constraint (to cubeleft) with a blend weight at 1. The transformations of the sphere will be totally overidden by the constraint. The transformation of cubeleft will lead the one of the sphere.
Now if you put on the sphere another constraint to another object, (cuberight) with a blend weight at 1 as well, the second constraint will override everything else. The transformation of cuberight will lead the one of the sphere.
Now let's see what happens when there is only one constraint from the sphere to cubeleft, with a blend weight at 0.5. XSI needs to average things between the transformation of the sphere and the transformation of cubeleft. So in a rough calculation we get this:
(sphere.posz + cubeleft.posz ) / 2 = [final posz of sphere]
But there is a problem here. The computation of the sphere's position could run into a cycle if the source sphere's posz and the resulting sphere's posz are values from the same frame. XSI needs a reference to do its calculation. And this reference is not the previous timeline frame, but the previous selected frame.
Indeed, when you jump from frame 75 to frame 50, the position of the sphere at frame 75 is the reference. If Softimage had to evaluate the real, correct position, it would need to reset each object's transformation, and replay the animation from the start. This is not possible, especially with rig systems that need many frames to compute, such as springs. When you jump from one frame to another, you just expect to land on that frame, not to have many frames played back.
So the correct formula would be:
([sphere.posz at previous selected frame] + [cubeleft.posz at current frame]) / 2 = [posz of sphere at current frame]
Now let's change this so it matches the logic of the constraints' blend weight slider.
([sphere.posz at previous selected frame] * 0.5 ) + ([cubeleft.posz at current frame] * 0.5) = [posz of sphere at current frame]
If you move the blend weight slider, it is easy to guess the factor for the simple transformation of the sphere, as the total must always equal 1.
So if your constraint's blend weight is at 0.3, just calculate 1 - 0.3 = 0.7 . This is the factor for the sphere's transforms.
So we get a new formula here :
([sphere.posz at previous selected frame] * (1 - [value of the constraint's blend weight slider at current frame]) ) + ([cubeleft.posz at current frame] * [value of the cns' blend weight slider at current frame]) = [posz of sphere at current frame]
It's getting messy, time for an excel sheet :)
Example:
Use the example scene. Say we go from frame 3 to frame 4.
Go to the first frame, reset the sphere's translation (delete any key if there are any), then go frame by frame to frame 3. Note the transformation of the sphere. In my scene, it is sphere.kine.local.pos.posz = -296.9394
Go to frame 4 and note the transformation of cubeleft. cubeleft.kine.local.pos.posz = -400
Note also the value of the blend weight slider : 0.96
Let's use the final formula we built above and put it into practise:
The formula is :
([sphere.posz at previous selected frame] * (1 - [value of the constraint's blend weight slider at current frame]) ) + ([cubeleft.posz at current frame] * [value of the cns' blend weight slider at current frame]) = [posz of sphere at current frame]
With the values we wrote down, we get:
(-296.9394 * (1 - 0.96)) + (-400 * 0.96) = (-296.9394 * 0.04) + -384 = -11.877576 + -384 = -395.877576 = posz of sphere at current frame
Now select the sphere at frame 4 and watch its position in Z, it should be the same result.
If you jump from frame 75 to frame 50 you can guess the position of the sphere at frame 50 using the same calculation.
Additional constraints
What happens if there is an additional constraint with a blend weight between 0 and 1 (like the additional constraint to cuberight) ? Well, XSI will average between the first result and the second constraint. You take the result of the formula above, and put it back in the same formula, except that the transforms of the sphere is replaced by the result of the first calculation. Here it goes:
(result of first calculation * (1 - value of the 2nd cns' blend weight slider at current frame) ) + (cuberight.posz at current frame * value of the 2nd cns' blend weight slider at current frame) = posz of sphere at current frame
And there is a case when things are much simple, it's when the constrained object is keyframed. When the sphere has a keyframe at posZ = 0, on the frame 0, the formula will always use "0" as the sphere's transform. So no need to use the previous selected frame. The system is stable and jumping from frame 50 to one random frame to frame 50 again will let the sphere appear in the memo cam I was talking about before.
This logic explains why we sometimes get unpredictable results on networks renders. To avoid these problems, it's a good idea to have a plotting script.
If this information is not correct, or if you have questions or suggestions, contact me.