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
)只有很小的影响,将NRx
迁移到一侧实际上是一种冒泡排序:通常需要O(N^2)个交换来完成……,分配版本比累积版本更可取。如果将500个旋转矩阵相乘,由于浮点问题,结果将趋向于漂移-结果可能会越来越不像旋转矩阵…第一个示例应该演示累积效应-但实际上它不起作用。我得到的旋转与第二个示例完全不同。累积=轴旋转&分配=旋转万向节正是我看到的,感谢您准确理解了我在原始问题中试图提出的问题。您能再解释一下累积/分配psuedo代码吗?我试图理解为什么数学如此不同。谢谢