了解WebGL中绕任意轴旋转背后的数学原理

4

最近,我一直在研究用于WebGL的一些矩阵库,以更好地理解应用于矩阵上的各种变换所需的数学知识。目前,我正在尝试更好地理解旋转变换中使用的数学知识。

具体而言,我已经了解了围绕三个轴旋转所使用的变换以及如何生成这些矩阵(如下所示)。

enter image description here

然而,我不明白围绕不是x、y或z轴的任意轴旋转所使用的方程式。

我当前正在阅读WebGL编程指南,在提供的库中,他们使用以下JS代码来围绕任意轴旋转(其中e是包含4x4矩阵的数组):

len = Math.sqrt(x*x + y*y + z*z);
if (len !== 1) {
  rlen = 1 / len;
  x *= rlen;
  y *= rlen;
  z *= rlen;
}
nc = 1 - c;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;

e[ 0] = x*x*nc +  c;
e[ 1] = xy *nc + zs;
e[ 2] = zx *nc - ys;
e[ 3] = 0;

e[ 4] = xy *nc - zs;
e[ 5] = y*y*nc +  c;
e[ 6] = yz *nc + xs;
e[ 7] = 0;

e[ 8] = zx *nc + ys;
e[ 9] = yz *nc - xs;
e[10] = z*z*nc +  c;
e[11] = 0;

e[12] = 0;
e[13] = 0;
e[14] = 0;
e[15] = 1;

据我所知,代码的第一部分用于规范化3D向量,但除此之外,我实在看不出它有什么意义。
例如,ncxyyzzxxsyszs代表什么?另外,以x*x*nc + c来计算e[0]的公式是怎么得出来的?
根据相关的SO帖子,我找到了一个绕任意轴旋转的矩阵如下图所示: enter image description here 这似乎与上面的JS代码有关(如果不是同一个)。
这个矩阵是如何生成的?我思考过如何绕任意轴旋转,但我能想到的唯一方法是将从原点延伸的3D向量分解为x、y和z三个部分,然后执行三个不同的旋转,这似乎相当低效。
使用一个矩阵来完成所有操作似乎更好,但我真的想了解那个矩阵是如何生成的。
最后,虽然我不确定,但看起来上面的矩阵似乎没有考虑轴与原点的平移。是否可以通过使用一个4x4矩阵,并在适当的位置使用Tx、Ty和Tz值来轻松处理?
谢谢。
2个回答

1
如果您需要绕角度θ旋转,则在代码中:
c = cos(theta);
nc = 1-cos(theta); // (or 1-c)
s = sin(theta);

因此,在代码中,

x只是ux

xy只是uxuy

xs只是uxsinθ

等等。 因此,在公式中,第一行的第三个表达式是uxuz(1-cosθ) + uysinθ,变成了zx * nc - ys

有了这个想法,你可以看到代码只是R公式的一个表达式,但代码将其表示为4x4矩阵而不是3x3。 第四维用于平移,但该表达式指定了所有三个方向的零平移。


这实际上非常有帮助,可以理解所有数学符号如何转换为变量。谢谢。 - HartleySan
2
代码与提供的公式不同,它通过对每个使用sin(theta)的项反转符号来实现。因此,zx * nc - ys 实际上应该是 zx * nc + ys。这实际上是负theta的公式。这是因为sine(-theta) = -sine(theta)和cosine(-theta) = cosine(theta)。因此,您可以说代码从公式相反方向旋转。 - MiguelMunoz
还有一点非常有帮助的是,有没有什么理由来决定采用哪种方式,或者完全是任意的,由编码人员决定采用哪种方式?谢谢。 - HartleySan
旋转方向完全由编码人员决定。但是公式可能是针对标准坐标系编写的,其中y随着向上移动而增加。但是许多绘图实现(例如Java Graphics对象)会使y随着向下移动而增加。因此,这也会颠倒旋转方向。因此,代码可能是为了补偿这一点而编写的。 - MiguelMunoz
非常有趣。我从你的解释中学到了很多。非常感谢。 - HartleySan

1
请在此处找到数学概述:

请在此处查找数学概述:

http://paulbourke.net/geometry/rotate/

这里有详细的解释:

http://web.archive.org/web/20140515121518/http://inside.mines.edu:80/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html

你说得对,这个旋转矩阵无法解释平移。
是的,你可以通过将平移 x 旋转相乘来创建一个先旋转再平移的矩阵:
    1 0 0 t1      r11 r12 r13 0
T = 0 1 0 t2  R = r21 r22 r23 0
    0 0 1 t3      r31 r32 r33 0
    0 0 0 1       0   0   0   1

        1 0 0 t1   r11 r12 r13 0   r11 r12 r13 t1
T x R = 0 1 0 t2 x r21 r22 r23 0 = r21 r22 r23 t2
        0 0 1 t3   r31 r32 r33 0   r31 r32 r33 t3
        0 0 0 1    0   0   0   1   0   0   0   1

如果您只想绕远离原点的任意轴旋转(即,围绕一条直线旋转),请查找第二个URL中的“6.2关于任意线旋转的归一化矩阵”的项目(http://web.archive.org/web/20140515121518/http://inside.mines.edu:80/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html)。

1
  1. 注意: 4.1 Txz:使用从轴向量分量(u,v,w)计算的sin和cos的Rz。 4.2 Tz:使用从轴向量分量(u,v,w)计算的sin和cos的Ry。
  2. 如何找到逆矩阵: http://www.mathsisfun.com/algebra/matrix-inverse.html
- Everton
1
不,作者使用了正确的顺序。当您将组合变换矩阵应用于向量/点(即行矩阵)时,您会发现效果就像是应用每个单独的变换,但是从右侧(最后一个矩阵)开始到左侧(第一个矩阵)。 - Everton
1
  1. 这意味着使用了绕轴旋转的矩阵,但为了获得正弦和余弦值,作者更喜欢使用旋转轴分量而不是反三角函数(http://en.wikipedia.org/wiki/Inverse_trigonometric_functions);我认为这是因为反三角函数在计算上很昂贵(当然,在这种情况下存在选项)。
  2. 是的,重点是将旋转轴与Z轴对齐,但如果旋转轴已经与z轴对齐,那么这些矩阵将无法起作用。
- Everton
1
5.1中的第二个矩阵(注意它是一个行矩阵)展示了如何从旋转矩阵(5.1中的第一个矩阵)给定的(X,Y,Z)计算(newX,newY,newZ)的公式。也就是说,它展示了如何在没有矩阵乘法符号的情况下进行旋转。 - Everton
1
关于WebGL问题,我认为你可以在这里找到一个信息丰富的主题:https://dev59.com/c3vZa4cB1Zd3GeqP-Ank - Everton
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接