Gradual Rotation

Started by
3 comments, last by Medo Mex 8 years, 4 months ago

I have a mesh and trying to get it to rotate gradually to look at the player at certain speed

Even if the player move around, the mesh should continue rotating until it points at the player at the same speed

I have the new rotation, what I'm trying to do is to smoothly change the current rotation to the new Quaternion

So I want to use Quaternion Slerp, but I'm not sure how exactly it should be accomplished since the player could be moving around.


CurrentQuaternion = Mesh->Rotation();
NewQuaternion = GetLookAt(...);
Advertisement

You can use NLERP to achieve the transition from one quaternion to another one :


q = Normalize(LERP(q1, q2, t));

It's cheaper than SLERP, the only difference is it doesn't rotate at a constant speed.

But if the player is moving around, maybe it's better to LERP the target position and look-at this target point.

@Alundra:

maybe it's better to LERP the target position and look-at this target point.

Any example?

I'm using something similar to the following and it only works well if the player is not moving around:


static float t = 0.0f;
t += RotationSpeed * ElapsedTime;
if (t > 1.0f)
    t = 1.0f;

q = Normalize(LERP(CurrentQuaternion, NewQuaternion, t));
If you LERP (with normalization), your speed will accelerate towards the middle of the rotation and decelerate close to the final orientation again. That kind of "ease in, ease out" may not at all be bad, it could even be desirable. However, it will still not necessarily work correctly or as intended (and neither will SLERP) if the player is moving. Imagine you have two quaternions and you SLERP having t go from 0 to 1 in, say, 100 steps. You somehow calculated (that's daunting already!) that you need exactly 100 steps to rotate at the desired speed. All is nice until frame #50 when the player moves. Now what! You can finish your old rotation and then start a new rotation to the then-current position of the player. Possibly you will now only need 81 steps (or possibly 140) to attain the desired constant speed. That will look correct, but it is probably not what you want. You could simply replace the target quaternion. Could you? If player moves in an inopportune direction fast enough, this will give a very unpleasing visual jump. Also, the arc length is now different, so your number of interpolation steps is wrong and you will rotate at a different speed. Bad! You can recalculate a new rotation from your now-current orientation to the player's updated position, and start SLERPing from 0 again. This is the correct approach, but your movements will still have a somewhat "robotic" feel with a sharp knack in the middle. If that is undesirable, I would try to solve the problem by attaching an "empty" (no idea what better name to give to it, but e.g. Blender has "empty" objects) to the player with some kind of soft constraint, such as a damped spring with constant speed, and then simply rotate to LookAt(emptyObject) every frame. You will only ever try to rotate directly towards the "empty" (without interpolating N steps), which the player drags behind him as if on a rubber band. Eventually, if the player stops moving, the attached "empty" will catch up with his position, and you will look at the player. No acceleration/deceleration, no jerks, no robotic knacks, no need to calculate how many SLERP steps you need.

All you need to do is calculate the direction to rotate in and add a fixed delta rotation per frame.

Once the difference is less than or equal to the fixed delta just snap. This will work for moving targets.

@Syntac_: Can you please give an example?

I'm trying to make the mesh rotation speed stay the same, even if the player move around

This topic is closed to new replies.

Advertisement