[Solved] Quaternions and fast rotations

(as in rapid movements and not computationally fast)



Hey guys I’ve hit a bit of a snag.

I’ve got an object rotating using quaternion multiplications. I make the quaternion I’m multiplying with (rotation speed) grow (object spinning faster and faster). As soon as it gets faster than a 180 degrees rotation per second my objects rotation suddenly kicks into reverse. It’s quite logical really the quaternion cannot represent a rotation bigger than one full rotation. But I don’t know if there is a way around it. What I want is to get the object to spin at speeds faster than one rotation per second. I don’t know if it’s even possible with quaternions.



I hope someone has a suggestion that will help me.



Here’s the relevant code: (tpf = delta time for the current update)

// Update angularSpeed with angularAcceleration.

final Quaternion angularMomentum = po.getAngularMomentum();

final Quaternion angularAcceleration = po.getAngularAcceleration();

final Quaternion slerpTarget1 = angularMomentum.mult(angularAcceleration);



angularMomentum.slerp(slerpTarget1, tpf);



// Update rotation with angularSpeed.

final Quaternion rotation = po.getRotation();

final Quaternion slerpTarget2 = rotation.mult(angularMomentum);



rotation.slerp(slerpTarget2, tpf);

Calculate your total movement not inside the quarternion then only calculate your movement per frame then.



(I.e. store your angular momentum as 3 floats as radians per second and then construct an already-scaled quarternion from them for each frame)



You can never spin faster than once per frame though as it becomes meaningless then…

I’m just guessing, but the reverse effect is probably similar to when you videotape a car tire spinning: when it rotates fast enough it starts moving backwards due it being translated into frames.

In terms of visualizing, you don’t want to go too fast or else it will just look weird and choppy.

Thanks guys,



@zarch, I mulled over the 3 floats ideas and I’m going to try it out, I’m only worried because it might reduce the accuracy of my movements. I find it difficult to visualize what’s going to happen so I guess I should go try and see…



@Sploreg

Thanks, but the reversing effect shows up at around 7 seconds, at which time I’ve only done 3 360 degree rotations… That’s several orders of magnutide away from actually producing the choppy effect you describe.



I understand the effect is a natural side effect from how I use the quaternions. I use it to represent a rotation per second. (Analog to velocity being distance per second) since a quaternion can only represent rotations between -180 and 180 degrees. I cannot go faster than those amount of degrees per second.



I shall try zarch’s suggestion, but if anyone knows another way of storing rotation speeds that would be usefull above 180degrees/second I would be much obliged. Perhaps I could change the second to be a millisecond. 180 degrees per millisecond is certainly fast enough. But it feels a bit cheaty :stuck_out_tongue:

Per millisecond would work too… well it would allow 1000 rps.

Internally the quaternion stores the rotations as a bunch of floats (+ some very clever math) so I don’t see why storing angular velocity as 3 floats would be less accurate.

@zarch said:
Per millisecond would work too... well it would allow 1000 rps.
Internally the quaternion stores the rotations as a bunch of floats (+ some very clever math) so I don't see why storing angular velocity as 3 floats would be less accurate.


No, in fact, in this case a Quaternion is only an approximation of angular velocity (and doesn't have the proper range)... three floats would be the _actual_ angular velocity.

I mean, I don't know bullet or its internals, but the physics engine I wrote myself uses quaternions only for _orientation_ but uses vec3 for rotations since they necessarily need to be larger than 180 degrees sometimes.

To make a quaternion into angular velocity you'd have to keep a scalar also.. and I don't even want to think of the math required to figure that out.

An update:

I replaced the quaternions for angular velocity and angular acceleration with vectors. And this gave me exactly the desired behavior. Now if I apply an angularAcceleration the object starts spinning up untill it becomes a blur, and if I then give it the opposite rotation it slows down and starts spinning in the opposite direction.



@pspeed: Fortunately the math required to figure that out was already implemented by a few heroic monkey engine coders :wink: Quaternion.fromAngles and Quaternion.toAngles contain exactly the magic that is needed.



Thanks everyone, I suppose this topic can be marked Solved do I do that or is it something the mods do?



The original code becomes:

[java]

// Update angularVelocity with angularAcceleration.

final Vector3f angularAcceleration = po.getAngularAcceleration();

final Vector3f angularVelocity = po.getAngularVelocity();



angularVelocity.addLocal(angularAcceleration.mult(tpf));



// Update rotation with angularVelocity.

final Quaternion rotation = po.getRotation();

final Quaternion delta = new Quaternion().fromAngles(angularVelocity.mult(tpf).toArray(null));



rotation.multLocal(delta);

[/java]

You do that, using the “edit topic” button hidden at the top of the page.