使用 OpenGL 进行正交投影以及如何实现相机或物体在空间中的移动
Posted
技术标签:
【中文标题】使用 OpenGL 进行正交投影以及如何实现相机或物体在空间中的移动【英文标题】:Orthographic Projection with OpenGL and how to implement camera or object movement in space 【发布时间】:2013-11-27 16:13:18 【问题描述】:我已经使用 GL_POLYGON 制作了一个带有显示列表的立方体。我已经在坐标的原点初始化了它,这意味着在 (0,0,0) 中。在我在 glutDisplayFunc 中调用的显示函数中,我使用了代码:
glLoadIdentity();
glOrtho(0,0,0,0,1,1);
glMatrixMode(GL_MODELVIEW);
我想通过 glOrtho 使用正交投影。好吧,我的问题是:考虑到我的窗口大小为 600x600,我仍然可以看到我的立方体是否正常?
此外,我想要一些关于如何使用相关 OpenGL 函数移动我的立方体或我的相机的指南。假设我想将我的相机向后移动(到 z 轴)或我的立方体向前移动(到 - z 轴)。我该怎么做?
【问题讨论】:
您的正交投影矩阵不正常。您正在将无限小的空间投影到图像平面上。你应该什么都看不到。 【参考方案1】:首先你还需要在调用glOrtho()
之前将glMatrixMode()
设置为GL_PROJECTION
,所以它看起来应该是这样的。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(...); // Replace ... with your values
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
要移动屏幕,您只需调用以下一个或多个函数。
glTranslate*() glRotate*() glScale*()您可以点击以上链接了解每个函数的作用方式和作用。但基本上:
glTranslate*()
平移/移动当前选定的矩阵。
glRotate*()
旋转当前选定的矩阵。
glScale*()
缩放当前选定的矩阵。
您还可以使用glPushMatrix() 和glPopMatrix() 来压入和弹出当前矩阵堆栈。
额外
另外请注意,您使用的是旧的和已弃用的函数。您不应该使用它们,而是现在假设您计算并创建自己的矩阵堆栈。
编辑
相机和物体
基本上,您可以通过结合上述功能来做到这一点。听起来可能比实际更难。
我将创建一个包含 1 个摄像头和 2 个对象的示例,主要是为了让您了解它的工作原理。
void render()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// The Camera Rotations & Translation
glRotatef(camera_pitch, -1f, 0f, 0f);
glRotatef(camera_yaw, 0f, 1f, 0f);
glTranslate(-camera_x, -camera_y, -camera_z);
// Object 1
glPushMatrix();
glRotatef(...);
glTranslate(...);
// Render Object 1
glPopMatrix();
// Object 2
glPushMatrix();
glRotatef(...);
glTranslate(...);
// Render Object 2
glPopMatrix();
再次将 ... 替换为您自己的值。
需要负向平移相机坐标的原因是因为为什么不移动相机,我们实际上是在“推动”(平移等)一切远离相机/中心的东西(从而相机始终位于中心)。
重要旋转后平移或平移后旋转的顺序很重要。当需要对相机进行变换时,您总是需要先旋转然后平移。
编辑
gluLookAt ?
gluLookAt 100% 相同,就像在我的示例中一样。
例子:
// The Camera Rotations & Translation
glRotatef(camera_pitch, -1f, 0f, 0f);
glRotatef(camera_yaw, 0f, 1f, 0f);
glTranslate(-camera_x, -camera_y, -camera_z);
这是我自己的函数,它与gluLookAt
100% 相同。 我怎么知道的?因为我看了原来的gluLookAt
函数,然后做了下面这个函数。
void lookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz)
float dx = eyex - centerx;
float dy = eyey - centery;
float dz = eyez - centerz;
float pitch = (float) Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));
float yaw = (float) Math.atan2(dz, dx);
pitch = -pitch;
yaw = yaw - 1.57079633f;
// Here you could call glLoadIdentity() if you want to reset the matrix
// glLoadIdentity();
glRotatef(Math.toDegrees(pitch), -1f, 0f, 0f);
glRotatef(Math.toDegrees(yaw), 0f, 1f, 0f);
glTranslatef(-eyex, -eyey, -eyez);
您可能需要更改 Math.*
调用,因为上面的代码不是用 C 编写的。
【讨论】:
相机怎么样?如果我想将相机移动到 z 轴的正方向,我应该调用什么函数?让我想将立方体留在坐标原点。 如果我没记错的话,glTranslate,glRotate,glScale 是用于对象的吗?不只是在您编写的这段代码中,我的意思是无处不在。 Kinda, glTranslate,glRotate,glScale 用于几何变换。因此,如果为什么要应用相机的反向 x、y、z、偏航、滚动等。在其他一切之前,它将一切都转换成一个点,就像通过相机看一样。 如果我只想移动相机怎么办。我不想在这些函数中应用反向的东西,因为我想看看 gluLookat 是如何工作的。 @johnjohngluLookAt
100% 像我上面的例子一样工作。看看编辑后的答案,我添加了gluLookAt
函数的工作原理。以上是关于使用 OpenGL 进行正交投影以及如何实现相机或物体在空间中的移动的主要内容,如果未能解决你的问题,请参考以下文章