如何将旋转矩阵锁定到地平线?

时间:2013-01-21 16:06:10

标签: matrix camera rotation geometry

我有3x3旋转矩阵的问题。是否可以调整任意现有的旋转矩阵,因此旋转被锁定到地平线(没有滚动,只是俯仰和下颚)?我需要让地平线始终“水平”,例如在某些FPS中使用相机。

1 个答案:

答案 0 :(得分:1)

您无法将现有的旋转矩阵转换为您想要的旋转矩阵(旋转矩阵的右矢量始终位于垂直于世界坐标系的上轴的平面中),您必须明确指定如何进行转型?现有的旋转矩阵可以围绕一大堆矢量旋转,以获得您想要的约束,但它们都可以为您提供不同的结果。

旋转的最自然矢量可能是现有旋转矩阵的前向矢量,但也可能是世界坐标系的前向或右向量。

我将举例说明旋转现有旋转矩阵的前向矢量。我假设你正在使用一个坐标系,就像默认的OpenGL坐标系,其中X是正确的,Y是向上的,Z是向后的,如果你的坐标系不同,你将需要调整它。

您将拥有以下世界来对象旋转矩阵:

[r1 u1 b1]
[r2 u2 b2]
[r3 u3 b3]

r*u*b*分别是您的旋转对象坐标系在您的世界坐标系中表示的正向,向上和向后矢量。

如上所述,您希望将右矢量约束到垂直于世界坐标系上轴的平面,这意味着r2应始终为0。现在我们不能只将r2设置为0,这会给你一个非常奇怪的变形,而不是一个干净的旋转。我们必须找到一些可以旋转的角度,这将在右侧平面上得到正确的矢量。

您的调整看起来像:

[nr1 nu1 nb1]     [r1 u1 b1]     [ar1 au1 ab1]
[nr2 nu2 nb2]  =  [r2 u2 b2]  *  [ar2 au2 ab2]
[nr3 nu3 nb3]     [r3 u3 b3]     [ar3 au3 ab3]

其中a*是您的调整,n*是您的新轮播矩阵。

a*旋转矩阵现在基本上只是围绕角度θ的前向矢量(Z轴)的旋转,以使r*向量返回到与向上矢量正交的平面中。世界坐标系。该θ可以通过<r1, r2, r3><r1, 0, r3>之间的点积来计算。

dotproduct(<r1, r2, r3>, <r1, 0, r3>) == length(<r1, r2, r3>) * length(<r1, 0, r3>) * cos(theta)

theta = acos(dotproduct(<r1, r2, r3>, <r1, 0, r3>) / (length(<r1, r2, r3>) * length(<r1, 0, r3>)))

然后旋转矩阵a*只是由glRotate3f(theta, 0, 0, 1)应用的旋转矩阵,或者可能是-1用于最后一个参数,现在太累了,无法考虑它。

请注意,如果您在用户输入上执行自己的俯仰和偏航应用程序,则只需在渲染对象的每一帧上计算世界到对象旋转矩阵,而不是维护增量变换矩阵(甚至可以进入万向节锁定。)在这种情况下,只需在使用输入时调整俯仰和偏航数字,然后确保以正确的顺序应用俯仰和偏航,首先偏航然后俯仰,如果你这样做,反过来你会得到滚动副作用。