OpenGL - How to draw multiple different 2D shapes using pop-up menu? - opengl

I'm trying to make a simple openGL application which creates shapes using mouse clicks. The shape required is selected using a pop-up menu opened using the right mouse button. Currently I have rectangle working and also a simple paint-esque function using points. They disappear once redrawn but that's a problem I'll worry about in the future.
Currently I'm trying to also implement a Line function as a menu option. I have the below code in place but when I select the Line option from the pop-up menu and click two points it doesn't seem to draw a line as expected. Can anyone point out where I'm going wrong here?
GLfloat x1, x2, y1, y2;
GLfloat x_Src, y_Src, x_Dest, y_Dest;
//used to change colour (To be implemented)
static int colour;
void menu(int);
void display(void)
{
glClearColor(0.0, 2.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(3.0);
glColor3f(1.0, 0.0, 0.0);
//Rectangle vertices
glBegin(GL_POLYGON);
glVertex2f(x1, y1);
glVertex2f(x1, y2);
glVertex2f(x2, y2);
glVertex2f(x2, y1);
glEnd();
//Line vertices
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINE);
glVertex2f(x_Src, y_Src);
glVertex2f(x_Dest, y_Dest);
glEnd();
glFlush();
return;
}
void MyRect(GLint button, GLint state, GLint x, GLint y)
{
static int first = 1;
if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)
{
if (first)
{
//first point in terms of window size
x1 = (x - 250.0) / 250.0;
y1 = -(y - 250) / 250.0;;
}
else
{
//second point in terms of window size
x2 = (x - 250.0) / 250.0;
y2 = -(y - 250) / 250.0;
glutPostRedisplay();
}
first = !first;
}
return;
}
void MyLine(GLint button, GLint state, GLint x, GLint y)
{
static int first = 1;
if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)
{
if (first)
{
x_Src = (x - 250.0) / 250.0;
y_Src = -(y - 250) / 250.0;
}
else
{
x_Dest = (x - 250.0) / 250.0;
y_Dest = -(y - 250) / 250.0;
glutPostRedisplay();
}
first = !first;
}
return;
}
//allows drawing of un-fixed line using mouse
void MyPaint(GLint x, GLint y)
{
glColor3f(0.0, 0.0, 0.0);
glPointSize(3.0);
glBegin(GL_POINTS);
glVertex2f((x - 250.0) / 250.0, -(y - 250.0) / 250.0);
glEnd();
glFlush();
return;
}
void MainMenu(int item)
{
//Remove motion function if exists and go to rectangle function
//prevents two functions running at once
if (item == 1)
{
glutMotionFunc(NULL);
glutMouseFunc(MyRect);
}
else if (item == 2)
{
glutMotionFunc(NULL);
glutMouseFunc(MyLine);
}
else if (item == 5)
{
glutMouseFunc(NULL);
glutMotionFunc(MyPaint);
}
glutPostRedisplay();
return;
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowSize(500, 500);
glutInitWindowPosition(500, 200);
glutCreateWindow("Draw Shapes");
glutDisplayFunc(display);
glutCreateMenu(MainMenu);
glutAddMenuEntry("Rectangle", 1);
glutAddMenuEntry("Line", 2);
glutAddMenuEntry("Circle", 3);
glutAddMenuEntry("Triangle", 4);
glutAddMenuEntry("Paintbrush", 5);
glutAddMenuEntry("Background colour", 6);
glutAddMenuEntry("Clear screen", 7);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
}

You need to use glBegin(GL_LINES) instead of glBegin(GL_LINE).
GL_LINE is an argument to the unrelated function glPolygonMode.

Related

Position the square on the left after it reaches the top

