rendered paste body/* Assignment 1 - Duy Nguyen: September 12, 2006 * This program draws a grid and allows the user to draw lines and polygons. * It handles techniques to draw lines at the pixel level, as well as filling * polygons as required. * * Just to note, this program uses triangle.c as a template for many of the * Glut functions. */#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h>#include <unistd.h>/*// Sometimes glu.h includes glut.h--sometimes not.*/#ifdef MAC_OSX# include <OpenGL/glu.h># include <GLUT/glut.h>#else # include <GL/glu.h> # include <GL/glut.h> #endif/* -------------------------------------------------------------------------- */// Function Declarationsint main(int argc, char *argv[]);static void display_CB(void); /* Called whenever redisplay needed */static void key_CB(unsigned char key, int x, int y); /* Called on key press */static void mouse_CB(int button, int state, int x, int y); /* Called on mouse click */static void mouse_move_CB(int x, int y);static void parseFile();static void saveFile();static void drawLines();static void drawGun();static void splitAndRotate(int* lineA, int* lineB, int* point, int angle);static void rotate(int* lineA, int* lineB, int angle);static void fire();static int length(int x1, int y1, int x2, int y2);/* -------------------------------------------------------------------------- */// Instance Variable Declarationsstatic int lines[1000][2][3];static int size = 0;static double gunAngle = 90.0;static int mouseX = 0;static int mode = 0; // 1 is war modestatic int pointX;static int pointY;/* -------------------------------------------------------------------------- */int main(int argc, char *argv[]){ int win; glutInit(&argc, argv); /* initialize GLUT system */ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowSize(800, 600); win = glutCreateWindow("Assignment 1"); /* create window */ /* set background to black */ glClearColor((GLclampf)0.0,(GLclampf)0.0,(GLclampf)0.0,(GLclampf)0.0); gluOrtho2D(0.0, 800.0, 0.0, 600.0); /* how object is mapped to window */ glutDisplayFunc(display_CB); /* set window's display callback */ glutKeyboardFunc(key_CB); /* set window's key callback */ glutMouseFunc(mouse_CB); /* set window's mouse callback */ glutMotionFunc(mouse_move_CB); parseFile(); // Read in any predone code glutMainLoop(); /* start processing events... */ /* Execution never reaches this point, so return value is failure */ return EXIT_FAILURE;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static void parseFile(){ if(!isatty(fileno(stdin))) { char temp[500]; while( fgets(temp, 500, stdin) != NULL) { const char delimiters[] = " "; char* token; char cp[500]; strcpy (cp, temp); token = strtok (cp, delimiters); if( strcmp(token, "line") == 0) { int a = atoi(strtok (NULL, delimiters)); int b = atoi(strtok (NULL, delimiters)); int c = atoi(strtok (NULL, delimiters)); int d = atoi(strtok (NULL, delimiters)); lines[size][0][0] = a; lines[size][0][1] = b; lines[size][0][2] = 1; lines[size][1][0] = c; lines[size][1][1] = d; lines[size][1][2]= 1; size++; } } }}static void saveFile(){ int i = 0; for(i = 0; i < size; i++) { int a = lines[i][0][0]; int b = lines[i][0][1]; int c = lines[i][1][0]; int d = lines[i][1][1]; if( a != 0 || b != 0 || c != 0 || d != 0) { printf("lines %d %d %d %d\n", a,b,c,d); } }}static void drawLines(){ glColor3d(.8, .8, .8); int i = 0; for( i = 0; i < size; i ++) { glBegin(GL_LINES); //Start Draw //printf("%d %d %d %d\n", lines[i][0][0],lines[i][0][1],lines[i][1][0],lines[i][1][1]); glVertex3f( lines[i][0][0], lines[i][0][1], 0); glVertex3f( lines[i][1][0], lines[i][1][1], 0); glEnd(); //End Draw }}static void drawGun(){ glColor3d(0, .8, 0); double a = sin(gunAngle*(3.1415/180)); double b = cos(gunAngle*(3.1415/180)); glBegin(GL_LINES); //Start Draw glVertex3f( 400, 0, 0); glVertex3f( b*50 + 400, a*50, 0); glEnd(); //End Draw}static void splitAndRotate(int* lineA, int* lineB, int* point, int angle){ //Split int x = lineB[0]; int y = lineB[1]; lineB[0] = point[0]; lineB[1] = point[1]; lines[size][0][0] = x; lines[size][0][1] = y; lines[size][0][2] = 1; lines[size][1][0] = point[0]; lines[size][1][1] = point[1]; lines[size][1][2]= 1; //Rotate if( lineA[0] == lines[size][0][0] ) //Vertical line { if(lineA[0] >=400) //on right side of screen { if(lineA[1] > lines[size][0][1]) { rotate(lineA, lineB, angle); rotate(lines[size][0], lines[size][1], -angle); } else { rotate(lineA, lineB, -angle); rotate(lines[size][0], lines[size][1], angle); } } else { if(lineA[1] > lines[size][0][1]) { rotate(lineA, lineB, -angle); rotate(lines[size][0], lines[size][1], angle); } else { rotate(lineA, lineB, angle); rotate(lines[size][0], lines[size][1], -angle); } } } else if( lineA[0] <= lines[size][0][0]) //lineA is leftmost anchor { //Rotate lineA positive rotate(lineA, lineB, angle); rotate(lines[size][0], lines[size][1], -angle); } else //lineA is rightmost anchor { rotate(lineA, lineB, -angle); rotate(lines[size][0], lines[size][1], angle); } //check line size size++;}static void rotate(int* lineA, int* lineB, int angle){ //Move to origin int a = lineA[0]; int b = lineA[1]; int mat[3][3] = {{1,0,-a}, {0,1,-b}, {0,0,1}}; int x = lineB[0]*mat[0][0] + lineB[1]*mat[0][1] + lineB[2]*mat[0][2]; int y = lineB[0]*mat[1][0] + lineB[1]*mat[1][1] + lineB[2]*mat[1][2]; int z = lineB[0]*mat[2][0] + lineB[1]*mat[2][1] + lineB[2]*mat[2][2]; lineB[0] = x; lineB[1] = y; lineB[2] = z; double rad = angle*(3.14/180); double mat2[3][3] = {{cos(rad),-sin(rad),0}, { sin(rad),cos(rad),0}, { 0,0,1}}; double x2 = lineB[0]*mat2[0][0] + lineB[1]*mat2[0][1] + lineB[2]*mat2[0][2]; double y2 = lineB[0]*mat2[1][0] + lineB[1]*mat2[1][1] + lineB[2]*mat2[1][2]; double z2 = lineB[0]*mat2[2][0] + lineB[1]*mat2[2][1] + lineB[2]*mat2[2][2]; lineB[0] = x2; lineB[1] = y2; lineB[2] = z2; int mat3[3][3] = {{1,0,a}, {0,1,b}, {0,0,1}}; x = lineB[0]*mat3[0][0] + lineB[1]*mat3[0][1] + lineB[2]*mat3[0][2]; y = lineB[0]*mat3[1][0] + lineB[1]*mat3[1][1] + lineB[2]*mat3[1][2]; z = lineB[0]*mat3[2][0] + lineB[1]*mat3[2][1] + lineB[2]*mat3[2][2]; lineB[0] = x; lineB[1] = y; lineB[2] = z;}static void fire(){ double a = sin(gunAngle*(3.1415/180)); double b = cos(gunAngle*(3.1415/180)); int gunX = (b*50 + 400); int gunY = (a*50); //Find intersecting line int bestLine = -1; pointX = 0; pointY = -20; //gun can't shoot down, so Y must be at least 0 int distance = 5000; int i = 0; for(i = 0; i < size; i++) { int x1 = lines[i][0][0]; int x2 = lines[i][1][0]; int y1 = lines[i][0][1]; int y2 = lines[i][1][1]; int yB = 0; int xB = 400; if (x2 != x1) { double m = (y2-y1)/(x2-x1); double m2 = tan(gunAngle*(3.14/180)); if(m != m2) { int newX = (yB - m2*xB - y1 + m*x1)/(m-m2); int newY = y1 + m*(newX-x1); printf("news: %d %d\n", newX, newY); if( x1 < x2) { if(newX >= x1 && newX <= x2) { if(length(400,0,newX,newY) < distance && length(400,0,newX,newY) > 50) { distance = length(400,0,newX,newY); pointX = newX; pointY = newY; bestLine = i; } } } else { if(newX <= x1 && newX >= x2) { if(length(400,0,newX,newY) < distance && length(400,0,newX,newY) > 50) { distance = length(400,0,newX,newY); pointX = newX; pointY = newY; bestLine = i; } } } } } else { double m2 = tan(gunAngle*(3.14/180)); int newX = x1; int newY = yB + m2*(newX-xB); if(length(400,0,newX,newY) < distance && length(400,0,newX,newY) > 50) { distance = length(400,0,newX,newY); pointX = newX; pointY = newY; bestLine = i; } } } //printf("%d %d\n", pointX, pointY); if(pointY < 0) { double m2 = tan(gunAngle*(3.14/180)); if(gunAngle < 90) { pointX = 400; pointY = 0 + m2*(pointX-400); } else(gunAngle > 90) { pointX = -400; pointY = 0 + m2*(pointX-400); } else { pointX = 400; pointY = 600; } } //shoot laser //printf("fire! %d %d\n", pointX, pointY); display_CB(); if(bestLine != -1) { splitAndRotate(lines[bestLine][0], lines[bestLine][1], point, 45); } sleep(3); pointX = 0; pointY = -20; printf("%d\n", size); display_CB(); saveFile();}static int length(int x1, int y1, int x2, int y2){ //printf("%d %d %d %d\n", x1, y1, x2, y2); int xd = x2-x1; int yd = y2-y1; return sqrt(xd*xd + yd*yd);}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ *//*// Function called whenever redisplay needed (try hiding the window and then// exposing it. The debug macro should print something.)*/static void display_CB(void){ glClear(GL_COLOR_BUFFER_BIT); /* clear the display */ drawLines(); drawGun(); glColor3d(.8, 0, 0); glBegin(GL_LINES); //Start Draw glVertex3f( 400, 0, 0); glVertex3f( pointX, pointY, 0); glEnd(); //End Draw glFlush(); /* Complete any pending operations */ glutSwapBuffers(); /* Make the drawing buffer the frame buffer and vice versa */}/* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ *//* Function called on key press */static void key_CB(unsigned char key, int x, int y) { if( key == 'q' ) { saveFile(); exit(0); }}/* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ *//* Function called on mouse click */static void mouse_CB(int button, int state, int x, int y) { //printf("%d %d %d\n", button, state, mode); if(button == 0 && state == 0) { mode = 2; mouseX = x; } if(button == 0 && state == 1) { mode = 1; mouseX = x; } if(button == 2 && state == 1) { fire(); }}/* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ *//* Function called on mouse move while depressed. */static void mouse_move_CB(int x, int y) { if(mode == 2) { if( x > mouseX) { gunAngle = gunAngle - 2; if( gunAngle < 0) gunAngle = 0; mouseX = x; } else if( x < mouseX) { gunAngle = gunAngle + 2; if( gunAngle > 180) gunAngle = 180; mouseX = x; } display_CB(); } //printf("%f\n", gunAngle);}