乘以矩阵

Mar*_*ram 3 opengl math 3d direct3d matrix

这两段伪代码有什么区别?

// 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
Run Code Online (Sandbox Code Playgroud)

每段代码之间只有很小的差异,但会导致很大的视觉差异.输入看起来像这样:

第1帧:旋转= 1弧度
worldMatrix*=旋转;
第2帧:旋转= 1弧度
worldMatrix*=旋转;
等等...

第1帧:旋转= 1弧度
worldMatrix =旋转;
第2帧:旋转= 2弧度
worldMatrix =旋转;
等等...

com*_*orm 8

实际上,结果应该是不同的(即使您没有考虑累积误差,如上所述).原因是顺序在旋转中很重要:旋转大约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
Run Code Online (Sandbox Code Playgroud)

关于伪代码的一些注释:这里的约定是我们从左到右乘以矩阵(这意味着点是行向量).此外,如果不清楚,(matrix)^N则进行矩阵求幂:将序列中的N副本相乘(matrix).

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

对于赋值情况,您可以计算角度frame * total_angle/total_frames.这相当于total_angle/total_frames顺序旋转frame时间,这很重要,因为这些小旋转与累积情况下使用的小旋转完全相同.因此,在赋值情况下,您的代码正在计算(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)交换来做它....