/* Example 2.6.cylinder.c: draw a cylinder by subdivision */ // by Jim X. Chen; September, 2000 #include #include #include #include #define ESC 27 #define SPACE 32 int Height=400, Width=400; int depth=0, circleRadius=2, cnt=1; static float vdata[4][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0} }; void normalize(float v[3]) { float d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); if (d == 0) { printf("zero length vector"); return; } v[0] /= d; v[1] /= d; v[2] /= d; } void drawtriangle(float *v1, float *v2, float *v3) { glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } void subdivideCylinder(float *v1, float *v2, int depth) { float v11[3], v22[3], v00[3] = {0, 0, 0}, v12[3]; float v01[3], v02[3]; int i; if (depth == 0) { glColor3f(v1[0]*v1[0], v1[1]*v1[1], v1[2]*v1[2]); for (i=0; i<3; i++) { v02[i] = v22[i] = v2[i]; v01[i] = v11[i] = v1[i]; } // the height of the cone along z axis drawtriangle(v11, v22, v00); // draw sphere at the cylinder's bottom // v01[2] = v02[2] = v00[2] = 1; v01[2] = v02[2] = v00[2] = 1.5; drawtriangle(v01, v02, v00); // draw sphere at the cylinder's bottom glBegin(GL_POLYGON); // draw the side rectangles of the cylinder glVertex3fv(v11); glVertex3fv(v22); glVertex3fv(v02); glVertex3fv(v01); glEnd(); return; } v12[0] = v1[0]+v2[0]; v12[1] = v1[1]+v2[1]; v12[2] = v1[2]+v2[2]; normalize(v12); subdivideCylinder(v1, v12, depth - 1); subdivideCylinder(v12, v2, depth - 1); } void drawCylinder(void) // draw a unit cylinder with bottom in xy plane { subdivideCylinder(vdata[0], vdata[1], depth); subdivideCylinder(vdata[1], vdata[2], depth); subdivideCylinder(vdata[2], vdata[3], depth); subdivideCylinder(vdata[3], vdata[0], depth); } void display(void) { if (circleRadius>Width/2 || circleRadius==1) { cnt=-cnt; depth++; depth = depth % 5; } circleRadius+=cnt; // clears both framebuffer and zbuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glRotatef(1.1, 0, 1, 0); // rotate 1.1 degrees alone y axis glPushMatrix(); glScalef(circleRadius, circleRadius, circleRadius); glTranslatef(0, 0, -0.75); drawCylinder(); glPopMatrix(); glutSwapBuffers(); } static void Reshape(int w, int h) { glClearColor (0.0, 0.0, 0.0, 1.0); // enables depth test for hidden surface removal glEnable(GL_DEPTH_TEST); Width = w; Height = h; glViewport (0, 0, Width, Height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho(-Width/2, Width/2, -Height/2, Height/2, -Width, Width); } static void Key(unsigned char key, int x, int y) { switch (key) { case ESC: exit(0); case SPACE: glutIdleFunc(NULL); display(); break; default: glutIdleFunc(display); } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE); glutInitWindowSize(Width, Height); glutCreateWindow("Example 2.6.cylinder.c: press SPACE & another key"); glutKeyboardFunc(Key); glutReshapeFunc(Reshape); glutDisplayFunc(display); glutIdleFunc(display); glutMainLoop(); }