3d 绕任意轴旋转
我正在为星际争霸2定制地图编程,并在3D中获得了一些数学问题。目前,我正在尝试创建一个点,并围绕任意轴旋转,该轴由x、y和z给定(xyz向量是标准化的) 我试了很多次,在网上读了很多东西,但我就是不知道它是如何正确工作的。我当前的脚本(你可能不懂语言,但没什么特别的)是打破一切长达数小时(无法正常工作)的结果: 我就是想不起数学。如果你能用简单的术语解释这是最好的解决方案,那么剪掉一段代码也会很好(但没有那么大的帮助,因为我计划将来做更多的3D工作)。。看看下面的部分。为方便起见,这是您需要的矩阵。有点毛茸茸的。θ是角度,ux、uy和uz是归一化的轴向量的x、y和z分量3d 绕任意轴旋转,3d,3d,我正在为星际争霸2定制地图编程,并在3D中获得了一些数学问题。目前,我正在尝试创建一个点,并围绕任意轴旋转,该轴由x、y和z给定(xyz向量是标准化的) 我试了很多次,在网上读了很多东西,但我就是不知道它是如何正确工作的。我当前的脚本(你可能不懂语言,但没什么特别的)是打破一切长达数小时(无法正常工作)的结果: 我就是想不起数学。如果你能用简单的术语解释这是最好的解决方案,那么剪掉一段代码也会很好(但没有那么大的帮助,因为我计划将来做更多的3D工作)。。看看下面的部分。为方便起见,这是您需要的矩
如果你不懂矩阵和向量,请发回来,我会帮助你。做这种旋转的一个有用方法是用。在实践中,我发现它们更容易使用,而且还有避免使用的额外好处 这是一个很好的演示,解释了它们如何以及为什么用于绕任意轴旋转(这是对用户问题的回答)。这是一个更高的层次,对新手来说会更好,所以我建议从这里开始 更新以避免链路腐蚀 链接站点中的文本: 毫无疑问,你们已经得出结论,绕轴旋转 通过原点和单位球体上的点(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 }
};