我有3x3旋转矩阵的问题。是否可以调整任意现有的旋转矩阵,因此旋转被锁定到地平线(没有滚动,只是俯仰和下颚)?我需要让地平线始终“水平”,例如在某些FPS中使用相机。
答案 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
用于最后一个参数,现在太累了,无法考虑它。
请注意,如果您在用户输入上执行自己的俯仰和偏航应用程序,则只需在渲染对象的每一帧上计算世界到对象旋转矩阵,而不是维护增量变换矩阵(甚至可以进入万向节锁定。)在这种情况下,只需在使用输入时调整俯仰和偏航数字,然后确保以正确的顺序应用俯仰和偏航,首先偏航然后俯仰,如果你这样做,反过来你会得到滚动副作用。