【问题标题】:Perform continuous animation with GLFW使用 GLFW 执行连续动画
【发布时间】:2021-12-06 13:34:15
【问题描述】:

我想使用 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 执行连续动画?

【问题讨论】:

  • 你见过Putting it together吗? glfw 程序的基本流程是一个while (!glfwWindowShouldClose(window)) 循环。

标签: opengl glut glfw


【解决方案1】:

通过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 毫秒左右运行一次.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-20
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多