// Simple OpenGL example for CS184 F06 by Nuttapong Chentanez, modified from sample code for CS184 on Sp06 #include #include #include #include #ifdef _WIN32 # include #else # include #endif #ifdef OSX #include #include #else #include #include #endif #include #include #ifdef _WIN32 static DWORD lastTime; #else static struct timeval lastTime; #endif #define PI 3.14159265 using namespace std; //**************************************************** // Some Classes //**************************************************** class Viewport; class Viewport { public: int w, h; // width and height }; //**************************************************** // Global Variables //**************************************************** Viewport viewport; float rotX = 0.0f, rotY = 0.0f, rotZ = 0.0f; float scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f; float camRotY = 9.0f; float viewAngle; void initScene(){ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Clear to black, fully transparent glClearDepth(1.0f); // Clear depth to futhest // Enable depth test glEnable(GL_DEPTH_TEST); // Draw pixel when its z is less than the existing z value glDepthFunc(GL_LESS); // Enable normal vector normalization, because we scale sphere non-uniformly glEnable(GL_NORMALIZE); // Setup viewport glViewport (0,0,viewport.w,viewport.h); // Setup projection matric glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, ((float)viewport.w)/((float)viewport.h), 0.01, 100.0f); glMatrixMode(GL_MODELVIEW); // indicate we are specifying camera transformations glLoadIdentity(); // make sure transformation is "zero'd" // Enable lighting calculation glEnable(GL_LIGHTING); // Create a light source glEnable(GL_LIGHT0); // Create light components float ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f }; float diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f }; float specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // This is point light source, if want directional light source, make w 0 float position[] = { 0.0f, 3.0f, -4.0f, 1.0f }; // Assign created components to GL_LIGHT0 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight); // Light is transformed by model-view matrix as well, // hence, if we want to specify the light // in the world coordinate, // need to declare it when model-view is identity glLightfv(GL_LIGHT0, GL_POSITION, position); } //**************************************************** // reshape viewport if the window is resized //**************************************************** void myReshape(int w, int h) { viewport.w = w; viewport.h = h; glViewport (0,0,viewport.w,viewport.h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, ((float)viewport.w)/((float)viewport.h), 0.01, 100.0f); } //**************************************************** // function that does the actual drawing of stuff //*************************************************** void drawCube() { // Set matrial float mcolor[] = { 1.0f, 0.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mcolor); float specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f }; glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection); glMateriali(GL_FRONT, GL_SHININESS, 96); // Give vertices in CCW order when viewed from outside glBegin(GL_QUADS); // Right glNormal3f(1,0,0); glVertex3f(1,-1,1); glVertex3f(1,-1,-1); glVertex3f(1,1,-1); glVertex3f(1,1,1); // Left glNormal3f(-1,0,0); glVertex3f(-1,-1,-1); glVertex3f(-1,-1,1); glVertex3f(-1,1,1); glVertex3f(-1,1,-1); // Front glNormal3f(0,0,1); glVertex3f(-1,-1,1); glVertex3f(1,-1,1); glVertex3f(1,1,1); glVertex3f(-1,1,1); // Back glNormal3f(0,0,-1); glVertex3f(-1,1,-1); glVertex3f(1,1,-1); glVertex3f(1,-1,-1); glVertex3f(-1,-1,-1); // Top glNormal3f(0,1,0); glVertex3f(-1,1,1); glVertex3f(1,1,1); glVertex3f(1,1,-1); glVertex3f(-1,1,-1); // Bottom glNormal3f(0,-1,0); glVertex3f(-1,-1,-1); glVertex3f(1,-1,-1); glVertex3f(1,-1,1); glVertex3f(-1,-1,1); glEnd(); } void drawSphere() { // Set matrial float mcolor[] = { 0.0f, 1.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mcolor); float specReflection[] = { 1.2f, 1.2f, 1.2f, 1.0f }; glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection); glMateriali(GL_FRONT, GL_SHININESS, 296); glBegin(GL_QUADS); const int numSubPhi = 30; const int numSubTheta = 30; float difPhi = PI / numSubPhi; float difTheta = 2*PI / numSubTheta; for (int i = 0; i < numSubPhi-1; i++) { for (int j = 0; j < numSubTheta; j++) { glNormal3f(sin(difPhi*i)*cos(difTheta*j), cos(difPhi*i), sin(difPhi*i)*sin(difTheta*j)); glVertex3f(sin(difPhi*i)*cos(difTheta*j), cos(difPhi*i), sin(difPhi*i)*sin(difTheta*j)); glNormal3f(sin(difPhi*i)*cos(difTheta*(j+1)), cos(difPhi*i), sin(difPhi*i)*sin(difTheta*(j+1))); glVertex3f(sin(difPhi*i)*cos(difTheta*(j+1)), cos(difPhi*i), sin(difPhi*i)*sin(difTheta*(j+1))); glNormal3f(sin(difPhi*(i+1))*cos(difTheta*(j+1)), cos(difPhi*(i+1)), sin(difPhi*(i+1))*sin(difTheta*(j+1))); glVertex3f(sin(difPhi*(i+1))*cos(difTheta*(j+1)), cos(difPhi*(i+1)), sin(difPhi*(i+1))*sin(difTheta*(j+1))); glNormal3f(sin(difPhi*(i+1))*cos(difTheta*j), cos(difPhi*(i+1)), sin(difPhi*(i+1))*sin(difTheta*j)); glVertex3f(sin(difPhi*(i+1))*cos(difTheta*j), cos(difPhi*(i+1)), sin(difPhi*(i+1))*sin(difTheta*j)); } } glEnd(); } void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); // clear the color buffer glClear(GL_DEPTH_BUFFER_BIT); // clear the depth buffer glMatrixMode(GL_MODELVIEW); // indicate we are specifying camera transformations glLoadIdentity(); // make sure transformation is "zero'd" gluLookAt(cos(camRotY)*5,2,sin(camRotY)*5,0,0,0,0,1,0); glPushMatrix(); glTranslatef(-2,0,0); glRotatef(rotX, 1,0,0); glRotatef(rotY, 0,1,0); glRotatef(rotZ, 0,0,1); drawCube(); glPopMatrix(); glPushMatrix(); glTranslatef(2,0,0); glScalef(scaleX,scaleY,scaleZ); drawSphere(); glPopMatrix(); glFlush(); glutSwapBuffers(); // swap buffers (we earlier set double buffer) } void myNormalKeys(unsigned char key, int x, int y) { switch (key) { case 'q': rotX += 10.0f; break; case 'a': rotX += 10.0f; break; case 'w': rotY -= 10.0f; break; case 's': rotY += 10.0f; break; case 'e': rotZ -= 10.0f; break; case 'd': rotZ -= 10.0f; break; case 'r': scaleX *= 1.2f; break; case 'f': scaleX /= 1.2f; break; case 't': scaleY *= 1.2f; break; case 'g': scaleY /= 1.2f; break; case 'y': scaleZ *= 1.2f; break; case 'h': scaleZ /= 1.2f; break; } } void mySpecialKeys(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: camRotY += PI/10.0f; break; case GLUT_KEY_RIGHT: camRotY -= PI/10.0f; break; } } //**************************************************** // for updating the position of the circle //**************************************************** void myFrameMove() { float dt; // Compute the time elapsed since the last time the scence is redrawn #ifdef _WIN32 DWORD currentTime = GetTickCount(); dt = (float)(currentTime - lastTime)*0.001f; #else timeval currentTime; gettimeofday(¤tTime, NULL); dt = (float)((currentTime.tv_sec - lastTime.tv_sec) + 1e-6*(currentTime.tv_usec - lastTime.tv_usec)); #endif // Don't need to concern about timing for this particular example, // but I leave it here as it should be pretty useful static float totalTime = 0.0f; // Accumulate the time since the program starts totalTime += dt; // Store the time lastTime = currentTime; glutPostRedisplay(); } //**************************************************** // the usual stuff, nothing exciting here //**************************************************** int main(int argc, char *argv[]) { //This initializes glut glutInit(&argc, argv); //This tells glut to use a double-buffered window with red, green, and blue channels glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Initalize theviewport size viewport.w = 400; viewport.h = 400; //The size and position of the window glutInitWindowSize(viewport.w, viewport.h); glutInitWindowPosition(0,0); glutCreateWindow(argv[0]); // Initialize timer variable #ifdef _WIN32 lastTime = GetTickCount(); #else gettimeofday(&lastTime, NULL); #endif initScene(); // quick function to set up scene glutDisplayFunc(myDisplay); // function to run when its time to draw something glutReshapeFunc(myReshape); // function to run when the window gets resized glutIdleFunc(myFrameMove); glutKeyboardFunc(myNormalKeys); glutSpecialFunc(mySpecialKeys); glutMainLoop(); // infinite loop that will keep drawing and resizing and whatever else return 0; }