旋转3D空间中的矢量

den*_*niz 47 math 3d vector rotation linear-algebra

我在opengl中制作了一个android项目,它使用加速计来计算特定轴的变化,我的目标是旋转我的类似航天器的物体的运动矢量.问题是我无法理解旋转矩阵背后的数学.默认运动矢量为0,1,0,表示+ y,因此对象在开头向上看.而我正在尝试旋转它的运动矢量,这样我就可以移动它所指向的物体.我可以在手机中收集旋转变化.x轴:旋转[0],y轴:旋转[1],z轴:旋转[2].如何使用旋转矩阵旋转运动矢量?

leg*_*s2k 143

如果要旋转矢量,则应构造所谓的旋转矩阵.

在2D中旋转

假设您想要将矢量或点旋转θ,则三角测量表明新坐标为

    x' = x cos ? ? y sin ?
    y' = x sin ? + y cos ?
Run Code Online (Sandbox Code Playgroud)

为了演示这个,让我们采用X和Y的基本轴; 当我们将X轴逆时针旋转90°时,我们应该将X轴转换为Y轴.X轴作为单位矢量是

    Unit vector along X axis = <1, 0>
    x' = 1 cos 90 ? 0 sin 90 = 0
    y' = 1 sin 90 + 0 cos 90 = 1
    New coordinates of the vector, <x', y'> = <0, 1>  ?  Y-axis
Run Code Online (Sandbox Code Playgroud)

当你理解这一点时,创建一个矩阵来做到这一点变得简单.矩阵只是一种以舒适,通用的方式执行此操作的数学工具,因此可以使用一种常用方法在一个步骤中组合和执行各种变换,如旋转,缩放和平移(移动).从线性代数,到2D中的点或矢量旋转,要构建的矩阵是

    |cos ?   ?sin ?| |x| = |x cos ? ? y sin ?| = |x'|
    |sin ?    cos ?| |y|   |x sin ? + y cos ?|   |y'|
Run Code Online (Sandbox Code Playgroud)

3D旋转

这适用于2D,而在3D中,我们需要考虑第三轴.在2D中围绕原点(点)旋转矢量仅仅意味着围绕Z轴(一条线)以3D旋转; 因为我们围绕Z轴旋转,所以它的坐标应该保持不变,即0°(旋转发生在3D平面的XY平面上).在3D中绕Z轴旋转

    |cos ?   ?sin ?   0| |x|   |x cos ? ? y sin ?|   |x'|
    |sin ?    cos ?   0| |y| = |x sin ? + y cos ?| = |y'|
    |  0       0      1| |z|   |        z        |   |z'|
Run Code Online (Sandbox Code Playgroud)

围绕Y轴将是

    | cos ?    0   sin ?| |x|   | x cos ? + z sin ?|   |x'|
    |   0      1       0| |y| = |         y        | = |y'|
    |?sin ?    0   cos ?| |z|   |?x sin ? + z cos ?|   |z'|
Run Code Online (Sandbox Code Playgroud)

围绕X轴将是

    |1     0           0| |x|   |        x        |   |x'|
    |0   cos ?    ?sin ?| |y| = |y cos ? ? z sin ?| = |y'|
    |0   sin ?     cos ?| |z|   |y sin ? + z cos ?|   |z'|
Run Code Online (Sandbox Code Playgroud)

请注意,完成旋转的轴在矩阵中没有sin或cos元素.我希望这能使轮换案例清晰.

组成

上述矩阵旋转物体,好像物体距离原点距离r =√(x 2 + y 2); 查找极坐标以了解原因.这种旋转将相对于世界空间起源.通常我们需要围绕自己的框架/枢轴旋转对象,而不是围绕世界.由于并非所有对象都处于世界原点,因此使用这些矩阵旋转将不会产生围绕对象自身框架旋转的所需结果.因此,您也需要了解翻译.您首先将对象转换(移动)到世界原点(以便对象的原点与世界对齐,从而使r = 0),使用这些矩阵中的一个(或多个)执行旋转,然后再将其转换回来到它以前的位置.变换应用的顺序很重要.

我恳请您阅读有关线性和仿射变换及其组合的信息,以便在使用代码中的变换进行一次性执行多次变换.如果不了解它背后的基本数学,调试转换将是一场噩梦.我发现这个讲座视频是一个非常好的资源.另一个资源是关于转换的教程,旨在直观并用动画说明想法.

注意:这种执行旋转的方法遵循欧拉角旋转系统,该系统更易于教导和掌握.这适用于2D和简单3D情况; 但是当需要同时围绕所有三个轴进行旋转时,由于该系统固有的缺陷表现为万向节锁定,因此欧拉角是不够的.在这种情况下,人们诉诸于Quaternion,这比这更先进但是在正确使用时不会受到万向节锁的影响.

  • 请记住,Quaternions没有解决万向节锁定与它无关.四元数和矩阵只是实际旋转/方向的编码.万向节锁定的原因不是编码而是顺序旋转.使用四元数来表示3个欧拉角将导致万向节锁定. (6认同)
  • 万向节锁定源于将旋转变换表示为围绕不同轴的多个分量旋转 - 也称为欧拉角.此方案允许您将一个轴旋转到另一个轴上,从而导致失去自由度和可怕的gimble锁定.需要用_1_表示3D旋转,只需要一个四元数而不是_3_.然后用它进行插值和合成,这有效地避免了万向节锁定.有关详细信息,请参阅[Quaterions及其在3D空间中的旋转应用](http://facultypages.morris.umn.edu/math/Ma4901/gravelle.pdf). (3认同)
  • 这正是我想说的.最后,四元数通常转换为矩阵(对于渲染器).这意味着再次编码不是问题,但实际上在每次旋转后失去一定程度的自由度. (3认同)
  • +1感谢你在接受我的批评时保持积极态度(很多人实际上并没有以开放的心态接受它,特别是我缺乏代表.) (3认同)
  • 如果有人对万向节锁定背后的原因感兴趣:http://sundaram.wordpress.com/2013/03/08/mathematical-reason-behind-gimbal-lock-in-euler-angles/ (2认同)
  • 同意.方向表示与slerp(动画)不同.当正确使用时(通过避免旋转连接),欧拉角受到万向节锁和矩阵,轴角,四元数可用于避免万向节锁定. (2认同)
  • 实际上,最初的措辞来自一个大师会员的OpenGL论坛,归功于[他](http://www.opengl.org/discussion_boards/showthread.php/180183-Quaternion-based-camera-still-has-gimbal -lock?p = 1245755&viewfull = 1#post1245755):)感谢你把它带到这里. (2认同)