glutPostRedisplay() 并不总是被调用?

glutPostRedisplay() not always being called?

我有一个使用 OpenGL 显示彩色立方体的程序。我正在使用 freeglut 来显示 OpenGL 实例。该程序应该允许用户在按住鼠标左键的同时用鼠标旋转立方体。每次鼠标移动后,光标应该位于 window 的中心,然后是 glutPostRedisplay();只能被调用它被调用几次然后停止被调用直到你释放鼠标左键。

my_cube.c

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/glew.h>
#include <GL/freeglut.h>

// ----------------------------------------------------------
// Function Prototypes
// ----------------------------------------------------------
void display();
void specialKeys();

// ----------------------------------------------------------
// Global Variables
// ----------------------------------------------------------
double rotate_y=0; 
double rotate_x=0;
float deltaAngleX = 0.0f;
float deltaAngleY = 0.0f;
int xOrigin = -1;
int yOrigin = -1;
int MSAA;
int MouseState = 0;
void enableMultisample(int msaa){
    if(msaa)
    {
        glEnable(GL_MULTISAMPLE);
        glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);

        //detect current settings
        GLint iMultiSample = 0;
        GLint iNumSamples = 0;
        glGetIntegerv(GL_SAMPLE_BUFFERS, &iMultiSample);
        glGetIntegerv(GL_SAMPLES, &iNumSamples);
        //printf("MSAA on, GL_SAMPLE_BUFFERS = %d, GL_SAMPLES = %d\n", iMultiSample, iNumSamples);
    }
    else
    {
        glDisable(GL_MULTISAMPLE);
        //printf("MSAA off\n");
    }
}


void mouseButton(int button, int state, int x, int y) {

    // only start motion if the left button is pressed
    if (button == GLUT_LEFT_BUTTON) {

        // when the button is released
        if (state == GLUT_UP) {
            //rotate_x += deltaAngleX;
            //rotate_y += deltaAngleY;
            xOrigin = -1;
            yOrigin = -1;
            MouseState = 0;
        }
        else  {// state = GLUT_DOWN
            xOrigin = x;
            yOrigin = y;
            MouseState = 1;
        }
    }
}
void mouseMove(int x, int y) {
    // this will only be true when the left button is down
    if (xOrigin >= 0) {
        int midWindowX = 1280 / 2;
        int midWindowY = 720 / 2;

        rotate_y -= (x - midWindowX) / 10.0f;
        rotate_x += (y - midWindowY) / 10.0f;
        glutWarpPointer(midWindowX, midWindowY);

        //glutPostRedisplay();

        printf("Rotate_X = %lf   :   Rotate_Y = %lf   :   Mouse_X = %d   :    Mouse_Y = %d\n", rotate_x, rotate_y, x, y);
        glutPostRedisplay();
    }
}

