/* dodecahedron.c Rotating with color interpolation */ /* Colors are assigned to the vertices */ /* Mouse buttons control direction of rotation */ #include #include #include #include #undef abs #define abs(a) ((a)>0.0?(a):(-(a))) GLfloat vertices[20][3]; GLfloat colors[][3] = {{1.0,0.0,0.0},{0.0,1.0,1.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,0.0,0.0}}; static GLfloat theta[] = {0.0,0.0,0.0}; static GLint axis = 2; static double Pi = 3.141592653589793238462643383279502884197; static int check_one = 0; static double check_sum = 0.0; static double check_ssq = 0.0; static double check_cnt = 0.0; static double check_len = 0.0; typedef GLfloat vert_typ[3]; static double phiaaa = 52.62263590; static double phibbb = 10.81231754; static double phiaa = 52.62263590; /* incrementable */ static double phibb = 10.81231754; static double phidel = 0.0001; static int phiseq = -1; /* ignore first case, not set up yet */ static double phival[9]; /* [3][3] a + 0 -, b + 0 1 */ static double phifct[9][2] = {{ 1.0,1.0}, { 1.0,0.0}, { 1.0,-1.0}, { 0.0,1.0}, { 0.0,0.0}, { 0.0,-1.0}, {-1.0,1.0}, {-1.0,0.0}, {-1.0,-1.0}}; static double phimin; /* minimum of phival */ static int phiidx; /* index to phifct of minimum */ static double d3len(vert_typ a, vert_typ b) { double x1, y1, z1, x2, y2, z2; x1 = a[0]; y1 = a[1]; z1 = a[2]; x2 = b[0]; y2 = b[1]; z2 = b[2]; return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)); } static void vertex_compute() { double phia, phib, phic, phid, thea, theb, the72, the, r; int i; /* base on unit sphere x*x+y*y+z*z=1 */ /* x=r*cos(the)*cos(phi) the 0 to 2Pi */ /* y=r*sin(the)*cos(phi) phi -Pi/2 to Pi/2 */ /* z=r*sin(phi) radians=Pi*degrees/180 */ r = 1.0; phia = Pi*phiaa/180.0; /* 4 sets of five points */ phib = Pi*phibb/180.0; phic = Pi*(-phibb)/180.0; phid = Pi*(-phiaa)/180.0; thea = 0.0; the72 = Pi*72.0/180; theb = the72/2.0; /* alternate layers split 72 degrees */ the = 0.0; for(i=0; i<5; i++) { vertices[i][0]=r*cos(the)*cos(phia); vertices[i][1]=r*sin(the)*cos(phia); vertices[i][2]=r*sin(phia); if(check_one==0) printf("i=%d, x=%6.3f, y=%6.3f, z=%6.3f \n", i, vertices[i][0], vertices[i][1], vertices[i][2]); the = the+the72; } the=0.0; for(i=5; i<10; i++) { vertices[i][0]=r*cos(the)*cos(phib); vertices[i][1]=r*sin(the)*cos(phib); vertices[i][2]=r*sin(phib); if(check_one==0) printf("i=%d, x=%6.3f, y=%6.3f, z=%6.3f \n", i, vertices[i][0], vertices[i][1], vertices[i][2]); the = the+the72; } the = theb; for(i=10; i<15; i++) { vertices[i][0]=r*cos(the)*cos(phic); vertices[i][1]=r*sin(the)*cos(phic); vertices[i][2]=r*sin(phic); if(check_one==0) printf("i=%d, x=%6.3f, y=%6.3f, z=%6.3f \n", i, vertices[i][0], vertices[i][1], vertices[i][2]); the = the+the72; } the=theb; for(i=15; i<20; i++) { vertices[i][0]=r*cos(the)*cos(phid); vertices[i][1]=r*sin(the)*cos(phid); vertices[i][2]=r*sin(phid); if(check_one==0) printf("i=%d, x=%6.3f, y=%6.3f, z=%6.3f \n", i, vertices[i][0], vertices[i][1], vertices[i][2]); the = the+the72; } } static void polygon(int a, int b, int c , int d, int e) { /* draw a polygon via list of indices of vertices */ glBegin(GL_POLYGON); glColor3fv(colors[a%8]); glVertex3fv(vertices[a]); glColor3fv(colors[b%8]); glVertex3fv(vertices[b]); glColor3fv(colors[c%8]); glVertex3fv(vertices[c]); glColor3fv(colors[d%8]); glVertex3fv(vertices[d]); glColor3fv(colors[e%8]); glVertex3fv(vertices[e]); glEnd(); /* just check stuff */ check_cnt = check_cnt + 1.0; check_len = d3len(vertices[a],vertices[b]); if(check_one==0) printf("a=%d, b=%d, l=%12.9f \n", a, b, check_len); check_sum = check_sum + check_len; check_ssq = check_ssq + check_len*check_len; check_cnt = check_cnt + 1.0; check_len = d3len(vertices[b],vertices[c]); if(check_one==0) printf("b=%d, c=%d, l=%12.9f \n", b, c, check_len); check_sum = check_sum + check_len; check_ssq = check_ssq + check_len*check_len; check_cnt = check_cnt + 1.0; check_len = d3len(vertices[c],vertices[d]); if(check_one==0) printf("c=%d, d=%d, l=%12.9f \n", c, d, check_len); check_sum = check_sum + check_len; check_ssq = check_ssq + check_len*check_len; check_cnt = check_cnt + 1.0; check_len = d3len(vertices[d],vertices[e]); if(check_one==0) printf("d=%d, e=%d, l=%12.9f \n", d, e, check_len); check_sum = check_sum + check_len; check_ssq = check_ssq + check_len*check_len; check_cnt = check_cnt + 1.0; check_len = d3len(vertices[e],vertices[a]); if(check_one==0) printf("e=%d, a=%d, l=%12.9f \n", e, a, check_len); check_sum = check_sum + check_len; check_ssq = check_ssq + check_len*check_len; } static void colorhedra(void) { /* map vertices to 12 faces */ polygon(0,1,2,3,4); polygon(0,1,6,10,5); polygon(1,2,7,11,6); polygon(2,3,8,12,7); polygon(3,4,9,13,8); polygon(4,0,5,14,9); polygon(15,16,11,6,10); polygon(16,17,12,7,11); polygon(17,18,13,8,12); polygon(18,19,14,9,13); polygon(19,15,10,5,14); polygon(15,16,17,18,19); } static void display(void) { int j; /* display callback, clear frame buffer and z buffer, */ /* rotate hedra and draw, swap buffers */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(theta[0], 1.0, 0.0, 0.0); glRotatef(theta[1], 0.0, 1.0, 0.0); glRotatef(theta[2], 0.0, 0.0, 1.0); colorhedra(); glFlush(); glutSwapBuffers(); /* just check stuff */ if(check_one==0 && check_cnt > 0.0) { check_one = 1; printf("cnt=%g, sum=%g, mean=%g, stddev=%g \n", check_cnt, check_sum, check_sum/check_cnt, sqrt((check_cnt*check_ssq - check_sum*check_sum)/ (check_cnt*check_cnt))); } if(phiseq>=0) phival[phiseq] = abs(d3len(vertices[0],vertices[1])- d3len(vertices[1],vertices[6]))+ abs(d3len(vertices[1],vertices[6])- d3len(vertices[6],vertices[10])); phiseq++; if(phiseq<9) { phiaa = phifct[phiseq][0]*phidel+phiaaa; phibb = phifct[phiseq][1]*phidel+phibbb; vertex_compute(); return; } phiseq = 0; phimin = phival[0]; phiidx = 0; for(j=1; j<9; j++) { if(phival[j] 360.0) theta[axis] = theta[axis] - 360.0; /* display(); */ glutPostRedisplay(); } static void mouse(int btn, int state, int x, int y) { /* mouse callback, selects an axis about which to rotate */ if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2; } static void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w <= h) glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w, 2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0); else glOrtho(-2.0 * (GLfloat)w / (GLfloat)h, 2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } int main(int argc, char *argv[]) { glutInit(&argc, argv); /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow(argv[0]); glutReshapeFunc(myReshape); vertex_compute(); glutDisplayFunc(display); glutIdleFunc(spinhedra); /* "spinhedra" setup */ glutMouseFunc(mouse); /* "mouse" setup */ glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */ glutMainLoop(); return 0; }