围绕任意轴的圆周旋转

时间:2011-07-17 02:21:32

标签: 3d

我正在编写星际争霸2自定义地图,并在3D中获得了一些数学方法。目前我正在尝试创建和旋转任意轴周围的点,由x,y和z给出(xyz向量被标准化)。

我一直在尝试很多并在互联网上阅读了很多东西,但我不知道它是如何正常工作的。我当前的脚本(你可能不知道语言,但没什么特别的)是几个小时打破所有内容的结果(无法正常工作):

    point CP;
fixed AXY;
point D;
point DnoZ;
point DXY_Z;
fixed AZ;
fixed LXY;
missile[Missile].Angle = (missile[Missile].Angle + missile[Missile].Acceleration) % 360.0;
missile[Missile].Acceleration += missile[Missile].AirResistance;
if (missile[Missile].Parent > -1) {
    D = missile[missile[Missile].Parent].Direction;
    DnoZ = Point(PointGetX(D),0.0);
    DXY_Z = Normalize(Point(SquareRoot(PointDot(DnoZ,DnoZ)),PointGetHeight(D)));
    AZ = MaxF(ACos(PointGetX(DXY_Z)),ASin(PointGetY(DXY_Z)))+missile[Missile].Angle;
    DnoZ = Normalize(DnoZ);
    AXY = MaxF(ACos(PointGetX(DnoZ)),ASin(PointGetY(DnoZ)));
    CP = Point(Cos(AXY+90),Sin(AXY+90));
    LXY = SquareRoot(PointDot(CP,CP));
    if (LXY > 0) {
        CP = PointMult(CP,Cos(AZ)/LXY);
        PointSetHeight(CP,Sin(AZ));
    } else {
        CP = Point3(0.0,0.0,1.0);
    }
} else {
    CP = Point(Cos(missile[Missile].Angle),Sin(missile[Missile].Angle));
}
missile[Missile].Direction = Normalize(CP);
missile[Missile].Position = PointAdd(missile[Missile].Position,PointMult(missile[Missile].Direction,missile[Missile].Distance));

我无法理解数学。如果你能用简单的术语解释它是最好的解决方案,那么剪切的代码也会很好(但不太有帮助,因为我计划将来做更多的3D东西)。

7 个答案:

答案 0 :(得分:22)

http://en.wikipedia.org/wiki/Rotation_matrix。请查看Rotation matrix from axis and angle部分。为方便起见,这里有您需要的矩阵。它有点毛茸茸。 theta是角度,ux,uy和uz是规范化轴向量的x,y和z分量

Here's the rotation matrix

如果您不了解矩阵和载体,请回复,我会帮助您。

答案 1 :(得分:11)

执行此类轮换的有用方法是使用quaternions执行此操作。在实践中,我发现它们更容易使用并且具有避免Gimbal lock的额外好处。

Here是一个很好的演练,解释了它们如何以及为什么用于围绕任意轴的旋转(它是对用户问题的响应)。它的级别更高,对于那个不熟悉这个想法的人来说会很好,所以我建议从那里开始。

更新以避免链接腐蚀

来自链接网站的文字:

毫无疑问,你已经得出结论,围绕轴旋转 穿过原点和单位球上的点(a,b,c) 三维是线性变换,因此可以 由矩阵乘法表示。我们会给你一个非常光滑的 确定该矩阵的方法,但要理解紧凑性 这个公式最好从一些评论开始。

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

M M' = I

我们通过'方便地表示转置。换句话说 正交矩阵的转置是它的逆。

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

现在旋转实际上甚至在正交之间有点特殊 转换,实际上它们也被称为特殊正交 变换(或矩阵)凭借其存在的性质 "取向保留"。将它们与反射相比较 也保持长度和角度,你会发现几何 保持方向的特征(或者#3;手性"如果你 prefer)在矩阵的行列式中具有数字对应物。 旋转矩阵具有行列式1,而反射矩阵具有行列式1 决定因素-1。事实证明,产品(或组成)两个 轮换再次轮换,这与事实是一致的 产品的决定因素是决定因素的产物(或1 in 轮换的情况)。

现在我们可以描述一个人可能遵循的循序渐进的方法 构建所需的矩阵(在我们简化整个过程和之前) 跳到答案!)。首先考虑我们旋转的步骤 单位矢量:

u = ai + bj + ck

这样它就符合"标准"也许是单位向量 k(正位z轴)。现在我们知道如何围绕z轴旋转; 这是在x,y上进行通常的2x2转换的问题 单独坐标:

       cos(r) sin(r)   0
M  =  -sin(r) cos(r)   0
         0      0      1

最后我们需要"撤消"把你带到k的初始轮换, 这很简单,因为这种转变的反转是(我们 召回)由矩阵转置表示。换句话说,如果 矩阵R表示将u转换为k,然后R'拿k到你, 我们可以写出这样的转换组成:

R' M R

很容易证实这种矩阵乘积成倍增加 时间你,再次回来:

R' M R u = R' M k = R' k = u

因此,这确实围绕由u。

定义的轴旋转

这个表达的一个优点是它干净地分离出来 M与Q和Q的相关性对角度r的依赖性。在...上 "轴"矢量你。但是,如果我们必须进行计算 细节,我们显然会有很多矩阵乘法。

所以,到了快捷方式。事实证明,当所有尘埃落定时 旋转之间的乘法与单位的乘法同构 四元。如果你之前没有见过它们,那么四元数就是一个 一种复数的四维推广。他们是 "发明"威廉·汉密尔顿于1843年发表:

