2
votes

I did a lot of research but really can't find how I am supposed to use quaternion to do the following:

I have source orientation and a target orientation, and I am trying to find the quaternion of a specific angle (ex 10 degree) that goes from one orientation toward the other.

I'm trying to understand quaternions and also want to avoid gimbal lock, so I need an answer that doesn't need to convert to euler angles.

I know there is the Slerp function but its like a "percentage" instead of an angle. Also I'm not sure how to find the difference between source and target.

Basically I'm trying to do the following, but with quaternions instead of vectors:

Vector3 source, target; //Lets pretend they are defined
Vector3 vect_dir = target - source;
float vect_length = Mathf.Min(10f * Time.deltaTime, vect_dir.magnitude);
Vector3 answer = vect_dir.normalized * vect_length;

Any one knows how to do the same with quaternions? The idea is to put a speed value (10 in the example) of my choice. Its very similar to using the Slerp function, except that I want a constant movement instead of a movement that goes fast and gradually slows down. I also would like to avoid using euler angles because of gimbal lock.

1

1 Answers

3
votes

Consider using Quaternion.RotateTowards

Quaternion.RotateTowards takes a Quaternion from, a Quaternion to, and a float maxDegreesDelta. Then, it returns whichever of these is closer to from:

  1. The Quaternion between from and to that is maxDegreesDelta degrees away from from

  2. to

So an example with Quaternions that corresponds to yours could be written like:

Quaternion source, target; //Lets pretend they are defined
Quaternion reachedRotation = Quaternion.RotateTowards(source, target, 10f * Time.deltaTime);

If you need the difference between the reached point and source, you can do some quaternion math:

Quaternion answer = Quaternion.Inverse(source) * midpoint;

As an alternative, you could determine the difference between target and source and express that in angle (magnitude) and axis (direction) form with Quaternion.ToAngleAxis:

Quaternion difference = Quaternion.Inverse(source) * target;
Vector3 differenceAxis;
float differenceAngle;
difference.ToAngleAxis(out differenceAngle, out differenceAxis);

And then, produce answer by capping differenceAngle:

Quaternion answer = Quaternion.AngleAxis(Mathf.Min(differenceAngle, 10f * Time.deltaTime), differenceAxis);

And if you want to find the rotation that results from "including" answer onto source, just multiply them (order is important):

reachedRotation = source * answer;

As a sidenote, your example with Vector3s could be written as:

Vector3 source, target; //Lets pretend they are defined
Vector3 answer = Vector3.MoveTowards(source, target, 10f * Time.deltaTime) - source;