Chris Pollett > Old Classes
> |
HW4 Solutions PageIn the interest of getting up solutions in a timely fashion and since I had a cold for a couple weeks, I am using student solutions for HW4 and HW5. Below is the homework the grader thought was the best: /************************************************* Project: CS116A Homework #4 File: viewport.cpp Purpose: to play with clipping window Date: Nov, 17, 2004 Programmer: Gabriel Laden **************************************************/ #include <stdlib.h> #include <cmath> #include <cstdio> #include <iostream> #include <fstream> #include <GL/glut.h> using namespace std; #define XSTATE 1 #define YSTATE 2 #define ZSTATE 3 #define LEFT 0 #define RIGHT 1 #define STRAIGHT 2 #define FORWARD 0 #define REVERSE 1 static int windowID1, windowID2; static int state = ZSTATE; static int xMax, yMax, zMax; static int xMaxScreen, yMaxScreen; static int theta; static float xTrans, yTrans; static int** list; static GLint*** ptsWindow1; static GLint*** ptsWindow2; static GLint* rectangle; static GLint* origRectangle; /*************************************************/ void init1(void) /* PURPOSE: Initializes window1 with some OpenGL methods */ { glutSetWindow(windowID1); glClearColor(0.0, 0.0, 0.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //rotation accumulator theta = 0; //translation accumulator xTrans = 0; yTrans = 0; //this is the red dashed rectangle rectangle = (GLint*)malloc(sizeof(GLint)*8); rectangle[0] = 0; rectangle[1] = 0; rectangle[2] = 0; rectangle[7] = 0; if(state == XSTATE){ xMaxScreen = yMax; yMaxScreen = zMax; glutReshapeWindow(yMax, zMax); gluOrtho2D(0.0, yMax, 0.0, zMax); rectangle[3] = zMax/2; rectangle[4] = yMax/2; rectangle[5] = zMax/2; rectangle[6] = yMax/2; } if(state == YSTATE){ xMaxScreen = zMax; yMaxScreen = xMax; glutReshapeWindow(zMax, xMax); gluOrtho2D(0.0, zMax, 0.0, xMax); rectangle[3] = xMax/2; rectangle[4] = zMax/2; rectangle[5] = xMax/2; rectangle[6] = zMax/2; } if(state == ZSTATE){ xMaxScreen = xMax; yMaxScreen = yMax; glutReshapeWindow(xMax, yMax); gluOrtho2D(0.0, xMax, 0.0, yMax); rectangle[3] = yMax/2; rectangle[4] = xMax/2; rectangle[5] = yMax/2; rectangle[6] = xMax/2; } //save a copy of this original origRectangle = (GLint*)malloc(sizeof(GLint)*8); for(int i=0; i<8; i++){ origRectangle[i] = rectangle[i]; } } /*************************************************/ void init2(void) //PURPOSE: Initializes window2 with some OpenGL methods { glutSetWindow(windowID2); glClearColor(0.0, 0.0, 0.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(state == XSTATE){ gluOrtho2D(0.0, yMax/2, 0.0, zMax/2); glutReshapeWindow(yMax/2, zMax/2); } if(state == YSTATE){ gluOrtho2D(0.0, zMax/2, 0.0, xMax/2); glutReshapeWindow(zMax/2, xMax/2); } if(state == ZSTATE){ gluOrtho2D(0.0, xMax/2, 0.0, yMax/2); glutReshapeWindow(xMax/2, yMax/2); } } /*************************************************/ void drawview1(void) /* PURPOSE: draw the two windows with view of scene */ { glutSetWindow(windowID1); glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 1.0); int listLength = list[0][0]; ptsWindow1 = (int***)malloc(sizeof(int**)*listLength); for(int i=0; i<listLength; i++){ int rowLength = list[i+1][0]; ptsWindow1[i] = (int**)malloc(sizeof(int*)*rowLength); if(state == XSTATE){ //pick out the y-z coords int index = 2; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow1[i][j][0] = list[i+1][index]; ptsWindow1[i][j][1] = list[i+1][index+1]; } } if(state == YSTATE){ //pick out the z-x coords int index = 3; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow1[i][j][0] = list[i+1][index]; ptsWindow1[i][j][1] = list[i+1][index-2]; } } if(state == ZSTATE){ //pick out the x-y coords int index = 1; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow1[i][j][0] = list[i+1][index]; ptsWindow1[i][j][1] = list[i+1][index+1]; } } } //ok, now draw the lines in window1 for(int i=0; i<listLength; i++){ glBegin(GL_LINE_LOOP); for(int j=0; j<list[i+1][0]; j++){ glVertex2iv(ptsWindow1[i][j]); } glEnd(); } //draw the red rectangle box glColor3f(1.0, 0.0, 0.0); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x00FF); glBegin(GL_LINE_LOOP); glVertex2i(rectangle[0],rectangle[1]); glVertex2i(rectangle[2],rectangle[3]); glVertex2i(rectangle[4],rectangle[5]); glVertex2i(rectangle[6],rectangle[7]); glEnd(); glDisable(GL_LINE_STIPPLE); glFlush(); } /*************************************************/ void drawview2(void) //PURPOSE: draw the two windows with view of scene { glutSetWindow(windowID2); glutPositionWindow(400, 400); glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 1.0); int listLength = list[0][0]; ptsWindow2 = (int***)malloc(sizeof(int**)*listLength); for(int i=0; i<listLength; i++){ int rowLength = list[i+1][0]; ptsWindow2[i] = (int**)malloc(sizeof(int*)*rowLength); if(state == XSTATE){ //pick out the y-z coords int index = 2; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow2[i][j][0] = list[i+1][index]; ptsWindow2[i][j][1] = list[i+1][index+1]; } } if(state == YSTATE){ //pick out the z-x coords int index = 3; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow2[i][j][0] = list[i+1][index]; ptsWindow2[i][j][1] = list[i+1][index-2]; } } if(state == ZSTATE){ //pick out the x-y coords int index = 1; for(int j=0; j<rowLength; j++, index+=3){ ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2); ptsWindow2[i][j][0] = list[i+1][index]; ptsWindow2[i][j][1] = list[i+1][index+1]; } } } //reverse translate the points //reverse rotate the points float x, y; float COSDEG = cos(-theta * 3.1415926536/180); float SINDEG = sin(-theta * 3.1415926536/180); for(int i=0; i<list[0][0]; i++){ glBegin(GL_LINE_LOOP); for(int j=0; j<list[i+1][0]; j++){ x = ptsWindow2[i][j][0] - xTrans; y = ptsWindow2[i][j][1] - yTrans; glVertex2i(x*COSDEG - y*SINDEG, x*SINDEG + y*COSDEG); } glEnd(); } glFlush(); } /*-----------------------------------------------*/ bool rotate(int direction) /* PURPOSE: Rotates the rectangle, if possible RECEIVES: direction - use LEFT or RIGHT */ { /* translate first point back to origin and translate other points by that amount first point is fixed at origin, rotate the other points +/- translate points back check to see if in bounds */ //save a copy of rectangle, if we have to restore GLint* temp =(GLint*)malloc(sizeof(GLint)*8); for(int i=0; i<8; i++){ temp[i] = rectangle[i]; } int tempTheta = theta; //rotate initial rectangle by accumulated theta if(direction == LEFT){ theta++; } else if(direction == RIGHT){ theta--; } float x, y; float COSDEG = cos(theta * 3.1415926536/180); float SINDEG = sin(theta * 3.1415926536/180); for(int i=2; i<8; i+=2){ x = origRectangle[i]*COSDEG - origRectangle[i+1]*SINDEG; y = origRectangle[i]*SINDEG + origRectangle[i+1]*COSDEG; rectangle[i] = x; rectangle[i+1] = y; } //translate back for(int i=2; i<8; i+=2){ rectangle[i] += xTrans; rectangle[i+1] += yTrans; } //check if points still inbounds bool fail = false; for(int i=0; i<8 && !fail; i+=2){ if(rectangle[i] < 0 || rectangle[i] > xMaxScreen){ fail = true; } if(rectangle[i+1] < 0 || rectangle[i+1] > yMaxScreen){ fail = true; } } if(fail){ //write back the temp array to the rectangle for(int i=0; i<8; i++){ rectangle[i] = temp[i]; } theta = tempTheta; return false; } return true; } /*-----------------------------------------------*/ void move(int direction) /* PURPOSE: Moves the rectangle, if possible RECEIVES: direction - use FORWARD or REVERSE */ { //save a copy of rectangle, if we have to restore GLint* temp =(GLint*)malloc(sizeof(GLint)*8); for(int i=0; i<8; i++){ temp[i] = rectangle[i]; } int tempXTrans = xTrans; int tempYTrans = yTrans; //points to use for slope int x0 = rectangle[0]; int y0 = rectangle[1]; int xEnd = rectangle[2]; int yEnd = rectangle[3]; //handle special cases first if(x0 == xEnd) { //vertical if(direction == FORWARD){ if(yEnd > y0){ yTrans++; } else{ yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i+1] = origRectangle[i+1] + yTrans; } } else if(direction == REVERSE){ if(yEnd < y0){ yTrans++; } else{ yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i+1] = origRectangle[i+1] + yTrans; } } } else if(y0 == yEnd) { //horizontal if(direction == FORWARD){ if(xEnd > x0){ xTrans++; } else{ xTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; } } else if(direction == REVERSE){ if(xEnd < x0){ xTrans++; } else{ xTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; } } } else { if((yEnd-y0)/(xEnd-x0) == 1){ //positive diagonal if(direction == FORWARD){ if(yEnd > y0){ xTrans++; yTrans++; } else{ xTrans--; yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; rectangle[i+1] = origRectangle[i+1] + yTrans; } } else if(direction == REVERSE){ if(yEnd < y0){ xTrans++; yTrans++; } else{ xTrans--; yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; rectangle[i+1] = origRectangle[i+1] + yTrans; } } } if((yEnd-y0)/(xEnd-x0) == -1){ //negative diagonal if(direction == FORWARD){ if(yEnd > y0){ xTrans--; yTrans++; } else{ xTrans++; yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; rectangle[i+1] = origRectangle[i+1] + yTrans; } } else if(direction == REVERSE){ if(yEnd < y0){ xTrans--; yTrans++; } else{ xTrans++; yTrans--; } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; rectangle[i+1] = origRectangle[i+1] + yTrans; } } } //non special cases float dy = yEnd - y0; float dx = xEnd - x0; float m = dy / dx; if(m > 0 && m < 1){ if((dy > 0 && direction == FORWARD) || (dy < 0 && direction == REVERSE)){ xTrans++; yTrans += m; } else{ xTrans--; yTrans -= m; } } else if(m > 1){ if((dy > 0 && direction == FORWARD) || (dy < 0 && direction == REVERSE)){ yTrans++; xTrans += 1/m; } else{ yTrans--; xTrans -= 1/m; } } else if(m > -1 && m < 0){ if((dy < 0 && direction == FORWARD) || (dy > 0 && direction == REVERSE)){ xTrans++; yTrans += m; } else{ xTrans--; yTrans -= m; } } else if (m < -1){ if((dy < 0 && direction == FORWARD) || (dy > 0 && direction == REVERSE)){ yTrans--; xTrans -= 1/m; } else{ yTrans++; xTrans += 1/m; } } for(int i=0; i<8; i+=2){ rectangle[i] = origRectangle[i] + xTrans; rectangle[i+1] = origRectangle[i+1] + yTrans; } } bool fail = false; //now rotate rectangle if(!rotate(STRAIGHT)){ fail = true; } //test xy coords for(int i=0; i<8 && !fail; i+=2){ if(rectangle[i] < 0 || rectangle[i] > xMaxScreen){ fail = true; } if(rectangle[i+1] < 0 || rectangle[i+1] > yMaxScreen){ fail = true; } if(xTrans < 0 || xTrans > xMaxScreen){ fail = true; } if(yTrans < 0 || yTrans > yMaxScreen){ fail = true; } } if(fail){ //write back the temp array to the rectangle for(int i=0; i<8; i++){ rectangle[i] = temp[i]; } xTrans = tempXTrans; yTrans = tempYTrans; } } /*-----------------------------------------------*/ void keyHandleFn(int key, int x, int y) /* PURPOSE: Handles keyboard events. The keyboard was very useful in testing this project RECEIVES: key - the special key (non a-z letter) pressed */ { switch(key) { case GLUT_KEY_LEFT: //rotate left rotate(LEFT); break; case GLUT_KEY_RIGHT: //rotate right rotate(RIGHT); break; case GLUT_KEY_UP: //forward move(FORWARD); break; case GLUT_KEY_DOWN: //reverse move(REVERSE); break; } glutPostRedisplay(); glutSetWindow(windowID2); glutPostRedisplay(); } /*-----------------------------------------------*/ void keyHandleFn1(unsigned char key, int x, int y) /* PURPOSE: Handles keyboard events like space and esc. The keyboard was very useful in testing this project RECEIVES: key - the special key (non a-z letter) pressed x - screen X position y - screen Y position RETURNS: nothing REMARKS: */ { switch(key) { case 'x': state = XSTATE; break; case 'y': state = YSTATE; break; case 'z': state = ZSTATE; break; } init1(); init2(); } /*************************************************/ void readParam(char f[]) /* PURPOSE: reads input parameters.txt, writes to globals */ { //read the txt file ifstream file(f, ios::in); char line[80]; //x, y window dimensions file.getline(line, 80); xMax = atoi(strtok(line, " ")); yMax = atoi(strtok(NULL, " ")); zMax = atoi(strtok(NULL, " ")); //# of polylines file.getline(line, 80); int length = atoi(strtok(line, " ")); list = (int**)malloc(sizeof(int*)*(length + 1)); list[0] = (int*)malloc(sizeof(int)); list[0][0] = length; for(int i=1; i<=length; i++){ file.getline(line, 80); int polyLength = atoi(strtok(line, " ")); list[i] = (int*)malloc(sizeof(int)*(polyLength * 3 + 1)); list[i][0] = polyLength; for(int j=1; j<polyLength*3+1; j++){ list[i][j] = atoi(strtok(NULL, " ")); } } file.close(); } /*************************************************/ void main(int argc, char** argv) /* PURPOSE: boilerplate code which launches windows */ { if(argc != 2){ cout << "Usage: viewport file\n"; } else{ readParam(argv[1]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(0, 0); //second window windowID2 = glutCreateWindow("Second Window"); init2(); glutDisplayFunc(drawview2); //first window windowID1 = glutCreateWindow("First Window"); init1(); glutDisplayFunc(drawview1); //Set up keyboard handlers glutSpecialFunc(keyHandleFn); // for arrow keys glutKeyboardFunc(keyHandleFn1); // for space esc glutMainLoop(); } } |