XNA 中的四元数旋转 [英] Quaternion rotation in XNA

查看:68
本文介绍了XNA 中的四元数旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做对了吗?

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

Well obviously not cause otherwise I wont be posting a question here, but I'm trying to do a Quaternion rotation of a model around another model.

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

Lets say I have a box model that has a vector3 position and a float rotation angle. I also have a frustum shaped model that is pointing towards the box model, with its position lets say 50 units from the box model. The frustum also has a vector3 position and a Quaternion rotation.

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

In scenario 1, the box and frustum are "unrotated". This is all fine and well. In scenario 2, I rotate the box only and I want the frustum to rotate with it (kinda like a chase camera) with the frustum always pointing directly at the box and at the same distance from the box as in the unrotated distance. Obviously if I just rotate the model and the frustum by using Matrix.CreateRotationY() for both the box and the frustum, the frustum is slightly offset to the side.

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

So I thought a Quaternion rotation of the frustum around the box would be best? To this end I have tried the following, with no luck. It draws my models on the screen, but it also draws what looks like a giant box to the screen and no matter how far away I move the camera the box is always in the way

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

For the purpose of testing, I have 3 boxes and their 3 associated frustums In my Game1 class I initialize the box[0] with positions and rotations

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 个框都绘制在同一位置但角度不同.然后做平截头体,我开始他们的位置:

So all 3 boxes drawn at the same position but at different angles. Then to do the frustums, I initiate their position:

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

然后尝试围绕它们关联的盒子模型旋转:

And then try and rotate around their associated box model:

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 类中绘制()它们,该类还有:

And finally, to draw the models, I Draw() them in my GameModel class which also has:

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() 中进行了 2 种类型的旋转吗?

Can anyone spot where I am going wrong? Is it because I am doing 2 types of rotations n the Draw()?

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

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

推荐答案

快速浏览一下,最好使用静态创建方法创建四元数,例如 Quaternion.CreateFromAxisAngle(Vector3.UnitY, rotation).四元数的 X、Y、Z 和 W 的值与位置没有任何关系.方便的静态方法处理棘手的数学问题.

From a quick glance, it would be best to create your Quaternions using a static create method such as Quaternion.CreateFromAxisAngle(Vector3. UnitY, rotation). The values of X,Y,Z and W of a Quaternion do not relate to position in any way. The handy static methods take care of the tricky math.

在您的情况下,您似乎希望在盒子旋转时保持平截头体指向盒子的同一侧,因此围绕盒子旋转平截头体.这需要在绘制方法中完成的翻译略有不同.

In your situation it appears as though you want to keep the frustum pointing at the same side of the box as the box rotates, therefore rotating the frustum about the box. This requires a slightly different approach to the translation done in your draw method.

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

In order to rotate an object about another, you first need to translate the object so that the centre of the desired rotation is at the origin. Then rotate the object and translate it back by the same amount as the first step.

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

So in you situation, something like this should do it (untested example code to follow);

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

假设:

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

希望这会有所帮助.

这篇关于XNA 中的四元数旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