Chris Pollett >
Old Classes
> |
HW1 Solutions Page/****************************************************** * Project: CS116B Homework #1 * File: cassini.cpp * Purpose: Code to draw the Cassini space probe * orbiting Saturn * * Start date: Feb 24, 2005 * Programmer: Chris Pollett * * Remarks: Although the C++ coding Guideline say you should not have magic * numbers this could be very tedious and unclear when arranging * the parts of the space probe and saturn. Instead, I separated * where these were drawn into separate functions but left * the rotation and translations of individual compoenents in these * functions. All other magic numbers were pulled out as constants. * *******************************************************/ #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> using namespace std; /* CONSTANTS */ //Light constants const GLfloat AMBIENT_LIGHT[] = {.2, .2, .2, 1 }; const GLfloat SUN_VECTOR[] = {100., 30., 70 }; //sun's position const GLfloat SUN_AMBIENT_SPECULAR[] = {.8, .8, .3, 1 }; const GLfloat SUN_DIFFUSE[] = {.5, .8, .8, 1 }; //Camera constants const GLfloat CAMERA_X = -15.0; //camera's position (looks at origin) const GLfloat CAMERA_Y = -8.0; const GLfloat CAMERA_Z = 20.0; const GLfloat UP_X = 0.0; //camera's up vector const GLfloat UP_Y = 1.0; const GLfloat UP_Z = 0.0; //View Volume const GLfloat NEAR_CLIP = 2.0; const GLfloat FAR_CLIP = 100; //Animation Speed clock_t FRAME_TIME = CLOCKS_PER_SEC/30; int ORBIT_TIME = 15; //time to make one orbit in seconds int FRAMES_PER_ORBIT = ORBIT_TIME*CLOCKS_PER_SEC/FRAME_TIME; /* GLOBALS */ GLsizei winWidth = 500, winHeight = 500; // used for size of window GLsizei initX = 50, initY = 50; // used for initial position of window GLfloat cassiniAngle = 0.0; //measures how far Cassini has roated in its orbit clock_t animationTime = clock(); // keeps time of last frame update /*-----------------------------------------------*/ void init(void) /* PURPOSE: sets the background color to black RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { glClearColor(0.0, 0.0, 0.0, 0.0); } /*-----------------------------------------------*/ void makeSunLight() /* PURPOSE: creates a light source which is supposed to fake the sun 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); } /*-----------------------------------------------*/ void drawSaturn() /* PURPOSE: Draws a 3D Saturns (a sphere and a ring) RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { GLfloat ambColor[]={1, 0.9, .6}; GLfloat specColor[]={.5, .5, .1}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambColor); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50); GLUquadricObj* saturn = gluNewQuadric(); gluQuadricDrawStyle(saturn, GLU_FILL); gluSphere(saturn, 5, 40, 40); gluDeleteQuadric(saturn); glPushMatrix(); glRotatef(90.0, 1.0, .5, 0.0); GLUquadricObj* rings = gluNewQuadric(); gluQuadricDrawStyle(rings, GLU_FILL); gluDisk(rings, 7, 10, 20, 20); gluDeleteQuadric(rings); glPopMatrix(); } /*-----------------------------------------------*/ void drawCassini() /* PURPOSE: Draws the Cassini space probe at the current aninimation angle RECEIVES: Nothing RETURNS: Nothing REMARKS: cassiniAngle -- is the current angle in probes rotation plane */ { GLfloat dishColor[]={.8, .8, .8}; GLfloat bodyColor[]={.4, .4, .2}; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50); glPushMatrix(); glRotatef(cassiniAngle, 0.0, 1.0, 0.0); glTranslatef(0.0, 0.0, -14.0); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, dishColor); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, dishColor); glutSolidCone(2.0, 1, 20, 20); glTranslatef(0.0, 0.0, 1.5); glPushMatrix(); glRotatef(90, 0.0, 1.0, 0.0); GLUquadricObj* antenna = gluNewQuadric(); gluQuadricDrawStyle(antenna, GLU_FILL); gluCylinder(antenna, .1, .1, 6.0, 20, 20); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(120, 1.0, 0.0, 0.0); gluCylinder(antenna, .05, .05, 4.0, 20, 20); glRotatef(30, 1.0, 0.0, 0.0); gluCylinder(antenna, .05, .05, 4.0, 20, 20); gluDeleteQuadric(antenna); glPopMatrix(); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, bodyColor); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, bodyColor); glutSolidCube(2.0); glPopMatrix(); } /*-----------------------------------------------*/ void drawFn() /* PURPOSE: Used to craw the complete scene saturn + probe and to swap scene buffers RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { //Compute Depths glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); makeSunLight(); drawSaturn(); drawCassini(); glutSwapBuffers(); } /*-----------------------------------------------*/ void animateFn() /* PURPOSE: Uses system clock to update the angle of the cassini space probe RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { clock_t newTime = clock(); int framesElapsed = (newTime - animationTime)/FRAME_TIME; if(framesElapsed >= 1) { animationTime = newTime; cassiniAngle += GLfloat(360*framesElapsed)/FRAMES_PER_ORBIT; if(cassiniAngle > 360) cassiniAngle -=360; 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); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, NEAR_CLIP, FAR_CLIP); gluLookAt(CAMERA_X, CAMERA_Y, CAMERA_Z, 0.0, 0.0, 0.0, UP_X, UP_Y, UP_Z); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main (int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); /*Notice added GLUT_DEPTH to do depth detection on Saturn's ring I am using double buffering for the animation */ glutInitWindowPosition(initX, initY); glutInitWindowSize(winWidth, winHeight); glutCreateWindow("Saturn and Cassini"); init(); glutDisplayFunc(drawFn); glutReshapeFunc(reshapeFn); glutIdleFunc(animateFn); glutMainLoop(); return 0; } /****************************************************** * Project: CS116B Homework #1 * File: spline.cpp * Purpose: Code to draw a cardinal spline specified * in the command line arguments to a GLUT window * * Start date: Feb 24, 2005 * Programmer: Chris Pollett * * Remarks: Command line looks like: * spline npts x1 y1 x2 y2 ... xnpts ynpts * * Matrix multiplication used to calculate spline point down with * OpenGL's matrix multiple so I had to take transposes of some * matrices. * This program assumes the spline can be drawn within * the current window dimension 0,0, winWidth, winHeight * *******************************************************/ #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 <iostream> #include <sstream> using namespace std; /* CONSTANTS */ const GLdouble TENSION = 1/2; const GLdouble s = (1 - TENSION)/2; const int SPLINE_NUM = 4; /* Degree of the cardinal spline plus one. Number of points to uniquely fix the spline As my code hinges on the fact this matches the size of matrices used in OpenGL this number cannot be altered and still have this program work. */ const int MATRIX_SIZE = SPLINE_NUM*SPLINE_NUM; const GLdouble splineMatrix[MATRIX_SIZE] = { -s, 2*s, -s, 0, 2 - s, s - 3, 0, 1, s - 2, 3 - 2*s, s, 0, s, -s, 0, 0 }; /* Matrix for cardinal spline -- transpose of book's since using OpenGL matrix mult which is on left hand side */ // Error Codes const int ERROR_FORMAT = 1; const int ERROR_ARGS = 4; /* GLOBALS */ GLsizei winWidth = 500, winHeight = 500; // used for size of window GLsizei initX = 50, initY = 50; // used for initial position of window GLsizei uSteps = (winWidth + winHeight)/2; //how many sample points of u in [0, 1] GLdouble *splinePts[2]; /* splinePts[0] is an array of x-values for spline splinePts[1] is an array of y-values for spline */ int numPts; /*-----------------------------------------------*/ int initSpline(int numargs, char** splineChars) /* PURPOSE: Loads splinePts global array of GLdouble's with x and y values stored as strings in splineChars RECEIVES: numargs -- number of points to parse splineChars[0] -- array of strings of x values splineChars[1] -- array of strings of y values RETURNS: Error codes if splineChars not in correct format REMARKS: */ { stringstream ss; ss << splineChars[1]; ss >> numPts; if(2*numPts+2 != numargs) return ERROR_FORMAT; //number of args doesn't match number of points if(numPts < SPLINE_NUM) return ERROR_ARGS; //number of points too small for a cubic Cardinal spline splinePts[0] = new GLdouble[numPts]; splinePts[1] = new GLdouble[numPts]; for(int i = 2, j = 0; j < numPts; i += 2, j++) { stringstream ss1, ss2; ss1 <<splineChars[i]; ss1 >> splinePts[0][j]; // put x values in array ss2 << splineChars[i+1]; ss2 >> splinePts[1][j]; // put y values in array } return 0; } /*-----------------------------------------------*/ GLdouble innerProduct(GLdouble vec1[], int off1, GLdouble vec2[], int off2) /* PURPOSE: Computes the inner product of two 4-vectors RECEIVES: vec1 - array of size at least 4 off1 - offset into this array at which to start computing inner product vec2 - second array of size at least 4 off2 - offset into this array at which to start computing inner product RETURNS: inner product of these two vectors REMARKS: Hard-coded towards four vectors at this point */ { return vec1[off1]*vec2[off2] + vec1[++off1]*vec2[++off2] + vec1[++off1]*vec2[++off2] + vec1[++off1]*vec2[++off2]; } /*-----------------------------------------------*/ void init(void) /* PURPOSE: Set the background of the GLUT window white when first drawn RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { glClearColor(1.0, 1.0, 1.0, 0.0); } /*-----------------------------------------------*/ void drawFn() /* PURPOSE: Draws cardinal spline to the GLUT window RECEIVES: Nothing RETURNS: Nothing REMARKS: */ { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 1.0); GLdouble curPts[MATRIX_SIZE]; //matrix for control points GLdouble mcPtsMatrix[MATRIX_SIZE]; // matrix product of control and spline matrix GLdouble uArray[SPLINE_NUM]; uArray[3] = 1; /* In [u^3 u^2 u 1] the 1 doesn't change so we initialize it here */ int i, j; for(i = 0; i < SPLINE_NUM; i++) { curPts[i + 2*SPLINE_NUM] = 0; curPts[i + 3*SPLINE_NUM] = 0; } for(i=0; i < numPts - 3; i++) { for(j = 0; j < SPLINE_NUM; j++) { curPts[j] = splinePts[0][i + j]; curPts[j + SPLINE_NUM] = splinePts[1][i + j]; } glLoadMatrixd(splineMatrix); glMultMatrixd(curPts); glGetDoublev(GL_MODELVIEW_MATRIX, mcPtsMatrix); glLoadIdentity(); glBegin(GL_LINE_STRIP); for(j = 0; j <= uSteps; j++) { uArray[2] = GLdouble(j)/uSteps; //load uArray with [ u^3 u^2 u 1] uArray[1] = uArray[2]*uArray[2]; uArray[0] = uArray[1]*uArray[2]; glVertex2d( innerProduct(uArray, 0, mcPtsMatrix, 0), innerProduct(uArray, 0, mcPtsMatrix, SPLINE_NUM)); } glEnd(); } glFlush(); } /*-----------------------------------------------*/ void reshapeFn(int newWidth, int newHeight) /* PURPOSE: Redraws GLUT window when it is moved or resized RECEIVES: newWidth -- new width of window newHeight -- new height of window RETURNS: Nothing REMARKS: */ { glViewport(0, 0, newWidth, newHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, newWidth, 0, newHeight); glMatrixMode(GL_MODELVIEW); glClear(GL_COLOR_BUFFER_BIT); uSteps = (newWidth + newHeight)/2; //update how many sample points of u in [0, 1] } int main (int argc, char **argv) { if(argc < 2) // No command line arguments supplied { cout << "To run: spline numpts x1 y1 x2 y2 ... xnumpts ynumpts" << endl; } int error = initSpline(argc, argv); //Now handle some other possible error cases if(error == ERROR_FORMAT) { cout << "Error: Command line arguments not in the correct format" << endl; cout << "To run: spline numpts x1 y1 x2 y2 ... xnumpts ynumpts" << endl; return error; } if(error == ERROR_ARGS) { cout << "Error: need at least four points to draw cardinal spline " << endl; cout << "To run: spline numpts x1 y1 x2 y2 ... xnumpts ynumpts" << endl; return error; } //Ready to go -- init and draw glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(initX, initY); glutInitWindowSize(winWidth, winHeight); glutCreateWindow("Cardinal Spline Tester"); init(); glutDisplayFunc(drawFn); glutReshapeFunc(reshapeFn); glutMainLoop(); return 0; } |