3d 绕任意轴旋转

3d 绕任意轴旋转,3d,3d,我正在为星际争霸2定制地图编程,并在3D中获得了一些数学问题。目前,我正在尝试创建一个点,并围绕任意轴旋转,该轴由x、y和z给定(xyz向量是标准化的) 我试了很多次,在网上读了很多东西,但我就是不知道它是如何正确工作的。我当前的脚本(你可能不懂语言,但没什么特别的)是打破一切长达数小时(无法正常工作)的结果: 我就是想不起数学。如果你能用简单的术语解释这是最好的解决方案,那么剪掉一段代码也会很好(但没有那么大的帮助,因为我计划将来做更多的3D工作)。。看看下面的部分。为方便起见,这是您需要的矩

我正在为星际争霸2定制地图编程,并在3D中获得了一些数学问题。目前,我正在尝试创建一个点,并围绕任意轴旋转,该轴由x、y和z给定(xyz向量是标准化的)

我试了很多次,在网上读了很多东西,但我就是不知道它是如何正确工作的。我当前的脚本(你可能不懂语言,但没什么特别的)是打破一切长达数小时(无法正常工作)的结果:

我就是想不起数学。如果你能用简单的术语解释这是最好的解决方案,那么剪掉一段代码也会很好(但没有那么大的帮助,因为我计划将来做更多的3D工作)。

。看看下面的部分。为方便起见,这是您需要的矩阵。有点毛茸茸的。θ是角度,ux、uy和uz是归一化的轴向量的x、y和z分量


如果你不懂矩阵和向量,请发回来,我会帮助你。

做这种旋转的一个有用方法是用。在实践中,我发现它们更容易使用,而且还有避免使用的额外好处

这是一个很好的演示,解释了它们如何以及为什么用于绕任意轴旋转(这是对用户问题的回答)。这是一个更高的层次,对新手来说会更好,所以我建议从这里开始

更新以避免链路腐蚀

链接站点中的文本:

毫无疑问,你们已经得出结论,绕轴旋转 通过原点和单位球体上的点(a、b、c) 三维是一种线性变换,因此可以 用矩阵乘法表示。我们将进行一次非常顺利的会议 确定该矩阵的方法,但要注意紧凑性 对于公式,明智的做法是先说几句话

三维旋转是相当特殊的线性旋转 转换,尤其是因为它们保留了 向量以及(当两个向量旋转时)两个向量之间的角度 向量。这种变换称为“正交”变换,它们是 由正交矩阵表示:

M M' = I
在这里,我们方便地用“.”表示转置。换句话说 正交矩阵的转置是其逆矩阵

考虑定义转换所需的数据。 您已经给出了旋转轴的符号,
ai+bj+ck
, 方便地假设为单位向量。唯一的其他基准是 旋转角度,这是因为我缺少一个更自然的性格 用r表示(旋转?),我们假设在 弧度

现在旋转实际上有点特别,即使是在正交旋转中 变换,实际上它们也被称为特殊正交变换 变换(或矩阵)凭借其存在的性质 “方向保持”。将它们与反射进行比较,它们是 同时保持长度和角度,你会发现 具有保持方向(或“惯用手”的特征,如果你 首选)在矩阵的行列式中有一个数值对应项。 旋转矩阵具有行列式1,而反射矩阵具有行列式1 行列式-1。结果表明,两种物质的产物(或成分)是 旋转也是一种旋转,这与 乘积的行列式是行列式的乘积(或 旋转的情况)

现在,我们可以描述一种可以遵循的逐步方法 构造所需的矩阵(在我们缩短整个过程和 跳到答案上来!)。首先考虑一个我们旋转的步骤 单位向量:

u = ai + bj + ck
u = ai + bj + ck
所以它可能与一个“标准”单位向量相吻合 k(正z轴)。现在我们知道如何绕z轴旋转; 这是一个在x,y上进行常规2x2变换的问题 仅坐标:

       cos(r) sin(r)   0
M  =  -sin(r) cos(r)   0
         0      0      1
最后,我们需要“撤销”将u带到k的初始旋转, 这很容易,因为这个变换的逆是(我们 召回)由矩阵转置表示。换句话说,如果 矩阵R表示从u到k的旋转,然后R'从k到u, 我们可以这样写出变换的组成:

R' M R
很容易证明,当矩阵的乘积相乘时 乘以u,再次将u返回:

R' M R u = R' M k = R' k = u
因此,这确实是绕u定义的轴旋转

这个表达式的一个优点是它清楚地将 从Q和Q'对角r的依赖性看M对角r的依赖性 “轴”向量u。但是如果我们必须在 详细来说,我们显然有很多矩阵乘法要做

所以,走捷径。事实证明,当所有的尘埃落定时 旋转之间的乘法同构于单位的乘法 四元数。四元数,如果你以前没见过的话,是一个 一种复数的四维推广。他们是 威廉·汉密尔顿于1843年“发明”:

[威廉·罗文·汉密尔顿爵士]

今天的3D图形程序员欠了他一大笔债

每个单位四元数
q=q0+q1*i+q2*j+q3*k
然后定义一个旋转矩阵:

     (q0² + q1² - q2² - q3²)      2(q1q2 - q0q3)          2(q1q3 + q0q2)

