/* Example 2.11.conesolar.c: draw a cone solar system */ // by Jim X. Chen; September, 2000 #include #include #include #include #define ESC 27 #define SPACE 32 int Height=600, Width=600; int depth=4, 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 subdivideCone(float *v1, float *v2, int depth) { float v11[3], v22[3], v00[3] = {0, 0, 0}, v12[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++) { v11[i] = v1[i]; v22[i] = v2[i]; } drawtriangle(v11, v22, v00); // bottom cover of the cone v00[2] = 1; // height of the cone, the tip on z axis drawtriangle(v11, v22, v00); // side cover of the cone return; } for (i=0; i<3; i++) v12[i] = v1[i]+v2[i]; normalize(v12); subdivideCone(v1, v12, depth - 1); subdivideCone(v12, v2, depth - 1); } void drawCone(void) // draw a unit cone with center at the origin and bottom in xy plane { subdivideCone(vdata[0], vdata[1], depth); subdivideCone(vdata[1], vdata[3], depth); subdivideCone(vdata[3], vdata[4], depth); subdivideCone(vdata[4], vdata[0], depth); } drawColorCoord(float xlen, float ylen, float zlen) { // coordinate lines glBegin(GL_LINES); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(0,0,zlen); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,ylen, 0); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(xlen,0,0); glEnd(); // coordinate labels: X, Y, Z glPushMatrix(); glTranslatef(xlen,0.,0.); glScalef(xlen/Width,xlen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'X'); glPopMatrix(); glPushMatrix(); glColor3f(0,1,0); glTranslatef(0., ylen,0.); glScalef(ylen/Width,ylen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'Y'); glPopMatrix(); glPushMatrix(); glColor3f(1,0,0); glTranslatef(0., 0.,zlen); glScalef(zlen/Width,zlen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'Z'); glPopMatrix(); } void drawSolar(float E, float e, float M, float m) { float alpha=30; // Global coordinates glLineWidth(3); drawColorCoord(Width/4, Width/4, Width/4); glPushMatrix(); glRotatef(e, 0.0, 1.0, 0.0); // rotating around the "sun"; proceed angle glRotatef(alpha, 0.0, 0.0, 1.0); // tilt angle glTranslatef(0., E, 0.0); glPushMatrix(); glScalef(Width/20,Width/20,Width/20); drawSphere(); glPopMatrix(); glPushMatrix(); glScalef(E/8,E,E/8); glRotatef(90, 1.0, 0.0, 0.0); // orient the cone drawCone(); glPopMatrix(); glRotatef(m, 0.0, 1.0, 0.); // rotating around the "earth" glTranslatef(M, 0., 0.); glLineWidth(1); drawColorCoord(Width/8, Width/8, Width/8); glScalef(E/8,E/8,E/8); drawSphere(); glPopMatrix(); } void display(void) { float angle; cnt++; depth = (cnt/100) % 6; angle= (float) cnt; // clears both framebuffer and zbuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawSolar(Width/4, angle, Width/6, 2*angle); 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: glRotatef(10, 1,1,1); glutIdleFunc(NULL); glutPostRedisplay(); break; default: glutIdleFunc(display); } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(Width, Height); glutCreateWindow("Example: press SPACE & another key"); glutKeyboardFunc(Key); glutReshapeFunc(Reshape); glutDisplayFunc(display); glutIdleFunc(display); glutMainLoop(); }