#include <stdio.h> // this library is for standard input and output
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit
#include <math.h>
float squareX = 0.0f;
float squareY = -0.3f;
float squareZ = 0.0f;
static int flag = 1;
void drawShape(void) {
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(162, 50);
glVertex2f(162, 10);
glVertex2f(220, 10);
glVertex2f(220, 50);
glVertex2f(162, 50);
glEnd();
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
// called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, (float)w, 0.0f, (float)h, -1.0f, 1.0f);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawShape();
glutSwapBuffers();
}
// make the square go up
void update(int value) {
if (flag) {
squareY += 1.0f;
if (squareY > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
// make the square go right
/* void update(int value) {
if (flag) {
squareX += 1.0f;
if (squareX > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
} */
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Moving Square");
initRendering();
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return(0);
}
I have uploaded this code before but this time I made the square go all the way up. The code just moves the square up, but I don't know how to position it on the left once it reaches the top, so then I can make it move to the right. I have uploaded a demonstration on how I want it to look below.
Preview:
What I want it to do next:
I recommend to initialize the variables squareX, squareY and squareZ with the start position of the rectangle:
float squareX = 162.0f;
float squareY = 0.0f;
float squareZ = 0.0f;
Do not draw a rectangle specific position, but draw a rectangle on the position (0,0) with a length (width, height). Let the model matrix (set by glTranslatef), do the job of the positioning:
void drawShape(void)
{
float width = 58.0f;
float height = 40.0f;
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glVertex2f(0, 0);
glEnd();
}
Use a variable state, which has stated the direction of the current movement:
int state = 1; // 0: stop; 1: move up; 2: move right
If the rectangle a certain position has reached, then the state has to be changed and a the new start position can be set. At the final position, the rectangle can stop or the process can even be restarted:
void update(int value)
{
if (state == 1) // 1 : move up
{
squareY += 1.0f;
if (squareY > 400.0)
{
state = 2;
squareX = 0.0f;
squareY = 180.0f;
}
}
else if (state == 2) // 2 : move right
{
squareX += 1.0f;
if (squareX > 400.0)
{
state = 0;
// restart
//state = 1;
//squareX = 162.0f;
//squareY = 0.0f;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}

No output for simple openGL line drawing program?

I am unable to understand why I am not getting any output for the given program. This problem has been occurring to me for my last 2 openGL programs, the previous one being DDA algorithm, again in which I didnt get any output. Is there a problem with the algorithm, or in my understanding how openGL works internally ?
#include <iostream>
#include <GL/glut.h>
using namespace std;
float X1 = 0, X2 = 100, Y1 = 0, Y2 = 400, X11, Y11, X22, Y22, slope, dely, delx, c, intercept, pi;
float absl(float x) {
if (x >= 0) return x;
return -1*x;
}
void drawScene() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
glClearColor(1.0, 1.0, 1.0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
//start bresenham algo
glBegin(GL_POINTS);
glVertex2f(X1, Y1);
while(X1 <= X2) {
X1++;
if(pi < 0) {
glVertex2f(X1, Y1);
}
else {
Y1++;
glVertex2f(X1, Y1);
}
float flag = (pi >= 0);
pi = pi + 2*dely - 2*delx*flag;
}
glEnd();
//end DDA algo
glFlush();
}
int main(int argc, char **argv) {
//cin >> X1 >> Y1 >> X2 >> Y2;
// dely = Y2 - Y1;
// delx = X2 - X1;
// pi = 2*dely - delx;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0,0);
glutCreateWindow("DDA");
glutDisplayFunc(drawScene);
glutMainLoop();
return 0;
}
gluOrtho2D defines a 2D orthographic projection matrix. But it also multiplies the current matrix on the matrix stack with the orthographic projection matrix and replaces the current matrix with the product.
Note, in OpenGL fixed function pipeline all matrix operations work like this (except glPushMatrix, glPopMatrix, glLoadMatrix and glLoadIdentity).
This means you have to replace the current matrix with the identity matrix (glLoadIdentity), befor you apply the orthographic projection matrix:
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
Or you do gluOrtho2D only one time before you start the main loop in the main function:
gluOrtho2D(0, 500, 0, 500);
glutMainLoop();
Since the display function is called (drawScene) continuously, you should use local control varibales and not modify X1 and Y1:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
glClearColor(0.0, 0.0, 0.0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
//start bresenham algo
int x = X1, y = Y1;
glBegin(GL_LINES);
glVertex2f(100, 400);
glVertex2f(400, 100);
glEnd();
glBegin(GL_POINTS);
glVertex2f(x, Y1);
while(x <= X2) {
x ++;
if(pi < 0) {
glVertex2f(x, y);
}
else {
y ++
glVertex2f(x, y);
}
}
int flag = (pi >= 0);
pi = pi + 2*dely - 2*delx*flag;
glEnd();

draw in animated opengl scene

i've a problem with drawing firework effect in animated scene when i clicked on mouse button. Why it don't drawing?
My Code:
#include<GL/glut.h>
struct Point {
GLint x;
GLint y;
};
Point p1, p2;
int ww=600,wh=400;
int xi,yi,xf,yf,y1b,x1b,y2b,x2b;
float px, py, t;
float x=0.,y=0.,x1=5.;
void update()
{
x+=0.01;
x1 -= 0.02;
if (x>6)
{
x -= 6;
x1 = 4;
}
}
There I create a function that draw firework effect on the basis of bezier curves. It will Okey if I draw on the static window.
// Bezier curve firework
void bezier(int xi, int yi, int xf, int yf)
{
// Coordinates for additional points of bezier curve
x1b = xi + rand()%15;
y1b = yi + rand()%5;
x2b = xf + rand()%15;
y2b = xf + rand()%5;
calculate and draw the curves
for (t=0.;t<=1.;t+=0.001)
{
px=(1-t)*(1-t)*(1-t)*xi+3*t*(1-t)*(1-t)*x1b+3*t*t*(1-t)*x2b+t*t*t*xf;
py=(1-t)*(1-t)*(1-t)*yi+3*t*(1-t)*(1-t)*y1b+3*t*t*(1-t)*y2b+t*t*t*yf;
glPointSize(2);
glBegin(GL_POINTS);
//glColor3f(1,0,0);
glVertex2d(px,py);
glEnd();
glFlush();
}
}
void initRendering()
{
glEnable(GL_DEPTH_TEST);
}
void reshaped(int w , int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (double)w/(double)h,1,200);
}
// If pressed ESC -> exit
void keyPressed(unsigned char k, int x, int y)
{
if(k==27)
{
exit(0);
}
}
Then, if I pressed mouse button it should call the function above and draw what I need. But nothing(
// If pressed mouse button -> draw firework effect
void mousePressed(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
xi=x;
yi=wh-y;
xf=x + 5.;
p1.x = xi; p1.y = yi;
p2.x = xf; p2.y = yi;
//drawLine(xi,yi,xf,yi);
bezier(xi, yi,xf, yi);
}
glutPostRedisplay();
}
There I create animated window. Two clouds move in gorizontal waves.
// Display a two moving clouds and the earth
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(x1,y,-5.0);
glBegin(GL_POLYGON);
glColor3f(1.,0.,0.5);
glVertex3f(-1.,1.,-5.);
glVertex3f(0.,2.,-5.);
glVertex3f(-2.,2.,-5.);
glVertex3f(1.,1.,-5.);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(x,y,-5.);
glBegin(GL_POLYGON);
glColor3f(0.,0.5,0.5);
glVertex3f(1.,0.7,-5.);
glVertex3f(1.5,1.0,-5.0);
glVertex3f(0.7,1.5,-5.0);
glVertex3f(0.0,2.0,-5.0);
glVertex3f(-0.7,1.5,-5.0);
glVertex3f(-1.4,1.6,-5.0);
glVertex3f(-1.7,1.0,-5.0);
glVertex3f(-1.5,0.7,-5.0);
glVertex3f(-1.0,0.5,-5.0);
glEnd();
glPopMatrix();
glBegin(GL_POLYGON);
glColor3f(1.,1.,1.5);
glVertex3f(-2.,-2.,-5.);
glVertex3f(-2.0,-2.0,-5.0);
glVertex3f(-1.0,-1.5,-5.0);
//glVertex3f(0.0,0.0,-5.0);
glVertex3f(2.0,-2.0,-5.0);
glVertex3f(1.2,-1.5,-5.0);
glEnd();
update();
glutSwapBuffers();
glFlush();
}
void myinit()
{
glViewport(0,0,ww,wh);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)ww,0.0,(GLdouble)wh);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc,char **argv)
{
// Initialization
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("Salute | Clouds");
initRendering();
// Registration
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshaped);
// Handler of
myinit();
glutKeyboardFunc(keyPressed);
glutMouseFunc(mousePressed);
// Main Loop
glutMainLoop();
return(0);
}
I think the problem is as follows:
I'm trying to draw my firework in an updated animated window. And every time I clicked on the screen, it is updated. And in the end, nothing is visible.
Actually the question:
How to make so that function glutMoseFunk would draw my salute in updated window?
While your scene is draw in perspective projection, the function bezier works with orthographic projection. This means you have to change the projection matrix befor you call bezier.
Further, do all the rendering in the main loop (display function). The event mousePressed should only be used to change parameters (set xi, yi, ...).
The display function may look like this:
int ww=400, wh=400;
void display()
{
// clear the frame buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// setup perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (double)ww/(double)wh,1,200);
// set model view matrix (identity matrix)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw scene
.....
// setup ortihgraphic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)ww,0.0,(GLdouble)wh);
bezier(xi, yi,xf, yi);
update();
glutSwapBuffers();
glutPostRedisplay();
}
The reshaped function should set the viewport and notice the window size only:
void reshaped(int w , int h)
{
ww = w;
wh = h;
glViewport(0, 0, ww, wh);
}

c++ OpenGL display problem for gluLookAt

I have been trying to solve this program:
Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing. Also the cube should rotate.
I have completed the coding and here it is. It seems to work fine except for 1 simple problem:
//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
glBegin(GL_POLYGON);
glVertex3fv(a);
glVertex3fv(b);
glVertex3fv(c);
glVertex3fv(d);
glEnd();
glFlush();
}
void drawCube(float v[8][3])
{
glColor3f(1,0,0);
drawPolygon(v[0],v[1],v[2],v[3]);
glColor3f(0,1,0);
drawPolygon(v[0],v[1],v[6],v[7]);
glColor3f(0,0,1);
drawPolygon(v[7],v[6],v[5],v[4]);
glColor3f(1,1,0);
drawPolygon(v[2],v[3],v[4],v[5]);
glColor3f(0,1,1);
drawPolygon(v[1],v[2],v[5],v[6]);
glColor3f(1,0,1);
drawPolygon(v[0],v[3],v[4],v[7]);
glFlush();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
//glRotatef(60,1,1,0);
drawCube(v);
glFlush();
}
void reshape(int width,int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2,2,-2,2,-2,2);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void mouse(int btn,int state,int x,int y)
{
if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
glRotatef(2,1,0,0);
if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
glRotatef(2,0,1,0);
if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
glRotatef(2,0,0,1);
glutPostRedisplay();
}
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void keyboard(unsigned char key,int x,int y)
{
if(key == 'x')
ex += 0.1;
if(key == 'X')
ex -= 0.1;
if(key == 'y')
ey += 0.1;
if(key == 'Y')
ey -= 0.1;
if(key == 'z')
ez += 0.1;
if(key == 'Z')
ez -= 0.1;
glMatrixMode(GL_PROJECTION);
gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
glutPostRedisplay();
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("spin cube");
glClearColor(1,1,1,0);
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
}
The cube rotates by mouse clicks
The camera moves by x/X y/Y z/Z
But the problem is that when i first press a key the display vanishes. Then the 2nd time it comes with properly moved camera. Why? I want the camera to just move and not vanish the display. What is wrong?
There are two mistakes in your program:
You're treating OpenGL like a scene graph with persistency – however OpenGL just draws pictures.
You apply viewpoint transformation to the projection matrix.
Both is fundamentally wrong. Here's a corrected version of your code:
//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
glBegin(GL_POLYGON);
glVertex3fv(a);
glVertex3fv(b);
glVertex3fv(c);
glVertex3fv(d);
glEnd();
}
void drawCube(float v[8][3])
{
glColor3f(1,0,0);
drawPolygon(v[0],v[1],v[2],v[3]);
glColor3f(0,1,0);
drawPolygon(v[0],v[1],v[6],v[7]);
glColor3f(0,0,1);
drawPolygon(v[7],v[6],v[5],v[4]);
glColor3f(1,1,0);
drawPolygon(v[2],v[3],v[4],v[5]);
glColor3f(0,1,1);
drawPolygon(v[1],v[2],v[5],v[6]);
glColor3f(1,0,1);
drawPolygon(v[0],v[3],v[4],v[7]);
}
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void display()
{
int win_width, win_height;
win_width = glutGet(GLUT_WINDOW_WIDTH);
win_height = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0,0,width,height);
glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2,2,-2,2,-2,2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
glRotatef(rot_x,1,0,0);
glRotatef(rot_y,0,1,0);
glRotatef(rot_z,0,0,1);
glColor3f(1,0,0);
//glRotatef(60,1,1,0);
drawCube(v);
glFinish();
}
void mouse(int btn,int state,int x,int y)
{
if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
rot_x += 2;
if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
rot_y += 2;
if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
rot_z += 2;
glutPostRedisplay();
}
void keyboard(unsigned char key,int x,int y)
{
if(key == 'x')
ex += 0.1;
if(key == 'X')
ex -= 0.1;
if(key == 'y')
ey += 0.1;
if(key == 'Y')
ey -= 0.1;
if(key == 'z')
ez += 0.1;
if(key == 'Z')
ez -= 0.1;
glutPostRedisplay();
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("spin cube");
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
}
gluLookAt shouldn't go in to the projection matrix but into the modelview. I would also suggest that you keep track of your cube rotation and eye position and apply them inside the display function instead:
//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
float cubex=0,cubey=0,cubez=0;
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
glBegin(GL_POLYGON);
glVertex3fv(a);
glVertex3fv(b);
glVertex3fv(c);
glVertex3fv(d);
glEnd();
}
void drawCube(float v[8][3])
{
glColor3f(1,0,0);
drawPolygon(v[0],v[1],v[2],v[3]);
glColor3f(0,1,0);
drawPolygon(v[0],v[1],v[6],v[7]);
glColor3f(0,0,1);
drawPolygon(v[7],v[6],v[5],v[4]);
glColor3f(1,1,0);
drawPolygon(v[2],v[3],v[4],v[5]);
glColor3f(0,1,1);
drawPolygon(v[1],v[2],v[5],v[6]);
glColor3f(1,0,1);
drawPolygon(v[0],v[3],v[4],v[7]);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
glRotatef(cubex, 1, 0, 0);
glRotatef(cubey, 0, 1, 0);
glRotatef(cubez, 0, 0, 1);
glColor3f(1,0,0);
//glRotatef(60,1,1,0);
drawCube(v);
glFinish();
}
void reshape(int width,int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2,2,-2,2,-2,2);
glutPostRedisplay();
}
void mouse(int btn,int state,int x,int y)
{
if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
cubex += 2;
if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
cubey += 2;
if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
cubez += 2;
glutPostRedisplay();
}
void keyboard(unsigned char key,int x,int y)
{
if(key == 'x')
ex += 0.1;
if(key == 'X')
ex -= 0.1;
if(key == 'y')
ey += 0.1;
if(key == 'Y')
ey -= 0.1;
if(key == 'z')
ez += 0.1;
if(key == 'Z')
ez -= 0.1;
glutPostRedisplay();
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("spin cube");
glClearColor(1,1,1,0);
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
}
This isn't 100% equivalent to what you were originally trying to achieve since it applies three accumulated consecutive rotations around the x, y and z axis respectively instead of incremental ones.
Also you don't need all the glFlush calls, a single call to glFinish at the end of the rendering should be sufficient, or even better; swap to double buffered rendering and use glutSwapBuffers instead.

