Search code examples
openglcodeblocksglut

How to use glutSpecialFunc correctly?


I wanna make my square go up when UO is pressed.

void displayScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glTranslatef(0,x,0);

    glBegin(GL_QUADS);
    glVertex3f(-0.4,-0.4, -5.0);
    glVertex3f( 0.4,-0.4, -5.0);
    glVertex3f( 0.4, 0.4, -5.0);
    glVertex3f(-0.4, 0.4, -5.0);
    glEnd();

    //x = x + 0.1;

    glutSwapBuffers();
}

I'm using gluSpecialFunc.

void ProcessSpecialKeys(unsigned char key, int x, int y)
{
    if (key == GLUT_KEY_UP)
    {
        x = x + 0.1;
    }

    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 480);
    glutInitWindowPosition(0,0);
    glutCreateWindow("OpenGL Window");
    init();
    glutDisplayFunc(displayScene);
    glutSpecialFunc(ProcessSpecialKeys);
    //glutKeyboardFunc(ProcessKeys);
    glutMainLoop();
    return 0;
}

When I leave x+=0.1 in the displayScene, the square goes up when I press any key.

Am I using glutSpecialFunc incorrectly? Because I used it before and it worked normally. What am I missing?


Solution

  • glutSpecialFunc is not invoked continuously when a key is held down. The callback is called once when a key is pressed.
    freeglut provides the glutSpecialUpFunc callback which is called when a key is released.

    Set a state when UP is pressed and reset the state when UP is released:

    int main(int argc, char** argv)
    {
        // [...]
        glutSpecialFunc(ProcessSpecialKeys);
        glutSpecialUpFunc(ReleaseSpecialKeys);
        // [...]
    }
    
    int keyUpPressed = 0;
    
    void ProcessSpecialKeys(unsigned char key, int x, int y)
    {
        if (key == GLUT_KEY_UP)
            keyUpPressed = 1;
    }
    
    void ReleaseSpecialKeys(unsigned char key, int x, int y)
    {
        if (key == GLUT_KEY_UP)
            keyUpPressed = 0;
    }
    

    Change the x dependent on the state of keyUpPressed. Continuously redraw the scene by calling glutPostRedisplay in displayScene

    void displayScene(void)
    {
        if (keyUpPressed)
            x += 0.1;
    
        // [...]
    
        glutSwapBuffers();
        glutPostRedisplay();
    }