/* * snowman.c * * derived from Smiley.c */ // #include #include #include #include #include #include #include #include int rgb = GL_TRUE; /* just use RGB color */ int doubleBuffer = GL_TRUE; /* double buffering */ int windType; GLint windW, windH; /* named parts of the snowman */ #define MAN_NONE 0 #define MAN_BOTTOM 1 #define MAN_MIDDLE 2 #define MAN_TOP 3 #define MAN_LEFTARM 4 #define MAN_RIGHTARM 5 #define MAN_RESET 6 int picked = MAN_NONE; /* mouse positions */ GLdouble lastX; GLdouble lastY; /* transformation parameters */ GLdouble translate_increment; float man_position[3] = {0.0, -3.5, 0.0}; float middle_RLangle = 0.0; float middle_FBangle = 0.0; float top_RLangle = 0.0; float top_FBangle = 0.0; float right_UDangle = 0.0; float right_FBangle = 0.0; float left_UDangle = 0.0; float left_FBangle = 0.0; float yaw = 0.0; /* rotate about Y axis */ float pitch = 0.0; /* rotate about X axis */ float dist = -12.0; /* distance from camera to object */ GLUquadricObj *myQuadricObj; /* shading values */ GLfloat ambient_light[4] = {0.0, 0.0, 1.0, 1.0}; GLfloat light_position[4] = {0.33333, 0.66667, 0.66667, 0.0}; GLfloat ambient_snow[4] = {0.2, 0.2, 0.2, 1.0}; GLfloat diffuse_snow[4] = {0.8, 0.8, 0.8, 1.0}; GLfloat specular_snow[4] = {1.0, 1.0, 8.0, 1.0}; GLfloat snow_shininess = 10; GLfloat ambient_coal[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat diffuse_coal[4] = {0.4, 0.4, 0.4, 1.0}; GLfloat specular_coal[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat coal_shininess = 1; GLfloat diffuse_carrot[4] = {1.0, 0.4, 0.0, 1.0}; /* function to set materials */ static void set_material(GLfloat *ambient, GLfloat *diffuse, GLfloat *specular, GLfloat shininess) { glMaterialfv (GL_FRONT, GL_AMBIENT, ambient); glMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse); glMaterialfv (GL_FRONT, GL_SPECULAR, specular); glMaterialf (GL_FRONT, GL_SHININESS, shininess); } /* Set background color, enable depth buffering */ static void Init(void) { /* Set background color */ glClearColor(0.2, 0.8, 1.0, 0.0); /* blue sky */ /* Enable depth buffer */ glEnable(GL_DEPTH_TEST); /* Set polygon attributes */ glPolygonMode (GL_FRONT, GL_FILL); //glEnable (GL_CULL_FACE); //glCullFace (GL_BACK); /* Set shading & lighting values*/ glShadeModel (GL_SMOOTH); glLightfv (GL_LIGHT0, GL_AMBIENT, ambient_light); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); /* Create quadric object for all of snowman's parts */ myQuadricObj = gluNewQuadric(); gluQuadricDrawStyle(myQuadricObj, (GLenum)GLU_FILL); gluQuadricNormals(myQuadricObj, (GLenum)GLU_SMOOTH); } /* Window size has changed: adjust viewport and perspective transformations */ static void Reshape(int width, int height) { float aspect; windW = (GLint)width; windH = (GLint)height; aspect = (float)windW / (float)windH; translate_increment = 0.1; /* Viewport fills the entire window */ glViewport(0, 0, width, height); /* Use perspective projection */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (60.0, aspect, 1.0, 1000.0); /* fovy, aspect, near, far */ /* Return to modelview mode */ glMatrixMode(GL_MODELVIEW); } /* Arrow keys change angle of rotation */ static void Key2(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: /* decrease angle about Y axis */ switch (picked) { case MAN_NONE: yaw -= 5.0; break; case MAN_BOTTOM: man_position[0] -= translate_increment; break; case MAN_MIDDLE: middle_RLangle += 5.0; break; case MAN_TOP: top_RLangle += 5.0; break; case MAN_RIGHTARM: right_FBangle -= 5.0; break; case MAN_LEFTARM: left_FBangle += 5.0; break; } break; case GLUT_KEY_RIGHT: /* increase angle about Y axis */ switch (picked) { case MAN_NONE: yaw += 5.0; break; case MAN_BOTTOM: man_position[0] += translate_increment; break; case MAN_MIDDLE: middle_RLangle -= 5.0; break; case MAN_TOP: top_RLangle -= 5.0; break; case MAN_RIGHTARM: right_FBangle += 5.0; break; case MAN_LEFTARM: left_FBangle -= 5.0; break; } break; case GLUT_KEY_UP: /* decrease angle about Z axis */ switch (picked) { case MAN_NONE: pitch -= 5.0; break; case MAN_BOTTOM: man_position[1] += translate_increment; break; case MAN_MIDDLE: middle_FBangle -= 5.0; break; case MAN_TOP: top_FBangle -= 5.0; break; case MAN_RIGHTARM: right_UDangle -= 5.0; break; case MAN_LEFTARM: left_UDangle += 5.0; break; } break; case GLUT_KEY_DOWN: /* increase angle about X axis */ switch (picked) { case MAN_NONE: pitch += 5.0; break; case MAN_BOTTOM: man_position[1] -= translate_increment; break; case MAN_MIDDLE: middle_FBangle += 5.0; break; case MAN_TOP: top_FBangle += 5.0; break; case MAN_RIGHTARM: right_UDangle += 5.0; break; case MAN_LEFTARM: left_UDangle -= 5.0; break; } break; default: return; } glutPostRedisplay(); /* force update of the display */ } /* Handle other keys */ static void Key(unsigned char key, int x, int y) { switch (key) { case 27: /* ESC to quit */ exit(1); case '+': dist += 1.0; /* move camera closer */ break; case '-': dist -= 1.0; /* move camera back */ break; default: return; } glutPostRedisplay(); /* force update of the display */ } /* Set modeling and viewing transformations, then draw the letter polygons */ #define BUFSIZE 64 #define BOTTOM_RADIUS 2.0 #define MIDDLE_RADIUS 1.5 #define TOP_RADIUS 1.0 #define ARM_WIDTH 0.25 #define ARM_LENGTH 6.0 /* actually, a scale */ #define ARM_SHIFT 2.25 /* MIDDLE_RADIUS + 1/2 of ARM_LENGTH */ static void DrawSnowman(void) { /* Transformation for entire puppet */ glLoadIdentity(); glTranslatef(0.0, 0.0, dist); /* step back */ glRotatef(pitch, 1.0, 0.0, 0.0); /* spin on X axis */ glRotatef(yaw, 0.0, 1.0, 0.0); /* spin on Y axis */ /* Draw the bottom of the snowman (root of the hierarchy) */ set_material(ambient_snow, diffuse_snow, specular_snow, snow_shininess); glTranslatef(man_position[0], man_position[1], man_position[2]); gluSphere (myQuadricObj, BOTTOM_RADIUS, 20, 10); /* Draw the middle of the snowman */ glTranslatef(0.0, BOTTOM_RADIUS, 0.0); /* move on top of snowman bottom */ glRotatef(middle_RLangle, 0.0, 0.0, 1.0); /* rotate around z axis */ glRotatef(middle_FBangle, 1.0, 0.0, 0.0); /* rotate around X axis */ glTranslatef(0.0, MIDDLE_RADIUS, 0.0); /* shift bottom to origin */ gluSphere (myQuadricObj, MIDDLE_RADIUS, 20, 10); /* Draw the top of the snowman */ glPushMatrix(); // save Tx for middle of snowman glTranslatef(0.0, MIDDLE_RADIUS, 0.0); /* move on top of snowman middle */ glRotatef(top_RLangle, 0.0, 0.0, 1.0); /* rotate around z axis */ glRotatef(top_FBangle, 1.0, 0.0, 0.0); /* rotate around X axis */ glTranslatef(0.0, TOP_RADIUS, 0.0); /* shift bottom to origin */ gluSphere (myQuadricObj, TOP_RADIUS, 20, 10); /* Draw hat & eyes & nose*/ glPushMatrix(); // save Tx for snowman's head set_material(ambient_coal, diffuse_coal, specular_coal, coal_shininess); glRotatef(17.0, 0.0, 1.0, 0.0); glRotatef(-7.0, 1.0, 0.0, 0.0); glTranslatef(0.0, 0.0, TOP_RADIUS); glutSolidSphere (TOP_RADIUS/6.0, 10, 6); // left eye glPopMatrix(); // restore Tx for snowman's head glPushMatrix(); // save Tx for snowman's head glRotatef(-17.0, 0.0, 1.0, 0.0); glRotatef(-7.0, 1.0, 0.0, 0.0); glTranslatef(0.0, 0.0, TOP_RADIUS); glutSolidSphere (TOP_RADIUS/6.0, 10, 6); // right eye glPopMatrix(); // restore Tx for snowman's head glPushMatrix(); // save Tx for snowman's head glTranslatef(0.0, TOP_RADIUS*0.5, 0.0); glRotatef(-90.0, 1.0, 0.0, 0.0); gluDisk(myQuadricObj, 1.0, TOP_RADIUS*2.0, 20, 1); // brim of hat gluCylinder(myQuadricObj,TOP_RADIUS, TOP_RADIUS, TOP_RADIUS, 20, 1); // hat glTranslatef(0.0, 0.0, TOP_RADIUS); gluDisk(myQuadricObj, 0.0, TOP_RADIUS, 20, 1); // top of hat glPopMatrix(); // restore Tx for snowman's head // glPushMatrix(); // save Tx for snowman's head glMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse_carrot); glTranslatef(0.0, 0.0, TOP_RADIUS); glutSolidCone (TOP_RADIUS/7.0, TOP_RADIUS/2.0, 10, 6); // carrot nose // glPopMatrix(); glPopMatrix(); // restore Tx for middle of snowman /* Draw the arms */ glPushMatrix(); // save Tx for middle of snowman glTranslatef(-MIDDLE_RADIUS, 0.0, 0.0); /* move to right side of snowman middle */ glRotatef(right_FBangle, 0.0, 1.0, 0.0); /* rotate around Y axis */ glRotatef(right_UDangle, 0.0, 0.0, 1.0); /* rotate around z axis */ glScalef(ARM_LENGTH, 1.0, 1.0); /* lengthen arm */ glTranslatef(-ARM_WIDTH/2.0, 0.0, 0.0); /* shift inner edge to origin */ glutSolidCube (ARM_WIDTH); glPopMatrix(); // restore Tx for middle of snowman //glPushMatrix(); // save Tx for middle of snowman glTranslatef(MIDDLE_RADIUS, 0.0, 0.0); /* move to left side of snowman middle */ glRotatef(left_FBangle, 0.0, 1.0, 0.0); /* rotate around Y axis */ glRotatef(left_UDangle, 0.0, 0.0, 1.0); /* rotate around z axis */ glScalef(ARM_LENGTH, 1.0, 1.0); /* lengthen arm */ glTranslatef(ARM_WIDTH/2.0, 0.0, 0.0); /* shift inner edge to origin */ glutSolidCube (ARM_WIDTH); //glPopMatrix(); // pop last item off of stack } /* Create pop-up window using GLUT */ #define ROTATE_BODY 1 void PopUp (int value) { if (value == MAN_RESET) { man_position[0] = 0.0; man_position[1] = -3.5; man_position[2] = 0.0; middle_RLangle = 0.0; middle_FBangle = 0.0; top_RLangle = 0.0; top_FBangle = 0.0; right_UDangle = 0.0; right_FBangle = 0.0; left_UDangle = 0.0; left_FBangle = 0.0; yaw = 0.0; /* rotate about Y axis */ pitch = 0.0; /* rotate about X axis */ dist = -7.0; /* distance from camera to object */ glPolygonMode (GL_FRONT, GL_FILL); DrawSnowman(); glutPostRedisplay(); } else picked = value; } void initMenu(void) { int menuid; /* create a menu and save the id */ menuid = glutCreateMenu(PopUp); /* add menu entries */ glutAddMenuEntry ("Rotate Body", MAN_NONE); glutAddMenuEntry ("Move Body", MAN_BOTTOM); glutAddMenuEntry ("Move Middle", MAN_MIDDLE); glutAddMenuEntry ("Move Head", MAN_TOP); glutAddMenuEntry ("Move Right Arm", MAN_RIGHTARM); glutAddMenuEntry ("Move Left Arm", MAN_LEFTARM); glutAddMenuEntry ("Reset", MAN_RESET); /* attach menu to right button */ glutAttachMenu (GLUT_RIGHT_BUTTON); } static void Draw(void) { /* clear the screen */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw the snowman */ DrawSnowman(); /* update the screen */ glFlush(); /* force all changes to be applied to buffer */ glutSwapBuffers(); /* display what you just drew */ } int main(int argc, char **argv) { /* Setup the window that logo will appear in */ windW = 300; windH = 300; glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH); windType = GLUT_DEPTH; windType |= (rgb) ? GLUT_RGB : GLUT_INDEX; windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; glutInitDisplayMode((GLenum)windType); if (glutCreateWindow("Snowman") == GL_FALSE) { exit(1); } Init(); initMenu(); glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutSpecialFunc(Key2); glutDisplayFunc(Draw); glutMainLoop(); }