C++ 在 OpenGL 中设置相机
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1672926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting up a camera in OpenGL
提问by Dalin Seivewright
I've been working on a game engine for awhile. I've started out with 2D Graphics with just SDL but I've slowly been moving towards 3D capabilities by using OpenGL. Most of the documentation I've seen about "how to get things done," use GLUT, which I am not using.
我一直在研究游戏引擎一段时间。我从仅使用 SDL 的 2D 图形开始,但我已经通过使用 OpenGL 逐渐转向 3D 功能。我见过的大多数关于“如何完成工作”的文档都使用 GLUT,但我没有使用。
The question is how do I create a "camera" in OpenGL that I could move around a 3D environment and properly display 3D models as well as sprites (for example, a sprite that has a fixed position and rotation). What functions should I be concerned with in order to setup a camera in OpenGL camera and in what order should they be called in?
问题是如何在 OpenGL 中创建一个“相机”,我可以在 3D 环境中移动并正确显示 3D 模型和精灵(例如,具有固定位置和旋转的精灵)。为了在 OpenGL 相机中设置相机,我应该关注哪些功能以及应该以什么顺序调用它们?
Here is some background information leading up to why I want an actual camera.
以下是一些导致我想要一台实际相机的背景信息。
To draw a simple sprite, I create a GL texture from an SDL surface and I draw it onto the screen at the coordinates of (SpriteX-CameraX) and (SpriteY-CameraY). This works fine but when moving towards actual 3D models it doesn't work quite right. The cameras location is a custom vector class (i.e. not using the standard libraries for it) with X, Y, Z integer components.
为了绘制一个简单的精灵,我从 SDL 表面创建了一个 GL 纹理,并将其绘制到屏幕上的坐标 (SpriteX-CameraX) 和 (SpriteY-CameraY) 上。这很好用,但是当转向实际的 3D 模型时,它工作得不太正确。相机位置是一个自定义矢量类(即不使用标准库),具有 X、Y、Z 整数分量。
I have a 3D cube made up of triangles and by itself, I can draw it and rotate it and I can actually move the cube around (although in an awkward way) by passing in the camera location when I draw the model and using that components of the location vector to calculate the models position. Problems become evident with this approach when I go to rotate the model though. The origin of the model isn't the model itself but seems to be the origin of the screen. Some googling tells me I need to save the location of the model, rotate it about the origin, then restore the model to its origal location.
我有一个由三角形组成的 3D 立方体,我可以绘制它并旋转它,我实际上可以通过在绘制模型时传入相机位置并使用该组件来移动立方体(尽管以一种笨拙的方式)的位置向量来计算模型的位置。但是,当我旋转模型时,这种方法的问题变得明显。模型的起源不是模型本身,而是屏幕的起源。一些谷歌搜索告诉我我需要保存模型的位置,围绕原点旋转它,然后将模型恢复到其原始位置。
Instead of passing in the location of my camera and calculating where things should be being drawn in the Viewport by calculating new vertices, I figured I would create an OpenGL "camera" to do this for me so all I would need to do is pass in the coordinates of my Camera object into the OpenGL camera and it would translate the view automatically. This tasks seems to be extremely easy if you use GLUT but I'm not sure how to set up a camera using just OpenGL.
与其传递我的相机的位置并通过计算新顶点来计算应在视口中绘制的位置,我想我会创建一个 OpenGL“相机”来为我做这件事,所以我需要做的就是传入我的相机对象的坐标到 OpenGL 相机,它会自动转换视图。如果您使用 GLUT,此任务似乎非常简单,但我不确定如何仅使用 OpenGL 设置相机。
EDIT #1 (after some comments):Following some suggestion, here is the update method that gets called throughout my program. Its been updated to create perspective and view matrices. All drawing happens before this is called. And a similar set of methods is executed when OpenGL executes (minus the buffer swap). The x,y,z coordinates are straight an instance of Camera and its location vector. If the camera was at (256, 32, 0) then 256, 32 and 0 would be passed into the Update method. Currently, z is set to 0 as there is no way to change that value at the moment. The 3D model being drawn is a set of vertices/triangles + normals at location X=320, Y=240, Z=-128. When the program is run, this is what is drawn in FILLmode and then in LINEmode and another one in FILL after movement, when I move the camera a little bit to the right. It likes like may Normals may be the cause, but I think it has moreso to do with me missing something extremely important or not completely understanding what the NEAR and FAR parameters for glFrustum actually do.
编辑 #1(经过一些评论):根据一些建议,这里是在我的程序中调用的更新方法。它已更新以创建透视和视图矩阵。所有绘图都发生在调用此之前。并且在 OpenGL 执行时会执行一组类似的方法(减去缓冲区交换)。x,y,z 坐标是 Camera 及其位置向量的一个实例。如果相机位于 (256, 32, 0) 则 256, 32 和 0 将被传递到 Update 方法中。目前,z 设置为 0,因为目前无法更改该值。正在绘制的 3D 模型是一组顶点/三角形 + 位于 X=320、Y=240、Z=-128 位置的法线。当程序运行时,这是在FILL模式下绘制的,然后在LINE模式下绘制,另一个在移动后填充,当我将相机向右移动一点时。它喜欢可能 Normals 可能是原因,但我认为这与我错过了一些非常重要的东西或没有完全理解 glFrustum 的 NEAR 和 FAR 参数实际上做了什么有关。
Before I implemented these changes, I was using glOrtho and the cube rendered correctly. Now if I switch back to glOrtho, one face renders (Green) and the rotation is quite weird - probably due to the translation. The cube has 6 different colors, one for each side. Red, Blue, Green, Cyan, White and Purple.
在我实施这些更改之前,我使用了 glOrtho 并且正确渲染了立方体。现在,如果我切换回 glOrtho,一张脸呈现(绿色)并且旋转非常奇怪 - 可能是由于平移。立方体有 6 种不同的颜色,每边一种。红色、蓝色、绿色、青色、白色和紫色。
int VideoWindow::Update(double x, double y, double z)
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum(0.0f, GetWidth(), GetHeight(), 0.0f, 32.0f, 192.0f);
glMatrixMode( GL_MODELVIEW );
SDL_GL_SwapBuffers();
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(0, 1.0f, 0.0f, 0.0f);
glRotatef(0, 0.0f, 1.0f, 0.0f);
glRotatef(0, 0.0f, 0.0f, 1.0f);
glTranslated(-x, -y, 0);
return 0;
}
EDIT FINAL: The problem turned out to be an issue with the Near and Far arguments of glFrustum and the Z value of glTranslated. While change the values has fixed it, I'll probably have to learn more about the relationship between the two functions.
编辑最终:问题原来是 glFrustum 的 Near 和 Far 参数和 glTranslated 的 Z 值的问题。虽然更改值已修复它,但我可能需要更多地了解这两个函数之间的关系。
采纳答案by tsalter
You need a view matrix, and a projection matrix. You can do it one of two ways:
您需要一个视图矩阵和一个投影矩阵。您可以通过以下两种方式之一进行操作:
Load the matrix yourself, using
glMatrixMode()
andglLoadMatrixf()
, after you use your own library to calculate the matrices.Use combinations of
glMatrixMode(GL_MODELVIEW)
andglTranslate()
/glRotate()
to create your view matrix, andglMatrixMode(GL_PROJECTION)
withglFrustum()
to create your projection matrix. Remember - your view matrix is the negative translation of your camera's position (As it's where you should move the worldto relative to the camera origin), as well as any rotations applied (pitch/yaw).
在您使用自己的库计算矩阵之后,使用
glMatrixMode()
和自己加载glLoadMatrixf()
矩阵。使用
glMatrixMode(GL_MODELVIEW)
和glTranslate()
/ 的组合glRotate()
来创建您的视图矩阵,并glMatrixMode(GL_PROJECTION)
使用与glFrustum()
来创建您的投影矩阵。请记住 - 您的视图矩阵是相机位置(因为它是您应该将世界移动到相对于相机原点的位置)以及应用的任何旋转(俯仰/偏航)的负平移。
Hope this helps, if I had more time I'd write you a proper example!
希望这会有所帮助,如果我有更多时间,我会为您写一个适当的示例!
回答by fa.
You have to do it using the matrix stack as for object hierarchy,
对于对象层次结构,您必须使用矩阵堆栈来执行此操作,
but the camera is inside the hierarchy so you have to put the inverse transform on the stack before drawing the objects as openGL only uses the matrix from 3D to camera.
但是相机位于层次结构内,因此您必须在绘制对象之前将逆变换放在堆栈上,因为 openGL 仅使用从 3D 到相机的矩阵。
回答by Ketan
If you have not checked then may be looking at following project would explain in detail what "tsalter" wrote in his post.
如果您还没有检查,那么可能正在查看以下项目会详细解释“tsalter”在他的帖子中所写的内容。
Camerafrom OGL SDK (CodeColony)
来自 OGL SDK (CodeColony) 的相机
Also look at Red book for explanation on viewing and how does model-view and projection matrix will help you create camera. It starts with good comparison between actual camera and what corresponds to OpenGL API. Chapter 3 - Viewing
另请参阅 Red book 以了解有关查看以及模型视图和投影矩阵如何帮助您创建相机的说明。它从实际相机和对应于 OpenGL API 的东西之间的良好比较开始。第 3 章 - 查看