/* 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. */ #include #include #include #include /* for cos(), sin(), and sqrt() */ #ifdef _WIN32 #include #endif #define GL_GLEXT_PROTOTYPES #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 /* 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 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] += dt; } theTime += dt; 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