c# - XNA 中的四元数旋转

标签 c# xna rotation

我做的对吗?

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

假设我有一个盒子模型,它有一个 vector3 位置和一个 float 旋转角度。 我还有一个指向盒子模型的截锥体模型,它的位置可以说是距离盒子模型 50 个单位。平截头体还有一个 vector3 位置和一个四元数旋转。

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

所以我认为平截头体围绕盒子进行四元数旋转是最好的? 为此,我尝试了以下方法,但没有成功。它在屏幕上绘制我的模型,但它也会在屏幕上绘制看起来像一个巨大盒子的东西,无论我将相机移动多远,盒子总是挡路

出于测试目的,我有 3 个盒子及其 3 个相关的截锥体 在我的 Game1 类中,我用位置和旋转初始化 box[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 类中 Draw() 它们,该类还具有:

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

最佳答案

快速浏览一下,最好使用静态创建方法创建四元数,例如 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);

假设:

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

希望这对您有所帮助。

关于c# - XNA 中的四元数旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10307763/

相关文章:

c# - Linq 扩展方法和错误处理

c# - 实时绘制变量图形以在 C# 中进行调试

c# - 具有结构和字段的泛型

objective-c - Sprite Kit 按 Y 转动节点

Java 二维旋转

c# - HttpWebRequest 自动发送需要的HttpRequests

c# - 无论如何,sitecore 中是否自动接受克隆通知?

C# XNA 桨球游戏

objective-c - 无法使用 anchorPoint 垂直定位 SKLabelNode

c# - 使用 gmail 发送电子邮件。错误 : The server response was: 5. 5.1 需要身份验证