| Multiple Particle Effects | |
| 1. Preparing the Ground | |
| Introduction | |
|
We are going to modify the engine and the gl renderer to allow us to define different kinds of particles,
which will be rendered in different ways.
Before you start, you should have already implemented some form of externally loaded particle texture. If you haven't done this, you can use my Soft Particles Tutorial. | |
| Definitions | |
| First, create a new file called "gl_particles.h" and store it in the "ref_gl" directory. Put the following into it: | |
#define PT_DEFAULT 0 #define PT_BEAM 1 #define PT_SPIRAL 2 | |
|
This file will hold our constants. PT_ constants will be used for the different Particle Types that we are going to define.
We need to include this file in several source files. Add a line like this: #include "..\ref_gl\gl_particles.h" // c14 particlesto the following files, with the other #include lines near the top of the file.
| |
| The particle structure | |
|
In order to specify what type each particle will be, we need somewhere to store that information for each particle.
Particles are defined in two places, once for the client, which creates and manages them, and once for the renderer which has to draw them. To both of these definitions, we will add two new pieces of information. The type of the particle is simply a number which we can refer to using the definitions we put in gl_particles.h. The length is a new vector value which we will add to store any additional information about the particle that we might need later. In the file client\client.h search for the following: | |
typedef struct particle_s
{
struct particle_s *next;
float time;
vec3_t org;
vec3_t vel;
vec3_t accel;
float color;
float colorvel;
float alpha;
float alphavel;
} cparticle_t;
| |
| and add two lines as marked | |
typedef struct particle_s
{
struct particle_s *next;
float time;
vec3_t org;
vec3_t vel;
vec3_t accel;
vec3_t length; // c14 particles
int type; // c14 particles
float color;
float colorvel;
float alpha;
float alphavel;
} cparticle_t;
| |
| And in the file client\ref.h search for the following: | |
typedef struct
{
vec3_t origin;
int color;
float alpha;
} particle_t;
| |
| and add two lines as marked | |
typedef struct
{
vec3_t origin;
vec3_t length; // c14 particles
int type; // c14 particles
int color;
float alpha;
} particle_t;
| |
| Passing the information from client to renderer | |
|
Now we need to ensure that the renderer receives the new information from the client. Make the following changes.
In client\cl_fx.c | |
V_AddParticle (org, color, alpha);
| |
| becomes | |
V_AddParticle (org, p->length, color, alpha, p->type); // c14 particles
| |
| In client\client.h | |
void V_AddParticle (vec3_t org, int color, float alpha); | |
| becomes | |
void V_AddParticle (vec3_t org, vec3_t length, int color, float alpha, int type); // c14 particles | |
| And in client\cl_view.c | |
void V_AddParticle (vec3_t org, vec3_t length, int color, float alpha, int type)
{
particle_t *p;
if (r_numparticles >= MAX_PARTICLES)
return;
p = &r_particles[r_numparticles++];
VectorCopy (org, p->origin);
p->color = color;
p->alpha = alpha;
}
| |
| becomes | |
void V_AddParticle (vec3_t org, vec3_t length, int color, float alpha, int type)
{
particle_t *p;
if (r_numparticles >= MAX_PARTICLES)
return;
p = &r_particles[r_numparticles++];
VectorCopy (org, p->origin);
VectorCopy (length, p->length); //c14 particles
p->color = color;
p->alpha = alpha;
p->type = type; //c14 particles
}
| |
| Setting the default particle type | |
|
Because particles get re-used, we should set the default particle type PT_DEFAULT for every particle which we are not
going to change. Otherwise there's a risk that an unchanged blaster spark, will suddenly look like a blood spatter, or something else.
This is a little tiresome. Everywhere that the color of a particle is set, we should follow that up by setting the type to PT_DEFAULT This needs to be done in 26 places in client\cl_fx.c and in 25 places in client\cl_newfx.c (although one of them is actually commented out). Follow this example from client\cl_fx.c: | |
if (type == MZ_LOGIN)
p->color = 0xd0 + (rand()&7); // green
else if (type == MZ_LOGOUT)
p->color = 0x40 + (rand()&7); // red
else
p->color = 0xe0 + (rand()&7); // yellow
| |
| becomes | |
if (type == MZ_LOGIN)
p->color = 0xd0 + (rand()&7); // green
else if (type == MZ_LOGOUT)
p->color = 0x40 + (rand()&7); // red
else
p->color = 0xe0 + (rand()&7); // yellow
p->type = PT_DEFAULT; // c14 particles
| |
| Rendering the default particle type | |
| Now the last thing we need to do at this stage is to change the renderer, so that it only draws default particles. As we add new particle types to the system, we will add new stages to the particle renderer to handle them. In the file ref_gl\gl_rmain.c find the following | |
for ( p = particles, i=0 ; i < num_particles ; i++,p++)
{
// hack a scale up to keep particles from disapearing
scale = ( p->origin[0] - r_origin[0] ) * vpn[0] +
| |
| and add the marked line. | |
for ( p = particles, i=0 ; i < num_particles ; i++,p++)
{
if (p->type != PT_DEFAULT) continue; // c14 particles
// hack a scale up to keep particles from disapearing
scale = ( p->origin[0] - r_origin[0] ) * vpn[0] +
| |
|
This is the beginning of the loop which renders all of the visible particles. We have added a line to tell it to ignore any
particle which is not the default type.
If you compile and run up the programs now (quake2.exe and ref_gl.dll) you should find that they work pretty much as previous. We're not yet trying to draw new particles so you shouldn't see any difference. In the next part of this tutorial, we will actually create our first new particle type Go to part 2 |