使用四元数进行正确旋转

时间:2013-10-04 00:17:06

标签: c# 3d xna rotation quaternions

旋转大理石有些问题 我已尝试使用Matrix.CreateFromYawPitchRollMatrix.CreateRotation,但有一些问题,我认为这是由于 Gimbal lock 效果。

所以,我尝试使用四元数,但没有改变 当仅在轴上移动时它可以正常工作,但是当在两个不同的轴上发生旋转时,大理石仍然在错误的轴上旋转。

这是我的代码:

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

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

Update方法中:

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

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

qRotation *= rot;

Draw方法中:

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

怎么了?在多个轴上使用Quaternion.CreateFromAxisAngle是不对的?

修改

我尝试直接计算大理石的旋转轴,而不是使用多个轴的组合:

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

angle是一个跟踪当前运动的浮动 这个解决方案似乎没有创建万向节锁,但大理石旋转不正确,似乎旋转速度不恒定,但随着时间的推移变得越来越慢,我无法理解为什么

如果我“连接”四元数,我会使用

获得每一帧
qRotation *= Quaternion.CreateFromAxisAngle(Vector3.Cross(speed, Vector3.Up), angle)

Gimbal lock 效果仍然可见。

1 个答案:

答案 0 :(得分:2)

以下是我解决这个问题的方法:

我假设speed是一个表示球滚动方向的矢量,其大小代表它在该方向上行进的速度。

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));

然后你可以将它连接到你的qRotation。此外,您可能需要在连接后规范化四元数。

更新:这个问题/线程的正确答案是颠倒了四元数连接的顺序。对于XNA,矩阵从左到右组合,四元数从右到左组合。