|
I am creating a custom animation editor that lets users modify the animation curves of various components. One component I am having trouble with is the rotation of an object. I allow the user to edit the rotation's euler components (actually just the z rotation since the editor is for 2D). When generating the final animation, I convert the euler animation curve to a set of four quaternion curves. The problem is that the tangents of the euler curve do not seem to correspond to the quaternion. Here is the animation curve for the z component of a curve:
If I calculate my quaternion curve by adding the keys the following way, the animation jumps around erratically (this example is adding the middle keyframe): If I add the quaternion key without using the euler z curve's tangents, the animation interpolates smoothly, but doesn't follow the swings of the curve: Obviously the tangents of the euler curve do not correspond with the tangents of the calculated quaternion curve. My question is how do I create a quaternion animation curve based on the euler animation curve, with properly translated tangents?
(comments are locked)
|
|
The quaternion is a math representation of a single rotation of some angle around an arbitrary axis, where x, y and z are the normalized vector that defines the axis orientation multiplied by sin(angle/2) and w is cos(angle/2). Since sin(0) is zero, the axis orientation becomes critical for small angles, and the interpolation functions may produce incredibly wrong orientations at these points. float angle = 0; Vector3 axis = Vector3.zero; // get the angle/axis equivalent of "rotation" rotation.ToAngleAxis(out angle, out axis); localRotationXKeyframes.Add(new Keyframe(time, axis.x)); localRotationYKeyframes.Add(new Keyframe(time, axis.y)); localRotationZKeyframes.Add(new Keyframe(time, axis.z)); localRotationWKeyframes.Add(new Keyframe(time, angle)); You will have to convert it back to quaternions using Quaternion.AngleAxis, of course. EDITED Paying a little more attention to your animation curve, I noticed that it strongly depends on the mid-point tangent. As a rule of thumb, you should add points for each curvature inflection - the top and bottom points, in this case:
This avoids problems with the tangents, since they are always zero at these points. Thanks for the advice! Unfortunately, I can't store the values as axis / angle temporarily since I'm dumping the quaternions directly into an Animation Mesh. I think I will tell users of my editor that they should try to add keyframes at the inflection points like you suggested. I eventually wrote a procedure to "Bake" a quaternion curve by iterating over my euler curve for the z axis. I divide each segment of the curve into 5 pieces and then sample at an even interval, calculating the tangents by the vectors between points. It's not exact, but it comes out pretty close to the original euler representation. This also gets around the limitation of a quaternion only being able to rotate up to 180 degrees. Since I'm sampling in small increments of the angle, it always goes in the direction I'm wanting.
Jan 13 '12 at 01:44 PM
echo17
It's a good alternative: evaluating the curve at other points will make the result way more precise. Anyway, if you want to try the tangents, I suppose they can be calculated by something like this: float delta = 0.1; // choose a suitable delta float t = curve.keys[n].time; Quaternion q = Quaternion.Euler(0,0,curve.keys[n].value); Quaternion q1 = Quaternion.Euler(0,0,curve.Evaluate(t-delta)); Quaternion q2 = Quaternion.Euler(0,0,curve.Evaluate(t+delta)); float inTgX = (q.x-q1.x)/delta; float outTgX = (q2.x-q.x)/delta; float inTgY = (q.y-q1.y)/delta; float outTgY = (q2.y-q.y)/delta; ... It's a pseudo-code, of course, but I believe the basic idea is valid.
Jan 13 '12 at 03:25 PM
aldonaletto
(comments are locked)
|



The depressing thing is that quaternions "go the way they want" - it's annoying! Quite simply, make a quaternion that goes from north to south pointing. A human would expect it to swing around through 180 degrees, staying on the z=0 plane. As you'll see this is not the case. It "decides" to go another route (and why wouldn't it? it's all the same). It's one of the love/hate things about quaternions. As a broad-general principle, the "LookAt" quaternion functions rather than the "fromTo" quaternion functions can, sometimes, help you quickly hack through this in gameplay.