Question

I have some problems with a rotating marble.
I've tried it with Matrix.CreateFromYawPitchRoll and Matrix.CreateRotation but there were some problems, I think it's due to the Gimbal lock effect.

So, I've tried using quaternions instead, but nothing changed.
When moving on only an axis it works fine, but when the rotation occurs on two different axes the marble still rotates on wrong axes.

Here's my code:

// declarations
Vector3 Position = Vector3.Zero;
Vector3 Rotation = Vector3.Zero;
Quaternion qRotation = Quaternion.Identity;

AbsoluteBoneTransforms = new Matrix[Model.Bones.Count]; 
Model.CopyAbsoluteBoneTransformsTo(AbsoluteBoneTransforms); 

In the Update method:

Position += speed;
Rotation = speed * MathHelper.ToRadians(-1.5f);

Quaternion rot = Quaternion.CreateFromAxisAngle(Vector3.Right, Rotation.Z) *
                Quaternion.CreateFromAxisAngle(Vector3.Backward, Rotation.X);

qRotation *= rot;

And in the Draw method:

effect.World = AbsoluteBoneTransforms[mesh.ParentBone.Index] * 
  Matrix.CreateFromQuaternion(qRotation) * Matrix.CreateTranslation(Position);

What's wrong? Is it wrong to use Quaternion.CreateFromAxisAngle on multiple axes?

EDIT

I've tried calculating directly the axis of rotation of my marble, instead of using combination of multiple axes:

angle += speed.Length() * angularVelocity;
qRotation = Quaternion.CreateFromAxisAngle(Vector3.Cross(speed, Vector3.Up), angle);
qRotation.Normalize();

angle is a float that keeps track of the current movement.
This solution doesn't seem to create Gimbal lock, but marble rotations aren't correct, it seems that the rotating speed is not constant, but became faster and slower over time, I can't understand why.

If I "concatenate" the quaternions I get every frame using

qRotation *= Quaternion.CreateFromAxisAngle(Vector3.Cross(speed, Vector3.Up), angle)

the Gimbal lock effect is still visible.

Was it helpful?

Solution

Here's how I've tackled that:

I'm assuming speed is a vector representing the direction the ball is rolling and whose magnitude represents the rate it is traveling in that direction.

Vector3 axis = Vector3.Cross(speed, Vector3.Up);
float angle = speed.Length();//factor by delta time if neccesary

Quaternion rotationThisFrame = Quaternion.CreateFromAxisAngle(axis, angle * (1/radiusOfBall));

then you can concatenate that to your qRotation. Also, you may need to normalize your quaternion after concatenation.

Update: The correct answer to this question/thread was reversing the order that quaternions concatenate in. With respect to XNA, matrices combine left to right, quaternions combine right to left.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top