/* Example 2.9.solar.c: draw a simplified 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); } 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) { drawColorCoord(Width/4, Width/4, Width/4); glPushMatrix(); glRotatef(e, 0.0, 1.0, 0.0); // rotating around the "sun"; proceed angle glTranslatef(E, 0.0, 0.0); glPushMatrix(); glScalef(Width/20,Width/20,Width/20); drawSphere(); glPopMatrix(); glRotatef(m, 0.0, 1.0, 0.0); // rotating around the "earth" glTranslatef(M, 0.0, 0.0); drawColorCoord(Width/8, Width/8, Width/8); glScalef(Width/40,Width/40,Width/40); drawSphere(); glPopMatrix(); } void display(void) { float angle; cnt++; angle = (float) cnt; // clears both framebuffer and zbuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawSolar(Width/4, angle, Width/12, 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(); }