// ----------------------------------------------------------
// display() Callback function
// ----------------------------------------------------------
void display(){

    //  Clear screen and Z-buffer
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    // Reset transformations
    //
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0f, (1280.0f/720.0f), 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    enableMultisample(MSAA);

    glTranslatef(0, 0, -4);
    glRotatef(180, 1.0, 0.0, 0.0);

    // Rotate when user changes rotate_x and rotate_y
    glRotatef( rotate_x, 1.0, 0.0, 0.0 );
    glRotatef( rotate_y, 0.0, 1.0, 0.0 );

    // Reset rotations
    if(rotate_x == 360.0f || rotate_x > 360.0f || rotate_x == -360 || rotate_x < -360) rotate_x = 0.0f;
    if(rotate_y == 360.0f || rotate_y > 360.0f || rotate_y == -360 || rotate_y < -360) rotate_y = 0.0f;

    //Multi-colored side - FRONT
    glBegin(GL_POLYGON);

    glColor3f( 0.0, 1.0, 0.0 );     glVertex3f( -0.5, -0.5, -0.5 );      // P4 is green
    glColor3f( 0.0, 0.0, 1.0 );     glVertex3f( -0.5,  0.5, -0.5 );      // P3 is blue
    glColor3f( 1.0, 0.0, 1.0 );     glVertex3f(  0.5,  0.5, -0.5 );      // P2 is purple
    glColor3f( 1.0, 0.0, 0.0 );     glVertex3f(  0.5, -0.5, -0.5 );      // P1 is red

    glEnd();

    // White side - BACK
    glBegin(GL_POLYGON);
    glColor3f(   1.0,  1.0, 1.0 );
    glVertex3f(  0.5, -0.5, 0.5 );
    glVertex3f(  0.5,  0.5, 0.5 );
    glVertex3f( -0.5,  0.5, 0.5 );
    glVertex3f( -0.5, -0.5, 0.5 );
    glEnd();

    // Purple side - RIGHT
    glBegin(GL_POLYGON);
    glColor3f(  1.0,  0.0,  1.0 );
    glVertex3f( 0.5, -0.5, -0.5 );
    glVertex3f( 0.5,  0.5, -0.5 );
    glVertex3f( 0.5,  0.5,  0.5 );
    glVertex3f( 0.5, -0.5,  0.5 );
    glEnd();

    // Green side - LEFT
    glBegin(GL_POLYGON);
    glColor3f(   0.0,  1.0,  0.0 );
    glVertex3f( -0.5, -0.5,  0.5 );
    glVertex3f( -0.5,  0.5,  0.5 );
    glVertex3f( -0.5,  0.5, -0.5 );
    glVertex3f( -0.5, -0.5, -0.5 );
    glEnd();

    // Blue side - TOP
    glBegin(GL_POLYGON);
    glColor3f(   0.0,  0.0,  1.0 );
    glVertex3f(  0.5,  0.5,  0.5 );
    glVertex3f(  0.5,  0.5, -0.5 );
    glVertex3f( -0.5,  0.5, -0.5 );
    glVertex3f( -0.5,  0.5,  0.5 );
    glEnd();

    // Red side - BOTTOM
    glBegin(GL_POLYGON);
    glColor3f(   1.0,  0.0,  0.0 );
    glVertex3f(  0.5, -0.5, -0.5 );
    glVertex3f(  0.5, -0.5,  0.5 );
    glVertex3f( -0.5, -0.5,  0.5 );
    glVertex3f( -0.5, -0.5, -0.5 );
    glEnd();

    glFlush();
    glutSwapBuffers();

}

// ----------------------------------------------------------
// specialKeys() Callback Function
// ----------------------------------------------------------
void specialKeys( int key, int x, int y ) {
    if(!MouseState){ 
        //  Right arrow - increase rotation by 5 degree
        if (key == GLUT_KEY_RIGHT)
            rotate_y -= 5;

        //  Left arrow - decrease rotation by 5 degree
        else if (key == GLUT_KEY_LEFT)
            rotate_y += 5;

        else if (key == GLUT_KEY_UP)
            rotate_x -= 5;

        else if (key == GLUT_KEY_DOWN)
            rotate_x += 5;

        //  Request display update
        glutPostRedisplay();
    } 
}

// ----------------------------------------------------------
// main() function
// ----------------------------------------------------------
int main(int argc, char* argv[]){
    for(int i; i<argc; i++){
        char *arg;
        arg = argv[i];
        const char msaaArg[4] = "MSAA";
        char *ret;

        ret = strstr(arg, msaaArg);

        if(ret != NULL){
            MSAA = (intptr_t)argv[i+1];
        }
    }

    //  Initialize GLUT and process user parameters
    glutInit(&argc,argv);

    //  Set Initial Size of window
    glutInitWindowSize(1280, 720);

    // Enable Multisampling
    glutSetOption(GLUT_MULTISAMPLE, 8);

    //  Request double buffered true color window with Z-buffer
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE);

    // Create window
    glewInit();
    glutCreateWindow("");

    // Get OpenGL Version
    printf("Using OpenGL Version: %s\n", glGetString(GL_VERSION)); 
    char title[150];
    const char* temp;
    strcpy(title, "Awesome Cube [OpenGL Version ");
    strcat(title, glGetString(GL_VERSION));
    temp = glGetString(GL_VERSION);
    strcat(title, "]");
    glutSetWindowTitle(title);

    //  Enable Z-buffer depth test
    glEnable(GL_DEPTH_TEST);

    // Enable Backface Culling
    glEnable(GL_CULL_FACE); 

    // Move mouse to the middle of the screen
    glutWarpPointer(1280/2, 720/2);

    // Callback functions
    glutDisplayFunc(display);
    glutSpecialFunc(specialKeys);
    glutMouseFunc(mouseButton);
    glutMotionFunc(mouseMove); 
    //  Pass control to GLUT for events
    glutMainLoop();

    return 0; 
}

