/* Copyright (c) Mark J. Kilgard, 1994. */ /* This program is freely distributable without licensing fees and is provided without guarantee or warrantee expressed or implied. This program is -not- in the public domain. */ #include #include #ifndef WIN32 #include #else #define random rand #define srandom srand #endif #include #include /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632 #endif GLboolean moving = GL_FALSE; #define MAX_PLANES 15 struct { float speed; /* zero speed means not flying */ GLfloat red, green, blue; float theta; float x, y, z, angle; } planes[MAX_PLANES]; #define v3f glVertex3f /* v3f was the short IRIS GL name for glVertex3f */ void draw(void) { GLfloat red, green, blue; int i; glClear(GL_DEPTH_BUFFER_BIT); /* paint black to blue smooth shaded polygon for background */ glDisable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glBegin(GL_POLYGON); glColor3f(0.0, 0.0, 0.0); v3f(-20, 20, -19); v3f(20, 20, -19); glColor3f(0.0, 0.0, 1.0); v3f(20, -20, -19); v3f(-20, -20, -19); glEnd(); /* paint planes */ glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT); for (i = 0; i < MAX_PLANES; i++) if (planes[i].speed != 0.0) { glPushMatrix(); glTranslatef(planes[i].x, planes[i].y, planes[i].z); glRotatef(290.0, 1.0, 0.0, 0.0); glRotatef(planes[i].angle, 0.0, 0.0, 1.0); glScalef(1.0 / 3.0, 1.0 / 4.0, 1.0 / 4.0); glTranslatef(0.0, -4.0, -1.5); glBegin(GL_TRIANGLE_STRIP); /* left wing */ v3f(-7.0, 0.0, 2.0); v3f(-1.0, 0.0, 3.0); glColor3f(red = planes[i].red, green = planes[i].green, blue = planes[i].blue); v3f(-1.0, 7.0, 3.0); /* left side */ glColor3f(0.6 * red, 0.6 * green, 0.6 * blue); v3f(0.0, 0.0, 0.0); v3f(0.0, 8.0, 0.0); /* right side */ v3f(1.0, 0.0, 3.0); v3f(1.0, 7.0, 3.0); /* final tip of right wing */ glColor3f(red, green, blue); v3f(7.0, 0.0, 2.0); glEnd(); glPopMatrix(); } glutSwapBuffers(); } void tick_per_plane(int i) { float theta = planes[i].theta += planes[i].speed; planes[i].z = -9 + 4 * cos(theta); planes[i].x = 4 * sin(2 * theta); planes[i].y = sin(theta / 3.4) * 3; planes[i].angle = ((atan(2.0) + M_PI_2) * sin(theta) - M_PI_2) * 180 / M_PI; if (planes[i].speed < 0.0) planes[i].angle += 180; } void add_plane(void) { int i; for (i = 0; i < MAX_PLANES; i++) if (planes[i].speed == 0) { #define SET_COLOR(r,g,b) \ planes[i].red=r; planes[i].green=g; planes[i].blue=b; switch (random() % 6) { case 0: SET_COLOR(1.0, 0.0, 0.0); /* red */ break; case 1: SET_COLOR(1.0, 1.0, 1.0); /* white */ break; case 2: SET_COLOR(0.0, 1.0, 0.0); /* green */ break; case 3: SET_COLOR(1.0, 0.0, 1.0); /* magenta */ break; case 4: SET_COLOR(1.0, 1.0, 0.0); /* yellow */ break; case 5: SET_COLOR(0.0, 1.0, 1.0); /* cyan */ break; } planes[i].speed = ((float) (random() % 20)) * 0.001 + 0.02; if (random() & 0x1) planes[i].speed *= -1; planes[i].theta = ((float) (random() % 257)) * 0.1111; tick_per_plane(i); if (!moving) glutPostRedisplay(); return; } } void remove_plane(void) { int i; for (i = MAX_PLANES - 1; i >= 0; i--) if (planes[i].speed != 0) { planes[i].speed = 0; if (!moving) glutPostRedisplay(); return; } } void tick(void) { int i; for (i = 0; i < MAX_PLANES; i++) if (planes[i].speed != 0.0) tick_per_plane(i); } void animate(void) { tick(); glutPostRedisplay(); } void visible(int state) { if (state == GLUT_VISIBLE) { if (moving) glutIdleFunc(animate); } else { if (moving) glutIdleFunc(NULL); } } /* ARGSUSED1 */ void keyboard(unsigned char ch, int x, int y) { switch (ch) { case ' ': if (!moving) { tick(); glutPostRedisplay(); } break; case 27: /* ESC */ exit(0); break; } } #define ADD_PLANE 1 #define REMOVE_PLANE 2 #define MOTION_ON 3 #define MOTION_OFF 4 #define QUIT 5 void menu(int item) { switch (item) { case ADD_PLANE: add_plane(); break; case REMOVE_PLANE: remove_plane(); break; case MOTION_ON: moving = GL_TRUE; glutChangeToMenuEntry(3, "Motion off", MOTION_OFF); glutIdleFunc(animate); break; case MOTION_OFF: moving = GL_FALSE; glutChangeToMenuEntry(3, "Motion", MOTION_ON); glutIdleFunc(NULL); break; case QUIT: exit(0); break; } } int main(int argc, char *argv[]) { glutInit(&argc, argv); /* use multisampling if available */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE); glutCreateWindow("glutplane"); glutDisplayFunc(draw); glutKeyboardFunc(keyboard); glutVisibilityFunc(visible); glutCreateMenu(menu); glutAddMenuEntry("Add plane", ADD_PLANE); glutAddMenuEntry("Remove plane", REMOVE_PLANE); glutAddMenuEntry("Motion", MOTION_ON); glutAddMenuEntry("Quit", QUIT); glutAttachMenu(GLUT_RIGHT_BUTTON); /* setup OpenGL state */ glClearDepth(1.0); glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 20); glMatrixMode(GL_MODELVIEW); /* add three initial random planes */ srandom(getpid()); add_plane(); add_plane(); add_plane(); /* start event processing */ glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }