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

Matrix 如何将旋转矩阵锁定到地平线?,matrix,camera,rotation,geometry,Matrix,Camera,Rotation,Geometry,我对3x3旋转矩阵有问题。这是否可能调整任意现有的旋转矩阵,从而将旋转锁定到地平线(没有滚动,只有俯仰和下颚)?我需要使地平线始终保持“水平”,例如,在某些FPS中使用相机 无法将现有旋转矩阵转换为受约束的旋转矩阵(即旋转矩阵的右向量始终位于垂直于世界坐标系上轴的平面内),必须明确指定转换方式?现有的旋转矩阵可以围绕一整串向量旋转,以获得所需的约束,但它们都可以给出不同的结果 最自然的旋转矢量可能是现有旋转矩阵的正向矢量,但也可能是世界坐标系的正向或右向矢量 我将给出一个关于现有旋转矩阵的正向向

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

无法将现有旋转矩阵转换为受约束的旋转矩阵(即旋转矩阵的右向量始终位于垂直于世界坐标系上轴的平面内),必须明确指定转换方式?现有的旋转矩阵可以围绕一整串向量旋转,以获得所需的约束,但它们都可以给出不同的结果

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

我将给出一个关于现有旋转矩阵的正向向量旋转的例子。我假设你使用的是一个坐标系,比如默认的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*
向量回到与世界坐标系的上向量正交的平面中。θ可以通过
之间的点积来计算

dotproduct(,)==length()*length()*cos(θ)
θ=acos(点积(,)/(长度()*长度())
然后旋转矩阵
a*
就是
glRotate3f(θ,0,0,1)
应用的旋转矩阵,或者最后一个参数可能是
-1
,现在想都想不起来了


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

可能仅围绕“向上”轴旋转?我很难想象你的问题。你能详细说明一下,或者给我们举一个矩阵的例子,说明你当前的变换,以及你下一步要做什么吗?问题是,我不仅需要绕“上”轴旋转,还需要绕“向右”轴旋转。这个矩阵,比如说,是一个随机正交旋转矩阵。需要“移除”围绕“向前/向后”轴的旋转。啊,我误解了你的问题,以为你只是想保持偏航。示例矩阵,即使是符号矩阵,仍然会很有帮助。感谢您的回复,这非常有用!但是,在最初的版本中,它对我不起作用。另外,可能对我来说最有价值的事情是关于由于偏航和俯仰顺序不正确而出现侧倾副作用的原因的说明。是的,如前所述,这取决于变换矩阵表示和世界轴的选择。有时右、上、前/后向量在行中而不是在列中,如OpenGL,有时人们使用相反的轴,有时人们使用Z作为世界上的轴,而不是OpenGL中的Y,因为所有这些都需要调整。是的,如果使用不同的旋转顺序,则会得到不同的效果,执行的旋转是相对于到该点的变换的,因此如果已经向前倾斜,则偏航将是关于向前倾斜的上方向向量,而不是关于世界坐标系的上方向向量,从而导致隐式滚动。另一种方法是先水平旋转,面向你想要的方向,然后朝这个方向向前俯仰。
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>)))