我正在尝试旋转 3d 对象,但在 for 循环中应用变换时它不会更新。
对象跳到最后一个位置。
如果 3d 对象不会在 for 循环中更新,如何在一系列更新中更新它的位置?
我认为您对 OpenGL 为您做了什么有错误的理解。我将尝试概述:
- Send vertex data to the GPU (once)
(this does only specify the (standard) shape of the object)
- Create matrices to rotate, translate or transform the object (per update)
- Send the matrices to the shader (per update)
(The shader then calculates the screen position using the original
vertex position and the transformation matrix)
- Tell OpenGL to draw the bound vertices (per update)
想象一下像 Web 客户端一样使用 OpenGL 进行编程 - 仅指定请求(更改矩阵和绑定内容)是不够的,您需要显式发送请求(发送转换数据并告诉 OpenGL 绘制)以接收答案(具有屏幕上的对象。)
可以从循环中绘制动画。
for ( ...) {
edit_transformation();
draw();
glFlush(); // maybe glutSwapBuffers() if you use GLUT
usleep(100); // not standard C, bad
}
你画,你冲洗/交换以确保你刚刚画的东西被发送到屏幕上,然后你就睡觉了。
但是,不建议在交互式应用程序中执行此操作。主要原因是当你在这个循环中时,没有其他东西可以运行。您的应用程序将无响应。
这就是为什么窗口系统是基于事件的。每隔几毫秒,窗口系统就会 ping 您的应用程序,以便您可以更新您的状态,例如做动画。这是空闲功能。当你的程序状态改变时,你告诉窗口系统你想再次绘制。然后由窗口系统调用你的显示函数。当系统告诉您时,您执行 OpenGL 调用。
如果您使用 GLUT 与窗口系统进行通信,则如下所示。其他库(如 GLFW)具有相同的功能。
int main() {
... // Create window, set everything up.
glutIdleFunc(update); // Register idle function
glutDisplayFunc(display); // Register display function
glutMainLoop(); // The window system is in charge from here on.
}
void update() {
edit_transformation(); // Update your models
glutPostRedisplay(); // Tell the window system that something changed.
}
void display() {
draw(); // Your OpenGL code here.
glFlush(); // or glutSwapBuffers();
}
只是调用 glTranslate、glRotate 等不会改变屏幕上的内容。为什么?因为 OpenGL 是一个简单的绘图 API,而不是场景图。它只知道绘制到像素帧缓冲区的点、线和三角形。而已。你想改变屏幕上的某些东西,你必须重新绘制它,即清除图片,然后重新绘制它。
顺便说一句:您不应该使用专用循环来实现动画(for、while 和 do while 都不行)。而是在空闲处理程序中执行动画并发出重绘事件。