XNA中的四元数旋转

我正在做以下事吗?

显然不是原因,否则我不会在这里发布一个问题,但我正在尝试围绕另一个模型进行模型的四元数轮换。

假设我有一个具有vector3位置和浮动旋转角度的盒子模型。 我还有一个平截头体形状的模型指向盒子模型,它的位置可以说是盒子模型的50个单位。 平截头体还具有向量3位置和四元数旋转。

在场景1中,框和平截头体是“未旋转的”。 这一切都很好。 在场景2中,我只旋转盒子,我希望平截头体随之旋转(有点像追逐相机),截头体总是直接指向盒子,与盒子的距离与未旋转的距离相同。 显然,如果我只是通过对盒子和平截头体使用Matrix.CreateRotationY()来旋转模型和平截头体,则平截头体稍微向侧面偏移。

所以我认为围绕盒子的圆锥体的四元数旋转最好? 为此我尝试了以下,没有运气。 它在屏幕上绘制我的模型,但它也在屏幕上绘制了一个看起来像一个巨大的盒子,无论我移动相机多远,盒子总是在路上

为了测试,我有3个盒子和3个相关的截头体在我的Game1类中,我用位置和旋转初始化盒子[0]

boxObject[0].Position = new Vector3(10, 10, 10); boxObject[1].Position = new Vector3(10, 10, 10); boxObject[2].Position = new Vector3(10, 10, 10); boxObject[0].Rotation = 0.0f; boxObject[1].Rotation = 45.0f; boxObject[2].Rotation = -45.0f; 

所以所有3个盒子都以相同的位置绘制,但角度不同。 然后做截头,我发起他们的立场:

 float f = 50.0f; frustumObject[0].Position = new Vector3(boxObject[0].Position.X, boxObject[0].Position.Y, boxObject[0].Position.Z + f); frustumObject[1].Position = new Vector3(boxObject[1].Position.X, boxObject[1].Position.Y, boxObject[1].Position.Z + f); frustumObject[2].Position = new Vector3(boxObject[2].Position.X, boxObject[2].Position.Y, boxObject[2].Position.Z + f); 

然后尝试围绕相关的盒子模型旋转:

 frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X, boxObject[0].Position.Y, boxObject[0].Position.Z + f, 0); frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X, boxObject[0].Position.Y, boxObject[0].Position.Z + f, 45); frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X, boxObject[0].Position.Y, boxObject[0].Position.Z + f, -45); 

最后,为了绘制模型,我在我的GameModel类中绘制它们,它们还具有:

 public Model CameraModel { get; set; } public Vector3 Position { get; set; } public float Rotation { get; set; } public Quaternion ModelRotation { get; set; } public void Draw(Matrix view, Matrix projection) { transforms = new Matrix[CameraModel.Bones.Count]; CameraModel.CopyAbsoluteBoneTransformsTo(transforms); // Draw the model foreach (ModelMesh myMesh in CameraModel.Meshes) { foreach (BasicEffect myEffect in myMesh.Effects) { // IS THIS CORRECT????? myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position); myEffect.View = view; myEffect.Projection = projection; myEffect.EnableDefaultLighting(); myEffect.SpecularColor = new Vector3(0.25f); myEffect.SpecularPower = 16; } myMesh.Draw(); } } 

任何人都可以找到我错的地方吗? 是因为我在Draw()中做了两种旋转吗?

myEffect.World = transforms [myMesh.ParentBone.Index] * Matrix.CreateRotationY(Rotation)* Matrix.CreateFromQuaternion(ModelRotation)* Matrix.CreateTranslation(Position);

从快速浏览一下,最好使用静态创建方法创建Quaternions,例如Quaternion.CreateFromAxisAngle(Vector3. UnitY, rotation) 。 四元数的X,Y,Z和W的值与位置无关。 方便的静态方法处理棘手的数学。

在您的情况下,似乎您希望在框旋转时将平截头体指向盒子的同一侧,从而使平截头体在盒子周围旋转。 这需要稍微不同的方法来完成绘制方法中的翻译。

为了使对象绕另一个旋转,首先需要平移对象,使所需旋转的中心位于原点。 然后旋转对象并将其向后平移与第一步相同的量。

所以在你的情况下,这样的事情应该这样做(未经测试的示例代码可以遵循);

 // Construct the objects boxObject.Position = new Vector3(10, 10, 10); boxObject.Rotation = 45.0f; frustumObject.Position = new Vector3(0, 0, 50f); // Note: this will be relative to the box (makes the math a bit simpler) frustumObject.TargetPosition = boxObject.Position; frustumObject.ModelRotation = Quaternion.CreateFromAxisAngle(Vector3. UnitY, boxObject.Rotation); // Note: this rotation angle may need to be in radians. // Box Draw() // Draw the box at its position, rotated about its centre. myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateRotationY(Rotation); // Frustum Draw() // Draw the frustum facing the box and rotated about the boxes centre. myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(TargetPosition); 

假设:

  • 盒子围绕自己的中心旋转
  • 平截头体面向盒子并围绕盒子中心旋转

希望这可以帮助。