我对 3x3 旋转矩阵有疑问。是否可以调整任意现有的旋转矩阵,因此旋转被锁定到地平线(没有滚动,只有俯仰和下巴)?例如,我需要使地平线始终“水平”,例如在某些 FPS 中使用相机。
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*
矩阵现在基本上只是围绕角度 theta 的前向矢量(Z 轴)的旋转,以使r*
矢量回到与世界坐标系的向上矢量正交的平面。该 theta 可以通过 和 之间的点积来<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)
Or 应用的旋转矩阵,也许-1
是最后一个参数,现在想起来太累了。
请注意,如果您在用户输入上执行自己的俯仰和偏航应用程序,那么在渲染对象的每一帧中计算一个世界到对象的旋转矩阵会更容易,而不是维护一个增量变换矩阵(甚至可能进入万向节锁定。 )在这种情况下,只需在使用输入时调整俯仰和偏航数,然后确保以正确的顺序应用俯仰和偏航,先偏航然后俯仰,如果你这样做,你会得到滚动作为副作用。