/* 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.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 #include #include #include /* for cos(), sin(), and sqrt() */ #include /* Some 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 void makePointList(void) { float angle, velocity, direction; int i; motion = 1; for (i=0; i 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); } } } void idle(void) { updatePointList(); if (spin) { angle += 0.3; newModel = 1; } glutPostRedisplay(); } void visible(int vis) { if (vis == GLUT_VISIBLE) { if (animate && (motion || spin)) { glutIdleFunc(idle); } } else { glutIdleFunc(NULL); } } void recalcModelView(void) { glPopMatrix(); glPushMatrix(); glRotatef(angle, 0.0, 1.0, 0.0); newModel = 0; } 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