Inaccurate Mouse Coordinates Returned

The issue is that the further the mouse click is from the top left origin (0,0) the greater the height inaccuracy when the vertex is plotted. Any ideas?
int WindowWidth = 19;
int WindowHeight = 13;
int mouseClickCount = 0;
int rectPlotted;
GLint x1;
GLint y1;
GLint x2;
GLint y2;
//Declare our functions with prototypes:
void display(void);
void init (void);
void processNormalKeys(unsigned char key, int x, int y);
void on_vertex_selected(GLint x, GLint y);
void on_mouse_event(int button, int state, int x, int y);
/////////////////////////////////// MAIN ////////////////////////////////
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
//start calculation of max window size available at 19:13 aspect ratio
int screenWidth = glutGet(GLUT_SCREEN_WIDTH);
int screenHeight = glutGet(GLUT_SCREEN_HEIGHT);
screenWidth = screenWidth/WindowWidth;
WindowWidth = WindowWidth*screenWidth;
screenHeight = screenHeight/WindowHeight;
WindowHeight = screenHeight*WindowHeight;
//end calculation
glutInitWindowSize (WindowWidth, WindowHeight);
glutInitWindowPosition (0, 0);
glutCreateWindow ("Plot a rectangle!");
glutDisplayFunc(display);
glutKeyboardFunc(processNormalKeys);
glutMouseFunc(on_mouse_event);
init();
glutMainLoop();
return 0;
}
/////////////////////////////////////////////////////////////////////////
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT); //clear all pixels
glFlush();
}
void init (void)
{
/* select clearing (background) color */
glClearColor (1.0, 1.0, 1.0, 0.0);
/* initialize viewing values */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WindowWidth, 0, WindowHeight, -1.0, 1.0);
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27) //esc
exit(0);
//Allows color change of most recently plotted rectangle
if (key == 98){ //b
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_QUADS);
glVertex2i(x1, y1);
glVertex2i(x1, y2);
glVertex2i(x2, y2);
glVertex2i(x2, y1);
glEnd();
glFlush();
}
if (key == 114){ //r
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x1, y1);
glVertex2i(x1, y2);
glVertex2i(x2, y2);
glVertex2i(x2, y1);
glEnd();
glFlush();
}
if (key == 103){ //g
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x1, y1);
glVertex2i(x1, y2);
glVertex2i(x2, y2);
glVertex2i(x2, y1);
glEnd();
glFlush();
}
}
void on_vertex_selected(GLint x, GLint y){
if(mouseClickCount == 0){
x1 = x;
y1 = y;
glColor3f(0.0, 0.0, 0.0);
glEnable(GL_POINT_SMOOTH);
glPointSize(5.0);
glBegin(GL_POINTS);
glVertex2i(x1, y1);
glEnd();
glFlush();
}
else{
x2 = x;
y2 = y;
glBegin(GL_POINTS);
glColor3f(1.0, 1.0, 1.0);
glVertex2i(x1,y1); //"clears" previous point to make way for the rectangle
glEnd();
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x1, y1);
glVertex2i(x1, y2);
glVertex2i(x2, y2);
glVertex2i(x2, y1);
glEnd();
glFlush();
}
}
void on_mouse_event(int button, int state, int x, int y){
if(button==GLUT_LEFT_BUTTON && state ==GLUT_DOWN && mouseClickCount == 0){
//y = y+20; //adjusts for VM mouse tracking error
on_vertex_selected(x, WindowHeight - y);
rectPlotted = 0;
}
if(button==GLUT_LEFT_BUTTON && state ==GLUT_UP && mouseClickCount == 0){
if(rectPlotted == 1){
return;
}
else{
mouseClickCount++;
}
}
if(button==GLUT_LEFT_BUTTON && state ==GLUT_DOWN && mouseClickCount == 1){
//y = y+20; //adjusts for VM mouse tracking error
on_vertex_selected(x, WindowHeight - y);
mouseClickCount = 0;
rectPlotted = 1;
}
}
Your glOrtho() call is almost certainly wrong. You pass the window size, not the window client area size. The difference is the size of the borders and the height of the caption.
Be aware that your actual window size will most probably be slightly different than what you asked at init time.
Simply said, implement a glutReshapeFunc()
I was compiling and running my code within Parallels VM v.6. This was the issue leading to inaccurate mouse coordinates being returned. I compiled and ran the exact same code on OS X without problem.