C++ 带有移动对象的gluLookAt和glFrustum

C++ 带有移动对象的gluLookAt和glFrustum,c++,opengl,C++,Opengl,原始问题/代码 我正在微调3D对象的渲染,并尝试使用gluLookAt实现跟随对象的摄影机,因为对象的中心y位置在达到最大高度后不断增加。下面是我设置ModelView和投影矩阵的代码部分: float diam = std::max(_framesize, _maxNumRows); float centerX = _framesize / 2.0f; float centerY = _maxNumRows / 2.0f + _cameraOffset; float centerZ = 0.0

原始问题/代码

我正在微调3D对象的渲染,并尝试使用
gluLookAt
实现跟随对象的摄影机,因为对象的中心y位置在达到最大高度后不断增加。下面是我设置ModelView和投影矩阵的代码部分:

float diam = std::max(_framesize, _maxNumRows);
float centerX = _framesize / 2.0f;
float centerY = _maxNumRows / 2.0f + _cameraOffset;
float centerZ = 0.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(centerX - diam,
          centerX + diam,
          centerY - diam,
          centerY + diam,
          diam,
          40 * diam);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0., 0., 2. * diam, centerX, centerY, centerZ, 0, 1.0, 0.0);
当前,该对象显示得非常远,并且似乎会进一步移回屏幕(-z)并向下(-y),直到最终消失

我做错了什么?如何使曲面显示在屏幕中央,占据全视图,并在对象更新时随对象移动


更新代码和当前版本

这是我当前的代码,它现在将对象置于死点并填充我的窗口

float diam = std::max(_framesize, _maxNumRows);
float centerX = _framesize / 2.0f;
float centerY = _maxNumRows / 2.0f + _cameraOffset;
float centerZ = 0.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(centerX - diam,
          centerX,
          centerY - diam,
          centerY,
          1.0,
          1.0 +  4 * diam);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(centerX, _cameraOffset, diam, centerX, centerY, centerZ, 0, 1.0, 0.0);

我仍然有一个问题,当被观察的物体开始移动时,它并没有完全居中。当它更新时,它看起来几乎向上抖动了一个像素,然后向下抖动了2个像素。最终,对象将离开当前视图。如何解决此抖动?

glFrustum
生成的透视投影矩阵定义了一个相机空间(作为输入的顶点空间),相机位于原点。您正在尝试使用不在原点的摄影机创建透视矩阵
glFrustum
无法做到这一点,因此您尝试的方法根本无法实现

有几种方法可以在相机不在原点的情况下生成透视矩阵。但是这样做真的没有意义

通常处理移动摄影机的方法是,简单地添加从世界空间到透视投影的摄影机空间的变换。这只是相对于相机旋转和平移世界。这就是gluLookAt的工作。但是你的参数也错了


前三个值是相机的世界空间位置。接下来的三个应该是相机应该看到的世界空间位置(对象的位置)。

Nicol Bolas的回答基本上说明了你做错了什么,所以我将跳过这一点。您正在寻找解决方案,而不是告诉您哪里出了问题,所以让我们直接开始

这是我用于投影矩阵的代码:

glViewport(0, 0, mySize.x, mySize.y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy, (float)mySize.x/(float)mySize.y, nearPlane, farPlane);
用一些词来描述它: glViewport设置openGL在窗口内部显示位置的大小和位置。不知道为什么,我也经常把它包括在投影更新中。若你们像我一样使用它,mySize是指定窗口尺寸的2D向量,openGL渲染区域将覆盖整个窗口。您应该熟悉接下来的两个调用,最后是
glupperspective
。第一个参数是“Y轴上的视野”。它以度为单位指定了你将看到的角度,我只使用了45度。虽然它可以用于缩放,但我更喜欢让相机操作。第二个参数是方面。它处理的是,如果渲染正方形,并且窗口大小不在1:1的比例,它仍然是正方形。第三个是近剪裁平面,比这更接近摄影机的几何体不会被渲染,和远平面一样,但相反,它设置了几何体渲染的最大距离

这是modelview矩阵的代码

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(  camera.GetEye().x,camera.GetEye().y,camera.GetEye().z,
camera.GetLookAt().x,camera.GetLookAt().y,camera.GetLookAt().z,
camera.GetUp().x,camera.GetUp().y,camera.GetUp().z);
还有一点你应该知道:同样,你可以使用前两个调用,所以我们跳到
gluLookAt
。我有一个摄像头类,可以处理所有的移动,旋转,诸如此类的事情。Eye、LookAt和Up是3D向量,这三个向量实际上是相机指定的所有内容。眼睛是相机的位置,它在空间中的位置。LookAt是您正在查看的对象的位置,或者更好地说是您正在查看的三维空间中的点,因为它实际上可以位于任何位置,而不仅仅是中心对象。如果你担心什么是上方向向量,这很简单。它是向量到向量(注视眼睛),但由于这样的向量数量是无限的,所以必须指定一个。如果您的相机位于
(0,0,0)
,并且您正在观看
(0,0,-1)
,并且您想站在腿上,则上方向向量将是
(0,1,0)
。如果您想倒立,请使用
(0,-1,0)
。如果你不明白,就写评论吧

由于没有任何camera类,因此需要单独存储这3个向量。我相信你们有点像你们移动的3D物体的中心。将该位置设置为每次更新后查看。同样在初始化阶段(制作3D对象时),选择相机的位置和上方向向量。每次更新对象位置后,以相同的方式更新摄影机位置。如果在Y轴上将对象向上移动1点,请对摄影机位置执行相同的操作。如果不希望旋转摄影机,则上方向向量保持不变。在每次这样的更新之后,使用更新的向量调用
gluLookAt

更新帖子:
如果没有更大的参照系,我真的不知道发生了什么(但我无论如何也不想知道)。我很少对什么事情感到好奇。如果“中心”是存储对象位置的三维矢量,为什么要将此对象的中心设置为窗口的右上角?如果它是中心,你应该在
glOrtho
的第2和第4个参数中也有+diam,如果这样做会让事情变得糟糕,那么你对变量使用了错误的名称,或者在这之前做了一些错误的事情。你在更新的帖子中设置了注视位置,但我不明白你为什么要用这些参数来观察眼睛。在
gluLookAt
中,前3个参数应该是:
centerX、centerY、centerZ-diam
。这将使您的相机位于与对象相同的X和Y位置,但您将从距离
diam

沿Z轴查看它,您的问题在于理解