origami.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
- /* 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 <stdlib.h>
- #include <stdio.h>
- #include <GL/glut.h>
- /* Uses EXT_polygon_offset extension if available to better
- render the fold outlines. */
- #if GL_EXT_polygon_offset
- int polygon_offset;
- #endif
- enum {
- FLAT, /* completely flat sheet of paper */
- FLAP1, /* left flap being folded in */
- FLAP2, /* right flap being folded int */
- CENTER2, /* right side folded up at center */
- WING2, /* right wing folded down */
- CENTER1, /* left side folded up at center */
- WING1, /* left wing folded down */
- FOLDED /* fully folded paper airplane */
- } States;
- int motion = 1;
- int spinning = 1;
- int state = FLAT;
- int click = 0;
- int delay = 0;
- int direction;
- float flap1_angle = 0;
- float flap2_angle = 0;
- float center1_angle = 0;
- float center2_angle = 0;
- float wing1_angle = 0;
- float wing2_angle = 0;
- /**
- These correspond to the polygons for the paper sections:
- +----------+----------+
- | /| |
- | 2 / | 3 |
- | / | |
- +------/ | ------+
- | /| | | |
- | 1 / | | | 4 |
- | / | | | |
- | / | | | |
- | / | 5 | 6 | |
- |/ | | | |
- + | | | +
- | 7 | | | 8 |
- | | | | |
- | | | | |
- | | | | |
- | | | | |
- | | | | |
- | | | | |
- +------+---+---+------+
- */
- typedef GLfloat Point[2];
- Point poly1[] =
- {
- {-1, 0},
- {-1 / 3.0, 2 / 3.0},
- {-1, 2 / 3.0}
- };
- Point poly2[] =
- {
- {-1, 1},
- {-1, 2 / 3.0},
- {-1 / 3.0, 2 / 3.0},
- {0, 1}
- };
- Point poly3[] =
- {
- {0, 1},
- {1, 1},
- {1, 2 / 3.0},
- {1 / 3.0, 2 / 3.0}
- };
- Point poly4[] =
- {
- {1 / 3.0, 2 / 3.0},
- {1, 2 / 3.0},
- {1, 0}
- };
- Point poly5[] =
- {
- {-1 / 3.0, 2 / 3.0},
- {0, 1},
- {0, -1.5},
- {-1 / 3.0, -1.5}
- };
- Point poly6[] =
- {
- {0, 1},
- {1 / 3.0, 2 / 3.0},
- {1 / 3.0, -1.5},
- {0, -1.5}
- };
- Point poly7[] =
- {
- {-1, 0},
- {-1 / 3.0, 2 / 3.0},
- {-1 / 3.0, -1.5},
- {-1, -1.5}
- };
- Point poly8[] =
- {
- {1, 0},
- {1 / 3.0, 2 / 3.0},
- {1 / 3.0, -1.5},
- {1, -1.5}
- };
- void
- polydlist(int dlist, int num, Point points[])
- {
- int i;
- glNewList(dlist, GL_COMPILE);
- glBegin(GL_POLYGON);
- for (i = 0; i < num; i++) {
- glVertex2fv(&points[i][0]);
- }
- glEnd();
- glEndList();
- }
- void
- idle(void)
- {
- if (spinning)
- click++;
- switch (state) {
- case FLAT:
- delay++;
- if (delay >= 80) {
- delay = 0;
- state = FLAP1;
- glutSetWindowTitle("origami (folding)");
- direction = 1;
- }
- break;
- case FLAP1:
- flap1_angle += 2 * direction;
- if (flap1_angle >= 180) {
- state = FLAP2;
- } else if (flap1_angle <= 0) {
- state = FLAT;
- }
- break;
- case FLAP2:
- flap2_angle += 2 * direction;
- if (flap2_angle >= 180) {
- state = CENTER2;
- } else if (flap2_angle <= 0) {
- state = FLAP1;
- }
- break;
- case CENTER2:
- center2_angle += 2 * direction;
- if (center2_angle >= 84) {
- state = WING2;
- } else if (center2_angle <= 0) {
- state = FLAP2;
- }
- break;
- case WING2:
- wing2_angle += 2 * direction;
- if (wing2_angle >= 84) {
- state = CENTER1;
- } else if (wing2_angle <= 0) {
- state = CENTER2;
- }
- break;
- case CENTER1:
- center1_angle += 2 * direction;
- if (center1_angle >= 84) {
- state = WING1;
- } else if (center1_angle <= 0) {
- state = WING2;
- }
- break;
- case WING1:
- wing1_angle += 2 * direction;
- if (wing1_angle >= 84) {
- state = FOLDED;
- } else if (wing1_angle <= 0) {
- state = CENTER1;
- }
- break;
- case FOLDED:
- delay++;
- if (delay >= 80) {
- delay = 0;
- glutSetWindowTitle("origami (unfolding)");
- direction = -1;
- state = WING1;
- }
- break;
- }
- glutPostRedisplay();
- }
- void
- draw_folded_plane(void)
- {
- /* *INDENT-OFF* */
- glPushMatrix();
- glRotatef(click, 0, 0, 1);
- glRotatef(click / 5.0, 0, 1, 0);
- glTranslatef(0, .25, 0);
- glPushMatrix();
- glRotatef(center1_angle, 0, 1, 0);
- glPushMatrix();
- glTranslatef(-.5, .5, 0);
- glRotatef(flap1_angle, 1, 1, 0);
- glTranslatef(.5, -.5, 0);
- glCallList(2);
- glPopMatrix();
- glCallList(5);
- glPushMatrix();
- glTranslatef(-1 / 3.0, 0, 0);
- glRotatef(-wing1_angle, 0, 1, 0);
- glTranslatef(1 / 3.0, 0, 0);
- glCallList(7);
- glPushMatrix();
- glTranslatef(-.5, .5, 0);
- glRotatef(flap1_angle, 1, 1, 0);
- glTranslatef(.5, -.5, 0);
- glCallList(1);
- glPopMatrix();
- glPopMatrix();
- glPopMatrix();
- glPushMatrix();
- glRotatef(-center2_angle, 0, 1, 0);
- glPushMatrix();
- glTranslatef(.5, .5, 0);
- glRotatef(-flap2_angle, -1, 1, 0);
- glTranslatef(-.5, -.5, 0);
- glCallList(3);
- glPopMatrix();
- glCallList(6);
- glPushMatrix();
- glTranslatef(1 / 3.0, 0, 0);
- glRotatef(wing2_angle, 0, 1, 0);
- glTranslatef(-1 / 3.0, 0, 0);
- glCallList(8);
- glPushMatrix();
- glTranslatef(.5, .5, 0);
- glRotatef(-flap2_angle, -1, 1, 0);
- glTranslatef(-.5, -.5, 0);
- glCallList(4);
- glPopMatrix();
- glPopMatrix();
- glPopMatrix();
- glPopMatrix();
- /* *INDENT-ON* */
- }
- void
- display(void)
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glColor3ub(67, 205, 128);
- #if GL_EXT_polygon_offset
- if (polygon_offset) {
- glPolygonOffsetEXT(0.5, 0.0);
- glEnable(GL_POLYGON_OFFSET_EXT);
- }
- #endif
- draw_folded_plane();
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glColor3ub(255, 255, 255);
- #if GL_EXT_polygon_offset
- if (polygon_offset) {
- glPolygonOffsetEXT(0.0, 0.0);
- /* XXX a bug in the unpatched IRIX 5.3 OpenGL posts
- GL_INVALID_ENUM when GL_POLYGON_OFFSET_EXT is disabled;
- please ignore it. */
- glDisable(GL_POLYGON_OFFSET_EXT);
- } else {
- glPushMatrix();
- glTranslatef(0, 0, .05);
- }
- #else
- glPushMatrix();
- glTranslatef(0, 0, .05);
- #endif
- draw_folded_plane();
- #if GL_EXT_polygon_offset
- if (!polygon_offset) {
- glPopMatrix();
- }
- #else
- glPopMatrix();
- #endif
- glutSwapBuffers();
- }
- void
- visible(int state)
- {
- if (state == GLUT_VISIBLE) {
- if (motion)
- glutIdleFunc(idle);
- } else {
- glutIdleFunc(NULL);
- }
- }
- void
- menu(int value)
- {
- switch (value) {
- case 1:
- direction = -direction;
- if (direction > 0) {
- glutSetWindowTitle("origami (folding)");
- } else {
- glutSetWindowTitle("origami (unfolding)");
- }
- break;
- case 2:
- motion = 1 - motion;
- if (motion) {
- glutIdleFunc(idle);
- } else {
- glutIdleFunc(NULL);
- }
- break;
- case 3:
- spinning = 1 - spinning;
- break;
- case 666:
- exit(0);
- }
- }
- int
- main(int argc, char **argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
- glutCreateWindow("origami");
- glutDisplayFunc(display);
- glutVisibilityFunc(visible);
- glClearColor(.488, .617, .75, 1.0);
- glMatrixMode(GL_PROJECTION);
- gluPerspective(40.0, 1.0, 0.1, 10.0);
- glMatrixMode(GL_MODELVIEW);
- gluLookAt(0, 0, 5.5,
- 0, 0, 0,
- 0, 1, 0);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glLineWidth(2.0);
- polydlist(1, sizeof(poly1) / sizeof(Point), poly1);
- polydlist(2, sizeof(poly2) / sizeof(Point), poly2);
- polydlist(3, sizeof(poly3) / sizeof(Point), poly3);
- polydlist(4, sizeof(poly4) / sizeof(Point), poly4);
- polydlist(5, sizeof(poly5) / sizeof(Point), poly5);
- polydlist(6, sizeof(poly6) / sizeof(Point), poly6);
- polydlist(7, sizeof(poly7) / sizeof(Point), poly7);
- polydlist(8, sizeof(poly8) / sizeof(Point), poly8);
- glutCreateMenu(menu);
- glutAddMenuEntry("Reverse direction", 1);
- glutAddMenuEntry("Toggle motion", 2);
- glutAddMenuEntry("Toggle spinning", 3);
- glutAddMenuEntry("Quit", 666);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- #if GL_EXT_polygon_offset
- polygon_offset = glutExtensionSupported("GL_EXT_polygon_offset");
- #endif
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }