123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
-
- /* Copyright (c) Mark J. Kilgard, 1997. */
-
- /* 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. */
-
- /* This example demonstrates how to render particle effects
- with OpenGL. A cloud of pinkish/orange particles explodes with the
- particles bouncing off the ground. When the EXT_point_parameters
- is present , the particle size is attenuated based on eye distance. */
-
-
- /*
- * $Log: pointblast.c,v $
- * Revision 1.2 2000/06/27 17:04:43 brianp
- * fixed compiler warnings
- *
- * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
- * Imported sources
- *
- * Revision 3.3 1998/07/26 01:24:27 brianp
- * removed include of gl.h
- *
- * Revision 3.2 1998/02/14 18:51:46 brianp
- * fixed a small compiler warning
- *
- * Revision 3.1 1998/02/14 18:45:25 brianp
- * optimized to use flat shading, don't blend ground polygon
- *
- * Revision 3.0 1998/02/14 18:42:29 brianp
- * initial rev
- *
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h> /* for cos(), sin(), and sqrt() */
- #define GL_GLEXT_LEGACY
- #include <GL/glut.h>
-
- /* Some <math.h> files do not define M_PI... */
- #ifndef M_PI
- #define M_PI 3.14159265
- #endif
-
- #if 0 /* For debugging. */
- #undef GL_EXT_point_parameters
- #endif
-
- static GLfloat angle = -150; /* in degrees */
- static int spin = 0;
- static int moving, begin;
- static int newModel = 1;
- static float theTime;
- static int repeat = 1;
- static int blend = 1;
- int useMipmaps = 1;
- int linearFiltering = 1;
-
- static GLfloat constant[3] = { 1/5.0, 0.0, 0.0 };
- static GLfloat linear[3] = { 0.0, 1/5.0, 0.0 };
- static GLfloat theQuad[3] = { 0.25, 0.0, 1/60.0 };
-
- #define MAX_POINTS 2000
-
- static int numPoints = 200;
-
- static GLfloat pointList[MAX_POINTS][3];
- static GLfloat pointTime[MAX_POINTS];
- static GLfloat pointVelocity[MAX_POINTS][2];
- static GLfloat pointDirection[MAX_POINTS][2];
- static int colorList[MAX_POINTS];
- static int animate = 1, motion = 0;
-
- static GLfloat colorSet[][4] = {
- /* Shades of red. */
- { 0.7, 0.2, 0.4, 0.5 },
- { 0.8, 0.0, 0.7, 0.5 },
- { 1.0, 0.0, 0.0, 0.5 },
- { 0.9, 0.3, 0.6, 0.5 },
- { 1.0, 0.4, 0.0, 0.5 },
- { 1.0, 0.0, 0.5, 0.5 },
- };
-
- #define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0]))
-
- #define DEAD (NUM_COLORS+1)
-
-
- #if 0 /* drand48 might be better on Unix machines */
- #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48())
- #else
- static float float_rand(void) { return rand() / (float) RAND_MAX; }
- #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand())
- #endif
-
- #define MEAN_VELOCITY 3.0
- #define GRAVITY 2.0
- #define TIME_DELTA 0.025 /* The speed of time. */
-
- /* Modeling units of ground extent in each X and Z direction. */
- #define EDGE 12
-
- static void
- makePointList(void)
- {
- float angle, velocity, direction;
- int i;
-
- motion = 1;
- for (i=0; i<numPoints; i++) {
- pointList[i][0] = 0.0;
- pointList[i][1] = 0.0;
- pointList[i][2] = 0.0;
- pointTime[i] = 0.0;
- angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0;
- direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0;
- pointDirection[i][0] = cos(direction);
- pointDirection[i][1] = sin(direction);
- velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0);
- pointVelocity[i][0] = velocity * cos(angle);
- pointVelocity[i][1] = velocity * sin(angle);
- colorList[i] = rand() % NUM_COLORS;
- }
- theTime = 0.0;
- }
-
- static void
- updatePointList(void)
- {
- float distance;
- int i;
-
- motion = 0;
- for (i=0; i<numPoints; i++) {
- distance = pointVelocity[i][0] * theTime;
-
- /* X and Z */
- pointList[i][0] = pointDirection[i][0] * distance;
- pointList[i][2] = pointDirection[i][1] * distance;
-
- /* Z */
- pointList[i][1] =
- (pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i];
-
- /* If we hit the ground, bounce the point upward again. */
- if (pointList[i][1] <= 0.0) {
- if (distance > EDGE) {
- /* Particle has hit ground past the distance duration of
- the particles. Mark particle as dead. */
- colorList[i] = NUM_COLORS; /* Not moving. */
- continue;
- }
-
- pointVelocity[i][1] *= 0.8; /* 80% of previous up velocity. */
- pointTime[i] = 0.0; /* Reset the particles sense of up time. */
- }
- motion = 1;
- pointTime[i] += TIME_DELTA;
- }
- theTime += TIME_DELTA;
- if (!motion && !spin) {
- if (repeat) {
- makePointList();
- } else {
- glutIdleFunc(NULL);
- }
- }
- }
-
- static void
- idle(void)
- {
- updatePointList();
- if (spin) {
- angle += 0.3;
- newModel = 1;
- }
- glutPostRedisplay();
- }
-
- static void
- visible(int vis)
- {
- if (vis == GLUT_VISIBLE) {
- if (animate && (motion || spin)) {
- glutIdleFunc(idle);
- }
- } else {
- glutIdleFunc(NULL);
- }
- }
-
- static void
- recalcModelView(void)
- {
- glPopMatrix();
- glPushMatrix();
- glRotatef(angle, 0.0, 1.0, 0.0);
- newModel = 0;
- }
-
- static void
- redraw(void)
- {
- int i;
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- if (newModel)
- recalcModelView();
-
- glDepthMask(GL_FALSE);
-
- /* Draw the floor. */
- /* glEnable(GL_TEXTURE_2D);*/
- glColor3f(0.5, 1.0, 0.5);
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0);
- glVertex3f(-EDGE, -0.05, -EDGE);
- glTexCoord2f(20.0, 0.0);
- glVertex3f(EDGE, -0.05, -EDGE);
- glTexCoord2f(20.0, 20.0);
- glVertex3f(EDGE, -0.05, EDGE);
- glTexCoord2f(0.0, 20.0);
- glVertex3f(-EDGE, -0.05, EDGE);
- glEnd();
-
- /* Allow particles to blend with each other. */
- glDepthMask(GL_TRUE);
-
- if (blend)
- glEnable(GL_BLEND);
-
- glDisable(GL_TEXTURE_2D);
- glBegin(GL_POINTS);
- for (i=0; i<numPoints; i++) {
- /* Draw alive particles. */
- if (colorList[i] != DEAD) {
- glColor4fv(colorSet[colorList[i]]);
- glVertex3fv(pointList[i]);
- }
- }
- glEnd();
-
- glDisable(GL_BLEND);
-
- glutSwapBuffers();
- }
-
- /* ARGSUSED2 */
- static void
- mouse(int button, int state, int x, int y)
- {
- /* Scene can be spun around Y axis using left
- mouse button movement. */
- if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
- moving = 1;
- begin = x;
- }
- if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
- moving = 0;
- }
- }
-
- /* ARGSUSED1 */
- static void
- mouseMotion(int x, int y)
- {
- if (moving) {
- angle = angle + (x - begin);
- begin = x;
- newModel = 1;
- glutPostRedisplay();
- }
- }
-
- static void
- menu(int option)
- {
- switch (option) {
- case 0:
- makePointList();
- break;
- #if GL_EXT_point_parameters
- case 1:
- glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, constant);
- break;
- case 2:
- glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, linear);
- break;
- case 3:
- glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
- break;
- #endif
- case 4:
- blend = 1;
- break;
- case 5:
- blend = 0;
- break;
- #if GL_EXT_point_parameters
- case 6:
- glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0);
- break;
- case 7:
- glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 10.0);
- break;
- #endif
- case 8:
- glEnable(GL_POINT_SMOOTH);
- break;
- case 9:
- glDisable(GL_POINT_SMOOTH);
- break;
- case 10:
- glPointSize(2.0);
- break;
- case 11:
- glPointSize(4.0);
- break;
- case 12:
- glPointSize(8.0);
- break;
- case 13:
- spin = 1 - spin;
- if (animate && (spin || motion)) {
- glutIdleFunc(idle);
- } else {
- glutIdleFunc(NULL);
- }
- break;
- case 14:
- numPoints = 200;
- break;
- case 15:
- numPoints = 500;
- break;
- case 16:
- numPoints = 1000;
- break;
- case 17:
- numPoints = 2000;
- break;
- case 666:
- exit(0);
- }
- glutPostRedisplay();
- }
-
- /* ARGSUSED1 */
- static void
- key(unsigned char c, int x, int y)
- {
- switch (c) {
- case 13:
- animate = 1 - animate; /* toggle. */
- if (animate && (motion || spin)) {
- glutIdleFunc(idle);
- } else {
- glutIdleFunc(NULL);
- }
- break;
- case ' ':
- animate = 1;
- makePointList();
- glutIdleFunc(idle);
- break;
- case 27:
- exit(0);
- }
- }
-
- /* Nice floor texture tiling pattern. */
- static char *circles[] = {
- "....xxxx........",
- "..xxxxxxxx......",
- ".xxxxxxxxxx.....",
- ".xxx....xxx.....",
- "xxx......xxx....",
- "xxx......xxx....",
- "xxx......xxx....",
- "xxx......xxx....",
- ".xxx....xxx.....",
- ".xxxxxxxxxx.....",
- "..xxxxxxxx......",
- "....xxxx........",
- "................",
- "................",
- "................",
- "................",
- };
-
- static void
- makeFloorTexture(void)
- {
- GLubyte floorTexture[16][16][3];
- GLubyte *loc;
- int s, t;
-
- /* Setup RGB image for the texture. */
- loc = (GLubyte*) floorTexture;
- for (t = 0; t < 16; t++) {
- for (s = 0; s < 16; s++) {
- if (circles[t][s] == 'x') {
- /* Nice blue. */
- loc[0] = 0x1f;
- loc[1] = 0x1f;
- loc[2] = 0x8f;
- } else {
- /* Light gray. */
- loc[0] = 0xca;
- loc[1] = 0xca;
- loc[2] = 0xca;
- }
- loc += 3;
- }
- }
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- if (useMipmaps) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
- gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
- GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
- } else {
- if (linearFiltering) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
- GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
- }
- }
-
- int
- main(int argc, char **argv)
- {
- int i;
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
-
- for (i=1; i<argc; i++) {
- if(!strcmp("-noms", argv[i])) {
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- printf("forcing no multisampling\n");
- } else if(!strcmp("-nomipmaps", argv[i])) {
- useMipmaps = 0;
- } else if(!strcmp("-nearest", argv[i])) {
- linearFiltering = 0;
- }
- }
-
- glutCreateWindow("point burst");
- glutDisplayFunc(redraw);
- glutMouseFunc(mouse);
- glutMotionFunc(mouseMotion);
- glutVisibilityFunc(visible);
- glutKeyboardFunc(key);
- glutCreateMenu(menu);
- glutAddMenuEntry("Reset time", 0);
- glutAddMenuEntry("Constant", 1);
- glutAddMenuEntry("Linear", 2);
- glutAddMenuEntry("Quadratic", 3);
- glutAddMenuEntry("Blend on", 4);
- glutAddMenuEntry("Blend off", 5);
- glutAddMenuEntry("Threshold 1", 6);
- glutAddMenuEntry("Threshold 10", 7);
- glutAddMenuEntry("Point smooth on", 8);
- glutAddMenuEntry("Point smooth off", 9);
- glutAddMenuEntry("Point size 2", 10);
- glutAddMenuEntry("Point size 4", 11);
- glutAddMenuEntry("Point size 8", 12);
- glutAddMenuEntry("Toggle spin", 13);
- glutAddMenuEntry("200 points ", 14);
- glutAddMenuEntry("500 points ", 15);
- glutAddMenuEntry("1000 points ", 16);
- glutAddMenuEntry("2000 points ", 17);
- glutAddMenuEntry("Quit", 666);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
-
- glShadeModel(GL_FLAT);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_POINT_SMOOTH);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPointSize(8.0);
- #if GL_EXT_point_parameters
- glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
- #endif
- glMatrixMode(GL_PROJECTION);
- gluPerspective( /* field of view in degree */ 40.0,
- /* aspect ratio */ 1.0,
- /* Z near */ 0.5, /* Z far */ 40.0);
- glMatrixMode(GL_MODELVIEW);
- gluLookAt(0.0, 1.0, 8.0, /* eye location */
- 0.0, 1.0, 0.0, /* center is at (0,0,0) */
- 0.0, 1.0, 0.); /* up is in postivie Y direction */
- glPushMatrix(); /* dummy push so we can pop on model
- recalc */
-
- makePointList();
- makeFloorTexture();
-
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }
|