#define CL_BlobExplosion R_BlobExplosion
#define CL_RunParticleEffect R_RunParticleEffect
#define CL_LavaSplash R_LavaSplash
-#define CL_RocketTrail2 R_RocketTrail2
void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width)
{
vec3_t right1, right2, diff, normal;
}
#else
#include "cl_collision.h"
+#include "image.h"
#endif
#define MAX_PARTICLES 32768 // default max # of particles at one time
cvar_t cl_particles_blood_alpha = {CVAR_SAVE, "cl_particles_blood_alpha", "0.5"};
cvar_t cl_particles_blood_bloodhack = {CVAR_SAVE, "cl_particles_blood_bloodhack", "1"};
cvar_t cl_particles_bulletimpacts = {CVAR_SAVE, "cl_particles_bulletimpacts", "1"};
+cvar_t cl_particles_explosions_bubbles = {CVAR_SAVE, "cl_particles_explosions_bubbles", "1"};
+cvar_t cl_particles_explosions_smoke = {CVAR_SAVE, "cl_particles_explosions_smokes", "0"};
+cvar_t cl_particles_explosions_sparks = {CVAR_SAVE, "cl_particles_explosions_sparks", "1"};
+cvar_t cl_particles_explosions_shell = {CVAR_SAVE, "cl_particles_explosions_shell", "0"};
cvar_t cl_particles_smoke = {CVAR_SAVE, "cl_particles_smoke", "1"};
cvar_t cl_particles_smoke_alpha = {CVAR_SAVE, "cl_particles_smoke_alpha", "0.5"};
cvar_t cl_particles_smoke_alphafade = {CVAR_SAVE, "cl_particles_smoke_alphafade", "0.55"};
{
cl_numparticles = 0;
cl_freeparticle = 0;
+ memset(particles, 0, sizeof(particle_t) * cl_maxparticles);
}
/*
{
int i;
+// COMMANDLINEOPTION: Client: -particles <number> changes maximum number of particles at once, default 32768
i = COM_CheckParm ("-particles");
if (i && i < com_argc - 1)
Cvar_RegisterVariable (&cl_particles_blood);
Cvar_RegisterVariable (&cl_particles_blood_alpha);
Cvar_RegisterVariable (&cl_particles_blood_bloodhack);
+ Cvar_RegisterVariable (&cl_particles_explosions_bubbles);
+ Cvar_RegisterVariable (&cl_particles_explosions_smoke);
+ Cvar_RegisterVariable (&cl_particles_explosions_sparks);
+ Cvar_RegisterVariable (&cl_particles_explosions_shell);
Cvar_RegisterVariable (&cl_particles_bulletimpacts);
Cvar_RegisterVariable (&cl_particles_smoke);
Cvar_RegisterVariable (&cl_particles_smoke_alpha);
#ifdef WORKINGLQUAKE
particles = (particle_t *) Hunk_AllocName(cl_maxparticles * sizeof(particle_t), "particles");
#else
- cl_part_mempool = Mem_AllocPool("CL_Part");
+ cl_part_mempool = Mem_AllocPool("CL_Part", 0, NULL);
particles = (particle_t *) Mem_Alloc(cl_part_mempool, cl_maxparticles * sizeof(particle_t));
#endif
- cl_numparticles = 0;
- cl_freeparticle = 0;
+ CL_Particles_Clear();
}
// list of all 26 parameters:
vec3_t org, dir;
int i, count, msgcount, color;
- MSG_ReadVector(org);
+ MSG_ReadVector(org, cl.protocol);
for (i=0 ; i<3 ; i++)
dir[i] = MSG_ReadChar () * (1.0/16);
msgcount = MSG_ReadByte ();
*/
void CL_ParticleExplosion (vec3_t org)
{
- int i, k;
+ int i;
//vec3_t v;
//vec3_t v2;
if (cl_stainmaps.integer)
CL_SpawnDecalParticleForPoint(org, 40, 48, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
i = CL_PointQ1Contents(org);
- if ((i == CONTENTS_SLIME || i == CONTENTS_WATER) && cl_particles.integer && cl_particles_bubbles.integer)
+ if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
{
- for (i = 0;i < 128 * cl_particles_quality.value;i++)
- particle(pt_bubble, PARTICLE_BILLBOARD, 0x404040, 0x808080, tex_bubble, false, PBLEND_ADD, 2, 2, (1.0f / cl_particles_quality.value) * lhrandom(128, 255), (1.0f / cl_particles_quality.value) * 256, 9999, -0.25, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, (1.0 / 16.0), 0);
+ if (cl_particles.integer && cl_particles_bubbles.integer && cl_particles_explosions_bubbles.integer)
+ for (i = 0;i < 128 * cl_particles_quality.value;i++)
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0x404040, 0x808080, tex_bubble, false, PBLEND_ADD, 2, 2, (1.0f / cl_particles_quality.value) * lhrandom(128, 255), (1.0f / cl_particles_quality.value) * 256, 9999, -0.25, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, (1.0 / 16.0), 0);
}
else
{
- /*
// LordHavoc: smoke effect similar to UT2003, chews fillrate too badly up close
// smoke puff
- if (cl_particles.integer && cl_particles_smoke.integer)
+ if (cl_particles.integer && cl_particles_smoke.integer && cl_particles_explosions_smoke.integer)
{
- for (i = 0;i < 64;i++)
+ for (i = 0;i < 32;i++)
{
+ int k;
+ vec3_t v, v2;
#ifdef WORKINGLQUAKE
- v2[0] = lhrandom(-64, 64);
- v2[1] = lhrandom(-64, 64);
- v2[2] = lhrandom(-8, 24);
+ v2[0] = lhrandom(-48, 48);
+ v2[1] = lhrandom(-48, 48);
+ v2[2] = lhrandom(-48, 48);
#else
for (k = 0;k < 16;k++)
{
- v[0] = org[0] + lhrandom(-64, 64);
- v[1] = org[1] + lhrandom(-64, 64);
- v[2] = org[2] + lhrandom(-8, 24);
+ v[0] = org[0] + lhrandom(-48, 48);
+ v[1] = org[1] + lhrandom(-48, 48);
+ v[2] = org[2] + lhrandom(-48, 48);
if (CL_TraceLine(org, v, v2, NULL, true, NULL, SUPERCONTENTS_SOLID) >= 0.1)
break;
}
VectorSubtract(v2, org, v2);
#endif
VectorScale(v2, 2.0f, v2);
- particle(pt_static, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 12, 12, 255, 512, 9999, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0, 0, 0, 0);
+ particle(pt_static, PARTICLE_BILLBOARD, 0xFFFFFF, 0xFFFFFF, tex_smoke[rand()&7], true, PBLEND_ADD, 12, 12, 32, 64, 9999, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0, 0, 0, 0);
}
}
- */
#if 1
- if (cl_particles.integer && cl_particles_sparks.integer)
+ if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
for (i = 0;i < 128 * cl_particles_quality.value;i++)
particle(pt_static, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.0f, 0.02f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-256, 256), lhrandom(-256, 256), lhrandom(-256, 256) + 80, 0, 0, 0, 0, 0.2, 0);
- }
-
- //if (cl_explosions.integer)
- // R_NewExplosion(org);
#elif 1
- if (cl_particles.integer && cl_particles_sparks.integer)
+ if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
for (i = 0;i < 64 * cl_particles_quality.value;i++)
particle(pt_ember, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.0f, 0.01f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 256, 9999, 0.7, 0, org[0], org[1], org[2], lhrandom(-256, 256), lhrandom(-256, 256), lhrandom(-256, 256) + 80, cl.time, 0, 0, 0, 0, 0);
- }
-
- //if (cl_explosions.integer)
- // R_NewExplosion(org);
#else
- if (cl_particles.integer && cl_particles_sparks.integer)
- {
- // sparks
+ if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
for (i = 0;i < 256 * cl_particles_quality.value;i++)
- {
- k = particlepalette[0x68 + (rand() & 7)];
- particle(pt_static, PARTICLE_SPARK, k, k, tex_particle, false, PBLEND_ADD, 1.5f, 0.05f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 160, 0, 0, 0, 0, 0.2, 0);
- }
- }
+ particle(pt_static, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.5f, 0.05f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 160, 0, 0, 0, 0, 0.2, 0);
+#endif
}
- if (cl_explosions.integer)
+ if (cl_particles_explosions_shell.integer)
R_NewExplosion(org);
-#endif
}
/*
vec3_t vel;
vec3_t offset;
int i, k;
+ float pscale;
if (!cl_particles.integer) return;
for (i = 0;i < 512 * cl_particles_quality.value;i++)
VectorScale (offset, 192, vel);
VectorScale (offset, 8, offset);
k = particlepalette[colorStart + (i % colorLength)];
- particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ALPHA, 1.5, 1.5, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 384, 0.3, 0, 0, org[0] + offset[0], org[1] + offset[1], org[2] + offset[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1, 0);
+ pscale = lhrandom(0.5, 1.5);
+ particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, pscale, pscale, (1.0f / cl_particles_quality.value) * 255, (1.0f/cl_particles_quality.value)*512, 9999, 0, 0, org[0] + offset[0], org[1] + offset[1], org[2] + offset[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, lhrandom(1.5, 3), 0);
}
}
*/
void CL_BlobExplosion (vec3_t org)
{
- if (cl_stainmaps.integer)
- R_Stain(org, 96, 80, 80, 80, 64, 176, 176, 176, 64);
- CL_SpawnDecalParticleForPoint(org, 40, 48, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
-
- if (cl_explosions.integer)
- R_NewExplosion(org);
+ CL_ParticleExplosion(org);
}
/*
#ifdef WORKINGLQUAKE
void R_RocketTrail (vec3_t start, vec3_t end, int type)
#else
-void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
+void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *ent)
#endif
{
vec3_t vec, dir, vel, pos;
if (speed)
speed = 1.0f / speed;
VectorSubtract(ent->state_current.origin, ent->state_previous.origin, vel);
+ color = particlepalette[color];
#endif
VectorScale(vel, speed, vel);
{
if (gamemode == GAME_GOODVSBAD2)
particle(pt_static, PARTICLE_BILLBOARD, particlepalette[0 + (rand()&255)], particlepalette[0 + (rand()&255)], tex_particle, false, PBLEND_ALPHA, 6, 6, qd*255, qd*384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ else if (gamemode == GAME_PRYDON)
+ particle(pt_static, PARTICLE_BILLBOARD, 0x103040, 0x204050, tex_particle, false, PBLEND_ADD, 6, 6, qd*128, qd*384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
else
particle(pt_static, PARTICLE_BILLBOARD, 0x502030, 0x502030, tex_particle, false, PBLEND_ADD, 6, 6, qd*128, qd*384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
}
break;
-
+#ifndef WORKINGLQUAKE
case 7: // Nehahra smoke tracer
dec = qd*7;
if (smoke)
if (smoke)
particle(pt_static, PARTICLE_BILLBOARD, 0x283880, 0x283880, tex_particle, false, PBLEND_ADD, 4, 4, qd*255, qd*1024, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
+ case 9: // glow trail
+ dec = qd*3;
+ if (smoke)
+ particle(pt_static, PARTICLE_BILLBOARD, color, color, tex_particle, false, PBLEND_ALPHA, 5, 5, qd*128, qd*320, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+#endif
}
// advance to next time and position
#endif
}
-void CL_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
-{
- float dec, len;
- vec3_t vec, pos;
- if (!cl_particles.integer) return;
- if (!cl_particles_smoke.integer) return;
-
- VectorCopy(start, pos);
- VectorSubtract(end, start, vec);
-#ifdef WORKINGLQUAKE
- len = VectorNormalize(vec);
-#else
- len = VectorNormalizeLength(vec);
-#endif
- color = particlepalette[color];
- dec = 3.0f / cl_particles_quality.value;
- while (len > 0)
- {
- particle(pt_static, PARTICLE_BILLBOARD, color, color, tex_particle, false, PBLEND_ALPHA, 5, 5, 128 / cl_particles_quality.value, 320 / cl_particles_quality.value, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
- len -= dec;
- VectorMA(pos, dec, vec, pos);
- }
-}
-
void CL_BeamParticle (const vec3_t start, const vec3_t end, vec_t radius, float red, float green, float blue, float alpha, float lifetime)
{
int tempcolor2, cr, cg, cb;
p->bounce = 0;
p->friction = 0;
p->gravity = 0;
- p->scalex *= 1.25f;
- p->scaley *= 1.25f;
+ p->scalex *= 2.0f;
+ p->scaley *= 2.0f;
}
else
{
static cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
+#define PARTICLETEXTURESIZE 32
+#define PARTICLEFONTSIZE (PARTICLETEXTURESIZE*8)
+
static qbyte shadebubble(float dx, float dy, vec3_t light)
{
float dz, f, dot;
static void setuptex(int texnum, qbyte *data, qbyte *particletexturedata)
{
int basex, basey, y;
- basex = ((texnum >> 0) & 7) * 32;
- basey = ((texnum >> 3) & 7) * 32;
- particletexture[texnum].s1 = (basex + 1) / 256.0f;
- particletexture[texnum].t1 = (basey + 1) / 256.0f;
- particletexture[texnum].s2 = (basex + 31) / 256.0f;
- particletexture[texnum].t2 = (basey + 31) / 256.0f;
- for (y = 0;y < 32;y++)
- memcpy(particletexturedata + ((basey + y) * 256 + basex) * 4, data + y * 32 * 4, 32 * 4);
+ basex = ((texnum >> 0) & 7) * PARTICLETEXTURESIZE;
+ basey = ((texnum >> 3) & 7) * PARTICLETEXTURESIZE;
+ particletexture[texnum].s1 = (basex + 1) / (float)PARTICLEFONTSIZE;
+ particletexture[texnum].t1 = (basey + 1) / (float)PARTICLEFONTSIZE;
+ particletexture[texnum].s2 = (basex + PARTICLETEXTURESIZE - 1) / (float)PARTICLEFONTSIZE;
+ particletexture[texnum].t2 = (basey + PARTICLETEXTURESIZE - 1) / (float)PARTICLEFONTSIZE;
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
+ memcpy(particletexturedata + ((basey + y) * PARTICLEFONTSIZE + basex) * 4, data + y * PARTICLETEXTURESIZE * 4, PARTICLETEXTURESIZE * 4);
}
void particletextureblotch(qbyte *data, float radius, float red, float green, float blue, float alpha)
int x, y;
float cx, cy, dx, dy, f, iradius;
qbyte *d;
- cx = lhrandom(radius + 1, 30 - radius);
- cy = lhrandom(radius + 1, 30 - radius);
+ cx = (lhrandom(radius + 1, PARTICLETEXTURESIZE - 2 - radius) + lhrandom(radius + 1, PARTICLETEXTURESIZE - 2 - radius)) * 0.5f;
+ cy = (lhrandom(radius + 1, PARTICLETEXTURESIZE - 2 - radius) + lhrandom(radius + 1, PARTICLETEXTURESIZE - 2 - radius)) * 0.5f;
iradius = 1.0f / radius;
alpha *= (1.0f / 255.0f);
- for (y = 0;y < 32;y++)
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
{
- for (x = 0;x < 32;x++)
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
{
dx = (x - cx);
dy = (y - cy);
f = (1.0f - sqrt(dx * dx + dy * dy) * iradius) * alpha;
if (f > 0)
{
- d = data + (y * 32 + x) * 4;
+ d = data + (y * PARTICLETEXTURESIZE + x) * 4;
d[0] += f * (red - d[0]);
d[1] += f * (green - d[1]);
d[2] += f * (blue - d[2]);
void particletextureclamp(qbyte *data, int minr, int ming, int minb, int maxr, int maxg, int maxb)
{
int i;
- for (i = 0;i < 32*32;i++, data += 4)
+ for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
{
data[0] = bound(minr, data[0], maxr);
data[1] = bound(ming, data[1], maxg);
void particletextureinvert(qbyte *data)
{
int i;
- for (i = 0;i < 32*32;i++, data += 4)
+ for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
{
data[0] = 255 - data[0];
data[1] = 255 - data[1];
{
int x, y, d, i, j, k, m;
float dx, dy, radius, f, f2;
- qbyte data[32][32][4], noise1[64][64], noise2[64][64], data2[64][16][4];
+ qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4], noise1[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise2[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise3[64][64], data2[64][16][4];
vec3_t light;
- qbyte particletexturedata[256*256*4];
+ qbyte *particletexturedata;
// a note: decals need to modulate (multiply) the background color to
// properly darken it (stain), and they need to be able to alpha fade,
// and white on black background) so we can alpha fade it to black, then
// we invert it again during the blendfunc to make it work...
- memset(particletexturedata, 255, sizeof(particletexturedata));
+ particletexturedata = Mem_Alloc(tempmempool, PARTICLEFONTSIZE*PARTICLEFONTSIZE*4);
+ memset(particletexturedata, 255, PARTICLEFONTSIZE*PARTICLEFONTSIZE*4);
// smoke
for (i = 0;i < 8;i++)
memset(&data[0][0][0], 255, sizeof(data));
do
{
- fractalnoise(&noise1[0][0], 64, 4);
- fractalnoise(&noise2[0][0], 64, 8);
+ fractalnoise(&noise1[0][0], PARTICLETEXTURESIZE*2, PARTICLETEXTURESIZE/8);
+ fractalnoise(&noise2[0][0], PARTICLETEXTURESIZE*2, PARTICLETEXTURESIZE/4);
m = 0;
- for (y = 0;y < 32;y++)
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
{
- dy = y - 16;
- for (x = 0;x < 32;x++)
+ dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
{
- dx = x - 16;
+ dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
d = (noise2[y][x] - 128) * 3 + 192;
if (d > 0)
- d = d * (256 - (int) (dx*dx+dy*dy)) / 256;
+ d = d * (1-(dx*dx+dy*dy));
d = (d * noise1[y][x]) >> 7;
d = bound(0, d, 255);
data[y][x][3] = (qbyte) d;
for (i = 0;i < 16;i++)
{
memset(&data[0][0][0], 255, sizeof(data));
- radius = i * 3.0f / 16.0f;
+ radius = i * 3.0f / 4.0f / 16.0f;
f2 = 255.0f * ((15.0f - i) / 15.0f);
- for (y = 0;y < 32;y++)
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
{
- dy = (y - 16) * 0.25f;
- for (x = 0;x < 32;x++)
+ dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
{
- dx = (x - 16) * 0.25f;
- f = (1.0 - fabs(radius - sqrt(dx*dx+dy*dy))) * f2;
+ dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ f = f2 * (1.0 - 4.0f * fabs(radius - sqrt(dx*dx+dy*dy)));
data[y][x][3] = (int) (bound(0.0f, f, 255.0f));
}
}
// normal particle
memset(&data[0][0][0], 255, sizeof(data));
- for (y = 0;y < 32;y++)
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
{
- dy = y - 16;
- for (x = 0;x < 32;x++)
+ dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
{
- dx = x - 16;
- d = (256 - (dx*dx+dy*dy));
+ dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ d = 256 * (1 - (dx*dx+dy*dy));
d = bound(0, d, 255);
data[y][x][3] = (qbyte) d;
}
memset(&data[0][0][0], 255, sizeof(data));
light[0] = 1;light[1] = 1;light[2] = 1;
VectorNormalize(light);
- for (y = 0;y < 32;y++)
- for (x = 0;x < 32;x++)
- data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light);
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
+ {
+ dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ // stretch upper half of bubble by +50% and shrink lower half by -50%
+ // (this gives an elongated teardrop shape)
+ if (dy > 0.5f)
+ dy = (dy - 0.5f) * 2.0f;
+ else
+ dy = (dy - 0.5f) / 1.5f;
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
+ {
+ dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ // shrink bubble width to half
+ dx *= 2.0f;
+ data[y][x][3] = shadebubble(dx, dy, light);
+ }
+ }
setuptex(tex_raindrop, &data[0][0][0], particletexturedata);
// bubble
memset(&data[0][0][0], 255, sizeof(data));
light[0] = 1;light[1] = 1;light[2] = 1;
VectorNormalize(light);
- for (y = 0;y < 32;y++)
- for (x = 0;x < 32;x++)
- data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
+ for (y = 0;y < PARTICLETEXTURESIZE;y++)
+ {
+ dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ for (x = 0;x < PARTICLETEXTURESIZE;x++)
+ {
+ dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+ data[y][x][3] = shadebubble(dx, dy, light);
+ }
+ }
setuptex(tex_bubble, &data[0][0][0], particletexturedata);
// blood particles
{
memset(&data[0][0][0], 255, sizeof(data));
for (k = 0;k < 24;k++)
- particletextureblotch(&data[0][0][0], 2, 96, 0, 0, 160);
+ particletextureblotch(&data[0][0][0], PARTICLETEXTURESIZE/16, 96, 0, 0, 160);
//particletextureclamp(&data[0][0][0], 32, 32, 32, 255, 255, 255);
particletextureinvert(&data[0][0][0]);
setuptex(tex_bloodparticle[i], &data[0][0][0], particletexturedata);
for (i = 0;i < 8;i++)
{
memset(&data[0][0][0], 255, sizeof(data));
- for (k = 0;k < 24;k++)
- particletextureblotch(&data[0][0][0], 2, 96, 0, 0, 96);
- for (j = 3;j < 7;j++)
- for (k = 0, m = rand() % 12;k < m;k++)
- particletextureblotch(&data[0][0][0], j, 96, 0, 0, 192);
+ m = 8;
+ for (j = 1;j < 10;j++)
+ for (k = min(j, m - 1);k < m;k++)
+ particletextureblotch(&data[0][0][0], (float)j*PARTICLETEXTURESIZE/64.0f, 96, 0, 0, 192 - j * 8);
//particletextureclamp(&data[0][0][0], 32, 32, 32, 255, 255, 255);
particletextureinvert(&data[0][0][0]);
setuptex(tex_blooddecal[i], &data[0][0][0], particletexturedata);
{
memset(&data[0][0][0], 255, sizeof(data));
for (k = 0;k < 12;k++)
- particletextureblotch(&data[0][0][0], 2, 0, 0, 0, 128);
+ particletextureblotch(&data[0][0][0], PARTICLETEXTURESIZE/16, 0, 0, 0, 128);
for (k = 0;k < 3;k++)
- particletextureblotch(&data[0][0][0], 14, 0, 0, 0, 160);
+ particletextureblotch(&data[0][0][0], PARTICLETEXTURESIZE/2, 0, 0, 0, 160);
//particletextureclamp(&data[0][0][0], 64, 64, 64, 255, 255, 255);
particletextureinvert(&data[0][0][0]);
setuptex(tex_bulletdecal[i], &data[0][0][0], particletexturedata);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#else
- particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+ particlefonttexture = loadtextureimage(particletexturepool, "particles/particlefont.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
+ if (!particlefonttexture)
+ particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
for (i = 0;i < MAX_PARTICLETEXTURES;i++)
particletexture[i].texture = particlefonttexture;
- // beam
- fractalnoise(&noise1[0][0], 64, 4);
+ // nexbeam
+ fractalnoise(&noise3[0][0], 64, 4);
m = 0;
for (y = 0;y < 64;y++)
{
+ dy = (y - 0.5f*64) / (64*0.5f+1);
for (x = 0;x < 16;x++)
{
- if (x < 8)
- d = x;
- else
- d = (15 - x);
- d = d * d * noise1[y][x] / (7 * 7);
+ dx = (x - 0.5f*16) / (16*0.5f+1);
+ d = (1 - (dx*dx)) * noise3[y][x];
data2[y][x][0] = data2[y][x][1] = data2[y][x][2] = (qbyte) bound(0, d, 255);
data2[y][x][3] = 255;
}
}
- particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "beam", 16, 64, &data2[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+ particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
+ if (!particletexture[tex_beam].texture)
+ particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "nexbeam", 16, 64, &data2[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
particletexture[tex_beam].s1 = 0;
particletexture[tex_beam].t1 = 0;
particletexture[tex_beam].s2 = 1;
particletexture[tex_beam].t2 = 1;
#endif
+ Mem_Free(particletexturedata);
}
static void r_part_start(void)