ptype_t type;
// LordHavoc: added for improved particle effects
float scale;
- int texnum;
+ short texnum;
+ short contents; // if non-zero, particles will die outside of this content type
float alpha; // 0-255
float time2; // used for various things (snow fluttering, for example)
vec3_t vel2; // used for snow fluttering (base velocity, wind for instance)
#define APIENTRY /* */
#endif
-extern void (APIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-extern void (APIENTRY *qglSelectTexture) (GLenum);
-
extern qboolean gl_mtexable;
// LordHavoc: ARB multitexure support
#define GL_T4F_C4F_N3F_V4F 0x2A2D
*/
-//void (APIENTRY *qglPolygonOffset)(GLfloat factor, GLfloat units);
-void (APIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-//void (APIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr);
-void (APIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-//void (APIENTRY *qglIndexPointer)(GLenum type, GLsizei stride, const GLvoid *ptr);
-void (APIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-//void (APIENTRY *qglEdgeFlagPointer)(GLsizei stride, const GLvoid *ptr);
-//void (APIENTRY *qglGetPointerv)(GLenum pname, void **params);
-void (APIENTRY *qglArrayElement)(GLint i);
-//void (APIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count);
-void (APIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-//void (APIENTRY *qglInterleavedArrays)(GLenum format, GLsizei stride, const GLvoid *pointer);
+//extern void (APIENTRY *qglPolygonOffset)(GLfloat factor, GLfloat units);
+extern void (APIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
+//extern void (APIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr);
+extern void (APIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
+//extern void (APIENTRY *qglIndexPointer)(GLenum type, GLsizei stride, const GLvoid *ptr);
+extern void (APIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
+//extern void (APIENTRY *qglEdgeFlagPointer)(GLsizei stride, const GLvoid *ptr);
+//extern void (APIENTRY *qglGetPointerv)(GLenum pname, void **params);
+extern void (APIENTRY *qglArrayElement)(GLint i);
+//extern void (APIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count);
+extern void (APIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+//extern void (APIENTRY *qglInterleavedArrays)(GLenum format, GLsizei stride, const GLvoid *pointer);
#else
#endif
-void (APIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-void (APIENTRY *qglSelectTexture) (GLenum);
-
-void (APIENTRY *glColorTableEXT)(int, int, int, int, int, const void*);
-
+extern void (APIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
+extern void (APIENTRY *qglSelectTexture) (GLenum);
+extern void (APIENTRY *glColorTableEXT)(int, int, int, int, int, const void*);
// LordHavoc: vertex transform
#include "transform.h"
int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
int particletexture;
-int smokeparticletexture;
+int smokeparticletexture[8];
int flareparticletexture;
int rainparticletexture;
int bloodcloudparticletexture;
void R_InitParticleTexture (void)
{
- int x,y,d;
+ int x,y,d,i;
float dx, dy, dz, f, dot;
byte data[32][32][4], noise1[32][32], noise2[32][32];
vec3_t normal, light;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- fractalnoise(&noise1[0][0], 32);
- fractalnoise(&noise2[0][0], 32);
- for (y = 0;y < 32;y++)
- for (x = 0;x < 32;x++)
- {
- data[y][x][0] = data[y][x][1] = data[y][x][2] = (noise1[y][x] >> 1) + 128;
- dx = x - 16;
- dy = y - 16;
- d = (noise2[y][x] * (255 - (dx*dx+dy*dy))) * (1.0f / 255.0f);
- if (d < 0) d = 0;
- if (d > 255) d = 255;
- data[y][x][3] = (byte) d;
- }
-
- /*
- for (x=0 ; x<34 ; x+=2)
- for (y=0 ; y<34 ; y+=2)
- data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%32)+192;
- for (x=0 ; x<32 ; x+=2)
- for (y=0 ; y<32 ; y+=2)
- {
- data[y ][x+1][0] = data[y ][x+1][1] = data[y ][x+1][2] = (int) (data[y ][x ][0] + data[y ][x+2][0]) >> 1;
- data[y+1][x ][0] = data[y+1][x ][1] = data[y+1][x ][2] = (int) (data[y ][x ][0] + data[y+2][x ][0]) >> 1;
- data[y+1][x+1][0] = data[y+1][x+1][1] = data[y+1][x+1][2] = (int) (data[y ][x ][0] + data[y ][x+2][0] + data[y+2][x ][0] + data[y+2][x+2][0]) >> 2;
- }
- for (x=0 ; x<32 ; x++)
+ for (i = 0;i < 8;i++)
{
- for (y=0 ; y<32 ; y++)
+ fractalnoise(&noise1[0][0], 32);
+ fractalnoise(&noise2[0][0], 32);
+ for (y = 0;y < 32;y++)
+ for (x = 0;x < 32;x++)
+ {
+ data[y][x][0] = data[y][x][1] = data[y][x][2] = (noise1[y][x] >> 1) + 128;
+ dx = x - 16;
+ dy = y - 16;
+ d = noise2[y][x] * 4 - 512;
+ if (d > 0)
+ {
+ if (d > 255)
+ d = 255;
+ d = (d * (255 - (int) (dx*dx+dy*dy))) >> 8;
+ if (d < 0) d = 0;
+ if (d > 255) d = 255;
+ data[y][x][3] = (byte) d;
+ }
+ else
+ data[y][x][3] = 0;
+ }
+
+ /*
+ for (x=0 ; x<34 ; x+=2)
+ for (y=0 ; y<34 ; y+=2)
+ data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%32)+192;
+ for (x=0 ; x<32 ; x+=2)
+ for (y=0 ; y<32 ; y+=2)
+ {
+ data[y ][x+1][0] = data[y ][x+1][1] = data[y ][x+1][2] = (int) (data[y ][x ][0] + data[y ][x+2][0]) >> 1;
+ data[y+1][x ][0] = data[y+1][x ][1] = data[y+1][x ][2] = (int) (data[y ][x ][0] + data[y+2][x ][0]) >> 1;
+ data[y+1][x+1][0] = data[y+1][x+1][1] = data[y+1][x+1][2] = (int) (data[y ][x ][0] + data[y ][x+2][0] + data[y+2][x ][0] + data[y+2][x+2][0]) >> 2;
+ }
+ for (x=0 ; x<32 ; x++)
{
- //data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%192)+32;
- dx = x - 16;
- dy = y - 16;
- d = (255 - (dx*dx+dy*dy));
- if (d < 0) d = 0;
- data[y][x][3] = (byte) d;
+ for (y=0 ; y<32 ; y++)
+ {
+ //data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%192)+32;
+ dx = x - 16;
+ dy = y - 16;
+ d = (255 - (dx*dx+dy*dy));
+ if (d < 0) d = 0;
+ data[y][x][3] = (byte) d;
+ }
}
+ */
+ smokeparticletexture[i] = texture_extension_number++;
+ glBindTexture(GL_TEXTURE_2D, smokeparticletexture[i]);
+ glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- */
- smokeparticletexture = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, smokeparticletexture);
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
fractalnoise(&noise1[0][0], 32);
fractalnoise(&noise2[0][0], 32);
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 2;
p->alpha = 255;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = particletexture;
p->scale = 2;
p->alpha = 255;
particle_t *p;
if (!r_particles.value) return; // LordHavoc: particles are optional
- for (i=0 ; i<1024 ; i++)
+ for (i=0 ; i<2048 ; i++)
{
if (!free_particles)
return;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = lhrandom(2,5);
p->alpha = rand()&255;
p->type = pt_fallfadespark;
for (j=0 ; j<3 ; j++)
{
- p->org[j] = org[j] + ((rand()&63)-32);
+ p->org[j] = org[j] + ((rand()&15)-8);
p->vel[j] = (rand()&511)-256;
}
p->vel[j] += 200;
p->next = active_particles;
active_particles = p;
- p->texnum = smokeparticletexture;
+ p->contents = 0;
+ p->texnum = smokeparticletexture[rand()&7];
p->scale = 12;
p->alpha = 80;
p->die = cl.time + 2;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 4;
p->alpha = 255;
p->type = pt_blob;
for (j=0 ; j<3 ; j++)
{
- p->org[j] = org[j] + ((rand()%32)-16);
+ p->org[j] = org[j] + ((rand()&15)-8);
p->vel[j] = (rand()%512)-256;
}
}
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 4;
p->alpha = 255;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
if (count == 1024)
{ // rocket explosion
p->texnum = flareparticletexture;
free_particles = p->next;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
if (type == 0) // sparks
{
- p->texnum = smokeparticletexture;
- p->scale = 10;
+ p->texnum = smokeparticletexture[rand()&7];
+ p->scale = 15;
p->alpha = 64;
p->color = (rand()&3)+12;
p->type = pt_bulletpuff;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 2;
p->alpha = 255;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = bloodcloudparticletexture;
p->scale = 12;
p->alpha = 96 + (rand()&63);
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 6;
p->alpha = 255;
org[1] = diff[1] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[1];
org[2] = z;
+ p->contents = 0;
p->scale = 1.5;
p->alpha = 255;
p->die = t;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 10;
p->alpha = 128;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = particletexture;
p->scale = 2;
p->alpha = 255;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 4;
p->alpha = (1 + rand()&7) * 32;
p->next = active_particles;
active_particles = p;
+ p->contents = 0;
p->vel[0] = p->vel[1] = p->vel[2] = 0;
p->die = cl.time + 2;
if (bubbles)
{
dec = 0.005f;
+ p->contents = contents;
p->texnum = bubbleparticletexture;
p->scale = lhrandom(1,2);
p->alpha = 255;
else
{
dec = 0.02f;
- p->texnum = smokeparticletexture;
- p->scale = lhrandom(4, 7);
+ p->texnum = smokeparticletexture[rand()&7];
+ p->scale = lhrandom(6, 10);
p->alpha = 64 + (rand()&31);
p->color = (rand()&3)+12;
p->type = pt_smoke;
case 7: // Nehahra smoke tracer
dec = 0.14f;
- p->texnum = smokeparticletexture;
- p->scale = lhrandom(6, 10);
+ p->texnum = smokeparticletexture[rand()&7];
+ p->scale = lhrandom(8, 12);
p->alpha = 64;
p->color = (rand()&3)+12;
p->type = pt_smoke;
VectorCopy (vec3_origin, p->vel);
+ p->contents = 0;
p->texnum = flareparticletexture;
p->scale = 8;
p->alpha = 192;
if (!p)
break;
+ a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (a == CONTENTS_SOLID || p->contents && p->contents != a)
+ {
+ p->die = -1;
+ continue;
+ }
VectorSubtract(p->org, r_refdef.vieworg, v);
if (DotProduct(v, v) >= 256.0f)
{
switch (p->type)
{
case pt_static:
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
case pt_fire:
p->ramp += time1;
else
p->color = ramp3[(int)p->ramp];
p->vel[2] += grav;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
case pt_explode:
case pt_explode2:
p->ramp += time3;
- if (p->ramp >= 8 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->ramp >= 8)
p->die = -1;
else
p->color = ramp2[(int)p->ramp];
for (i=0 ; i<3 ; i++)
p->vel[i] += p->vel[i]*dvel;
p->vel[2] -= grav;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
case pt_blob2:
for (i=0 ; i<2 ; i++)
p->vel[i] -= p->vel[i]*dvel;
p->vel[2] -= grav;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
case pt_grav:
p->vel[2] -= grav1;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
case pt_slowgrav:
p->vel[2] -= grav;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
- p->die = -1;
break;
// LordHavoc: gunshot spark showers
case pt_dust:
p->ramp += time1;
p->scale -= frametime * 4;
- if (p->ramp >= 8 || p->scale <= 0 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->ramp >= 8 || p->scale <= 0)
p->die = -1;
else
p->color = ramp3[(int)p->ramp];
p->vel[0] = (rand()&63)-32 + p->vel2[0];
p->vel[1] = (rand()&63)-32 + p->vel2[1];
p->vel[2] = (rand()&63)-32 + p->vel2[2];
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
- p->die = -1;
}
break;
case pt_bulletpuff:
case pt_fadespark:
p->alpha -= frametime * 256;
p->vel[2] -= grav;
- if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->alpha < 1)
p->die = -1;
break;
case pt_fadespark2:
p->alpha -= frametime * 512;
p->vel[2] -= grav;
- if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->alpha < 1)
p->die = -1;
break;
case pt_fallfadespark:
p->alpha -= frametime * 256;
p->vel[2] -= grav1;
- if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->alpha < 1)
p->die = -1;
break;
case pt_fallfadespark2:
p->alpha -= frametime * 512;
p->vel[2] -= grav1;
- if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+ if (p->alpha < 1)
p->die = -1;
break;
case pt_bubble:
p->vel[1] = (rand()&63)-32;
}
p->alpha -= frametime * 64;
- if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+ if (p->alpha < 1)
p->die = -1;
break;
}