乘以矩阵

时间:2010-11-09 22:15:03

标签: 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);
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弧度
  worldMatrix * =旋转;
  第2帧:旋转= 1弧度
  worldMatrix * =旋转;
  等...

     

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

2 个答案:

答案 0 :(得分: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

关于伪代码的一些注释:这里的约定是我们从左到右乘以矩阵(这意味着点是行向量)。此外,如果不清楚,(matrix)^N是矩阵取幂:将N的{​​{1}}副本按顺序复制在一起。

对于累积情况,您的OQ以单位矩阵开头,将其与小旋转(matrix)Rx相乘;您的Ry等于我的rotation。然后它将(Rx*Ry)乘以该矩阵多次;这意味着对于任何给定的框架,worldMatrix = worldMatrix

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


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

您应该选择哪一个取决于您想要的行为。累积版本将近似地近似围绕X轴和Y轴之间的对角线的旋转;赋值版本就像旋转万向节一样。

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


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

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

在赋值情况下,你正在对X进行所有旋转,然后对Y进行所有旋转。这会使旋转变大,这会产生影响。可视化差异的一种方法是想象一组坐标轴:大的X旋转将原始Y轴旋转到线外,因此Y旋转的应用方式不同。

在数学术语中,之所以存在如此大的差异,原因在于,一般来说,轮换不是可交换的:换句话说,顺序很重要。请注意,小旋转近似可交换(当旋转角度接近零时,(Rx)^frame * (Ry)^frameRx * Ry之间的差异以二次方式逼近零 - 将角度减半会减少差异系数为4),但是当你将所有小型旋转组合成两个大型旋转时,你做了很多重新排序,它会产生巨大的差异。即使每个单独的交换(Ry * Rx - > Rx * Ry)只有很小的影响,将N Ry * Rx迁移到一边实际上是一个冒泡的类别:你需要O (N ^ 2)互相交换....

答案 1 :(得分:2)

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

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