- Home /

# Lerping a Quaternion the long way around

So we all know that Quanternion.Lerp() moves from one rotation to the other over the shortest possible distance.

I would like to know if there is a way to make the Lerp go in the opposite direction.

My initial impulse was to find the rotation at the "halfway rotation" in the lerp (where t = 0.5) between two rotations and then reverse the rotation to face the opposite direction. With this new rotation, I would rotate from my start to that, and then from there to my end, but I have absolutely no idea how to "reverse" the angle of the rotation.

Is what I'm asking even possible?

Haven't tried Quaternion.Lerp() in particular, but for other Lerps, the t value is automatically clamped to [0..1].

**Answer** by drizztmainsword
·
Jun 08, 2012 at 04:08 AM

Okay, I got this to do what I wanted. It might be a bit more annoying to pull off, but it provides that much more customization to my sword swings, so that works out.

What I did is add a third rotation for the midpoint along my path. Then, if I've set up the slash to use that mid rotation, I fire off this bit of code (understand that "lerpTime" is a 0 - 1 float for the lerp).

```
if (0.5f >= lerpTime)
relativeRotation = Quaternion.Lerp(startRotation, midRotation, lerpTime * 2);
else
relativeRotation = Quaternion.Lerp(midRotation, endRotation, (lerpTime - 0.5f) * 2);
```

Thus, so long as the difference between startRotation and midRotation and midRotation and endRotation are each less than 180 degrees from each other, the movement looks correct. With a sword slash, this also allows me to incorporate sweeping motions and little flicks that might have otherwise been very difficult to pull off.

I hope this is useful to other folks beside me. I know doing sword slashes through code isn't exactly a broad use case.

I cant see the code here. I have the same issue and would love to know the answer!

I converted it to Yoda syntax, so that the html parser won't mess it up.

I think it is also worth mentioning that midRotation is calculated like this:

```
Quaternion midRotation = Quaternion.Slerp(startRotation, endRotation, 0.5f) * Quaternion.AngleAxis(180f, Vector3.forward);
```

Set Vector3.forward to your rotation axis.

**Answer** by Maeslezo
·
Jan 26, 2017 at 02:42 PM

I think those solutions are weird or at least not very "quaternion" friendly.

I have written the lerp and slerp myself, with a flag to indicate whether you want to force the short way or not. I am pretty sure that Unity checks that to invert the rotation. With this code, you can indicate if you want that behaviour.

I have checked myself and it seems it works ok, but check yourself just in case:

```
public static class QuaternionExtension
{
public static Quaternion Lerp(Quaternion p, Quaternion q, float t, bool shortWay)
{
if (shortWay)
{
float dot = Quaternion.Dot(p, q);
if (dot < 0.0f)
return Lerp(ScalarMultiply(p, -1.0f), q, t, true);
}
Quaternion r = Quaternion.identity;
r.x = p.x * (1f - t) + q.x * (t);
r.y = p.y * (1f - t) + q.y * (t);
r.z = p.z * (1f - t) + q.z * (t);
r.w = p.w * (1f - t) + q.w * (t);
return r;
}
public static Quaternion Slerp(Quaternion p, Quaternion q, float t, bool shortWay)
{
float dot = Quaternion.Dot(p, q);
if (shortWay)
{
if (dot < 0.0f)
return Slerp(ScalarMultiply(p, -1.0f), q, t, true);
}
float angle = Mathf.Acos(dot);
Quaternion first = ScalarMultiply(p, Mathf.Sin((1f - t) * angle));
Quaternion second = ScalarMultiply(q, Mathf.Sin((t) * angle));
float division = 1f / Mathf.Sin(angle);
return ScalarMultiply(Add(first, second), division);
}
public static Quaternion ScalarMultiply(Quaternion input, float scalar)
{
return new Quaternion(input.x * scalar, input.y * scalar, input.z * scalar, input.w * scalar);
}
public static Quaternion Add(Quaternion p, Quaternion q)
{
return new Quaternion(p.x + q.x, p.y + q.y, p.z + q.z, p.w + q.w);
}
}
```

**Answer** by Wolfram
·
Jun 02, 2012 at 12:57 AM

It certainly is. And there is probably also a simpler/better way to do it, but since I'm not a Master of Quaternion, I'd suggest this:

find the Quaternion covered by your lerp with Quaternion.FromToRotation(A,B)

convert that to Angle/Axis representation with Quaternion.ToAngleAxis(angle,axis)

what you now want is to rotate around that axis by angle-360, for example with the help of transform.RotateAround()

Okay, so that totally makes sense, but how do I get those A and B Vector3's?

I tried to jump that step by by using the Inverse of my starting rotation multiplied by my ending rotation as the rotation that, if applied to the start, would end up with the end rotation, but that doesn't give the best results…

I think the fundamental problem is that the rotation isn't just along one axis.

For some more context: I'm using this code as part of a dynamic slashing system for a sword swing. I basically have a starting position and rotation and an ending position and rotation for the sword, and I'm lerping between them. I'm going to add arc code to the position of the sword so that the hand doesn't move in a straight line, but I want the rotation of the sword to be correct before I start using bezier curves.

The problem is that most sword swings are quite wide, thus I need to lerp in the "wrong" direction.

Hm? A and B are simply the rotation quaternions of your start and end position, for example Quaternion.FromToRotation(source.transform.rotation,target.transform.rotation).

If ins$$anonymous$$d of transforms/quaternions you have direction Vector3's (not eulerAngle Vector3's), you could ins$$anonymous$$d find your rotation axis simply by using the cross product of the two direciton vectors.

I tried A and B with quaternions and the compiler yelled at me. So I looked the function up in the documentation and it says that Quaternion.FromToRotation(A, B) takes in Vector3's, not Quaternions.

Woops, my bad, sorry. Quaternion.FromToRotation() already requires directional vectors, so you can ignore that stuff about the cross product.

Well, what is your source where you want to derive A and B from, are these two Transforms? If so, and if the "direction" is determined by the +Z(=blue) axis, you coud use Quaternion.FromToRotation(source.transform.forward,target.transform.forward)

The points aren't in Transforms. They're Vector3s and Quaternions that I set with a custom inspector using their own set of handles.

The positions and rotations are all relative to the root of the character.

**Answer** by bmod
·
Jan 06, 2018 at 08:25 PM

This works for me:

`Quaternion.SlerpUnclamped(a, b, -t);`

(Note the negative t value)

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.