glutWarpPointer() 生成新的鼠标移动回调;设置标志并忽略扭曲生成的运动回调:

bool warped = false;
void mouseMove( int x, int y )
{
    if( warped )
    {
        warped = false;
        return;
    }

    // this will only be true when the left button is down
    if( xOrigin >= 0 )
    {
        int midWindowX = 1280 / 2;
        int midWindowY = 720 / 2;

        rotate_y -= ( x - midWindowX ) / 10.0f;
        rotate_x += ( y - midWindowY ) / 10.0f;

        warped = true;
        glutWarpPointer( midWindowX, midWindowY );

        printf( "Rotate_X = %lf   :   Rotate_Y = %lf   :   Mouse_X = %d   :    Mouse_Y = %d\n", rotate_x, rotate_y, x, y );
        glutPostRedisplay();
    }
}

总计:

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>

// ----------------------------------------------------------
// Function Prototypes
// ----------------------------------------------------------
void display();
void specialKeys();

// ----------------------------------------------------------
// Global Variables
// ----------------------------------------------------------
double rotate_y = 0;
double rotate_x = 0;
float deltaAngleX = 0.0f;
float deltaAngleY = 0.0f;
int xOrigin = -1;
int yOrigin = -1;
int MouseState = 0;

void mouseButton( int button, int state, int x, int y )
{
    // only start motion if the left button is pressed
    if( button == GLUT_LEFT_BUTTON )
    {
        // when the button is released
        if( state == GLUT_UP )
        {
            //rotate_x += deltaAngleX;
            //rotate_y += deltaAngleY;
            xOrigin = -1;
            yOrigin = -1;
            MouseState = 0;
        }
        else
        {
            // state = GLUT_DOWN
            xOrigin = x;
            yOrigin = y;
            MouseState = 1;
        }
    }
}

bool warped = false;
void mouseMove( int x, int y )
{
    if( warped )
    {
        warped = false;
        return;
    }

    // this will only be true when the left button is down
    if( xOrigin >= 0 )
    {
        int midWindowX = 1280 / 2;
        int midWindowY = 720 / 2;

        rotate_y -= ( x - midWindowX ) / 10.0f;
        rotate_x += ( y - midWindowY ) / 10.0f;

        warped = true;
        glutWarpPointer( midWindowX, midWindowY );

        printf( "Rotate_X = %lf   :   Rotate_Y = %lf   :   Mouse_X = %d   :    Mouse_Y = %d\n", rotate_x, rotate_y, x, y );
        glutPostRedisplay();
    }
}

