2012-02-02 36 views
5

当我尝试改变方向时,我的相机围绕一个点旋转。如果我旋转我的相机,例如说,在Y轴上旋转30度,而不是相机朝右看30度,相机将旋转它正在看的点。为什么我的相机用这个数学旋转一点?

o is the camera, A and B are 3D models. The lines show line-of-sight. 
This is what I expect: 
    A B 
    | >/
    |/
    |/
    |/ 
    o 

This is what actually happens: 
    A B 
    |\ 
    | \ 
    | \ 
    | > \ 
      o 

现在,根据我的理解,为了移动相机,我必须以相反的量移动世界。所以如果我想在Z轴上移动+1,我会在Z轴上翻译世界-1。由于我使用四元数来表示方位,因此我使用相机四元数的倒数(因为方向总是单位四元数,我使用共轭进行优化,而不是计算倒数)以适当的量旋转世界。

这里是我怎么转换四元数矩阵,其中q是倒四元数:

[1 - 2 * (q.y * q.y + q.z * q.z) 2 * (q.x * q.y - q.w * q.z)  2 * (q.x * q.z + q.w * q.y)   0] 
|2 * (q.x * q.y + q.w * q.z)  1 - 2 * (q.x * q.x + q.z * q.z) 2 * (q.y * q.z - q.w * q.x)   0| 
|2 * (q.x * q.z - q.w * q.y)  2 * (q.y * q.z + q.w * q.z)  1 - 2 * (q.x * q.x + q.y * q.y)  0| 
[0         0         0         1] 

在那之后,我设置的矩阵的平移分量:

[... ... ... -x] 
|... ... ... -y| 
|... ... ... -z| 
[0  0  0  1] 

最后我将它乘到模型视图矩阵堆栈上,然后渲染所有对象。 我很确定这个数学是正确的,但它不会产生我期待的结果。显然,向前和向右的向量是问题,所以我唯一的问题是为什么他们错了,如果我想要得到我期待的结果,应该如何设置它们。谢谢。编号: 我从this guy's quaternion camera class找到解决方案。首先我构造一个旋转矩阵,就像我之前做的那样,但是我从第一,第二和第三列(分别为xa,ya和za)获取矩阵的列向量。然后,我这样设置矩阵的平移分量:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

然后将所得矩阵可乘以到模型视图矩阵堆栈,它完美。

+0

使您的编辑解决方案,并接受它。这就是我们如何标记在这里解决的问题。我想你应该得到一些解释。我会为此写一个答案。 – datenwolf 2012-02-02 08:41:10

回答

1

编辑:我已经找到了这个人的四元数相机类的解决方案。首先我构造一个像我之前做的旋转矩阵,但是接下来我从第一列,第二列和第三列(分别是xa, ya和za)获得矩阵的列向量。然后我设置的平移分量的 这样的矩阵:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

然后将所得矩阵可乘以到模型视图矩阵 栈,它完美。

是的,这正是我所建议的,只是有点不同。你必须明白,OpenGL没有摄像头,但是你只需要向相反的方向移动世界,所以你需要找到逆变换矩阵。

相机只是旋转和移动。这使事情变得非常简单。平移的正反面只是具有相反符号的相同向量,而旋转矩阵的反面是它的转置(交换了列和行)。现在看看均质变换矩阵状的OpenGL使用它们:

R t 
0 1 

左上方的3×3是旋转部分,最右边的列是平移向量。我想其余的你已经知道了。

0

说实话,试图找到一个矩阵乘以模块视图矩阵是非常复杂和非常容易出错的。有很多混乱和特殊情况。例如,如果您正在仰视90度,则两个轴会变得相同。一个合乎逻辑的问题是:如果你正在回头,所以你通过最高点,你的向上的向量应该倒置,对吧?但是如果你错过了0.0001度呢?那么你应该围绕这一点转动头脑,这样你的向上的向量仍然存在。

在我看来,最好的方法是从另一个角度来看问题。让我们假设两种情况:

  • 倒挂是不可能的:
    • 保持一个点为您的相机的位置和经/纬度方向。用 简单的正弦/余弦运算可以得到方向矢量。你向上向量是(0,1,0)
    • 车削只不过是修改的纬度和经度
  • 倒挂可能:
    • 除了摄像头位置,保持向上和目标的载体。
    • 转向时,计算右=目标x向上,然后将目标更改为x *向右+ y *向上
    • 然后,您需要对目标向量进行归一化并计算新向上。尽管如此,Lot的案件仍然可以处理 。

所有这些之后,你只需拨打gluLookAt

+0

“说实话,试图找到一个与模块视图矩阵相乘的矩阵非常复杂,并且非常容易出错。”不,这不对。矩阵是考虑相对坐标方向最直接的方式。前3列中的每一列都是变换坐标系的基矢量之一。第四栏是相对翻译。从视图向量和目标向量中写下相机矩阵,然后用所有三角函数写出它们要容易得多。 – datenwolf 2012-02-02 11:36:46

+0

我知道。我所说的是,例如,如果你有三种不同的动作(比如移动,扭转和滚动)直到下一帧,那么在位置/纬度/经度上这样做最容易,最后将其转换为矩阵,而不是尝试将每个操作应用到前一个的矩阵中。 – Shahbaz 2012-02-02 12:54:08