[威廉罗恩汉密尔顿爵士] http://www-gap.dcs.st-and.ac.uk/~history/Mathematicians/Hamilton.html

今天的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²)

验证Q是正交矩阵,即。那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是 真的是轮换。

但围绕Q轴旋转的是什么?从什么角度来看?好, 给定角度r和单位矢量:

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

因此:

q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c,

我们能够获得所需的属性乘以Q"修复" U:

Q u = u

让我们做一个简单的例子,而不是通过冗长的代数。

u = 0i + 0.6j + 0.8k成为我们的单位向量,r = pi是我们的旋转角度。

然后四元数是:

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

  = 0 + 0i + 0.6j + 0.8k

和旋转矩阵:

        -1     0     0

Q =      0  -0.28  0.96

         0   0.96  0.28

在这个具体案例中,很容易验证Q Q' = I和det(Q)= 1。

我们还计算:

Q u = [ 0, -0.28*0.6 + 0.96*0.8, 0.96*0.6 + 0.28*0.8 ]'

    = [ 0, 0.6, 0.8 ]'

    =  u

即。单位矢量u定义旋转轴,因为它是固定的"由Q。

最后,我们说明旋转角度为pi(或180°) 通过考虑Q如何作用于方向上的单位向量 正x轴的垂直于u:

i + 0j + 0k,  or as a vector, [ 1, 0, 0 ]'

然后是Q [ 1, 0, 0 ]' = [-1, 0, 0 ]',它是[1,0,0的旋转 ]'通过角度pi关于你。

作为四元数和四元组旋转表示的参考 一些额外的表示方法(以及它们的优点 for),请看这里的详细信息:

[代表3D旋转] http://gandalf-library.sourceforge.net/tutorial/report/node125.html

概要

给定角度r以弧度和单位向量u = ai + bj + ck或[a,b,c]',定义:

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然后影响所需的旋转,特别是:

Q u = u

答案 2 :(得分:5)

要执行3D旋转,您只需将旋转点偏移到原点并围绕每个轴顺序旋转,将结果存储在每个轴旋转之间,以便与下一个旋转操作一起使用。该算法如下所示:

将点偏移到原点。

Point of Rotation = (X1, Y1, Z1)
Point Location    = (X1+A, Y1+B, Z1+C)

(Point Location - Point of Rotation) = (A, B, C).

围绕Z轴执行旋转。

    A' = A*cos ZAngle - B*sin ZAngle
    B' = A*sin ZAngle + B*cos ZAngle
    C' = C.

接下来,围绕Y轴执行旋转。

    C'' = C'*cos YAngle - A'*sin YAngle
    A'' = C'*sin YAngle + A'*cos YAngle
    B'' = B'   

现在执行关于X轴的最后一次旋转。

    B''' = B''*cos XAngle - C''*sin XAngle
    C''' = B''*sin XAngle + C''*cos XAngle
    A''' = A''

最后,将这些值添加回原始旋转点。

Rotated Point = (X1+A''', Y1+B''', Z1+C''');

我发现这个link非常有帮助。它定义了如何围绕X,Y和Z轴执行单独旋转。

在数学上,您可以像这样定义一组操作:

enter image description here

答案 3 :(得分:2)

以下是您可以用来围绕任何轴旋转的内容,无论是x,y还是z。 Rx,Ry和Rz分别表示围绕a,x,y和z的旋转。

enter image description here

答案 4 :(得分:0)

对于使用矩阵的三维任意轴的旋转,我有一个页面here。矩阵(here)的链接解释和推导包括以下旋转/平移矩阵。这是一个矩阵,它产生的结果是通过(a,b,c)旋转点(x,y,z)的方向,方向矢量⟨u,v,w⟩为角度θ。

matrix of rotation about an arbitrary axis

结果是这三点:

rotated point

该页面包含源代码下载的链接。如果您想以交互方式进行旋转,可以在this site处进行。尝试使用示例旋转链接来了解正在发生的事情。

Twist and Shout!

答案 5 :(得分:0)

进行编程的一种非常简洁的方法,尤其是如果您能够使用矩阵进行操作(例如在Matlab中)的是Rodrigues' Rotation Formula

该公式使用一个非常简单的公式绕着由单位矢量R定义的轴以角度\hat{u} = [u_x,u_y,u_z]绕轴创建旋转矩阵phi

R=I+sin(phi)·W + (1-cos(phi))·W²

其中I是单位矩阵,W是由单位向量u的分量给出的矩阵:

W= [0 -uz uy; uz 0 -ux; -uy ux 0];

请注意,向量u是单位向量非常重要,也就是说,u的范数必须为1。

您可以检查欧氏轴的公式是否与Wikipedia上的公式完全相同,并由Aakash Anuj在此处发布。

自从我发现它以来,我仅将其用于旋转。希望对任何人有帮助。

答案 6 :(得分:0)

axis-angle 直接转换为四元数;假设轴是单位向量,角度是围绕该轴的自旋。轴被赋予规则的 (x,y,z) 方向坐标。四元数是 (cos(theta),sin(theta)*x, sin(theta)*y, sin(theta)*z) 然后适当相乘。

可以通过使用 Rodrigues Rotation Formula 围绕轴角旋转 (1,0,0),(0,1,0),(0,0,1) 来形成基础,结果如下...然后{ {1}}、forwardright 向量可用于将点缩放到正确位置。 (这只是一个矩阵,但本质上是转置的,这样 axii 就可以立即提取出来,在任何特定点为您提供相对的“向上”)

up