// ----------------------------------------------------------
// display() Callback function
// ----------------------------------------------------------
void display()
{
    //  Clear screen and Z-buffer
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // Reset transformations
    //
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0f, ( 1280.0f / 720.0f ), 0.1f, 100.0f );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glTranslatef( 0, 0, -4 );
    glRotatef( 180, 1.0, 0.0, 0.0 );

    // Rotate when user changes rotate_x and rotate_y
    glRotatef( rotate_x, 1.0, 0.0, 0.0 );
    glRotatef( rotate_y, 0.0, 1.0, 0.0 );

    // Reset rotations
    if( rotate_x == 360.0f || rotate_x > 360.0f || rotate_x == -360 || rotate_x < -360 ) rotate_x = 0.0f;
    if( rotate_y == 360.0f || rotate_y > 360.0f || rotate_y == -360 || rotate_y < -360 ) rotate_y = 0.0f;

    //Multi-colored side - FRONT
    glBegin( GL_POLYGON );

    glColor3f( 0.0, 1.0, 0.0 );     glVertex3f( -0.5, -0.5, -0.5 );      // P4 is green
    glColor3f( 0.0, 0.0, 1.0 );     glVertex3f( -0.5, 0.5, -0.5 );      // P3 is blue
    glColor3f( 1.0, 0.0, 1.0 );     glVertex3f( 0.5, 0.5, -0.5 );      // P2 is purple
    glColor3f( 1.0, 0.0, 0.0 );     glVertex3f( 0.5, -0.5, -0.5 );      // P1 is red

    glEnd();

    // White side - BACK
    glBegin( GL_POLYGON );
    glColor3f( 1.0, 1.0, 1.0 );
    glVertex3f( 0.5, -0.5, 0.5 );
    glVertex3f( 0.5, 0.5, 0.5 );
    glVertex3f( -0.5, 0.5, 0.5 );
    glVertex3f( -0.5, -0.5, 0.5 );
    glEnd();

    // Purple side - RIGHT
    glBegin( GL_POLYGON );
    glColor3f( 1.0, 0.0, 1.0 );
    glVertex3f( 0.5, -0.5, -0.5 );
    glVertex3f( 0.5, 0.5, -0.5 );
    glVertex3f( 0.5, 0.5, 0.5 );
    glVertex3f( 0.5, -0.5, 0.5 );
    glEnd();

    // Green side - LEFT
    glBegin( GL_POLYGON );
    glColor3f( 0.0, 1.0, 0.0 );
    glVertex3f( -0.5, -0.5, 0.5 );
    glVertex3f( -0.5, 0.5, 0.5 );
    glVertex3f( -0.5, 0.5, -0.5 );
    glVertex3f( -0.5, -0.5, -0.5 );
    glEnd();

    // Blue side - TOP
    glBegin( GL_POLYGON );
    glColor3f( 0.0, 0.0, 1.0 );
    glVertex3f( 0.5, 0.5, 0.5 );
    glVertex3f( 0.5, 0.5, -0.5 );
    glVertex3f( -0.5, 0.5, -0.5 );
    glVertex3f( -0.5, 0.5, 0.5 );
    glEnd();

    // Red side - BOTTOM
    glBegin( GL_POLYGON );
    glColor3f( 1.0, 0.0, 0.0 );
    glVertex3f( 0.5, -0.5, -0.5 );
    glVertex3f( 0.5, -0.5, 0.5 );
    glVertex3f( -0.5, -0.5, 0.5 );
    glVertex3f( -0.5, -0.5, -0.5 );
    glEnd();

    glFlush();
    glutSwapBuffers();
}

// ----------------------------------------------------------
// specialKeys() Callback Function
// ----------------------------------------------------------
void specialKeys( int key, int x, int y )
{
    if( !MouseState )
    {
        //  Right arrow - increase rotation by 5 degree
        if( key == GLUT_KEY_RIGHT )
            rotate_y -= 5;

        //  Left arrow - decrease rotation by 5 degree
        else if( key == GLUT_KEY_LEFT )
            rotate_y += 5;

        else if( key == GLUT_KEY_UP )
            rotate_x -= 5;

        else if( key == GLUT_KEY_DOWN )
            rotate_x += 5;

        //  Request display update
        glutPostRedisplay();
    }
}

// ----------------------------------------------------------
// main() function
// ----------------------------------------------------------
int main( int argc, char* argv[] )
{
    //  Initialize GLUT and process user parameters
    glutInit( &argc, argv );

    //  Set Initial Size of window
    glutInitWindowSize( 1280, 720 );

    //  Request double buffered true color window with Z-buffer
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );

    // Create window
    glewInit();
    glutCreateWindow( "" );

    //  Enable Z-buffer depth test
    glEnable( GL_DEPTH_TEST );

    // Enable Backface Culling
    glEnable( GL_CULL_FACE );

    // Move mouse to the middle of the screen
    glutWarpPointer( 1280 / 2, 720 / 2 );

    // Callback functions
    glutDisplayFunc( display );
    glutSpecialFunc( specialKeys );
    glutMouseFunc( mouseButton );
    glutMotionFunc( mouseMove );
    //  Pass control to GLUT for events
    glutMainLoop();

    return 0;
}