使用GLFW执行连续动画



我想使用OpenGL实现一个可以通过鼠标点击启动和暂停的动画。由于我目前使用的是GLFW,所以GLUT中的函数不再适用。

在GLUT中,可以这样实现:

void windowMouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
// start
glutIdleFunc(idleFunction);
}
else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
// pause
glutIdleFunc(NULL);
}
}

然而,glutIdleFunc()在GLFW中不起作用。我只是写了一个编码框架来执行我的目标,但在寻找合适的函数来代替glutIdleFunc()时陷入了困境。

void mouse_button_callback(GLFWwindow* window, int button, int action, int mode)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
// start
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
// pause
}
}

GLFW中是否有功能可以替代之前的功能?或者有任何方法来执行连续动画与GLFW?

创意glfwPostEmptyEvent()glfwWaitEventsTimeout():

// g++ main.cpp `pkg-config --cflags --libs glfw3 gl`
#include <GLFW/glfw3.h>
void (*idleFunc)(GLFWwindow*) = nullptr;
void idle( GLFWwindow* aWindow )
{
static float angle = 0.0f;
static double prvTime = glfwGetTime();
const double curTime = glfwGetTime();
const double dt = (curTime - prvTime);
prvTime = curTime;
angle += 60.0 * dt;
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
glRotatef( angle, 0, 0, 1 );
glBegin(GL_TRIANGLES);
glColor3ub( 0, 255, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f(  0.5, -0.5 );
glVertex2f(  0.0,  0.5 );
glEnd();
glPopMatrix();
glfwSwapBuffers( aWindow );
}
void display( GLFWwindow* aWindow )
{
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3ub( 255, 0, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f(  0.5, -0.5 );
glVertex2f(  0.0,  0.5 );
glEnd();
glfwSwapBuffers( aWindow );
}
void button( GLFWwindow* window, int button, int action, int mode )
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
idleFunc = idle;
glfwPostEmptyEvent();
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
idleFunc = nullptr;
glfwPostEmptyEvent();
}
}
int main( int, char** )
{
glfwInit();
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
glfwSetMouseButtonCallback( window, button );
while( !glfwWindowShouldClose( window ) )
{
if(idleFunc)
{
idleFunc(window);
glfwWaitEventsTimeout(0.016);
}
else
{
display(window);
glfwWaitEvents();
}
}
glfwTerminate();
}

glfwPostEmptyEvent()main()glfwWindowShouldClose()循环的结构可以让你模拟glutPostRedisplay()的行为,glfwWaitEventsTimeout()可以让idleFunc()(如果有的话)每16毫秒左右运行一次。