Search code examples
copenglglutfreeglut

glutPostRedisplay() not always being called?


I have a program in which a coloured cube is displayed with OpenGL. I am using freeglut to display the OpenGL instance. The program is supposed to allow the user to rotate the cube with their mouse while they are holding their left mouse button down. After each mouse movement the cursor is supposed to be centered in the window then glutPostRedisplay(); is meant to be called only it gets called a few times then stops getting called until you release the left mouse button.

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; 
}

Solution

  • glutWarpPointer() generates a new mouse motion callback; set a flag and ignore warp-generated motion callbacks:

    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();
        }
    }
    

    All together:

    #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;
    }