Chris Pollett > Old Classes >
CS116b

( Print View )

Student Corner:
  [Grades Sec1]

  [Submit Sec1]

  [Email List Sec1]

  [
Lecture Notes]

Course Info:
  [Texts & Links]
  [Topics]
  [Grading]
  [HW Info]
  [Exam Info]
  [Regrades]
  [Honesty]
  [Announcements]

HW Assignments:
  [Hw1]  [Hw2]  [Hw3]
  [Hw4]  [Hw5]

Practice Exams:
  [Mid1]  [Mid2]  [Final]

                           












HW1 Solutions Page

Return to homework 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;
}

Return to homework page.