4

在 OpenGL 中,我正在尝试创建一个自由飞行相机。我的问题是 Y 轴上的旋转。相机应始终在 Y 世界轴上旋转,而不是在本地方向上。我尝试了几种矩阵乘法,但都没有结果。和

camMatrix = camMatrix  * yrotMatrix 

沿局部轴旋转相机。与

camMatrix = yrotMatrix * camMatrix

沿世界轴旋转相机,但始终围绕原点旋转。但是,旋转中心应该是相机。有人出主意吗?

4

4 回答 4

7

3D 编程更棘手的方面之一是正确进行复杂的转换。

在 OpenGL 中,每个点都先用模型/视图矩阵转换,然后再用投影矩阵转换。

模型视图矩阵获取每个点并将其转换为从相机的角度来看它应该位于的位置。投影矩阵转换点的坐标,以便可以轻松地将 X 和 Y 坐标映射到窗口。

要获得正确的模式/视图矩阵,您必须从一个单位矩阵(不改变顶点的矩阵)开始,然后对相机的位置和方向应用变换,然后以相反的顺序应用对象的位置和方向。

您需要记住的另一件事是,旋转始终围绕以原点 (0,0,0) 为中心的轴。因此,当您为相机应用旋转变换时,您是在转动它(就像您转动头部一样)还是围绕原点运行(就像地球围绕太阳运行一样)取决于您之前是否应用了平移变换。

因此,如果您想同时旋转和环绕相机,您需要:

  1. 应用旋转来定位相机
  2. 应用翻译来定位它
  3. 应用旋转以围绕原点旋转相机
  4. (可选)应用平移以在其设置的方向上移动相机,以将其移动到围绕 (0,0,0) 以外的点的轨道上。

例如,如果您想将相机指向一个不是 (0,0,0) 的点,并且在设定的距离处绕该点运行,同时还能够俯仰或偏航相机,事情会变得更加复杂。请参阅此处以获取 WebGL 中的示例。寻找GLViewerBase.prototype.display

红皮书 更详细地介绍了变换。

另请注意gluLookAt,您可以使用它来将相机指向某物,而无需使用旋转。

于 2012-04-08T08:42:17.557 回答
3

n与使用矩阵相比,您可能会发现创建一个存储位置和正交法线以及轴并适当旋转它们的相机类更容易,u例如:v

https://github.com/sgolodetz/hesperus2/blob/master/Shipwreck/MapEditor/GUI/Camera.java

https://github.com/sgolodetz/hesperus2/blob/master/Shipwreck/MapEditor/Math/MathUtil.java

然后你写这样的东西:

if(m_keysDown[TURN_LEFT])
{
    m_camera.rotate(new Vector3d(0,0,1), deltaAngle);
}

当需要为相机设置视图时,您可以:

gl.glLoadIdentity();
glu.gluLookAt(m_position.x, m_position.y, m_position.z,
              m_position.x + m_nVector.x, m_position.y + m_nVector.y, m_position.z + m_nVector.z,
              m_vVector.x, m_vVector.y, m_vVector.z);

如果您想知道如何围绕任意轴旋转(0,0,1),请参阅MathUtil.rotate_about_axis上面的代码。

于 2012-04-06T19:22:30.173 回答
2

如果您不想根据前一帧的相机进行转换,我的建议可能只是丢弃矩阵复合并重新计算每一帧。我认为没有办法用单个矩阵来做你想做的事情,因为它将平移和旋转存储在一起。

我想如果你只想要一个俯仰/偏航相机,只需将这些值存储为两个浮点数,然后基于此重建矩阵。也许类似于伪代码:

onFrameUpdate() {
  newPos = camMatrix * (0,0,speed) //move forward along the camera axis
  pitch += mouse_move_x;
  yaw += mouse_move_y;

  camMatrix = identity.translate(newPos)
  camMatrix = rotate(camMatrix, (0,1,0), yaw)
  camMatrix = rotate(camMatrix, (1,0,0), pitch)
}
于 2012-04-06T19:13:05.673 回答
0

沿世界轴旋转相机,但始终围绕原点旋转。但是,旋转中心应该是相机。有人出主意吗?

我假设矩阵以这种方式存储在内存中(如果矩阵是线性一维数组,数字表示元素索引):

0   1   2   3    //row 0
4   5   6   7    //row 1
8   9   10  11   //row 2
12  13  14  15   //row 3

解决方案

  1. 将相机矩阵的最后一行存储在临时变量中。
  2. 将相机矩阵的最后一行设置为 (0, 0, 0, 1)
  3. 利用camMatrix = yrotMatrix * camMatrix
  4. 从临时变量中恢复相机矩阵的最后一行。
于 2012-04-08T08:52:05.743 回答