/* * Bouncing ball demo. * * This program is in the public domain * * Brian Paul * * Conversion to GLUT by Mark J. Kilgard */ #include <math.h> #include <stdlib.h> #include <string.h> #include <GL/glut.h> #define COS(X) cos( (X) * 3.14159/180.0 ) #define SIN(X) sin( (X) * 3.14159/180.0 ) #define RED 1 #define WHITE 2 #define CYAN 3 GLboolean IndexMode = GL_FALSE; GLuint Ball; GLenum Mode; GLfloat Zrot = 0.0, Zstep = 180.0; GLfloat Xpos = 0.0, Ypos = 1.0; GLfloat Xvel = 2.0, Yvel = 0.0; GLfloat Xmin = -4.0, Xmax = 4.0; GLfloat Ymin = -3.8, Ymax = 4.0; GLfloat G = -9.8; static GLuint make_ball(void) { GLuint list; GLfloat a, b; GLfloat da = 18.0, db = 18.0; GLfloat radius = 1.0; GLuint color; GLfloat x, y, z; list = glGenLists(1); glNewList(list, GL_COMPILE); color = 0; for (a = -90.0; a + da <= 90.0; a += da) { glBegin(GL_QUAD_STRIP); for (b = 0.0; b <= 360.0; b += db) { if (color) { glIndexi(RED); glColor3f(1, 0, 0); } else { glIndexi(WHITE); glColor3f(1, 1, 1); } x = radius * COS(b) * COS(a); y = radius * SIN(b) * COS(a); z = radius * SIN(a); glVertex3f(x, y, z); x = radius * COS(b) * COS(a + da); y = radius * SIN(b) * COS(a + da); z = radius * SIN(a + da); glVertex3f(x, y, z); color = 1 - color; } glEnd(); } glEndList(); return list; } static void reshape(int width, int height) { float aspect = (float) width / (float) height; glViewport(0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-6.0 * aspect, 6.0 * aspect, -6.0, 6.0, -6.0, 6.0); glMatrixMode(GL_MODELVIEW); } /* ARGSUSED1 */ static void key(unsigned char k, int x, int y) { switch (k) { case 27: /* Escape */ exit(0); } } static void draw(void) { GLint i; glClear(GL_COLOR_BUFFER_BIT); glIndexi(CYAN); glColor3f(0, 1, 1); glBegin(GL_LINES); for (i = -5; i <= 5; i++) { glVertex2i(i, -5); glVertex2i(i, 5); } for (i = -5; i <= 5; i++) { glVertex2i(-5, i); glVertex2i(5, i); } for (i = -5; i <= 5; i++) { glVertex2i(i, -5); glVertex2f(i * 1.15, -5.9); } glVertex2f(-5.3, -5.35); glVertex2f(5.3, -5.35); glVertex2f(-5.75, -5.9); glVertex2f(5.75, -5.9); glEnd(); glPushMatrix(); glTranslatef(Xpos, Ypos, 0.0); glScalef(2.0, 2.0, 2.0); glRotatef(8.0, 0.0, 0.0, 1.0); glRotatef(90.0, 1.0, 0.0, 0.0); glRotatef(Zrot, 0.0, 0.0, 1.0); glCallList(Ball); glPopMatrix(); glFlush(); glutSwapBuffers(); } static void idle(void) { static float vel0 = -100.0; static double t0 = -1.; double t, dt; t = glutGet(GLUT_ELAPSED_TIME) / 1000.; if (t0 < 0.) t0 = t; dt = t - t0; t0 = t; Zrot += Zstep*dt; Xpos += Xvel*dt; if (Xpos >= Xmax) { Xpos = Xmax; Xvel = -Xvel; Zstep = -Zstep; } if (Xpos <= Xmin) { Xpos = Xmin; Xvel = -Xvel; Zstep = -Zstep; } Ypos += Yvel*dt; Yvel += G*dt; if (Ypos < Ymin) { Ypos = Ymin; if (vel0 == -100.0) vel0 = fabs(Yvel); Yvel = vel0; } glutPostRedisplay(); } static void visible(int vis) { if (vis == GLUT_VISIBLE) glutIdleFunc(idle); else glutIdleFunc(NULL); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowPosition(0, 0); glutInitWindowSize(600, 450); IndexMode = argc > 1 && strcmp(argv[1], "-ci") == 0; if (IndexMode) glutInitDisplayMode(GLUT_INDEX | GLUT_DOUBLE); else glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Bounce"); Ball = make_ball(); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glDisable(GL_DITHER); glShadeModel(GL_FLAT); glutDisplayFunc(draw); glutReshapeFunc(reshape); glutVisibilityFunc(visible); glutKeyboardFunc(key); if (IndexMode) { glutSetColor(RED, 1.0, 0.0, 0.0); glutSetColor(WHITE, 1.0, 1.0, 1.0); glutSetColor(CYAN, 0.0, 1.0, 1.0); } glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }