- Home /

# Calculate quaternion animation curve's tangents from a euler animation curve

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):

```
float time = 1.7f;
float rotationZ = 90.0f;
float inTangent = -500.0f;
float outTangent = 500.0f
q = Quaternion.Euler(0, 0, rotationZ);
localRotationXKeyframes.Add(new Keyframe(time, q.x, inTangent, outTangent));
localRotationYKeyframes.Add(new Keyframe(time, q.y, inTangent, outTangent));
localRotationZKeyframes.Add(new Keyframe(time, q.z, inTangent, outTangent));
localRotationWKeyframes.Add(new Keyframe(time, q.w, inTangent, outTangent));
```

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:

```
float time = 1.7f;
float rotationZ = 90.0f;
q = Quaternion.Euler(0, 0, rotationZ);
localRotationXKeyframes.Add(new Keyframe(time, q.x));
localRotationYKeyframes.Add(new Keyframe(time, q.y));
localRotationZKeyframes.Add(new Keyframe(time, q.z));
localRotationWKeyframes.Add(new Keyframe(time, q.w));
```

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?

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.

**Answer** by aldonaletto
·
Jan 13, 2012 at 11:36 AM

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.

If you can use an alternative format, convert the quaternion to its angle/axis representation (see the functions Quaternion.AngleAxis and Quaternion.ToAngleAxis):

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.

In those cases where you rotate only around a fixed axis, you can store the angle alone and convert it back with Quaternion.Euler (or AngleAxis, if the axis isn't x, y or z).

**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 $$anonymous$$esh. 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.

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.

**Answer** by tinyant
·
Dec 20, 2017 at 08:08 PM

Anyone make success transfer euler curve to quaternion Curve?

### Your answer

### Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

### Follow this Question

### Related Questions

How can I set the tangents of Keyframes in an AnimationCurve through scripting? 1 Answer

Is it possible to compare Quaternions if the axes are the same? 1 Answer

Problem snapping object to different normals, but maintaining x axis orientation 0 Answers

Fixing the rotation around a particular axis using Quaternions? 2 Answers

Vector3.forward only moves me in 2 directions when rotating 1 Answer