/* Example 2.7.sphere.c: draw a sphere 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[6][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.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 subdivideSphere(float *v1, float *v2, float *v3, long depth) { float v12[3], v23[3], v31[3]; int i; if (depth == 0) { glColor3f(v1[0]*v1[0], v2[1]*v2[1], v3[2]*v3[2]); drawtriangle(v1, v2, v3); return; } for (i = 0; i < 3; i++) { v12[i] = v1[i]+v2[i]; v23[i] = v2[i]+v3[i]; v31[i] = v3[i]+v1[i]; } normalize(v12); normalize(v23); normalize(v31); subdivideSphere(v1, v12, v31, depth - 1); subdivideSphere(v2, v23, v12, depth - 1); subdivideSphere(v3, v31, v23, depth - 1); subdivideSphere(v12, v23, v31, depth - 1); } void drawSphere(void) // draw a cone with z=height and bottom in xy plane { subdivideSphere(vdata[0], vdata[1], vdata[2], depth); subdivideSphere(vdata[0], vdata[2], vdata[4], depth); subdivideSphere(vdata[0], vdata[4], vdata[5], depth); subdivideSphere(vdata[0], vdata[5], vdata[1], depth); subdivideSphere(vdata[3], vdata[1], vdata[5], depth); subdivideSphere(vdata[3], vdata[5], vdata[4], depth); subdivideSphere(vdata[3], vdata[4], vdata[2], depth); subdivideSphere(vdata[3], vdata[2], vdata[1], 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); glPushMatrix(); glScalef(circleRadius, circleRadius, circleRadius); drawSphere(); 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); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); } 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.7.sphere.c: press SPACE & another key"); glutKeyboardFunc(Key); glutReshapeFunc(Reshape); glutDisplayFunc(display); glutIdleFunc(display); glutMainLoop(); }