2

我有一些旋转大理石的问题。
我试过了Matrix.CreateFromYawPitchRollMatrix.CreateRotation但有一些问题,我认为这是由于万向节锁定效应。

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

这是我的代码:

// 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是一个跟踪当前运动的浮点数。
此解决方案似乎没有创建Gimbal lock,但大理石旋转不正确,似乎旋转速度不是恒定的,而是随着时间的推移变得越来越快,我不明白为什么。

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

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

云台锁定效果依然可见。

4

1 回答 1

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,矩阵从左到右组合,四元数从右到左组合。

于 2013-10-04T11:54:54.370 回答