/* displayList.c - Jon McCormack, March 2004 */ /* Program to demonstrate the use of display lists: * loads a shape using display lists then calls several instances. * Also demonstrates the use of glutIdleFunc to animate the shapes. * * This program uses display lists to create multiple instances of a * single object. It also demonstrates the use of glutIdleFunc to do * animation. Use the left button to speed up the animation, right button * to slow down. Middle button to reset to the default speed. * * You might like to experiment with changing the constants to see how * this changes the graphics output. * * As an exercise you might like to modify the program so that it defines a * set of display lists with stars of different numbers of points in each. * A more advanced modification would be to use keyboard commands to * change the number of points/radii in each star while the program is * running. * */ /* Copyright 2004 Jon McCormack * Last modified 22 March 2004 * Updated March 23 2004: Simplified drawStar function loop * Updated March 29 2004: Removed platform dependencies */ #include #include #include #ifdef __APPLE__ #include #else #include #endif #define INNER_RADIUS 0.3 /* star inner radius */ #define OUTER_RADIUS 1.0 /* star outer radius */ #define NUM_STAR_POINTS 8 /* number of points on the star */ #define NUM_STARS 8 /* number of stars in the animation */ #define ROT_INC 0.1 /* how much to rotate each frame */ #define STAR_IDX 1 /* display list for the star */ /* * local static variables: g_rotate used to keep track of global rotation * g_rotInc is the rotation increment each frame * */ static GLfloat g_rotate = 0; static GLfloat g_rotInc = ROT_INC; /* degree increment for rotation animation */ /* * drawStar * * Draws a star with an inner radius, outer radius * and number of points. Note that this creates non-simple polygons. * */ void drawStar(GLfloat inner, GLfloat outer, int numPoints) { GLfloat step = M_PI * 2.0 / (GLfloat)(2 * numPoints); register int i; GLfloat angle, r; glBegin(GL_LINE_LOOP); for (i = 0; i < numPoints * 2; ++i) { r = (i % 2 == 0 ? inner : outer); angle = i * step; glVertex2f(r * cos(angle), r * sin(angle)); } glEnd(); } /* * display * * This function is called by the GLUT to display the graphics * */ void display(void) { register int i; register GLfloat c; /* used to change color of each star */ /* set matrix mode to modelview */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear( GL_COLOR_BUFFER_BIT ); for (i = 0; i < NUM_STARS; ++i) { /* save matrix */ glPushMatrix(); /* draw the stars in a large circle */ glRotatef(360.0/NUM_STARS * i, 0, 0, 1); glTranslatef(OUTER_RADIUS, 0,0); /* this command does the animated rotation of each star */ glRotatef(g_rotate + (3 * i), 0, 0, 1); /* make each star a different colour */ c = 1.0/NUM_STARS * (GLfloat)i; glColor3f(1.0 - c, 0.0, c); /* call the display list - which draws the star */ glCallList(STAR_IDX); /* restore modelview matrix */ glPopMatrix(); } glFlush(); /* force OpenGL output */ } /* * myReshape * * This function is called whenever the user (or OS) reshapes the * OpenGL window. The GLUT sends the new window dimensions (x,y) * */ void myReshape(int w, int h) { /* set viewport to new width and height */ /* note that this command does not change the CTM */ glViewport(0, 0, w, h); /* * set viewing window in world coordinates */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* init projection matrix */ if (w <= h) glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, -1.0, 1.0); else glOrtho(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -1.0, 1.0); /* set matrix mode to modelview */ glMatrixMode(GL_MODELVIEW); } /* * myKey * * responds to key presses from the user */ void myKey(unsigned char k, int x, int y) { switch (k) { case 'q': case 'Q': exit(0); break; default: printf("Unknown keyboard command \'%c\'.\n", k); break; } } /* * myMouse * * function called by the GLUT when the user presses a mouse button * * Here we increment the global rotation rate with each press - left to do a * positive increment, right for negative, middle to reset */ void myMouse(int btn, int state, int x, int y) { if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) g_rotInc += ROT_INC; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) g_rotInc = ROT_INC; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) g_rotInc -= ROT_INC; /* force redisplay */ glutPostRedisplay(); } /* * myIdleFunc * * increments the rotation variable within glutMainLoop */ void myIdleFunc(void) { g_rotate += g_rotInc; /* force glut to call the display function */ glutPostRedisplay(); } /* * main * * Initialization and sets graphics callbacks * */ int main(int argc, char **argv) { /* glutInit MUST be called before any other GLUT/OpenGL calls */ glutInit(&argc, argv); /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow("Star Instance Test"); /* set callback functions */ glutReshapeFunc(myReshape); glutDisplayFunc(display); glutIdleFunc(myIdleFunc); glutKeyboardFunc(myKey); glutMouseFunc(myMouse); /* set clear colour */ glClearColor(1.0, 1.0, 1.0, 1.0); /* set current colour to black */ glColor3f(0.0, 0.0, 0.0); /* create star display list */ glNewList(STAR_IDX,GL_COMPILE); /* draws a star */ drawStar(INNER_RADIUS, OUTER_RADIUS, NUM_STAR_POINTS); glEndList(); glutMainLoop(); return 0; }