Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Math 乘矩阵_Math_Opengl_3d_Matrix_Direct3d - Fatal编程技术网

Math 乘矩阵

Math 乘矩阵,math,opengl,3d,matrix,direct3d,Math,Opengl,3d,Matrix,Direct3d,这两段伪代码之间的区别是什么 // Multiplying a matrix by the difference between each frame float difference = current - previous; // Time since previous frame float angle = difference / 500; matrix rotation; rotation.RotateX(angle); rotation.RotateY(angle); worldMa

这两段伪代码之间的区别是什么

// Multiplying a matrix by the difference between each frame
float difference = current - previous; // Time since previous frame
float angle = difference / 500;
matrix rotation;
rotation.RotateX(angle);
rotation.RotateY(angle);
worldMatrix *= rotation; // Note multiply

// Multiplying a matrix by the difference between current and start
float difference = current - start; // Time since first frame
float angle = difference / 500;
matrix rotation;
rotation.RotateX(angle);
rotation.RotateY(angle);
worldMatrix = rotation; // Note assignment
每段代码之间只有很小的差异,但会导致很大的视觉差异。输入如下所示:

第1帧:旋转=1弧度
世界矩阵*=旋转
第2帧:旋转=1弧度
世界矩阵*=旋转
等等

第1帧:旋转=1弧度
世界矩阵=旋转
第2帧:旋转=2弧度
世界矩阵=旋转
等等


区别似乎在于第一个样本将通过旋转矩阵改变当前世界矩阵。第二个示例用旋转矩阵替换世界矩阵。如果在此之前没有对世界矩阵应用任何其他操作,您可能看不到任何差异,但如果在此之前应用了任何操作,则第二个代码示例将丢弃这些操作

问题是,您是否希望对世界矩阵的更改是累积的?第一个代码示例将给您一个累积效应,第二个不会。

实际上,结果应该不同(即使您没有考虑累积误差,如上所述)。原因是顺序在旋转中很重要:先绕X旋转,然后绕Y旋转,不同于先绕Y旋转,然后绕X旋转

在矩阵表示法中(据我所知,您的设置),您具有以下理想行为:

let angle = (end - start)/500
  Rx = rotate.RotateX(angle)
  Ry = rotate.RotateY(angle)

then, foreach frame in (0..500):
cumulative: Rc = Rx * Ry * Rx * Ry * ... * Rx * Ry
               = (Rx * Ry)^frame
assignment: Ra = Rx * Rx * ... * Ry * Ry * ....
               = (Rx)^frame * (Ry)^frame
关于伪代码的一些注释:这里的惯例是我们从左到右乘矩阵(这意味着点是行向量)。此外,如果不清楚,
(矩阵)^N
是矩阵求幂:按顺序将
N
(矩阵)
的副本相乘

对于累积情况,OQ从一个单位矩阵开始,依次乘以小旋转
Rx
Ry
;你的
旋转
等于我的
(Rx*Ry)
。然后它将
worldMatrix
乘以该矩阵多次;这意味着对于任何给定帧,
worldMatrix
=
initial_worldMatrix*(Rx*Ry)^frame

对于赋值情况,将角度计算为
frame*total_angle/total_frames
。这相当于按顺序旋转
总角度/总帧
次,这很重要,因为这些小旋转与累积情况下使用的小旋转完全相同。因此,在赋值情况下,您的代码正在计算
(Rx)^frame*(Ry)^frame
,并每次将worldMatrix重置为该值


关键是这些是不同的矩阵;即使有完美的数学,它们也应该看起来不同

你应该选择哪一个取决于你想要什么样的行为。累积版本将近似于围绕X轴和Y轴之间的对角线轴旋转;分配版本的作用类似于旋转万向节

如果您确实想要累积行为,有比将多达500个矩阵相乘更好的方法(如上所述,您的矩阵将由于浮点错误而漂移)。具体来说,可以围绕Z轴旋转45度,然后围绕X轴旋转帧/500,然后围绕Z轴旋转-45度,以获得类似的效果


要详细说明这两种情况之间的区别:

在累积的情况下,你先围绕X旋转一点,然后围绕Y旋转一点,重复多次。如果旋转很小,则组合两个小旋转的结果将是围绕某个轴的小旋转(如果它们不是那么小,则轴可能不完全位于这两个轴之间,但仍然是特定旋转)。关键是,如果你重复这对旋转,结果将是该轴上的旋转越来越多,不管它是什么

在赋值的情况下,你要做的是围绕X的旋转,然后围绕Y的旋转。这会使旋转变大,这会产生不同。可视化差异的一种方法是想象一组坐标轴:较大的X旋转将使原始Y轴偏离直线,从而以不同的方式应用Y旋转


用数学术语来说,之所以会有如此大的差异,是因为一般来说,旋转是不可交换的:换句话说,顺序很重要。请注意,小旋转近似可交换(当旋转角度接近零时,
Rx*Ry
Ry*Rx
之间的差值以二次方式接近零——将角度减半可将差值减少4倍),但当您将所有小旋转合并为两个大旋转时,你做了这么多的重新排序,这使一个巨大的差异。即使每个单独的交换(
Rx*Ry
->
Ry*Rx
)只有很小的影响,将N
Rx
迁移到一侧实际上是一种冒泡排序:通常需要O(N^2)个交换来完成……

,分配版本比累积版本更可取。如果将500个旋转矩阵相乘,由于浮点问题,结果将趋向于漂移-结果可能会越来越不像旋转矩阵…第一个示例应该演示累积效应-但实际上它不起作用。我得到的旋转与第二个示例完全不同。累积=轴旋转&分配=旋转万向节正是我看到的,感谢您准确理解了我在原始问题中试图提出的问题。您能再解释一下累积/分配psuedo代码吗?我试图理解为什么数学如此不同。谢谢