移动3D世界 - OpenGL

时间:2015-06-30 16:21:40

标签: c++ opengl 3d camera rotation

所以我目前正在研究一些游戏元素,包括OpenGL中的一些类似引擎的东西,我已经遇到了这个问题。 (处理3D世界) 我正在通过鼠标获得世界上的旋转角度,如下所示:

int prevX = mouse.x;
int prevY = mouse.y;

GetCursorPos(&mouse);

cam.xRot -= atan(prevX-mouse.x);
cam.yRot -= atan(prevY-mouse.y);

似乎运作良好。 (xRot实际上意味着围绕Y轴旋转,yRot围绕x轴旋转) 相机旋转很好。然后我开始研究相对于相机的运动。经过一些绘画和绝望的尝试后,我来到了这里:

//W
if (keys[57])
       {
           cam.z += cos(angleY)*cos(angleX)*cam.speed;
           cam.x -= cos(angleY)*sin(angleX)*cam.speed;
           cam.y += sin(angleY);
       }
//S
if (keys[53])
       {
          cam.z -= cos(angleY)*cos(angleX)*cam.speed;
          cam.x += cos(angleY)*sin(angleX)*cam.speed;
          cam.y -= sin(angleY);
       }
//A
if (keys[41])
       {
          cam.z += sin(angleX)*cam.speed;
          cam.x += cos(angleX)*cam.speed;
       }
//D
if (keys[44])
       {
          cam.z -= cos(angleY)*sin(angleX)*cam.speed;
          cam.x -= cos(angleY)*cos(angleX)*cam.speed;
       }

它也有效,但问题是当我绕z轴(深度为1)旋转相机时。我尝试了一些组合等,但似乎没有任何工作。我错过了什么? 我把上面的等式做成如下: 当我把它作为2D x和z时我想要向前移动相机旋转零角度我需要只在z轴方向上移动,以一种积极的方式让我们使用一个函数,它的最大值在那里=> COS。当我旋转90度并需要向前移动时,我需要在x轴上移动所以让我们使用sin因为我们需要相反的。处理2D井。 现在我需要添加z轴,所以我可能只是将x和y的值限制为第二个角度的cos(yRot或围绕x的旋转角度,如果你想要的话),并使它成为y轴上的实际运动。 是的,但是当我绕z旋转并且基本上切换y和x轴时,我说问题。 怎么办呢? :d

哦,顺便说一下,我已经阅读了一些其他的教程,我注意到有些人使用不同的方式使用向量等。今天的游戏有什么常见的方式?我不太喜欢经常使用测角功能。也许我的方法不是最好的一个吗?

1 个答案:

答案 0 :(得分:1)

在摄像机管理方面,大多数人似乎都比以前困难得多。关键点是矩阵数学。

考虑具有世界矩阵W的对象,其由旋转和翻译部分组成。如果我们想要将此对象移动到右侧,我们可以将相应的转换矩阵乘以W(请注意,所有进一步的解释都假定使用列向量和列主要矩阵的OpenGL表示法):

W* = W * T(x, 0, 0)

重要的是乘法顺序。如果将平移矩阵乘以右侧,它将在对象的局部坐标系中移动对象。如果将它乘以左侧,它将在全局坐标系中移动它。类似地,我们可以将旋转矩阵相乘以在其局部坐标系中旋转对象:

W** = W* * Rx(phi)

现在,相机的视图矩阵有点棘手,因为它实际上是一个倒置矩阵。因此,如果您有一个视图矩阵V,则必须将逆矩阵乘以左侧:

V*  = T(-x, 0, 0) * V
V** = Rx(-phi) * V*
//...

然而,其中一个问题是向上矢量的固定。如果围绕局部y轴执行旋转,则向上方向可能会发生变化。我们可以计算一个适应矩阵,避免这种情况,但只是从两个角度重新计算整个旋转矩阵可能要容易得多。重新计算矩阵后,必须将其重新定位在旧位置(全局位置,因此将平移矩阵乘以左侧)。计算旧位置需要一些数学运算(因为矩阵是反转的):

pos = -tx * first row - ty * second row - tz * third row
where tx is the entry in the first row, last column
      ty is the entry in the second row, last column
      tz is the entry in the third row, last column

摘要

如果要保持灵活的摄像机表示,请存储视图矩阵和两个旋转角度。如果要移动相机,只需乘以平移矩阵即可。如果要围绕局部x轴旋转摄像机,请更改角度并乘以旋转矩阵。如果要围绕局部y轴旋转,请更改角度并重新计算整个矩阵,包括重新定位。

您当前的解决方案基本上是这样做的,因为三角测量结果恰好是相关位置矩阵的条目。但正如您所看到的,维护非常麻烦,如果您想允许第三次轮换,则必须更改整个代码。

拥抱矩阵数学!