Chris Pollett >
Old Classes
> |
HW2 Solutions Page/****************************************************** * Project: CS116B Homework #2 * File: SplineDrawer.cpp * Purpose: Draw 3D extrusions of B-spline in * a GUI environment where user can click * points and then extrude the B-spline. * The user can also change his orientation * * Start date: Apr 8, 2005 * Programmer: Chris Pollett * * Remarks: Longer than I expected * *******************************************************/ #ifdef WIN32 #include<windows.h> //for windows #include <GL/glut.h> #include <GL/glu.h> #endif #ifdef __APPLE__ //for MAC /* I created my project under xcode. I chose new C++ tool as the kind of project. Then under External frameworks and libraries I added the two frameworks: OpenGL.framework and GLUT.framework. (Frameworks are in /Library/Frameworks) */ #include <OpenGL/gl.h> #include <OpenGL/glu.h> #include <GLUT/glut.h> #endif #ifdef linux // for linux /*My compile line was: g++ -I /usr/X11R6/include -L /usr/X11R6/lib -lglut -lGL \ -lGLU -lX11 -lXmu -lXi -lm name.cpp -o name */ #include <GL/glut.h> #include <GL/glu.h> #endif #include <cmath> #include <ctime> #include <iostream> #include <sstream> #include <vector> using namespace std; /* CONSTANTS */ //Font stuff void** FONT = GLUT_BITMAP_9_BY_15; const int FONT_WIDTH = 10; const int FONT_HEIGHT = 16; // Screen location of the label used to draw the position GLfloat cameraPositionLabelX = 20.0; GLfloat cameraPositionLabelY = 20.0; //4x4 homogeneous matrix stuff const int MATRIX_DIM = 4; const int MATRIX_SIZE = MATRIX_DIM*MATRIX_DIM; //Light constants const GLfloat AMBIENT_LIGHT[] = {.3, .3, .3, 1 }; const GLfloat SUN_VECTOR[] = {1000, 2500., 1000.0 }; //sun's position const GLfloat SUN_AMBIENT_SPECULAR[] = {1, 1, .3, 1 }; const GLfloat SUN_DIFFUSE[] = {.5, 1, 1, 1 }; //Draw MODES const int NUM_DRAW_MODES = 2; enum {USE_GLU, USE_HOMEMADE}; //Extrusion and Bezier constants const GLfloat EXTRUDE_DELTA = 10.0; const int SUBDIVISION_DEPTH = 3; // number of times to do subdivision when drawing curve const int NUM_FORWARD_DIFF_INTERVALS = 10; /* Prototypes */ void drawOneExtrusion(GLfloat direction[], vector<GLfloat> pts, GLfloat extent); /* CLASS DEFINITIONS */ /*-----------------------------------------------*/ class Extrusion /* PURPOSE: Encapsulates the notion of one B-spline curve extrusion Contains a sequence of control points for the B-spline, a direction in which the extrusion is going away from (a unit vector), and a distance the curve is extruded REMARK: It probably would be one elegant to have direction be the vector toward which we are extruding rather than away from which we are extruding. */ { private: vector<GLfloat> pts; // B-spline control points GLfloat direction[3]; // direction away from extrusion GLfloat extent; // how far public: /*-----------------------------------------------*/ Extrusion() /* PURPOSE: Constructor - sets up defaults for extrusion These are that the direction is away from the z axis RECEIVES: Nothing RETURNS: a default extrusion REMARKS: */ { direction[0] = 0.0; //initially 1. on z -axis direction[1] = 0.0; direction[2] = 1.0; pts.clear(); extent = 0.0; // intially no extrusion } /*-----------------------------------------------*/ void addPoint(GLfloat x, GLfloat y, GLfloat z) /* PURPOSE: Adds a control point to this extrusion RECEIVES: x,y,z coordinates of the point to add RETURNS: Nothing REMARKS: */ { pts.push_back(x); pts.push_back(y); pts.push_back(z); } /*-----------------------------------------------*/ void setDirection(GLfloat x, GLfloat y, GLfloat z) /* PURPOSE: Sets the current direction that the extrusion should be directed away from RECEIVES: x,y,z coordinates of the direction RETURNS: Nothing REMARKS: */ { direction[0] = x; direction[1] = y; direction[2] = z; } /*-----------------------------------------------*/ void addExtent(GLfloat value) /* PURPOSE: To add to the distance this extrusion extrudes an amount value RECEIVES: value - the amount more this extrusion should extrude RETURNS: Nothing REMARKS: */ { extent += value; } /*-----------------------------------------------*/ void draw(GLfloat drawSize) /* PURPOSE: Draws this extrusion RECEIVES: drawSize -- if the extrusion has a zero extent then we draw the control points for the extrusion as cubes of size drawSize RETURNS: Nothing REMARKS: */ { if(extent) { drawOneExtrusion(direction, pts, extent); } else { for(unsigned int i = 0; i < pts.size(); i += 3) { glPushMatrix(); glTranslatef(pts[i], pts[i+1], pts[i+2]); glutSolidCube(drawSize); glPopMatrix(); } } } }; /* GLOBALS */ GLsizei winWidth = 300, winHeight = 300; // used for size of window GLsizei initX = 50, initY = 50; // used for initial position of window //Camera Variables GLfloat cameraX = 0.0; //camera's direction (looks at origin) GLfloat cameraY = 0.0; GLfloat cameraZ = 1.0; GLfloat cameraDistance = 1500.0; //camera's initial distance from the origin GLfloat cameraDistanceDelta = 50.0; //amount distance can change when tap a key once GLfloat cameraNear = 1.1*winHeight; // nearest to the origin camera can get; GLfloat cameraFar = 20*winHeight; // farthest from the origin camera can get GLfloat upX = 0.0; //camera's up vector GLfloat upY = 1.0; GLfloat upZ = 0.0; GLfloat rightX = 1.0; //camera's right vector GLfloat rightY = 0.0; GLfloat rightZ = 0.0; //Draw Mode int drawMode = USE_GLU; //Display Lists GLuint axisList; //Vector holding all the extrusions so far vector<Extrusion> extrusions; /*-----------------------------------------------*/ void drawString(GLfloat x, GLfloat y, string outString) /* PURPOSE: Draws a string at the specified coordinates on the viewing plane RECEIVES: x - the x coordinate to draw the string at y - the y coordinate to draw the string at outString - the string to output RETURNS: Nothing REMARKS: */ { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, winWidth, 0, winHeight); for(unsigned int i = 0; i< outString.size(); i++) { glRasterPos2f( x + FONT_WIDTH*i, y); glutBitmapCharacter(FONT, outString[i]); } glPopMatrix(); glMatrixMode(GL_MODELVIEW); } /*-----------------------------------------------*/ void normalize(GLfloat& x, GLfloat& y, GLfloat& z) /* PURPOSE: normalizes the supplied x, y, z values RECEIVES: x,y,z values to compute a unit vector from RETURNS: Nothing REMARKS: */ { GLfloat length = sqrt(x*x + y*y+ z*z); x /= length; y /= length; z /= length; } /*-----------------------------------------------*/ void rotateVectorAboutVector(GLfloat angle, GLfloat rx, GLfloat ry, GLfloat rz, GLfloat& x, GLfloat& y, GLfloat& z) /* PURPOSE: rotate the second supplied vector by angle about first supplied vector RECEIVES: rx - x coordinate of axis of rotation ry - y coordinate of axis of rotation rz - z coordinate of axis of rotation x - x coordinate of vector to rotate y - y coordinate of vector to rotate z - z coordinate of vector to rotate RETURNS: nothing REMARKS: changes x, y, z by reference */ { GLdouble curPts[MATRIX_SIZE]; //matrix for vector to rotate int i; for(i = 0; i < MATRIX_DIM; i++) { curPts[i + 2*MATRIX_DIM] = 0; curPts[i + 3*MATRIX_DIM] = 0; } curPts[0] = x; curPts[1] = y; curPts[2] = z; curPts[3] = 1; //homogeneous coordinates glPushMatrix(); glLoadIdentity(); glRotatef(angle, rx, ry, rz); glMultMatrixd(curPts); glGetDoublev(GL_MODELVIEW_MATRIX, curPts); glPopMatrix(); x = (GLfloat) (curPts[0]/curPts[3]); y = (GLfloat) (curPts[1]/curPts[3]); z = (GLfloat) (curPts[2]/curPts[3]); //dividing since using homogeneous coordinates } /*-----------------------------------------------*/ void convertCubicBSplineBezier(GLfloat bArray[], GLfloat bezArray[]) /* PURPOSE: Converts an array of data for a cubic B-spline into an array of data for a cubic Bezier curve RECEIVES: bArray - the control point data for the B-spline (Notice 1-d array so values congruent to 0%3 are x's; 1%3 are y's and 2%3 are z's bezArray - array to store control points of Bezier curve RETURNS: Nothing REMARKS: bArray must have size offset+4*3 bezArray must have size 4*3 */ { // zeroth control point bezArray[0] = (bArray[0] + 4*bArray[3] + bArray[6])/6; bezArray[1] = (bArray[1] + 4*bArray[4] + bArray[7])/6; bezArray[2] = (bArray[2] + 4*bArray[5] + bArray[8])/6; // 3rd control point bezArray[9] = (bArray[3] + 4*bArray[6] + bArray[9])/6; bezArray[10] = (bArray[4] + 4*bArray[7] + bArray[10])/6; bezArray[11] = (bArray[5] + 4*bArray[8] + bArray[11])/6; // Now get 1st control point bezArray[3] = (bArray[6] - bArray[0])/6 + bezArray[0]; bezArray[4] = (bArray[7] - bArray[1])/6 + bezArray[1]; bezArray[5] = (bArray[8] - bArray[2])/6 + bezArray[2]; //Now get second control point bezArray[6] = bezArray[9 ] - (bArray[9 ] - bArray[3])/6; bezArray[7] = bezArray[10] - (bArray[10] - bArray[4])/6; bezArray[8] = bezArray[11] - (bArray[11] - bArray[5])/6; } /*-----------------------------------------------*/ void init(void) /* PURPOSE: sets the background color to black, sets up display list for coordinate axes, initializes extrusions vector RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { glClearColor(0.0, 0.0, 0.0, 0.0); axisList = glGenLists(1); GLUquadricObj* axis = gluNewQuadric(); gluQuadricDrawStyle(axis, GLU_FILL); glNewList(axisList, GL_COMPILE); glPushMatrix(); gluCylinder(axis, .1*winWidth, .1*winWidth, winHeight, 10, 10); glRotatef(90.0, 1, 0.0, 0.0); glTranslatef(0.0, 0.0, -1.0); gluCylinder(axis, .1*winWidth, .1*winWidth, winHeight, 10, 10); glRotatef(90.0, 0.0, 1.0, 0.0); glTranslatef(-1.0, 0.0, 0.0); gluCylinder(axis, .1*winWidth, .1*winWidth, winHeight, 10, 10); glPopMatrix(); glEndList(); Extrusion startExtrusion; extrusions.push_back(startExtrusion); } /*-----------------------------------------------*/ void drawLabels() /* PURPOSE: Draws the labels for what the current draw mode is and where the camera position is RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { stringstream labelStream; labelStream.precision(1); labelStream.setf(ios::fixed); labelStream << "x=" << cameraDistance*cameraX << "; y=" << cameraDistance*cameraY << "; z=" << cameraDistance*cameraZ; drawString(cameraPositionLabelX, cameraPositionLabelY, labelStream.str()); if(drawMode == USE_GLU) { drawString(cameraPositionLabelX, winHeight - cameraPositionLabelY - FONT_HEIGHT, "Spline Draw Mode: GLU"); } else { drawString(cameraPositionLabelX, winHeight - cameraPositionLabelY - FONT_HEIGHT, "Spline Draw Mode: HomeMade"); } } /*-----------------------------------------------*/ void drawOneGLUExtrusion(GLfloat direction[], vector<GLfloat> pts, GLfloat extent) /* PURPOSE: Draws a spline surface, using OpenGL spline functions, which is the extrusion of the supplied points of the passed extent in the given direction RECEIVES: pts - points to use in curve (assumed to be divisble by 3) direction - 3-array direction to extrude towards extent - distance to extrude numPts - number of points in curve RETURNS: Nothing REMARKS: */ { int numPts = pts.size(); GLfloat vertices[48]; GLfloat vKnots[8] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // for starting curve we use a uniform B-spline GLfloat uKnots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; // for extruded direction we use a Bezier curve GLUnurbsObj *surface = gluNewNurbsRenderer(); for(int i = 0; i < numPts - 9; i += 3 ) { /* For each point that has been clicked we take it, and the three points after it to make surface which in one direction is a uniform cubic B-spline curve on those points and in the other direction is a cubic Bezier curve of conisting of control points all on a line in the direction of the extrusion */ for(int k = 0; k < 12; k += 3) // 12 is from 4 points each of which has x,y,z { for(int j=0; j < 4; j++) { /* Give Bezier control points all on a line. Rather than equally space them, which means I have to divide by 3, I probably should have done something with powers of 2. */ vertices[k + j*12] = pts[i + k] - j*extent*direction[0]/3; vertices[k + j*12 + 1] = pts[i + k + 1] - j*extent*direction[1]/3; vertices[k + j*12 + 2] = pts[i + k + 2] - j*extent*direction[2]/3; } } gluBeginSurface(surface); gluNurbsSurface(surface, 8, uKnots, 8, vKnots, 12, 3, vertices, 4, 4, GL_MAP2_VERTEX_3); gluEndSurface(surface); } gluDeleteNurbsRenderer(surface); } /*-----------------------------------------------*/ void drawExtrusionUsingForwardDifferencing(GLfloat offsetVector[], GLfloat bezCurve[], int numIntervals) /* PURPOSE: draws an extruded version of the supplied bezier curve RECEIVES: offsetVector - vector giving direction to extrude bezCurve - single array with four control points of the Bezier Curve depth - how many subdivisions to do before drawing using forward differencing RETURNS: Nothing REMARKS: */ { /* To begin let's work out the coefficient \vec{a}, \vec{b}, \vec{c}, \vec{d} in \vec{a}u^3 + \vec{b}u^2 +\vec{c}u +\vec{d} */ int i,j; GLfloat a[3], b[3], c[3] ,d[3]; for(j = 0; j < 3; j++) { a[j] = -bezCurve[j] + 3*bezCurve[j + 3] - 3*bezCurve[j + 6] + bezCurve[j + 9]; b[j] = 3*bezCurve[j] - 6*bezCurve[j + 3] + 3*bezCurve[j + 6]; c[j] = -3*bezCurve[j] + 3*bezCurve[j + 3]; d[j] = bezCurve[j]; } /* Now we initialze our various forward differences */ GLfloat delta = 1.0/( (GLfloat)numIntervals); GLfloat zeroDiff[3], firstDiff[3], secondDiff[3], thirdDiff[3]; GLfloat nextZeroDiff[3], nextFirstDiff[3], nextSecondDiff[3]; for(int j = 0; j < 3; j++) { zeroDiff[j] = d[j]; firstDiff[j] = ((a[j]*delta + b[j])*delta +c[j])*delta; //Look it's Horner's rule!! secondDiff[j] = (6*a[j]*delta + 2*b[j])*delta*delta; thirdDiff[j] = 6*a[j]*delta*delta*delta; } //Now let's draw the Bezier curve for(i = 0; i < numIntervals; i++) { // compute next step along curve for(j = 0; j < 3; j++) { nextZeroDiff[j] = zeroDiff[j] + firstDiff[j]; nextFirstDiff[j] = firstDiff[j] + secondDiff[j]; nextSecondDiff[j] = secondDiff[j] + thirdDiff[j]; } //Draw a Quad for this part of the extrusion glBegin(GL_QUADS); glVertex3f(zeroDiff[0], zeroDiff[1], zeroDiff[2]); glVertex3f(zeroDiff[0] + offsetVector[0], zeroDiff[1] + offsetVector[1], zeroDiff[2] + offsetVector[2]); glVertex3f(nextZeroDiff[0] + offsetVector[0], nextZeroDiff[1] + offsetVector[1], nextZeroDiff[2] + offsetVector[2]); glVertex3f(nextZeroDiff[0], nextZeroDiff[1], nextZeroDiff[2]); glEnd(); //set up for next iteration for(j = 0; j < 3; j++) { zeroDiff[j] = nextZeroDiff[j]; firstDiff[j] = nextFirstDiff[j]; secondDiff[j] = nextSecondDiff[j]; } } } /*-----------------------------------------------*/ void drawExtrusionUsingSubdivisions(GLfloat offsetVector[], GLfloat bezCurve[], int depth) /* PURPOSE: draws an extruded version of the supplied bezier curve RECEIVES: offsetVector - vector giving direction to extrude bezCurve - single array with four control points of the Bezier Curve depth - how many subdivisions to do before drawing using forward differencing RETURNS: Nothing REMARKS: */ { if(depth <= 1) { drawExtrusionUsingForwardDifferencing(offsetVector, bezCurve, NUM_FORWARD_DIFF_INTERVALS); } else { depth--; GLfloat frontHalf[12], backHalf[12], tmp[3]; for(int i = 0; i < 3; i++) { frontHalf[i] = bezCurve[i]; // zeroth control front backHalf[i+9] = bezCurve[i+9]; // third control back frontHalf[i+3] = (bezCurve[i] + bezCurve[i+3])/2; //first control front backHalf[i+6] = (bezCurve[i+6] + bezCurve[i+9])/2; // second control back tmp[i] = (bezCurve[i+3] + bezCurve[i+6])/2; //tmp point use for remaining controls frontHalf[i+6] = (frontHalf[i+3] + tmp[i])/2; // second control front backHalf[i+3] = (backHalf[i+6] + tmp[i])/2; // first control back backHalf[i] = (frontHalf[i+6] + backHalf[i+3])/2; // zeroth control back frontHalf[i+9] = backHalf[i]; // third control front } drawExtrusionUsingSubdivisions(offsetVector, frontHalf, depth); drawExtrusionUsingSubdivisions(offsetVector, backHalf, depth); } } /*-----------------------------------------------*/ void drawOneHomeExtrusion(GLfloat direction[], vector<GLfloat> pts, GLfloat extent) /* PURPOSE: Draws a spline surface, using spline drawing functions created for this assignment, which is the extrusion of the supplied points of the passed extent in the given direction RECEIVES: pts - points to use in curve (assumed to be divisble by 3) direction - 3-array direction to extrude towards extent - distance to extrude numPts - number of points in curve RETURNS: Nothing REMARKS: */ { int numPts = pts.size(); GLfloat bPoints[12], bezPoints[12]; GLfloat dirVector[3]; for(int k = 0; k < 3; k++) { dirVector[k] = - direction[k]*extent; } for(int i = 0; i < numPts - 9; i += 3 ) { for(int j = 0; j < 12; j++) { bPoints[j] = pts[j + i]; } convertCubicBSplineBezier(bPoints, bezPoints); drawExtrusionUsingSubdivisions(dirVector, bezPoints, SUBDIVISION_DEPTH); } } /*-----------------------------------------------*/ void drawOneExtrusion(GLfloat direction[], vector<GLfloat> pts, GLfloat extent) /* PURPOSE: Draws a spline surface which is the extrusion of the supplied points of the passed extent in the given direction RECEIVES: pts - points to use in curve direction - 3-array direction to extrude towards extent - distance to extrude numPts - number of points in curve RETURNS: Nothing REMARKS: */ { switch(drawMode) { case USE_GLU: drawOneGLUExtrusion(direction, pts, extent); break; case USE_HOMEMADE: drawOneHomeExtrusion(direction, pts, extent); break; } } /*-----------------------------------------------*/ void drawExtrusions() /* PURPOSE: Draws all of the extrusions in the scene RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { // Set up how we draw the points. GLfloat drawSize; GLfloat sizes[2]; // Store supported point size range GLfloat step; // Store supported point size increments // Get supported point size range and step size glGetFloatv(GL_POINT_SIZE_RANGE,sizes); glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step); // Specify the point size drawSize = (winWidth < winHeight) ? winWidth/50 : winHeight/50; if(drawSize > sizes[1]) drawSize = sizes[1]; drawSize = winWidth/100; for(unsigned int i = 0; i < extrusions.size(); i++) { extrusions[i].draw(drawSize); } } /*-----------------------------------------------*/ void drawFn() /* PURPOSE: Used to craw the complete scene saturn + probe and to swap scene buffers RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, SUN_VECTOR); glLightfv(GL_LIGHT0, GL_AMBIENT, SUN_AMBIENT_SPECULAR); glLightfv(GL_LIGHT0, GL_DIFFUSE, SUN_DIFFUSE); glLightfv(GL_LIGHT0, GL_SPECULAR, SUN_AMBIENT_SPECULAR); glEnable(GL_LIGHT0); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, AMBIENT_LIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-winWidth/2, winWidth/2, -winHeight/2, winHeight/2, winWidth/2, 20*winWidth); gluLookAt(cameraX*cameraDistance, cameraY*cameraDistance, cameraZ*cameraDistance, 0.0, 0.0, 0.0, upX, upY, upZ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //Compute Depths glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glCallList(axisList); // draw the coordinate axes drawLabels(); drawExtrusions(); glutSwapBuffers(); } /*-----------------------------------------------*/ void mouseFn(int button, int state, int xPos, int yPos) /* PURPOSE: Handle nonspecial key events (mainly space key and 1 key) RECEIVES: button - which button was pressed state - whether button is up or down xPos - x position of mouse yPos - y position of mouse RETURNS: Nothing REMARKS: */ { GLfloat adjustedRightPos = xPos - winWidth/2; // position in right direction relative to camera GLfloat adjustedUpPos = yPos - winHeight/2; // position in Up direction relative to camera GLfloat adjustedDistance = cameraDistance - .51*winWidth; //put point so not immediately clipped (winWidth/2 is distance to clipping plane) GLfloat x = adjustedDistance*cameraX + adjustedRightPos*rightX - adjustedUpPos*upX; GLfloat y = adjustedDistance*cameraY + adjustedRightPos*rightY - adjustedUpPos*upY; GLfloat z = adjustedDistance*cameraZ + adjustedRightPos*rightZ - adjustedUpPos*upZ; if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { extrusions[extrusions.size()-1].addPoint(x, y, z); glutPostRedisplay(); // cause scene to be redrawn } } /*-----------------------------------------------*/ void keyFn(unsigned char key, int xPos, int yPos) /* PURPOSE: Handle nonspecial key events (mainly space key and 1 key) RECEIVES: key - key being pressed xPos - x position of mouse yPos - y position of mouse RETURNS: Nothing REMARKS: */ { bool sceneChanged = false; int end = extrusions.size() - 1; switch(key) { case '1': drawMode ++; drawMode %= NUM_DRAW_MODES; sceneChanged = true; break; case ' ': extrusions[end].addExtent(EXTRUDE_DELTA); extrusions[end].setDirection(cameraX, cameraY, cameraZ); sceneChanged = true; break; } if(sceneChanged) { glutPostRedisplay(); // cause scene to be redrawn } } /*-----------------------------------------------*/ void keyUpFn(unsigned char key, int xPos, int yPos) /* PURPOSE: Handle nonspecial key release events This is mainly used for the space key to handle when the extrusion stops RECEIVES: key - key being pressed xPos - x position of mouse yPos - y position of mouse RETURNS: Nothing REMARKS: */ { Extrusion nextExtrusion; switch(key) { case ' ': extrusions.push_back(nextExtrusion); break; } } /*-----------------------------------------------*/ void specialKeyFn(int key, int xPos, int yPos) /* PURPOSE: Handle arrow key events RECEIVES: key - key being pressed xPos - x position of mouse yPos - y position of mouse RETURNS: Nothing REMARKS: */ { bool sceneChanged = false; int modifiers = glutGetModifiers(); switch(key) { case GLUT_KEY_UP: if(modifiers == GLUT_ACTIVE_SHIFT) { cameraDistance -= cameraDistanceDelta; if(cameraDistance < cameraNear) cameraDistance = cameraNear; } else { rotateVectorAboutVector(-1, rightX, rightY, rightZ, cameraX, cameraY, cameraZ); rotateVectorAboutVector(-1, rightX, rightY, rightZ, upX, upY, upZ); } sceneChanged = true; break; case GLUT_KEY_DOWN: if(modifiers == GLUT_ACTIVE_SHIFT) { cameraDistance += cameraDistanceDelta; if(cameraDistance > cameraFar) cameraDistance = cameraFar; } else { rotateVectorAboutVector(1, rightX, rightY, rightZ, cameraX, cameraY, cameraZ); rotateVectorAboutVector(1, rightX, rightY, rightZ, upX, upY, upZ); } sceneChanged = true; break; case GLUT_KEY_LEFT: rotateVectorAboutVector(-1, cameraX, cameraY, cameraZ, upX, upY, upZ); rotateVectorAboutVector(-1, cameraX, cameraY, cameraZ, rightX, rightY, rightZ); sceneChanged = true; break; case GLUT_KEY_RIGHT: rotateVectorAboutVector(1, cameraX, cameraY, cameraZ, upX, upY, upZ); rotateVectorAboutVector(1, cameraX, cameraY, cameraZ, rightX, rightY, rightZ); sceneChanged = true; break; } if(sceneChanged) { normalize(cameraX, cameraY, cameraZ); normalize(upX, upY, upZ); normalize(rightX, rightY, rightZ); glutPostRedisplay(); // cause scene to be redrawn } } /*-----------------------------------------------*/ void reshapeFn(int newWidth, int newHeight) /* PURPOSE: To redraw scene when window gets resized. RECEIVES: newWidth -- new window x size newHeight -- new window y size RETURNS: Nothing REMARKS: */ { glViewport(0, 0, newWidth, newHeight); winWidth = newWidth; winHeight = newHeight; glutPostRedisplay(); // cause scene to be redrawn } int main (int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition(initX, initY); glutInitWindowSize(winWidth, winHeight); glutCreateWindow("Constructive Spline Drawer"); init(); glutDisplayFunc(drawFn); glutReshapeFunc(reshapeFn); glutSpecialFunc(specialKeyFn); glutKeyboardFunc(keyFn); glutKeyboardUpFunc(keyUpFn); glutMouseFunc(mouseFn); glutMainLoop(); return 0; } |