Created
February 21, 2011 02:15
-
-
Save kusold/836581 to your computer and use it in GitHub Desktop.
Requires GLUT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //////////////////////////////////////////////////////// | |
| // | |
| // A simple OpenGL program that allows you to place | |
| // line segments, rotate them, and scale them. Some | |
| // other features are changing the color via a right | |
| // click menu, creating a star, creating a polygon, | |
| // and creating a spiral. | |
| // | |
| // When 200 lines are drawn, you need to clear the | |
| // window to draw more. | |
| // | |
| // Author: Mike Kusold | |
| // Date: 1/24/2011 | |
| // | |
| //////////////////////////////////////////////////////// | |
| #include <GL/glut.h> | |
| #include <GL/gl.h> | |
| #include <math.h> | |
| #include "Lab01.h" | |
| #define MAX_LINES 200 // max number of lines allowed to be displayed. | |
| #define MAX_VERTICES 2 // a line has two vertices. | |
| #define TRUE 1 | |
| #define FALSE 0 | |
| #define PI (atan((float) 1) * 4) // PI | |
| /** | |
| * Globals | |
| */ | |
| int windowWidth = 500, // display window width | |
| windowHeight = 500; // display window height | |
| float u = 1; // x-axis positioner | |
| float v = 0; // y-axis positioner | |
| int D = 10; // scale | |
| float rotate = PI/6; | |
| int nop = 0; // number of primitives NEED TO CHECK AGAINST MAX_LINES! | |
| float colors[3]; // current color in RGB | |
| int number_of_sides = 5; | |
| float angle = PI/6; | |
| int scale = 2; | |
| int mode = GLUT_RGB|GLUT_SINGLE; | |
| /* Structure for a line */ | |
| typedef struct line { | |
| bool clicked; // set to true if the point was selected via mouse. | |
| float lcolor[3]; // color of the line in RGB | |
| int x[MAX_VERTICES]; // x0 and x1 coordinates | |
| int y[MAX_VERTICES]; // y0 and y1 coordinates | |
| } line; | |
| line lines[MAX_LINES]; // used to store the lines | |
| void colormenu(int selected) { | |
| switch (selected) { | |
| case 0: | |
| // white | |
| colors[0] = 1.0; | |
| colors[1] = 1.0; | |
| colors[2] = 1.0; | |
| break; | |
| case 1: | |
| // red | |
| colors[0] = 1.0; | |
| colors[1] = 0.0; | |
| colors[2] = 0.0; | |
| break; | |
| case 2: | |
| // green | |
| colors[0] = 0.0; | |
| colors[1] = 1.0; | |
| colors[2] = 0.0; | |
| break; | |
| case 3: | |
| // blue | |
| colors[0] = 0.0; | |
| colors[1] = 0.0; | |
| colors[2] = 1.0; | |
| break; | |
| } | |
| } | |
| /** | |
| * This only executes when the left mouse button is pushed down. | |
| */ | |
| void getMousePosition(int button, int state, int x, int y) { | |
| if( (button == GLUT_LEFT_BUTTON) && (state == GLUT_UP) ) { | |
| /* Insert to vertex buffers */ | |
| lines[nop].x[0] = x; | |
| lines[nop].y[0] = windowHeight - y; /* GLUT and GL define the origin at different positions */ | |
| lines[nop].clicked = TRUE; | |
| lines[nop].lcolor[0] = colors[0]; | |
| lines[nop].lcolor[1] = colors[1]; | |
| lines[nop].lcolor[2] = colors[2]; | |
| } | |
| } | |
| void polygon(int sides) { | |
| int i; | |
| unsigned char command; | |
| for(i=0; i<sides; i++) { | |
| command = 'f'; | |
| key(command, 0, 0); | |
| rotate = (2*PI)/sides; | |
| command = 't'; | |
| key(command, 0, 0); | |
| } | |
| rotate = PI/6; | |
| } | |
| void star(int sides) { | |
| int i; | |
| unsigned char command; | |
| for(i=0; i<sides; i++) { | |
| command = 'f'; | |
| key(command, 0, 0); | |
| rotate = (4*PI)/sides; | |
| command = 't'; | |
| key(command, 0, 0); | |
| } | |
| rotate = PI/6; | |
| } | |
| void spiral(int sides, float angle, float scale) { | |
| int i; | |
| unsigned char command; | |
| for(i=0; i<sides; i++) { | |
| command = 'f'; | |
| key(command, 0, 0); | |
| rotate = angle; | |
| command = 't'; | |
| u = u * (scale/1.50); | |
| v = v* (scale/1.50); | |
| key(command, 0, 0); | |
| command = 'S'; | |
| key(command, 0, 0); | |
| } | |
| rotate = PI/6; | |
| } | |
| void clear() { | |
| int i,j; | |
| for(i = 0; i < nop; i++) { | |
| for(j=0; j < MAX_VERTICES; j++) { | |
| lines[nop].x[j] = 0; | |
| lines[nop].y[j] = 0; | |
| } | |
| lines[nop].clicked = FALSE; | |
| lines[nop].lcolor[0] = 1.0; | |
| lines[nop].lcolor[1] = 1.0; | |
| lines[nop].lcolor[2] = 1.0; | |
| } | |
| nop = 0; | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| } | |
| void key(unsigned char key, int x, int y) { | |
| float u2, v2; | |
| /* When ‘f’ is pressed, connect the current point (x,y) and the next point (x’,y’) with a line segment. | |
| The next point is calculated as: | |
| x’ = x + D * u | |
| y’ = y + D * v | |
| where (u,v) is the direction that the line is heading to. | |
| */ | |
| if(key == 'f') { | |
| // create a new independant line | |
| if(lines[nop].clicked == TRUE && (nop < MAX_LINES)) { | |
| lines[nop].x[1] = lines[nop].x[0] + D*u; | |
| lines[nop].y[1] = lines[nop].y[0] + D*v; | |
| glBegin(GL_LINES); | |
| glColor3f(lines[nop].lcolor[0],lines[nop].lcolor[1],lines[nop].lcolor[2]); | |
| glVertex2i(lines[nop].x[0], lines[nop].y[0]); | |
| glVertex2i(lines[nop].x[1], lines[nop].y[1]); | |
| glEnd();nop++; | |
| } | |
| // create a line based up the (x1,y1) coordinates of the previous line. | |
| else if (nop!=0 && (nop < MAX_LINES)) { | |
| lines[nop].x[0] = lines[nop-1].x[1]; | |
| lines[nop].y[0] = lines[nop-1].y[1]; | |
| lines[nop].x[1] = lines[nop].x[0] + D*u+u; | |
| lines[nop].y[1] = lines[nop].y[0] + D*v+v; | |
| lines[nop].lcolor[0] = colors[0]; | |
| lines[nop].lcolor[1] = colors[1]; | |
| lines[nop].lcolor[2] = colors[2]; | |
| glBegin(GL_LINES); | |
| glColor3f(lines[nop].lcolor[0],lines[nop].lcolor[1],lines[nop].lcolor[2]); | |
| glVertex2i(lines[nop].x[0], lines[nop].y[0]); | |
| glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]); | |
| glEnd(); | |
| nop++; | |
| } | |
| } | |
| if(key == 't') { | |
| /* When ‘t’ is pressed, you will turn the direction of the line by an angle of A. In other words, you | |
| will rotate (u,v) in the following way: | |
| u’ = u cos(A) – v sin(A) | |
| v’ = u sin(A) + v cos(A). | |
| A = 30 degrees | |
| */ | |
| u2 = u*cos(rotate) - v*sin(rotate); | |
| v2 = u*sin(rotate) + v*cos(rotate); | |
| u=u2; | |
| v=v2; | |
| lines[nop-1].x[1] = lines[nop-1].x[0] + D*u; | |
| lines[nop-1].y[1] = lines[nop-1].y[0] + D*v; | |
| glBegin(GL_LINES); | |
| glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]); | |
| glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]); | |
| glEnd(); | |
| } | |
| if(key == 'S') { | |
| /* When ‘S’ is pressed, you scale up the (u,v) vector by 50%, that is: | |
| u’ = 1.5 * u | |
| v’ = 1.5 * v | |
| */ | |
| u = u*1.5; | |
| v = v*1.5; | |
| lines[nop-1].x[1] = lines[nop-1].x[0] + D*u; | |
| lines[nop-1].y[1] = lines[nop-1].y[0] + D*v; | |
| glBegin(GL_LINES); | |
| glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]); | |
| glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]); | |
| glEnd(); | |
| } | |
| if(key == 's') { | |
| /* When ‘s’ is pressed, you scale down the (u,v) vector by 50%, that is: | |
| u’ = 0.5 * u | |
| v’ = 0.5 * v | |
| */ | |
| u = u*0.5; | |
| v = v*0.5; | |
| lines[nop-1].x[1] = lines[nop-1].x[0] + D*u; | |
| lines[nop-1].y[1] = lines[nop-1].y[0] + D*v; | |
| glBegin(GL_LINES); | |
| glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]); | |
| glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]); | |
| glEnd(); | |
| } | |
| if(key == 'q') { | |
| /* Exit program */ | |
| exit(0); | |
| } | |
| if(key == 'p') { | |
| polygon(6); | |
| } | |
| if( key == 'a') { | |
| star(5); | |
| } | |
| if( key == 'r') { | |
| spiral(20,(PI/4),1.05f); | |
| } | |
| if( key == 'c') { | |
| clear(); | |
| } | |
| glFlush(); | |
| glutPostRedisplay(); /* Now display everything in the buffers */ | |
| } | |
| /** | |
| * Needed for when the user resizes the window. | |
| * Plea to users: Please don't! | |
| */ | |
| void reshape(GLsizei w, GLsizei h) { | |
| /* Adjust clipping box */ | |
| glMatrixMode(GL_PROJECTION); | |
| glLoadIdentity(); | |
| gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h); | |
| glMatrixMode(GL_MODELVIEW); | |
| glLoadIdentity(); | |
| /* Adjust viewport and clear */ | |
| glViewport(0,0,w,h); | |
| glutPostRedisplay(); /* Now display everything in the buffers */ | |
| /* Save new window size in global variables */ | |
| windowWidth = w; | |
| windowHeight = h; | |
| } | |
| void display_all() | |
| { | |
| int p_idx, //Primative Index | |
| v_idx = 0; // Vertex Index | |
| if ( nop!=0) { | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| for(p_idx=0; (p_idx < nop); p_idx++) { //Cycle through until all primatives are drawn. | |
| glColor3f(lines[p_idx].lcolor[0], lines[p_idx].lcolor[1], lines[p_idx].lcolor[2]); | |
| glBegin(GL_LINES); | |
| for(v_idx = 0; v_idx < MAX_VERTICES; v_idx++) { //Cycle through max vertices | |
| glVertex2i(lines[p_idx].x[v_idx], lines[p_idx].y[v_idx]); | |
| } | |
| glEnd(); | |
| } | |
| } | |
| glFlush(); // force OpenGL to draw all the objects | |
| } | |
| void display() | |
| { | |
| glClearColor(0,0,0,1); /* Black Background */ | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| /*Set World view */ | |
| glMatrixMode(GL_PROJECTION); | |
| glLoadIdentity(); | |
| gluOrtho2D(0, windowHeight, 0, windowWidth); | |
| display_all(); | |
| } | |
| void init() { | |
| colors[0] = 1.0; | |
| colors[1] = 0.0; | |
| colors[2] = 0.0; | |
| glColor3f(colors[0],colors[1],colors[2]); /* Draw in Red */ | |
| glViewport(0,0, windowWidth, windowHeight); /* Set viewport */ | |
| } | |
| int main(int argc, char** argv) | |
| { | |
| glutInit(&argc, argv); | |
| glutInitWindowSize(windowWidth, windowHeight); | |
| glutInitDisplayMode(mode); | |
| glutCreateWindow("Mike Kusold's Lab 01"); | |
| init(); | |
| /* Register Callbacks */ | |
| glutDisplayFunc(display); | |
| glutReshapeFunc(reshape); | |
| glutKeyboardFunc(key); /* register the callback that will be called when a key is pressed */ | |
| glutMouseFunc(getMousePosition); /* register the callback that will be called when a key is pressed */ | |
| // glutMotionFunc(); /*register the callback that will be called when the mouse is in motion while a buton is pressed */ | |
| // create menu | |
| glutCreateMenu(colormenu); | |
| glutAddMenuEntry("White", 0); | |
| glutAddMenuEntry("Red", 1); | |
| glutAddMenuEntry("Green", 2); | |
| glutAddMenuEntry("Blue", 3); | |
| glutAttachMenu(GLUT_RIGHT_BUTTON); | |
| glutMainLoop(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| void getMousePosition(int button, int state, int x, int y); | |
| void colormenu(int selected); | |
| void key(unsigned char key, int x, int y); | |
| void polygon(int sides); | |
| void star(int sides); | |
| void spiral(int sides, int angle, int scale); | |
| void clear(); | |
| void reshape(GLsizei w, GLsizei h); | |
| void display_all(); | |
| void display(); | |
| void init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment