/* split_cube6.c Rotating split_cube with color sections */ /* 4 pyramids build a cube */ /* color of faces must be shaded to see edges */ /* pyramids must be offset to see "split" */ /* does wireframe make it better or worse? */ /* give command line "x" to start worse case */ /* Mouse buttons control direction of rotation */ /* "O" and "o" make offset bigger and smaller */ /* "C" and "c" make color distinct or closer */ /* "F" and "f" make rotation faster or slower */ /* "W" and "w" make wireframe or solid */ #include #include #include static GLfloat vertices[][3] = { {-1.0,-1.0,-1.0}, {-1.0,-1.0, 1.0}, /* 0,1 */ {-1.0, 1.0,-1.0}, {-1.0, 1.0, 1.0}, { 1.0,-1.0,-1.0}, /* 2,3,4 */ { 1.0,-1.0, 1.0}, { 1.0, 1.0,-1.0}, { 1.0, 1.0, 1.0}, /* 5,6,7 */ { 0.0, 0.0, 0.0}}; /* 8 */ static GLfloat offsets[][3] = { { 0.0, 0.0,-1.0}, {-1.0, 0.0, 0.0}, { 0.0,-1.0, 0.0}, /* 0,1,2 */ { 0.0, 0.0, 1.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}}; /* 3,4,5 */ static GLfloat colors[][3] = { {1.0,0.0,0.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}, {0.0,1.0,1.0}}; static GLfloat theta[] = {0.0,0.0,0.0}; static GLint axis = 2; static double colorset = 0.1; /* 'C' or 'c' */ static double offset = 0.2; /* 'O' or 'o' */ static double rotation = 0.5; /* 'F' or 'f' */ static int wireframe = 0; /* 'W' or 'w' */ static int hide = 0; /* no function prototypes used here because the functions are defined */ /* before they are used */ static void triangle(int color, int a, int b, int c, int off) { int i,j,k; GLfloat overtices[3][3]; /* offset vertices */ GLfloat ocolors[3][3]; /* offset face colors */ k=a; for(i=0; i<3; i++) { if(i==1) k=b; if(i==2) k=c; for(j=0; j<3; j++) { overtices[i][j]=vertices[k][j]+offset*offsets[off][j]; ocolors[i][j]=colors[color][j]-colorset*(double)i; } } /* draw a triangle face via list of vertices */ if(!wireframe) { glBegin(GL_POLYGON); glColor3fv(ocolors[0]); glVertex3fv(overtices[0]); glColor3fv(ocolors[1]); glVertex3fv(overtices[1]); glColor3fv(ocolors[2]); glVertex3fv(overtices[2]); glEnd(); } else /* wireframe, three lines */ { glLineWidth(2.0); glBegin(GL_LINES); glColor3fv(colors[color]); glVertex3fv(overtices[0]); glVertex3fv(overtices[1]); glVertex3fv(overtices[0]); glVertex3fv(overtices[2]); glVertex3fv(overtices[1]); glVertex3fv(overtices[2]); glEnd(); } } /* end triangle */ static void square(int color, int a, int b, int c, int d, int off) { int i,j,k; GLfloat overtices[4][3]; /* offset vertices */ GLfloat ocolors[4][3]; /* offset face colors */ k=a; for(i=0; i<4; i++) { if(i==1) k=b; if(i==2) k=c; if(i==3) k=d; for(j=0; j<3; j++) { overtices[i][j]=vertices[k][j]+offset*offsets[off][j]; ocolors[i][j]=colors[color][j]-colorset*(double)i; } } /* draw a square face via list of vertices */ if(!wireframe) { glBegin(GL_POLYGON); glColor3fv(ocolors[0]); glVertex3fv(overtices[0]); glColor3fv(ocolors[1]); glVertex3fv(overtices[1]); glColor3fv(ocolors[2]); glVertex3fv(overtices[2]); glColor3fv(ocolors[3]); glVertex3fv(overtices[3]); glEnd(); } else /* wireframe, four lines */ { glLineWidth(2.0); glBegin(GL_LINES); glColor3fv(colors[color]); glVertex3fv(overtices[0]); glVertex3fv(overtices[1]); glVertex3fv(overtices[1]); glVertex3fv(overtices[2]); glVertex3fv(overtices[2]); glVertex3fv(overtices[3]); glVertex3fv(overtices[3]); glVertex3fv(overtices[0]); glEnd(); } } /* end square */ static void pyramid(int color, int a, int b, int c, int d, int e, int off) { /* draw a pyramid via list of vertices (a,b,c,d,e peak) */ triangle(color, a,b,e, off); triangle(color, b,c,e, off); triangle(color, c,d,e, off); triangle(color, d,a,e, off); square(color, a,b,c,d, off); } /* end pyramid */ static void colorsplit_cube(void) { /* map vertices to 6 pyramids with 5 faces each */ pyramid(0, 0,2,6,4,8, 0); /* color, 4 vertices, offset -Z */ pyramid(1, 1,3,2,0,8, 1); /* -X */ pyramid(2, 0,4,5,1,8, 2); /* -Y */ pyramid(3, 5,7,3,1,8, 3); /* +Z */ pyramid(4, 4,6,7,5,8, 4); /* +X */ pyramid(5, 3,7,6,2,8, 5); /* +Y */ } /* end colorsplit_cube */ static void printstring(void *font, char *string) { int len, i; len = (int) strlen(string); for (i = 0; i < len; i++) glutBitmapCharacter(font, string[i]); } /* end printstring */ static void printhelp(void) { /* aqua, lower left */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, 500, 0, 500, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor3f(0.0, 1.0, 1.0); /* hide for graphics class, use -x */ if(!hide) { glRasterPos2i(100, 480); printstring(GLUT_BITMAP_HELVETICA_18, "Cube split into six pyramids"); } glRasterPos2i(5, 65); printstring(GLUT_BITMAP_HELVETICA_12, "O or o changes offset"); glRasterPos2i(5, 53); printstring(GLUT_BITMAP_HELVETICA_12, "F or f changes fast rotation"); glRasterPos2i(5, 41); printstring(GLUT_BITMAP_HELVETICA_12, "C or c changes color blending"); glRasterPos2i(5, 29); printstring(GLUT_BITMAP_HELVETICA_12, "W or w changes to wire frame"); glRasterPos2i(5, 17); printstring(GLUT_BITMAP_HELVETICA_12, "arrow keys change rotation axis"); glRasterPos2i(5, 5); printstring(GLUT_BITMAP_HELVETICA_12, "mouse button selects rotation axis"); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } /* end printhelp */ static void display(void) { /* display callback, clear frame buffer and z buffer, */ /* rotate split_cube 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); colorsplit_cube(); printhelp(); glFlush(); glutSwapBuffers(); } /* end display */ static void spinSplit_Cube(void) { /* Idle callback, spin split_cube 'rotation' degrees about selected axis */ theta[axis] = theta[axis] + rotation; if(theta[axis] > 360.0) theta[axis] = theta[axis] - 360.0; /* display(); */ glutPostRedisplay(); } /* end spinSplit_Cube */ 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; } /* end mouse */ static void keyboard(unsigned char key, int x, int y) { switch (key) { case 'O': offset=offset+0.1; if(offset>0.5) offset=0.5; break; case 'o': offset=offset-0.1; if(offset<0.0) offset=0.0; break; case 'C': colorset=colorset+0.04; if(colorset>0.5) colorset=0.5; break; case 'c': colorset=colorset-0.04; if(colorset<0.0) colorset=0.0; break; case 'F': rotation=rotation+0.25; if(rotation>5.0) rotation=5.0; break; case 'f': rotation=rotation-0.25; if(rotation<0.0) rotation=0.0; break; case 'W': wireframe=1; break; case 'w': wireframe=0; break; } } /* end keyboard */ static void special(int k, int x, int y) { switch(k) { case GLUT_KEY_LEFT: axis = 1; break; case GLUT_KEY_RIGHT: axis = 2; break; case GLUT_KEY_DOWN: axis = 0; break; case GLUT_KEY_UP: wireframe = 1-wireframe; break; } } static void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w <= h) /* 2.0 -> 2.5 makes objects smaller */ glOrtho(-2.5, 2.5, -2.5 * (GLfloat)h / (GLfloat)w, 2.5 * (GLfloat)h / (GLfloat)w, -10.0, 10.0); else glOrtho(-2.5 * (GLfloat)w / (GLfloat)h, 2.5 * (GLfloat)w / (GLfloat)h, -2.5, 2.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } /* end myReshape */ int main(int argc, char *argv[]) { glutInit(&argc, argv); if(argc>1) if(argv[1][0]=='x' || argv[1][1]=='x') /* start with worse recognition */ { colorset = 0.0; offset = 0.0; rotation = 0.5; hide = 1; } /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow("split_cube6"); glutReshapeFunc(myReshape); /* enable resize/reshape */ glutDisplayFunc(display); /* enable display */ glutIdleFunc(spinSplit_Cube); /* enable idle function */ glutMouseFunc(mouse); /* enable mouse */ glutKeyboardFunc(keyboard); /* enable keyboard */ glutSpecialFunc(special); /* enable arrow keys */ glEnable(GL_DEPTH_TEST); /* enable hidden surface removal */ glutMainLoop(); return 0; } /* end split_cube6.c */