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 =旋转;
等等...
实际上,结果应该是不同的(即使您没有考虑累积误差,如上所述).原因是顺序在旋转中很重要:旋转大约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以单位矩阵开始,将其乘以小的旋转Rx并Ry连续; 你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)交换来做它....