#include "stdio.h" #include #include static GLfloat spin = 0; static int level = 4; static int model = 0; static GLfloat rotx, roty; static int ox = -1, oy = -1; static int mot; #define PAN 1 #define ROT 2 void movelight(int x, int y) { spin += (x-ox); ox = x; oy = y; if (spin > 360.) spin -= 360.; if (spin < -360.) spin -= -360.; glutPostRedisplay(); } void rotate(int x, int y) { rotx += x-ox; if (rotx > 360.) rotx -= 360.; else if (rotx < -360.) rotx += 360.; roty += y-oy; if (roty > 360.) roty -= 360.; else if (roty < -360.) roty += 360.; ox = x; oy = y; glutPostRedisplay(); } void motion(int x, int y) { if (mot == PAN) movelight(x, y); else if (mot == ROT) rotate(x,y); } void mouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) { switch(button) { case GLUT_LEFT_BUTTON: mot = PAN; motion(ox = x, oy = y); break; case GLUT_RIGHT_BUTTON: mot = ROT; motion(ox = x, oy = y); break; case GLUT_MIDDLE_BUTTON: break; } } else if (state == GLUT_UP) { mot = 0; } } void togglewire(void) { static int toggle = 0; toggle ^= 1; glPolygonMode(GL_FRONT_AND_BACK, toggle ? GL_LINE : GL_FILL); } extern void sphere(int level); void genmodel(void) { glNewList(1, GL_COMPILE); if (model) { GLUquadricObj *q = gluNewQuadric(); gluSphere(q, 1.0, 10*level, 10*level); gluDeleteQuadric(q); } else { sphere(level-1); } glEndList(); } void togglemodel(void) { model ^= 1; genmodel(); } void levelup(void) { level += 1; if (level > 7) level = 7; genmodel(); } void leveldown(void) { level -= 1; if (level <= 0) level = 1; genmodel(); } void help(void) { printf("'h' - help\n"); printf("'t' - tessellation style\n"); printf("'UP' - increase tessellation\n"); printf("'DOWN' - decrease tessellation\n"); printf("left mouse - rotate sphere\n"); printf("right mouse - move light\n"); } void init(void) { GLfloat specular[4] = { 1., 1., 1., 1. }; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); genmodel(); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30); } void display(void) { GLfloat position[] = { 0.0, 0.0, 3.5, 1.0 }; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0, 0.0, -5.0); glPushMatrix(); glRotatef(spin, 1.0, 0.0, 0.0); glRotatef(0.0, 1.0, 0.0, 0.0); glLightfv(GL_LIGHT0, GL_POSITION, position); glPopMatrix(); glRotatef(rotx, 0., 1., 0.); glRotatef(roty, 1., 0., 0.); glCallList(1); glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); } /*ARGSUSED1*/ void key(unsigned char key, int x, int y) { switch(key) { case 't': togglemodel(); break; case 'w': togglewire(); break; case 'h': help(); break; case '\033': exit(EXIT_SUCCESS); break; default: break; } glutPostRedisplay(); } /*ARGSUSED1*/ void special(int key, int x, int y) { switch(key) { case GLUT_KEY_UP: levelup(); break; case GLUT_KEY_DOWN: leveldown(); break; } glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowSize(512, 512); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); (void)glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutKeyboardFunc(key); glutSpecialFunc(special); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMotionFunc(motion); glutMainLoop(); return 0; }