Commit code circa 2006
This commit is contained in:
22
Makefile
Executable file
22
Makefile
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
SRC = main.cpp
|
||||||
|
OBJ = main.o
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CXX = g++
|
||||||
|
LD = $(CXX)
|
||||||
|
|
||||||
|
CFLAGS = -g -g2 -p -pg -ggdb -c `sdl-config --cflags`
|
||||||
|
LDFLAGS = -g -g2 -pg -ggdb -lSDL -lX11 -lGL -lGLU `sdl-config --libs`
|
||||||
|
|
||||||
|
TARGET = glparticletest
|
||||||
|
|
||||||
|
all : $(OBJ)
|
||||||
|
$(LD) $(LDFLAGS) -o $(TARGET) $(OBJ)
|
||||||
|
|
||||||
|
%.o : %.cpp
|
||||||
|
$(CXX) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.PHONY : clean
|
||||||
|
clean:
|
||||||
|
rm *.o
|
||||||
|
rm $(TARGET)
|
||||||
55
common.h
Executable file
55
common.h
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef __COMMON_H__
|
||||||
|
#define __COMMON_H__
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* global defines */
|
||||||
|
#define SCREEN_WIDTH 640
|
||||||
|
#define SCREEN_HEIGHT 480
|
||||||
|
#define SCREEN_BPP 16
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
/* main screen surface */
|
||||||
|
SDL_Surface *surface;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GLfloat x;
|
||||||
|
GLfloat y;
|
||||||
|
GLfloat z;
|
||||||
|
} Vector;
|
||||||
|
|
||||||
|
Vector cameraPosition = {0.0F, 0.0F, 0.0F};
|
||||||
|
Vector cameraLook = {0.0F, 0.0F, -1.0F};
|
||||||
|
|
||||||
|
char *pTextures[] = {"pBlue.bmp", "pGreen.pcx", "pRed.pcx"};
|
||||||
|
|
||||||
|
/* copy v2 to v1 */
|
||||||
|
void vectorCopy(Vector *v1, Vector *v2)
|
||||||
|
{
|
||||||
|
v1->x = v2->x;
|
||||||
|
v1->y = v2->y;
|
||||||
|
v1->z = v2->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns a floating point value between -ceiling and ceiling */
|
||||||
|
GLfloat frand(GLfloat ceiling)
|
||||||
|
{
|
||||||
|
if ( ((rand() / ((RAND_MAX+1)/2) )) < 0)
|
||||||
|
return (rand() / ( ((float) RAND_MAX+1) / -ceiling));
|
||||||
|
else
|
||||||
|
return (rand() / ( ((float) RAND_MAX+1) / ceiling));
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "particle.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "init.h"
|
||||||
|
|
||||||
|
PEmitter theEmitter[2];
|
||||||
|
|
||||||
|
#endif // __COMMON_H__ 1
|
||||||
94
draw.h
Executable file
94
draw.h
Executable file
@@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
/* anything related to drawing is in here
|
||||||
|
* including texture loading and setting */
|
||||||
|
|
||||||
|
#ifndef __DRAW_H__
|
||||||
|
#define __DRAW_H__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
extern PEmitter theEmitter[2];
|
||||||
|
|
||||||
|
int drawGLScene( GLvoid )
|
||||||
|
{
|
||||||
|
/* These are to calculate our fps */
|
||||||
|
static GLint T0 = 0;
|
||||||
|
GLint t = 0;
|
||||||
|
static GLint Frames = 0;
|
||||||
|
|
||||||
|
/* Clear The Screen And The Depth Buffer */
|
||||||
|
glPointSize(3.0f);
|
||||||
|
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity( );
|
||||||
|
glTranslatef(0.0f, 1.0f, -20.0f);
|
||||||
|
|
||||||
|
|
||||||
|
DrawEmitter(&theEmitter[0]);
|
||||||
|
DrawEmitter(&theEmitter[1]);
|
||||||
|
|
||||||
|
/* Draw it to the screen */
|
||||||
|
SDL_GL_SwapBuffers( );
|
||||||
|
|
||||||
|
Frames++;
|
||||||
|
t = SDL_GetTicks();
|
||||||
|
if (t - T0 >= 1000) {
|
||||||
|
GLfloat seconds = (t - T0) / 1000.0;
|
||||||
|
GLfloat fps = Frames / seconds;
|
||||||
|
printf("%d frames in %g seconds = %g FPS (new time %g)\n", Frames, seconds, fps, (float)time(NULL));
|
||||||
|
T0 = t;
|
||||||
|
Frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateEmitter(&theEmitter[0], t - T0);
|
||||||
|
UpdateEmitter(&theEmitter[1], t - T0);
|
||||||
|
|
||||||
|
T0 = t;
|
||||||
|
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function to reset our viewport after a window resize */
|
||||||
|
int resizeWindow( int width, int height )
|
||||||
|
{
|
||||||
|
GLfloat ratio;
|
||||||
|
|
||||||
|
/* Protect against a divide by zero */
|
||||||
|
if ( height == 0 ) height = 1;
|
||||||
|
|
||||||
|
ratio = ( GLfloat )width / ( GLfloat )height;
|
||||||
|
|
||||||
|
/* set the viewport, viewing volume, perspective, etc etc */
|
||||||
|
|
||||||
|
glViewport( 0, 0, ( GLint )width, ( GLint )height );
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity( );
|
||||||
|
gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
|
||||||
|
/* Reset The Modelview matrix */
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* general OpenGL initialization function */
|
||||||
|
int initGL( GLvoid )
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Setup shading, clearing, depth testing, and rendering hints */
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||||
|
glClearDepth( 1.0f );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glDepthFunc( GL_LEQUAL );
|
||||||
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||||
|
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __DRAW_H__
|
||||||
34
init.h
Executable file
34
init.h
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef __INIT_H__
|
||||||
|
#define __INIT_H__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/* function to release/destroy our resources and restore the old desktop
|
||||||
|
* (if we've clobbered it) */
|
||||||
|
void Quit( int returnCode )
|
||||||
|
{
|
||||||
|
SDL_Quit( );
|
||||||
|
exit( returnCode );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function to handle key press events */
|
||||||
|
void handleKeyPress( SDL_keysym *keysym )
|
||||||
|
{
|
||||||
|
switch ( keysym->sym )
|
||||||
|
{
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
Quit( 0 );
|
||||||
|
break;
|
||||||
|
case SDLK_F1:
|
||||||
|
/* this toggles fullscreen mode
|
||||||
|
*/
|
||||||
|
SDL_WM_ToggleFullScreen( surface );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __INIT_H__
|
||||||
205
main.cpp
Executable file
205
main.cpp
Executable file
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* A particle system using triangles and textured particles
|
||||||
|
* you can also switch between textured triangles and colored points
|
||||||
|
* and you can change the emitter's position/direction.
|
||||||
|
*
|
||||||
|
* The actual action goes on in particle.h, but I figured main.cpp is where
|
||||||
|
* most folks would start reading. This isn't a complete system; I had intended
|
||||||
|
* to implement textured particles, but I didn't get that implemented by my 6 am deadline.
|
||||||
|
* I'm going to go ahead and leave in the code for textured polys/quads (which
|
||||||
|
* does nothing right now) because I intend to implement that in the future.
|
||||||
|
*
|
||||||
|
* I also haven't profiled this code, so I have no idea how efficient it is. However,
|
||||||
|
* since this is my *first ever* attempt at a particle system, I don't think it's
|
||||||
|
* too bad considering I churned it out in 6 hours without anyone else's code to guide me.
|
||||||
|
* So take this as you will. :)
|
||||||
|
*
|
||||||
|
* Written with openGL and SDL (http://www.libsdl.org).
|
||||||
|
*
|
||||||
|
* Andrew Kesterson, Feb. 2005.
|
||||||
|
*
|
||||||
|
* NOTE: Textured polys are currently not implemented, but now that I have the particles
|
||||||
|
* distributing around the emitter properly and fading correctly, it is *definitely* next
|
||||||
|
* on the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int main( int argc, char **argv )
|
||||||
|
{
|
||||||
|
/* Flags and stuff for the state machine and SDL */
|
||||||
|
int videoFlags;
|
||||||
|
int done = FALSE;
|
||||||
|
SDL_Event event;
|
||||||
|
const SDL_VideoInfo *videoInfo;
|
||||||
|
int isActive = TRUE;
|
||||||
|
GLfloat emitterColors[2][3] = {
|
||||||
|
//{1.0, 1.0, 1.0},
|
||||||
|
{0.0, 0.0, 0.0},
|
||||||
|
{0.0, 0.5, 1.0}};
|
||||||
|
Vector emitterSpeeds[2] = {
|
||||||
|
{0.00f, 0.0001f, 0.0f},
|
||||||
|
{0.00f, 0.005f, 0.0f}};
|
||||||
|
Vector emitterGravities[2] = {
|
||||||
|
{0.002f, -0.0f, 0.0f},
|
||||||
|
{0.00f, -0.00001f, 0.00f}};
|
||||||
|
Vector emitterPositions[2] = {
|
||||||
|
{0.0f, 0.0f, -50.0f},
|
||||||
|
{0.0f, -2.0f, -50.0f}};
|
||||||
|
Vector randPositions[2] = {
|
||||||
|
{5.7f, 5.7f, 0.0f},
|
||||||
|
{.5f, 3.5f, .5f}
|
||||||
|
};
|
||||||
|
Vector randSpeeds[2] = {
|
||||||
|
{0.001f, 0.001f, 0.0f},
|
||||||
|
{0.000f, 0.00f, 0.000f}
|
||||||
|
};
|
||||||
|
Vector randGravities[2] = {
|
||||||
|
{0.0f, 0.0f, 0.0f},
|
||||||
|
{0.000005f, 0.0f, 0.000005f},
|
||||||
|
};
|
||||||
|
|
||||||
|
srand((long)time(NULL));
|
||||||
|
|
||||||
|
PopulateEmitter(&theEmitter[0],
|
||||||
|
GL_TRUE,
|
||||||
|
emitterColors[0],
|
||||||
|
0.0001F,
|
||||||
|
1000,
|
||||||
|
&emitterGravities[0],
|
||||||
|
&emitterPositions[0],
|
||||||
|
&emitterSpeeds[0],
|
||||||
|
&randGravities[0],
|
||||||
|
&randPositions[0],
|
||||||
|
&randSpeeds[0],
|
||||||
|
500,
|
||||||
|
GL_POINTS,
|
||||||
|
0);
|
||||||
|
PopulateEmitter(&theEmitter[1],
|
||||||
|
GL_TRUE,
|
||||||
|
emitterColors[1],
|
||||||
|
0.0002F,
|
||||||
|
5000,
|
||||||
|
&emitterGravities[1],
|
||||||
|
&emitterPositions[1],
|
||||||
|
&emitterSpeeds[1],
|
||||||
|
&randGravities[1],
|
||||||
|
&randPositions[1],
|
||||||
|
&randSpeeds[1],
|
||||||
|
1400,
|
||||||
|
GL_POINTS,
|
||||||
|
0);
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize SDL */
|
||||||
|
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Video initialization failed: %s\n",
|
||||||
|
SDL_GetError( ) );
|
||||||
|
Quit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the video info */
|
||||||
|
videoInfo = SDL_GetVideoInfo( );
|
||||||
|
|
||||||
|
if ( !videoInfo )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Video query failed: %s\n",
|
||||||
|
SDL_GetError( ) );
|
||||||
|
Quit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask SDL for a OpenGL double buffered context with various flags. */
|
||||||
|
videoFlags = SDL_OPENGL;
|
||||||
|
videoFlags |= SDL_GL_DOUBLEBUFFER;
|
||||||
|
videoFlags |= SDL_HWPALETTE;
|
||||||
|
videoFlags |= SDL_RESIZABLE;
|
||||||
|
|
||||||
|
/* Can we have hardware surfaces? */
|
||||||
|
if ( videoInfo->hw_available )
|
||||||
|
videoFlags |= SDL_HWSURFACE;
|
||||||
|
else
|
||||||
|
videoFlags |= SDL_SWSURFACE;
|
||||||
|
|
||||||
|
/* Hardware blits? */
|
||||||
|
if ( videoInfo->blit_hw )
|
||||||
|
videoFlags |= SDL_HWACCEL;
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
||||||
|
|
||||||
|
/* get the main SDL surface */
|
||||||
|
surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
|
||||||
|
videoFlags );
|
||||||
|
|
||||||
|
if ( !surface )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) );
|
||||||
|
Quit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( initGL( ) == FALSE )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Could not initialize OpenGL.\n" );
|
||||||
|
Quit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
|
||||||
|
|
||||||
|
/* wait for events */
|
||||||
|
while ( !done )
|
||||||
|
{
|
||||||
|
/* handle the events in the queue, pumped by the SDL event machine */
|
||||||
|
|
||||||
|
while ( SDL_PollEvent( &event ) )
|
||||||
|
{
|
||||||
|
switch( event.type )
|
||||||
|
{
|
||||||
|
case SDL_ACTIVEEVENT:
|
||||||
|
/* Gained or lost window focus. */
|
||||||
|
if ( event.active.gain == 0 )
|
||||||
|
isActive = FALSE;
|
||||||
|
else
|
||||||
|
isActive = TRUE;
|
||||||
|
break;
|
||||||
|
case SDL_VIDEORESIZE:
|
||||||
|
/* handle resize event */
|
||||||
|
surface = SDL_SetVideoMode( event.resize.w,
|
||||||
|
event.resize.h,
|
||||||
|
16, videoFlags );
|
||||||
|
if ( !surface )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
|
||||||
|
Quit( 1 );
|
||||||
|
}
|
||||||
|
resizeWindow( event.resize.w, event.resize.h );
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
/* handle key presses */
|
||||||
|
handleKeyPress( &event.key.keysym );
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
|
/* handle quit requests */
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw the scene */
|
||||||
|
if ( isActive ) {
|
||||||
|
drawGLScene( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean ourselves up and exit */
|
||||||
|
Quit( 0 );
|
||||||
|
|
||||||
|
/* Should never even get here */
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
280
particle.h
Executable file
280
particle.h
Executable file
@@ -0,0 +1,280 @@
|
|||||||
|
#ifndef __PARTICLE_H__
|
||||||
|
#define __PARTICLE_H__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/* max particles per emitter */
|
||||||
|
#define MAX_PARTICLES 256
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLint aliveTime; /* time the particle's been alive */
|
||||||
|
GLint lifetime; /* how long this particle should stay alive (in ms) */
|
||||||
|
GLfloat alpha;
|
||||||
|
Vector speed;
|
||||||
|
Vector pos;
|
||||||
|
Vector iGrav;
|
||||||
|
} Particle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLboolean active; /* emitter active? */
|
||||||
|
GLint lifetime; /* base lifetime of particles from this emitter */
|
||||||
|
GLint lifeEdge; /* the random adjustment to each particle's lifetime
|
||||||
|
(between lifeEdge and lifeEdge*2) */
|
||||||
|
GLfloat alphaFade; /* a floating point value between 0.0 and 1.0 that tells
|
||||||
|
how much transparency should be added to the particle each frame */
|
||||||
|
|
||||||
|
Vector pos; /* base position of particles from this emitter */
|
||||||
|
Vector speed; /* base speed (direction) of particles from this emitter */
|
||||||
|
Vector pGrav; /* the base x, y, and z gravity acting on
|
||||||
|
particles from this emitter*/
|
||||||
|
|
||||||
|
Vector rSpeed; /* the random speed adjustment applied to particles */
|
||||||
|
Vector rGrav; /* the random gravity adjustment applied to particles */
|
||||||
|
Vector rPos; /* the random position adjustment applied to particles */
|
||||||
|
|
||||||
|
Particle particles[MAX_PARTICLES]; /* the actual particles */
|
||||||
|
GLfloat texCoords[4][2]; // the texture coordinates for all quad or triangle particles
|
||||||
|
GLuint texHandle; /* the texture handle for all particles from this emitter*/
|
||||||
|
GLuint pType; /* GL_POINTS, GL_TRIANGLES, or GL_QUADS.*/
|
||||||
|
GLfloat color[3]; /* color of particles in this emitter */
|
||||||
|
|
||||||
|
GLfloat size[2]; /* the size in X and Y of all particles from this emitter */
|
||||||
|
|
||||||
|
} PEmitter;
|
||||||
|
|
||||||
|
|
||||||
|
void DrawParticle(Particle *particle, PEmitter *emitter)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* set up the texturing if we're not doing points */
|
||||||
|
if ( emitter->pType != GL_POINTS ) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, emitter->texHandle);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBegin(emitter->pType);
|
||||||
|
|
||||||
|
if ( emitter->pType == GL_TRIANGLES ) {
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[0][0],
|
||||||
|
emitter->texCoords[0][1]);
|
||||||
|
glVertex3f(particle->pos.x - ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y - ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[1][0],
|
||||||
|
emitter->texCoords[1][1]);
|
||||||
|
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y - ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[2][0],
|
||||||
|
emitter->texCoords[2][1]);
|
||||||
|
glVertex3f(particle->pos.x,
|
||||||
|
particle->pos.y + ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( emitter->pType == GL_QUADS ) {
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[0][0],
|
||||||
|
emitter->texCoords[0][1]);
|
||||||
|
glVertex3f(particle->pos.x - ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y + ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[1][0],
|
||||||
|
emitter->texCoords[1][1]);
|
||||||
|
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y - ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[2][0],
|
||||||
|
emitter->texCoords[2][1]);
|
||||||
|
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y - ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
|
||||||
|
glColor3f(emitter->color[0],
|
||||||
|
emitter->color[1],
|
||||||
|
emitter->color[2]);
|
||||||
|
glTexCoord2f(emitter->texCoords[3][0],
|
||||||
|
emitter->texCoords[3][1]);
|
||||||
|
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||||
|
particle->pos.y + ( emitter->size[1] / 2),
|
||||||
|
particle->pos.z);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glColor4f(emitter->color[0], emitter->color[1], emitter->color[2], particle->alpha);
|
||||||
|
glVertex3f(particle->pos.x, particle->pos.y, particle->pos.z);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint DrawEmitter(PEmitter *emitter)
|
||||||
|
{
|
||||||
|
/* this function assumes the viewport and etc has already been setup
|
||||||
|
* (e.g., call this from within your main GL drawing function) */
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
Particle *currParticle;
|
||||||
|
|
||||||
|
if ( !emitter ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( emitter->active != GL_TRUE ) {
|
||||||
|
return 0; // emitter not active, but this isn't an error
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0 ; i < MAX_PARTICLES ; i++ ) {
|
||||||
|
currParticle = &emitter->particles[i];
|
||||||
|
|
||||||
|
/* draw the particle given its type */
|
||||||
|
DrawParticle(currParticle, emitter);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetParticle(Particle *particle, PEmitter *emitter)
|
||||||
|
{
|
||||||
|
particle->aliveTime = 0;
|
||||||
|
|
||||||
|
/* get a new lifetime for the particle based on the base from the emitter + random adj */
|
||||||
|
particle->lifetime = emitter->lifetime + (rand() % (emitter->lifeEdge*2)) - emitter->lifeEdge;
|
||||||
|
particle->alpha = 1.0F;
|
||||||
|
|
||||||
|
/* reset the particle's x, y, z position from the emitter base */
|
||||||
|
vectorCopy(&particle->pos, &emitter->pos);
|
||||||
|
if ( emitter->rPos.x != 0.0f)
|
||||||
|
particle->pos.x += frand( emitter->rPos.x);
|
||||||
|
if ( emitter->rPos.y != 0.0f )
|
||||||
|
particle->pos.y += frand( emitter->rPos.y );
|
||||||
|
if ( emitter->rPos.z != 0.0f )
|
||||||
|
particle->pos.z += frand( emitter->rPos.z );
|
||||||
|
|
||||||
|
/* reset the particle's gravity from the base gravity of the emitter + rand adjust */
|
||||||
|
vectorCopy(&particle->iGrav, &emitter->pGrav);
|
||||||
|
if ( emitter->rGrav.x != 0.0f )
|
||||||
|
particle->iGrav.x += frand( emitter->rGrav.x );
|
||||||
|
if ( emitter->rGrav.y != 0.0f )
|
||||||
|
particle->iGrav.y += frand( emitter->rGrav.y );
|
||||||
|
if ( emitter->rGrav.z != 0.0f )
|
||||||
|
particle->iGrav.z += frand( emitter->rGrav.z );
|
||||||
|
|
||||||
|
/* reset the particle's speed from the base gravity of the emitter + rand adjust */
|
||||||
|
vectorCopy(&particle->speed, &emitter->speed);
|
||||||
|
if ( emitter->rSpeed.x != 0.0f )
|
||||||
|
particle->speed.x += frand( emitter->rSpeed.x);
|
||||||
|
if ( emitter->rSpeed.y != 0.0f )
|
||||||
|
particle->speed.y += frand( emitter->rSpeed.y);
|
||||||
|
if ( emitter->rSpeed.z != 0.0f )
|
||||||
|
particle->speed.z += frand( emitter->rSpeed.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateEmitter(PEmitter *emitter, GLuint timePassed)
|
||||||
|
{
|
||||||
|
/* here's where we do the emitter's logic. It's assumed
|
||||||
|
* we're being called once per frame, so we don't do any
|
||||||
|
* time calculations, other than updating the lifetimes
|
||||||
|
* ... timePassed is the number of ms passed since the last call */
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
Particle *currParticle;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < MAX_PARTICLES ; i++ ) {
|
||||||
|
currParticle = &emitter->particles[i];
|
||||||
|
|
||||||
|
currParticle->aliveTime += timePassed;
|
||||||
|
|
||||||
|
if ( currParticle->aliveTime >= currParticle->lifetime ) {
|
||||||
|
/* this particle has died; set it to inactive and reset its lifetime/pos/dir */
|
||||||
|
ResetParticle(currParticle,emitter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply gravity and such to the particle */
|
||||||
|
|
||||||
|
currParticle->speed.x += currParticle->iGrav.x;
|
||||||
|
currParticle->speed.y += currParticle->iGrav.y;
|
||||||
|
currParticle->speed.z += currParticle->iGrav.z;
|
||||||
|
|
||||||
|
currParticle->pos.x += (currParticle->speed.x);
|
||||||
|
currParticle->pos.y += (currParticle->speed.y);
|
||||||
|
currParticle->pos.z += (currParticle->speed.z);
|
||||||
|
|
||||||
|
/* the alpha is a constant drop over the lifetime of the particle */
|
||||||
|
currParticle->alpha -= emitter->alphaFade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint PopulateEmitter(PEmitter *emitter,
|
||||||
|
GLboolean active,
|
||||||
|
GLfloat color[],
|
||||||
|
GLfloat alphaFade,
|
||||||
|
GLint lifetime,
|
||||||
|
Vector *pGrav,
|
||||||
|
Vector *pos,
|
||||||
|
Vector *speed,
|
||||||
|
Vector *rgrav,
|
||||||
|
Vector *rpos,
|
||||||
|
Vector *rspeed,
|
||||||
|
GLint lifeEdge,
|
||||||
|
GLuint pType,
|
||||||
|
GLuint texHandle)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if ( !emitter ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter->active = active;
|
||||||
|
|
||||||
|
emitter->color[0] = color[0];
|
||||||
|
emitter->color[1] = color[1];
|
||||||
|
emitter->color[2] = color[2];
|
||||||
|
|
||||||
|
emitter->lifetime = lifetime;
|
||||||
|
emitter->lifeEdge = lifeEdge;
|
||||||
|
emitter->alphaFade = alphaFade;
|
||||||
|
|
||||||
|
vectorCopy(&emitter->pGrav, pGrav);
|
||||||
|
vectorCopy(&emitter->pos, pos);
|
||||||
|
vectorCopy(&emitter->speed, speed);
|
||||||
|
vectorCopy(&emitter->rSpeed, rspeed);
|
||||||
|
vectorCopy(&emitter->rPos, rpos);
|
||||||
|
vectorCopy(&emitter->rGrav, rgrav);
|
||||||
|
|
||||||
|
|
||||||
|
emitter->pType = pType;
|
||||||
|
emitter->texHandle = texHandle;
|
||||||
|
|
||||||
|
for ( i = 0; i < MAX_PARTICLES; i++ ) {
|
||||||
|
ResetParticle(&emitter->particles[i],emitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __PARTICLE_H__
|
||||||
Reference in New Issue
Block a user