Q  =      2(q2q1 + q0q3)     (q0² - q1² + q2² - q3²)      2(q2q3 - q0q1)

          2(q3q1 - q0q2)          2(q3q2 + q0q1)     (q0² - q1² - q2² + q3²)
        -1     0     0

Q =      0  -0.28  0.96

         0   0.96  0.28
     (q0² + q1² - q2² - q3²)      2(q1q2 - q0q3)          2(q1q3 + q0q2)

Q  =      2(q2q1 + q0q3)     (q0² - q1² + q2² - q3²)      2(q2q3 - q0q1)

          2(q3q1 - q0q2)          2(q3q2 + q0q1)     (q0² - q1² - q2² + q3²)
验证Q是正交矩阵,即
Q'=I
,意味着 本质上,Q的行构成正交基。那么,为了 例如,第一行的长度应为1:

(q0² + q1² - q2² - q3²)² + 4(q1q2 - q0q3)² + 4(q1q3 + q0q2)²

  = (q0² + q1² - q2² - q3²)² + 4(q1q2)² + 4(q0q3)² + 4(q1q3)² + 4(q0q2)²

  = (q0² + q1² + q2² + q3²)²

  =  1
前两行应该有点积零:

  [ (q0² + q1² - q2² - q3²), 2(q1q2 - q0q3), 2(q1q3 + q0q2) ]

   * [ 2(q2q1 + q0q3), (q0² - q1² + q2² - q3²), 2(q2q3 - q0q1) ]

 = 2(q0² + q1² - q2² - q3²)(q2q1 + q0q3)

   + 2(q1q2 - q0q3)(q0² - q1² + q2² - q3²)

   + 4(q1q3 + q0q2)(q2q3 - q0q1)

 = 4(q0²q1q2 + q1²q0q3 - q2²q0q3 - q3²q2q1)

   + 4(q3²q1q2 - q1²q0q3 + q2²q0q3 - q0²q2q1)

 =  0
通常也可以显示
det(Q)=1
,因此Q是 真的是轮换

Rotated Point = (X1+A''', Y1+B''', Z1+C''');
但是Q是绕什么轴旋转的呢?从什么角度看?好, 给定角度r和单位矢量:

u = ai + bj + ck
u = ai + bj + ck
与前面一样,对应的四元数为:

q = cos(r/2) + sin(r/2) * u

  = cos(r/2) + sin(r/2) ai + sin(r/2) bj + sin(r/2) ck
q = cos(pi/2) + sin(pi/2) * u

  = 0 + 0i + 0.6j + 0.8k
因此:

q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c,
我们能够得到期望的性质,即乘以Q“fix
q0 = cos(r/2),  q1 = sin(r/2) a,  q2 = sin(r/2) b,  q3 = sin(r/2) c
     (q0² + q1² - q2² - q3²)      2(q1q2 - q0q3)          2(q1q3 + q0q2)

Q  =      2(q2q1 + q0q3)     (q0² - q1² + q2² - q3²)      2(q2q3 - q0q1)

          2(q3q1 - q0q2)          2(q3q2 + q0q1)     (q0² - q1² - q2² + q3²)
Q u = u
Point of Rotation = (X1, Y1, Z1)
Point Location    = (X1+A, Y1+B, Z1+C)

(Point Location - Point of Rotation) = (A, B, C).
    A' = A*cos ZAngle - B*sin ZAngle
    B' = A*sin ZAngle + B*cos ZAngle
    C' = C.
    C'' = C'*cos YAngle - A'*sin YAngle
    A'' = C'*sin YAngle + A'*cos YAngle
    B'' = B'   
    B''' = B''*cos XAngle - C''*sin XAngle
    C''' = B''*sin XAngle + C''*cos XAngle
    A''' = A''
Rotated Point = (X1+A''', Y1+B''', Z1+C''');
    const nt = q.θ * del;  // scaled angle by some dT
    const s  = Math.sin( nt ); // sin/cos are the function of exp()
    const c1 = Math.cos( nt );
    const c = 1- c1;

    const qx = /*Axis unit vector X*/;
    const qy = /*Axis unit vector Y*/;
    const qz = /*Axis unit vector Z*/;

    const cnx = c*qx;
    const cny = c*qy;
    const cnz = c*qz;

    const xy = cnx*qy;  // x * y / (xx+yy+zz) * (1 - cos(2t))
    const yz = cny*qz;  // y * z / (xx+yy+zz) * (1 - cos(2t))
    const xz = cnz*qx;  // x * z / (xx+yy+zz) * (1 - cos(2t))

    const wx = s*qx;     // x / sqrt(xx+yy+zz) * sin(2t)
    const wy = s*qy;     // y / sqrt(xx+yy+zz) * sin(2t)
    const wz = s*qz;     // z / sqrt(xx+yy+zz) * sin(2t)

    const xx = cnx*qx;  // y * y / (xx+yy+zz) * (1 - cos(2t))
    const yy = cny*qy;  // x * x / (xx+yy+zz) * (1 - cos(2t))
    const zz = cnz*qz;  // z * z / (xx+yy+zz) * (1 - cos(2t))

    const basis = { right  :{ x : c1 + xx, y : wz + xy, z : xz - wy }
                  , up     :{ x : xy - wz, y : c1 + yy, z : wx + yz }
                  , forward:{ x : wy + xz, y : yz - wx, z : c1 + zz }
                  };