这两段伪代码之间有什么区别?
// 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;
等...
答案 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_frames
次total_angle/total_frames
次,这很重要,因为这些小旋转与累积情况下使用的小旋转完全相同。因此,在赋值情况下,您的代码计算frame
,并且每次都将worldMatrix重置为该值。
关键是这些是不同的矩阵;即使有完美的数学,它们也应该看起来不同。
您应该选择哪一个取决于您想要的行为。累积版本将近似地近似围绕X轴和Y轴之间的对角线的旋转;赋值版本就像旋转万向节一样。
如果您确实需要累积行为,则有比将多达500个矩阵相乘的更好方法(如上所述,由于浮点错误,您的矩阵会漂移)。具体来说,您可以围绕Z轴旋转45度,然后围绕X轴旋转框架/ 500,然后围绕Z轴旋转-45度,以获得类似的效果。
详细说明两种情况之间的区别:
在累积的情况下,你正在旋转一点关于X,然后稍微关于Y,重复多次。如果旋转很小,组合两个小旋转的结果将是围绕某些轴的小旋转(如果它们不是那么小,轴可能不完全在两者之间,但是它仍然是一个特定的轮换)。关键是,如果你重复那对旋转,结果将是在该轴上越来越多的旋转,无论它是什么。
在赋值情况下,你正在对X进行所有旋转,然后对Y进行所有旋转。这会使旋转变大,这会产生影响。可视化差异的一种方法是想象一组坐标轴:大的X旋转将原始Y轴旋转到线外,因此Y旋转的应用方式不同。
在数学术语中,之所以存在如此大的差异,原因在于,一般来说,轮换不是可交换的:换句话说,顺序很重要。请注意,小旋转近似可交换(当旋转角度接近零时,(Rx)^frame * (Ry)^frame
和Rx * Ry
之间的差异以二次方式逼近零 - 将角度减半会减少差异系数为4),但是当你将所有小型旋转组合成两个大型旋转时,你做了很多重新排序,它会产生巨大的差异。即使每个单独的交换(Ry * Rx
- > Rx * Ry
)只有很小的影响,将N Ry * Rx
迁移到一边实际上是一个冒泡的类别:你需要O (N ^ 2)互相交换....
答案 1 :(得分:2)
差异似乎是第一个样本将通过旋转矩阵改变当前世界矩阵。第二个样本通过旋转矩阵替换世界矩阵。如果在此之前没有对世界矩阵应用其他操作,您可能看不出任何差异,但如果在此之前应用了任何操作,则第二个代码示例将丢弃这些操作。
问题是,您是否希望对世界矩阵的更改是否累积?第一个代码示例将为您提供累积效果,第二个代码示例将不会。