在XNA、C#中使用矩阵时,对操作顺序感到困惑

本文关键字:操作 顺序 XNA | 更新日期: 2023-09-27 18:21:41

这里有两段不同的代码

这就是我从开始的

Vector2 hold = Vector2.Transform(pos1, mat1);
Matrix inv = Matrix.Invert(mat2);
Vector2 pos2 = Vector2.Transform(hold, inv);

这就是我被告知的简化版

Matrix matrix1to2 = mat1 * Matrix.Invert(mat2);
Vector2 pos2 = Vector2.Transform(pos1, matrix1to2);

我不明白的是,为什么简化版中的第一行没有

Matrix matrix1to2 = Matrix.Invert(mat2)*mat1;

由于按照矩阵顺序,右边的东西将首先生效,而在原始文件中,我们有mat1在第一个中相乘

编辑:下图显示了所需的操作顺序

http://www.riemers.net/images/Tutorials/XNA/Csharp/Series2D/mat1.png

教程中说,要创建此转换,请使用;

Matrix carriageMat = Matrix.CreateTranslation(0, -carriage.Height, 0) * Matrix.CreateScale(playerScaling) 
* Matrix.CreateTranslation(xPos, yPos, 0) * Matrix.Identity;

如果顺序是从左到右,为什么这样做?

在XNA、C#中使用矩阵时,对操作顺序感到困惑

因为按照矩阵顺序,右边的东西首先生效在原始文件中,mat1在第一个中相乘

实际上,"左边的东西"首先生效。矩阵应用于顶点的顺序与你阅读它们的顺序相同(假设你习惯了拉丁语)。

在XNA中,通常按SRT(缩放、旋转、平移)顺序执行变换。这样,在将对象移动到世界空间之前,对象将围绕其自己的原点进行缩放和旋转(在自己的轴上旋转)。

例如:如果我想把一个物体旋转Pi/2,沿着X轴移动100个单位,我可以使用:

var rotate = Matrix.CreateRotationY(MathHelper.PiOver2);
var translate = Matrix.CreateTranslation(new Vector3(100,0,0));
var worldMatrix = rotate * translate;

相反,如果我想将对象向右移动100个单位,然后绕世界原点(0,0,0)旋转以获得某种轨道效果(而不是像第一个例子中那样旋转),我会使用

var worldMatrix = translate * rotate;

你也可以在物体的轴上旋转,沿着世界X轴移动100个单位,绕着世界原点旋转:

var worldMatrix = rotateSpin * translate * rotateOrbit;

其中,rotateSpinrotateOrbit是分别定义旋转(绕对象原点的旋转)和轨道(平移后绕世界原点的转动)的旋转矩阵。请注意,操作影响服务顶点的顺序是从左到右。