如何始终从特定方向旋转

时间:2010-07-22 09:53:52

标签: math 3d

(事先道歉。我的数学技巧和描述的力量似乎暂时离开了我) 想象一下屏幕上有一组带有两组控件的立方体。一组控件可以将立方体左右旋转(也就是偏航或Y甚至Z,具体取决于一个人的数学倾向)和另一组控件可以上下旋转(也就是俯仰或X)。

我想做的是使两个设置的sof控件始终相对于查看器/屏幕旋转立方体,而不管立方体当前如何旋转。

矩阵或基于四元数的旋转的常规组合无法实现此效果,因为旋转以串行方式应用(每次旋转从前一个旋转“开始”)。

e.g。使用伪代码 combinatedRotation = RotateYaw(90) * RotatePitch(45) 会给我一个看似“滚动”到一侧的立方体,因为Pitch旋转也已经旋转。 (或者对于一个更具戏剧性的例子RotateYaw(180) * RotatePitch(45)将产生一个立方体,其中显示音调与屏幕相反的方向)

有人可以指示我或者提供正确的方法使两个旋转相互独立,这样无论多维数据集当前如何旋转,Yaw和Pitch的工作“与预期的”相对于屏幕控制?

1 个答案:

答案 0 :(得分:2)

编辑3:我刚刚想到,下面的解决方案虽然正确,但却不必要地复杂化。您可以通过简单地将旋转矩阵乘以方向矩阵来计算新的方向来实现相同的效果:

M = R * M

虽然与问题无关,但这也可以正确处理不是由纯旋转组​​成的方向矩阵,但也包含平移,倾斜等。

(编辑完3)


您需要一个变换矩阵,其中包含对象局部坐标系的当前旋转轴。然后,您将旋转应用于该矩阵。

在数学术语中,您从身份矩阵开始,如下所示:

M = [1  0  0  0]
    [0  1  0  0]
    [0  0  1  0]
    [0  0  0  1]

此矩阵包含三个向量U,V和W,它们在世界坐标系中表示对象局部坐标系的三个单位向量:

M = [Ux Vx Wx 0]
    [Uy Vy Wy 0]
    [Uz Vz Wz 0]
    [0  0  0  1]

当您想要旋转对象时,旋转每个向量 in situ 。换句话说,将旋转独立应用于矩阵中的U,V和W中的每一个。

渲染时,只需将M作为单个变换应用于对象。 (如果你想知道,不要自己应用旋转;只是矩阵。)

编辑2:(在第一次编辑之前出现,因为它为其提供了上下文。)

在最初发布这个答案很久之后,我已经意识到我可能没有意识到你可能对如何应用每个控件的旋转感到误解。

这个想法不是累积每个控件应用的旋转并单独应用它们。相反,您应该立即将每个增量旋转(即每次一个滑块控件触发更改事件)应用于U,V和W向量。

更具体地说,不要说,“总的来说,垂直控制已经移动了47°而水平控制已经移动了-21°”并将它们应用为两个大的旋转。这将表现出同样的问题,激发了你的问题。取而代之的是,“垂直滑块刚移动0.23°”,绕U轴旋转U,V和W 0.23°。

简而言之,下面描述的90°偏航后跟45°俯仰可能不是你想要的。

编辑:根据要求,这里是90°偏航的情况,然后45°俯仰平移在实践中......

由于你从单位矩阵开始,基础向量将只是你的世界单位向量:

U = [1]  V = [0]  W = [0]
    [0]      [1]      [0]
    [0]      [0]      [1]

要应用90°偏航,围绕Z轴旋转每个基础向量(反映我的数学倾向),这几乎是微不足道的:

U = [0]  V = [-1]  W = [0]
    [1]      [ 0]      [0]
    [0]      [ 0]      [1]

因此,在90°偏航之后,变换矩阵将是:

M = [0 -1  0  0]
    [1  0  0  0]
    [0  0  1  0]
    [0  0  0  1]

将此矩阵应用于主体将在Z周围实现所需的90°旋转。

然后应用45°间距(我将采用围绕X轴),我们在YZ平面中旋转新的基础向量,这次是45°:

U = [0  ]  V = [-1]  W = [ 0  ]
    [0.7]      [ 0]      [-0.7]
    [0.7]      [ 0]      [ 0.7]

因此,新的变换矩阵是:

M = [0    -1   0    0]
    [0.7   0  -0.7  0]
    [0.7   0   0.7  0]
    [0     0   0    1]

如果将两个旋转相乘:

Yaw(90)*Pitch(45) = [0 -1 0 0]*[1  0    0    0] = [0  -0.7  0.7  0]
                    [1  0 0 0] [0  0.7 -0.7  0]   [1   0    0    0]
                    [0  0 1 0] [0  0.7  0.7  0]   [0   0.7  0.7  0]
                    [0  0 0 1] [0  0    0    1]   [0   0    0    1]

Pitch(45)*Yaw(90) = [1  0    0    0]*[0 -1 0 0] = [0    -1   0    0]
                    [0  0.7 -0.7  0] [1  0 0 0]   [0.7   0  -0.7  0]
                    [0  0.7  0.7  0] [0  0 1 0]   [0.7   0   0.7  0]
                    [0  0    0    1] [0  0 0 1]   [0     0   0    1]

你会注意到第二种形式与通过操纵基础矢量产生的变换矩阵相同,但这只是巧合(当混合90°和45°旋转时非常常见)。在一般情况下,应用程序的顺序都不会与基础变换匹配。

我已经没精力了,所以我希望到目前为止的解释能让事情变得更加清晰,而不是更加混乱。