//////////////////////////////////////////////////// // scene.cpp // Template code for drawing an interesting scene. //////////////////////////////////////////////////// #ifdef WIN32 #include #endif #include #include #include #include #include void drawTable(); void draw_table_leg(float x, float y); void save_image(); const int STRLEN = 100; typedef char STR[STRLEN]; int Win[2]; // window (x,y) size ////////////////////////////////////////////////////// // PROC: glut_key_action() // DOES: this function gets called for any keypresses ////////////////////////////////////////////////////// void glut_key_action(unsigned char key, int x, int y) { if (key=='q') { exit(0); } else if (key=='s') { save_image(); } glutPostRedisplay(); } ///////////////////////////////////////// // PROC: save_image // DOES: saves the current image to a ppm file ///////////////////////////////////////// void save_image() { FILE *fp; STR fname; const maxVal=255; register int y; unsigned char *pixels; strcpy(fname,"scene.ppm"); printf("Saving image %s: %d x %d\n", fname,Win[0],Win[1]); fp = fopen(fname,"wb"); if (!fp) { printf("Unable to open file '%s'\n",fname); return; } fprintf(fp, "P6\n"); fprintf(fp, "%d %d\n", Win[0], Win[1]); fprintf(fp, "%d\n", maxVal); pixels = new unsigned char [3*Win[0]]; for ( y = Win[1]-1; y>=0; y-- ) { glReadPixels(0,y,Win[0],1,GL_RGB,GL_UNSIGNED_BYTE, (GLvoid *) pixels); fwrite(pixels, 3, Win[0], fp); } fclose(fp); } /********************************************************* PROC: myinit() DOES: performs most of the OpenGL intialization -- don't change **********************************************************/ void myinit(void) { GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 }; GLfloat lmodel_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat local_view[] = { 0.0 }; /**** set lighting parameters ****/ glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); /* glFrontFace (GL_CW); */ glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); } /********************************************************* PROC: set_colour(); DOES: draws a teapot of the given colour -- don't change **********************************************************/ void set_colour(float r, float g, float b) { float ambient = 0.2f; float diffuse = 0.7f; float specular = 0.4f; GLfloat mat[4]; /**** set ambient lighting parameters ****/ mat[0] = ambient*r; mat[1] = ambient*g; mat[2] = ambient*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_AMBIENT, mat); /**** set diffuse lighting parameters ******/ mat[0] = diffuse*r; mat[1] = diffuse*g; mat[2] = diffuse*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_DIFFUSE, mat); /**** set specular lighting parameters *****/ mat[0] = specular*r; mat[1] = specular*g; mat[2] = specular*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_SPECULAR, mat); glMaterialf (GL_FRONT, GL_SHININESS, 0.5); } /********************************************************* PROC: display() DOES: this gets called by the event handler to draw the scene, so this is where you need to build your scene -- make your changes and additions here Add other procedures if you like. **********************************************************/ void display(void) { /* glClearColor (red, green, blue, alpha */ /* Ignore the meaning of the 'alpha' value for now */ glClearColor(0.7f,0.7f,0.9f,1.0f); /* set the background colour */ /* OK, now clear the screen with the background colour */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw a yellow teapot */ set_colour(1, 1, 0.6f); /* yellow */ glutSolidTeapot(1.0); /* draw another white teapot y=2 units up */ glTranslatef(0,2,0); /* translate by y=2 */ set_colour(1, 1, 1); /* white */ glutSolidTeapot(1.0); /* draw a third red teapot x= -2 units (to the left) */ /* note that each translation is RELATIVE to the previous one */ glTranslatef(-2,0,0); /* translate by x = -2 */ set_colour(1, 0, 0); /* red */ glutSolidTeapot(1.0); /* let's now undo these relative transformations */ glTranslatef(2,-2,0); /* An easier way to undo relative transformations is enclose them between glPushMatrix() and glPopMatrix calls. The glPopMatrix() restores the coordinate system in effect at the time of the most recent glPushMatrix(). */ glPushMatrix(); glTranslatef(-2,0,0); set_colour(0,1,0.6f); glutSolidSphere(1.0,10,10); glPopMatrix(); glPushMatrix(); glTranslatef(2,-0.5 ,0); glRotatef(-90, 1,0,0); // rotate -90 deg about x set_colour(0,0.6f,1); /* mostly blue */ glutSolidCone(1.0, 3.0,10,8); glPopMatrix(); glPushMatrix(); glTranslatef(4,0,0); set_colour(0,1,0.6f); /* mostly green */ glutSolidCone(1.0, 3.0,10,8); glPopMatrix(); glPushMatrix(); glTranslatef(2,2,0); set_colour(1,0.2f,0.2f); /* red torus */ glutSolidTorus(0.2,0.5,16,10); glPopMatrix(); glPushMatrix(); glTranslatef(0,-5,0); /* brown table */ set_colour(0.8f,0.4f,0.5f); glRotatef(-90,1,0,0); /* rotate table */ glScalef(4,4,4); /* scale by 4 */ drawTable(); glPopMatrix(); glPushMatrix(); glTranslatef(0,-1,2); /* place on table-top (y=-1) and to the front */ glScalef(1,4,1); /* scale in y */ set_colour(1,0,1); /* magenta colour */ glTranslatef(0,0.5,0); glutSolidCube(1.0); glPopMatrix(); glFlush(); } /********************************************************* PROC: myReshape() DOES: handles the window being resized -- don't change **********************************************************/ void myReshape(int w, int h) { Win[0] = w; Win[1] = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /*** this defines the field of view of the camera ***/ /*** Making the first 4 parameters larger will give ***/ /*** a larger field of view, therefore making the ***/ /*** objects in the scene appear smaller ***/ glFrustum(-1,1,-1,1,4,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /*** this sets the virtual camera ***/ /*** gluLookAt( x,y,z, x,y,z x,y,z ); ***/ /*** camera look-at camera-up ***/ /*** pos'n point vector ***/ /*** place camera at (x=4, y=6, z=20), looking at origin, y-axis being up ***/ gluLookAt(4,6,20,0,0,0,0,1,0); } /********************************************************* PROC: main() DOES: calls initialization, then hands over control to the event handler, which calls display() whenever the screen needs to be redrawn **********************************************************/ int main(int argc, char** argv) { glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition (0, 0); glutInitWindowSize(300,300); glutCreateWindow(argv[0]); myinit(); glutReshapeFunc (myReshape); glutKeyboardFunc( glut_key_action ); printf("An OpenGL Still Life\n"); printf("Press 's' to save image\n"); printf("Press 'q' to quit\n"); glutDisplayFunc(display); glutMainLoop(); return 0; // never reached } /********************************************************* PROC: drawTable() DOES: draws a table, built from polygons -- add more functions of your own like this, if you can understand what is going on here **********************************************************/ void drawTable() { /* draw table top */ glBegin(GL_POLYGON); glNormal3f(0,0,1); glVertex3f(-1,-1,1); glVertex3f(1,-1,1); glVertex3f(1,1,1); glVertex3f(-1,1,1); glEnd(); /* draw the four table legs */ draw_table_leg(-0.6f,-0.7f); draw_table_leg(0.6f,-0.7f); draw_table_leg(0.6f,0.7f); draw_table_leg(-0.6f,0.7f); } /********************************************************* PROC: draw_table_leg(x,y) DOES: draws a table leg in the given location **********************************************************/ void draw_table_leg(float x, float y) { glPushMatrix(); glTranslatef(x,y,0.5f); glScalef(0.2f,0.2f,1); glutSolidCube(1.0); glPopMatrix(); return; }