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