编辑 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]
当你想旋转对象时,旋转每个向量原位。换句话说,将旋转独立地应用于矩阵中的 U、V 和 W 中的每一个。
渲染时,只需将 M 作为单个变换应用到您的对象。 (如果您想知道,不要自己应用旋转;只应用矩阵。)
编辑 2:(出现在第一次编辑之前,因为它为其提供了上下文。)
在最初发布该答案很久后重新访问该答案时,我意识到我可能没有发现您可能对如何从每个控件应用轮换的误解。
这个想法不是累积每个控件要应用的旋转并分别应用它们。相反,您应该将每个增量旋转(即,每次滑块控件触发更改事件时)立即应用于 U、V 和 W 向量。
更具体地说,不要说“总共,垂直控件移动了 47°,水平控件移动了 -21°”,而是将它们作为两个大旋转应用。这将展示与激发您的问题相同的问题。相反,假设“垂直滑块移动了 0.23°”,然后将 U、V 和 W 绕 X 轴旋转 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° 旋转时很常见)。在一般情况下,应用顺序都不会匹配基变换。
我已经筋疲力尽了,所以我希望到目前为止的解释能让事情更清楚,而不是更混乱。