#define NUMVERTEXNORMALS 162
siextern float r_avertexnormals[NUMVERTEXNORMALS][3];
#define m_bytenormals r_avertexnormals
-#define VectorNormalizeFast VectorNormalize
#define CL_PointQ1Contents(v) (Mod_PointInLeaf(v,cl.worldmodel)->contents)
-typedef unsigned char qbyte;
+typedef unsigned char unsigned char;
#define cl_stainmaps.integer 0
void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
{
vec3_t right1, right2, diff, normal;
VectorSubtract (org2, org1, normal);
- VectorNormalizeFast (normal);
+ VectorNormalize (normal);
// calculate 'right' vector for start
VectorSubtract (r_vieworigin, org1, diff);
- VectorNormalizeFast (diff);
+ VectorNormalize (diff);
CrossProduct (normal, diff, right1);
// calculate 'right' vector for end
VectorSubtract (r_vieworigin, org2, diff);
- VectorNormalizeFast (diff);
+ VectorNormalize (diff);
CrossProduct (normal, diff, right2);
vert[ 0] = org1[0] + width * right1[0];
vert[10] = org2[1] + width * right2[1];
vert[11] = org2[2] + width * right2[2];
}
-void fractalnoise(qbyte *noise, int size, int startgrid)
+void fractalnoise(unsigned char *noise, int size, int startgrid)
{
int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower;
int *noisebuf;
for (sizepower = 0;(1 << sizepower) < size;sizepower++);
if (size != (1 << sizepower))
- Sys_Error("fractalnoise: size must be power of 2\n");
+ {
+ Con_Printf("fractalnoise: size must be power of 2\n");
+ return;
+ }
for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
if (startgrid != (1 << gridpower))
- Sys_Error("fractalnoise: grid must be power of 2\n");
+ {
+ Con_Printf("fractalnoise: grid must be power of 2\n");
+ return;
+ }
startgrid = bound(0, startgrid, size);
// normalize noise and copy to output
for (y = 0;y < size;y++)
for (x = 0;x < size;x++)
- *noise++ = (qbyte) (((n(x,y) - min) * 256) / max);
+ *noise++ = (unsigned char) (((n(x,y) - min) * 256) / max);
free(noisebuf);
#undef n
}
right[0] -= d * forward[0];
right[1] -= d * forward[1];
right[2] -= d * forward[2];
- VectorNormalizeFast(right);
+ VectorNormalize(right);
CrossProduct(right, forward, up);
}
#if QW
#include "pmove.h"
extern qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace);
#endif
-float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int hitbmodels, void **hitent, int hitsupercontentsmask)
+trace_t CL_TraceBox (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers)
{
#if QW
pmtrace_t trace;
#else
RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
#endif
- VectorCopy(trace.endpos, impact);
- VectorCopy(trace.plane.normal, normal);
- return trace.fraction;
+ return trace;
}
#else
#include "cl_collision.h"
{
pblend_t blendmode;
porientation_t orientation;
+ qboolean lighting;
}
particletype_t;
typedef enum
{
- pt_alphastatic, pt_static, pt_spark, pt_beam, pt_rain, pt_raindecal, pt_snow, pt_bubble, pt_blood, pt_grow, pt_decal, pt_entityparticle, pt_total
+ pt_alphastatic, pt_static, pt_spark, pt_beam, pt_rain, pt_raindecal, pt_snow, pt_bubble, pt_blood, pt_smoke, pt_decal, pt_entityparticle, pt_total
}
ptype_t;
// must match ptype_t values
particletype_t particletype[pt_total] =
{
- {PBLEND_ALPHA, PARTICLE_BILLBOARD}, //pt_alphastatic
- {PBLEND_ADD, PARTICLE_BILLBOARD}, //pt_static
- {PBLEND_ADD, PARTICLE_SPARK}, //pt_spark
- {PBLEND_ADD, PARTICLE_BEAM}, //pt_beam
- {PBLEND_ADD, PARTICLE_SPARK}, //pt_rain
- {PBLEND_ADD, PARTICLE_ORIENTED_DOUBLESIDED}, //pt_raindecal
- {PBLEND_ADD, PARTICLE_BILLBOARD}, //pt_snow
- {PBLEND_ADD, PARTICLE_BILLBOARD}, //pt_bubble
- {PBLEND_MOD, PARTICLE_BILLBOARD}, //pt_blood
- {PBLEND_ADD, PARTICLE_BILLBOARD}, //pt_grow
- {PBLEND_MOD, PARTICLE_ORIENTED_DOUBLESIDED}, //pt_decal
- {PBLEND_ALPHA, PARTICLE_BILLBOARD}, //pt_entityparticle
+ {PBLEND_ALPHA, PARTICLE_BILLBOARD, false}, //pt_alphastatic
+ {PBLEND_ADD, PARTICLE_BILLBOARD, false}, //pt_static
+ {PBLEND_ADD, PARTICLE_SPARK, false}, //pt_spark
+ {PBLEND_ADD, PARTICLE_BEAM, false}, //pt_beam
+ {PBLEND_ADD, PARTICLE_SPARK, false}, //pt_rain
+ {PBLEND_ADD, PARTICLE_ORIENTED_DOUBLESIDED, false}, //pt_raindecal
+ {PBLEND_ADD, PARTICLE_BILLBOARD, false}, //pt_snow
+ {PBLEND_ADD, PARTICLE_BILLBOARD, false}, //pt_bubble
+ {PBLEND_MOD, PARTICLE_BILLBOARD, false}, //pt_blood
+ {PBLEND_ADD, PARTICLE_BILLBOARD, false}, //pt_smoke
+ {PBLEND_MOD, PARTICLE_ORIENTED_DOUBLESIDED, false}, //pt_decal
+ {PBLEND_ALPHA, PARTICLE_BILLBOARD, false}, //pt_entityparticle
};
typedef struct particle_s
float bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
float gravity; // how much gravity affects this particle (1.0 = normal gravity, 0.0 = none)
float friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
- qbyte color[4];
-#ifndef WORKINGLQUAKE
- entity_render_t *owner; // decal stuck to this entity
+ unsigned char color[4];
+ unsigned short owner; // decal stuck to this entity
model_t *ownermodel; // model the decal is stuck to (used to make sure the entity is still alive)
vec3_t relativeorigin; // decal at this location in entity's coordinate space
vec3_t relativedirection; // decal oriented this way relative to entity's coordinate space
-#endif
}
particle_t;
cvar_t cl_decals_time = {CVAR_SAVE, "cl_decals_time", "0"};
cvar_t cl_decals_fadetime = {CVAR_SAVE, "cl_decals_fadetime", "20"};
-#ifndef WORKINGLQUAKE
-static mempool_t *cl_part_mempool;
-#endif
-
void CL_Particles_Clear(void)
{
cl_numparticles = 0;
#ifdef WORKINGLQUAKE
particles = (particle_t *) Hunk_AllocName(cl_maxparticles * sizeof(particle_t), "particles");
#else
- cl_part_mempool = Mem_AllocPool("CL_Part", 0, NULL);
- particles = (particle_t *) Mem_Alloc(cl_part_mempool, cl_maxparticles * sizeof(particle_t));
+ particles = (particle_t *) Mem_Alloc(cl_mempool, cl_maxparticles * sizeof(particle_t));
#endif
CL_Particles_Clear();
}
{
#ifdef WORKINGLQUAKE
// No clue what to do here...
-#else
- Mem_FreePool (&cl_part_mempool);
#endif
}
return part;
}
-void CL_SpawnDecalParticleForSurface(void *hitent, const vec3_t org, const vec3_t normal, int color1, int color2, int texnum, float size, float alpha)
+void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t normal, int color1, int color2, int texnum, float size, float alpha)
{
particle_t *p;
if (!cl_decals.integer)
p->time2 = cl.time;
#ifndef WORKINGLQUAKE
p->owner = hitent;
- p->ownermodel = p->owner->model;
- Matrix4x4_Transform(&p->owner->inversematrix, org, p->relativeorigin);
- Matrix4x4_Transform3x3(&p->owner->inversematrix, normal, p->relativedirection);
+ p->ownermodel = cl_entities[p->owner].render.model;
+ Matrix4x4_Transform(&cl_entities[p->owner].render.inversematrix, org, p->relativeorigin);
+ Matrix4x4_Transform3x3(&cl_entities[p->owner].render.inversematrix, normal, p->relativedirection);
VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
#endif
}
{
int i;
float bestfrac, bestorg[3], bestnormal[3];
- float frac, v[3], normal[3], org2[3];
-#ifdef WORKINGLQUAKE
- void *besthitent = NULL, *hitent;
-#else
- entity_render_t *besthitent = NULL, *hitent;
-#endif
+ float org2[3];
+ int besthitent = 0, hitent;
+ trace_t trace;
bestfrac = 10;
for (i = 0;i < 32;i++)
{
VectorRandom(org2);
VectorMA(org, maxdist, org2, org2);
- frac = CL_TraceLine(org, org2, v, normal, true, &hitent, SUPERCONTENTS_SOLID);
- if (bestfrac > frac)
+ trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, &hitent, SUPERCONTENTS_SOLID, false);
+ if (bestfrac > trace.fraction)
{
- bestfrac = frac;
+ bestfrac = trace.fraction;
besthitent = hitent;
- VectorCopy(v, bestorg);
- VectorCopy(normal, bestnormal);
+ VectorCopy(trace.endpos, bestorg);
+ VectorCopy(trace.plane.normal, bestnormal);
}
}
if (bestfrac < 1)
#if WORKINGLQUAKE
pointfile = COM_LoadTempFile (name);
#else
- pointfile = FS_LoadFile(name, tempmempool, true);
+ pointfile = (char *)FS_LoadFile(name, tempmempool, true);
#endif
if (!pointfile)
{
}
Con_Printf("Reading %s...\n", name);
+ VectorClear(leakorg);
c = 0;
s = 0;
pointfilepos = pointfile;
void CL_ParticleExplosion (vec3_t org)
{
int i;
+ trace_t trace;
//vec3_t v;
//vec3_t v2;
if (cl_stainmaps.integer)
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)
+ trace = CL_TraceBox(org, vec3_origin, vec3_origin, v, true, NULL, SUPERCONTENTS_SOLID, false);
+ if (trace.fraction >= 0.1)
break;
}
- VectorSubtract(v2, org, v2);
+ VectorSubtract(trace.endpos, org, v2);
#endif
VectorScale(v2, 2.0f, v2);
- particle(particletype + pt_static, 0xFFFFFF, 0xFFFFFF, tex_smoke[rand()&7], 12, 32, 64, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0);
+ particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 12, 32, 64, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0);
}
}
void CL_Smoke (vec3_t org, vec3_t dir, int count)
{
- vec3_t org2, org3;
+ vec3_t org2;
int k;
+ trace_t trace;
if (!cl_particles.integer) return;
org2[0] = org[0] + 0.125f * lhrandom(-count, count);
org2[1] = org[1] + 0.125f * lhrandom(-count, count);
org2[2] = org[2] + 0.125f * lhrandom(-count, count);
- CL_TraceLine(org, org2, org3, NULL, true, NULL, SUPERCONTENTS_SOLID);
- particle(particletype + pt_grow, 0x101010, 0x202020, tex_smoke[rand()&7], 3, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 1024, 0, 0, org3[0], org3[1], org3[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0);
+ trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, NULL, SUPERCONTENTS_SOLID, false);
+ particle(particletype + pt_smoke, 0x101010, 0x202020, tex_smoke[rand()&7], 3, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 1024, 0, 0, trace.endpos[0], trace.endpos[1], trace.endpos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0);
}
}
}
void CL_BloodPuff (vec3_t org, vec3_t vel, int count)
{
float s;
- vec3_t org2, org3;
+ vec3_t org2;
+ trace_t trace;
// bloodcount is used to accumulate counts too small to cause a blood particle
if (!cl_particles.integer) return;
if (!cl_particles_blood.integer) return;
org2[0] = org[0] + 0.125f * lhrandom(-bloodcount, bloodcount);
org2[1] = org[1] + 0.125f * lhrandom(-bloodcount, bloodcount);
org2[2] = org[2] + 0.125f * lhrandom(-bloodcount, bloodcount);
- CL_TraceLine(org, org2, org3, NULL, true, NULL, SUPERCONTENTS_SOLID);
- particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768 / cl_particles_quality.value, cl_particles_blood_alpha.value * 384 / cl_particles_quality.value, 0, -1, org3[0], org3[1], org3[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 1);
+ trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, NULL, SUPERCONTENTS_SOLID, false);
+ particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768 / cl_particles_quality.value, cl_particles_blood_alpha.value * 384 / cl_particles_quality.value, 0, -1, trace.endpos[0], trace.endpos[1], trace.endpos[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 1);
bloodcount -= 16 / cl_particles_quality.value;
}
}
{
int k;
float t, z, minz, maxz;
+ particle_t *p;
if (!cl_particles.integer) return;
if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
{
k = particlepalette[colorbase + (rand()&3)];
if (gamemode == GAME_GOODVSBAD2)
- particle(particletype + pt_snow, k, k, tex_particle, 20, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0);
+ p = particle(particletype + pt_snow, k, k, tex_particle, 20, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0);
else
- particle(particletype + pt_snow, k, k, tex_particle, 1, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0);
+ p = particle(particletype + pt_snow, k, k, tex_particle, 1, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0);
+ if (p)
+ VectorCopy(p->vel, p->relativedirection);
}
break;
default:
- Host_Error("CL_ParticleRain: unknown type %i (0 = rain, 1 = snow)\n", type);
+ Con_Printf ("CL_ParticleRain: unknown type %i (0 = rain, 1 = snow)\n", type);
}
}
o[1] = lhrandom(mins[1], maxs[1]);
o[2] = lhrandom(mins[2], maxs[2]);
VectorSubtract(o, center, v);
- VectorNormalizeFast(v);
+ VectorNormalize(v);
VectorScale(v, 100, v);
v[2] += sv_gravity.value * 0.15f;
particle(particletype + pt_static, 0x903010, 0xFFD030, tex_particle, 1.5, lhrandom(64, 128) / cl_particles_quality.value, 128 / cl_particles_quality.value, 1, 0, o[0], o[1], o[2], v[0], v[1], v[2], 0.2);
dec = qd*3;
if (smoke)
{
- particle(particletype + pt_grow, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*125, qd*cl_particles_smoke_alphafade.value*125, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0);
+ particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*125, qd*cl_particles_smoke_alphafade.value*125, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0);
particle(particletype + pt_static, 0x801010, 0xFFA020, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*288, qd*cl_particles_smoke_alphafade.value*1400, 0, 0, pos[0], pos[1], pos[2], lhrandom(-20, 20), lhrandom(-20, 20), lhrandom(-20, 20), 0);
}
if (bubbles)
// FIXME: make it gradually stop smoking
dec = qd*3;
if (smoke)
- particle(particletype + pt_grow, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*100, qd*cl_particles_smoke_alphafade.value*100, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0);
+ particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*100, qd*cl_particles_smoke_alphafade.value*100, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0);
break;
particle(particletype + pt_alphastatic, color, color, tex_particle, 5, qd*128, qd*320, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0);
break;
#endif
+ default:
+ Sys_Error("CL_RocketTrail: unknown trail type %i\n", type);
}
// advance to next time and position
// smoke puff
if (cl_particles_smoke.integer)
for (f = 0;f < count;f += 4.0f / cl_particles_quality.value)
- particle(particletype + pt_grow, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), dir[0] + lhrandom(-count, count) * 0.5f, dir[1] + lhrandom(-count, count) * 0.5f, dir[2] + lhrandom(-count, count) * 0.5f, 0);
+ particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), dir[0] + lhrandom(-count, count) * 0.5f, dir[1] + lhrandom(-count, count) * 0.5f, dir[2] + lhrandom(-count, count) * 0.5f, 0);
}
void CL_Tei_PlasmaHit(const vec3_t org, const vec3_t dir, int count)
// smoke puff
if (cl_particles_smoke.integer)
for (f = 0;f < count;f += 4.0f / cl_particles_quality.value)
- particle(particletype + pt_grow, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), dir[0] + lhrandom(-count, count), dir[1] + lhrandom(-count, count), dir[2] + lhrandom(-count, count), 0);
+ particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), dir[0] + lhrandom(-count, count), dir[1] + lhrandom(-count, count), dir[2] + lhrandom(-count, count), 0);
// sparks
if (cl_particles_sparks.integer)
{
particle_t *p;
int i, maxparticle, j, a, content;
- float gravity, dvel, bloodwaterfade, frametime, f, dist, normal[3], v[3], org[3], oldorg[3];
-#ifdef WORKINGLQUAKE
- void *hitent;
-#else
- entity_render_t *hitent;
-#endif
+ float gravity, dvel, bloodwaterfade, frametime, f, dist, org[3], oldorg[3];
+ int hitent;
+ trace_t trace;
// LordHavoc: early out condition
if (!cl_numparticles)
if (p->type == particletype + pt_rain)
{
// raindrop - splash on solid/water/slime/lava
- if (CL_TraceLine(oldorg, p->org, v, normal, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK) < 1)
+ trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK, false);
+ if (trace.fraction < 1)
{
- VectorCopy(v, p->org);
- // splash
- p->type = particletype + pt_raindecal;
// convert from a raindrop particle to a rainsplash decal
+ VectorCopy(trace.endpos, p->org);
+ VectorCopy(trace.plane.normal, p->vel);
+ VectorAdd(p->org, p->vel, p->org);
+ p->type = particletype + pt_raindecal;
p->texnum = tex_rainsplash[0];
p->time2 = cl.time;
p->alphafade = p->alpha / 0.4;
- VectorCopy(normal, p->vel);
- VectorAdd(p->org, normal, p->org);
p->bounce = 0;
p->friction = 0;
p->gravity = 0;
else if (p->type == particletype + pt_blood)
{
// blood - splash on solid
- if (CL_TraceLine(oldorg, p->org, v, normal, true, &hitent, SUPERCONTENTS_SOLID) < 1)
+ trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, &hitent, SUPERCONTENTS_SOLID, false);
+ if (trace.fraction < 1)
{
- VectorCopy(v, p->org);
+ // convert from a blood particle to a blood decal
+ VectorCopy(trace.endpos, p->org);
+ VectorCopy(trace.plane.normal, p->vel);
+ VectorAdd(p->org, p->vel, p->org);
#ifndef WORKINGLQUAKE
if (cl_stainmaps.integer)
- R_Stain(v, 32, 32, 16, 16, p->alpha * p->size * (1.0f / 40.0f), 192, 48, 48, p->alpha * p->size * (1.0f / 40.0f));
+ R_Stain(p->org, 32, 32, 16, 16, p->alpha * p->size * (1.0f / 40.0f), 192, 48, 48, p->alpha * p->size * (1.0f / 40.0f));
#endif
if (!cl_decals.integer)
{
}
p->type = particletype + pt_decal;
- // convert from a blood particle to a blood decal
p->texnum = tex_blooddecal[rand()&7];
#ifndef WORKINGLQUAKE
p->owner = hitent;
- p->ownermodel = hitent->model;
- Matrix4x4_Transform(&hitent->inversematrix, v, p->relativeorigin);
- Matrix4x4_Transform3x3(&hitent->inversematrix, normal, p->relativedirection);
- VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
+ p->ownermodel = cl_entities[hitent].render.model;
+ Matrix4x4_Transform(&cl_entities[hitent].render.inversematrix, p->org, p->relativeorigin);
+ Matrix4x4_Transform3x3(&cl_entities[hitent].render.inversematrix, p->vel, p->relativedirection);
#endif
p->time2 = cl.time;
p->alphafade = 0;
- VectorCopy(normal, p->vel);
- VectorAdd(p->org, normal, p->org);
p->bounce = 0;
p->friction = 0;
p->gravity = 0;
}
else
{
- if (CL_TraceLine(oldorg, p->org, v, normal, true, &hitent, SUPERCONTENTS_SOLID) < 1)
+ trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, NULL, SUPERCONTENTS_SOLID, false);
+ if (trace.fraction < 1)
{
- VectorCopy(v, p->org);
+ VectorCopy(trace.endpos, p->org);
if (p->bounce < 0)
{
p->type = NULL;
}
else
{
- dist = DotProduct(p->vel, normal) * -p->bounce;
- VectorMA(p->vel, dist, normal, p->vel);
+ dist = DotProduct(p->vel, trace.plane.normal) * -p->bounce;
+ VectorMA(p->vel, dist, trace.plane.normal, p->vel);
if (DotProduct(p->vel, p->vel) < 0.03)
VectorClear(p->vel);
}
{
// snow flutter
p->time2 = cl.time + (rand() & 3) * 0.1;
- p->vel[0] += lhrandom(-32, 32);
- p->vel[1] += lhrandom(-32, 32);
- p->vel[2] += lhrandom(-32, 32);
+ p->vel[0] = p->relativedirection[0] + lhrandom(-32, 32);
+ p->vel[1] = p->relativedirection[1] + lhrandom(-32, 32);
+ //p->vel[2] = p->relativedirection[2] + lhrandom(-32, 32);
}
#ifdef WORKINGLQUAKE
a = CL_PointQ1Contents(p->org);
#endif
p->type = NULL;
break;
- case pt_grow:
- p->size += frametime * 15;
+ case pt_smoke:
+ //p->size += frametime * 15;
break;
case pt_decal:
// FIXME: this has fairly wacky handling of alpha
p->alphafade = cl.time > (p->time2 + cl_decals_time.value) ? (255 / cl_decals_fadetime.value) : 0;
#ifndef WORKINGLQUAKE
- if (p->owner->model == p->ownermodel)
+ if (cl_entities[p->owner].render.model == p->ownermodel)
{
- Matrix4x4_Transform(&p->owner->matrix, p->relativeorigin, p->org);
- Matrix4x4_Transform3x3(&p->owner->matrix, p->relativedirection, p->vel);
+ Matrix4x4_Transform(&cl_entities[p->owner].render.matrix, p->relativeorigin, p->org);
+ Matrix4x4_Transform3x3(&cl_entities[p->owner].render.matrix, p->relativedirection, p->vel);
}
else
p->type = NULL;
#define MAX_PARTICLETEXTURES 64
// particletexture_t is a rectangle in the particlefonttexture
-typedef struct
+typedef struct particletexture_s
{
rtexture_t *texture;
float s1, t1, s2, t2;
#define PARTICLETEXTURESIZE 64
#define PARTICLEFONTSIZE (PARTICLETEXTURESIZE*8)
-static qbyte shadebubble(float dx, float dy, vec3_t light)
+static unsigned char shadebubble(float dx, float dy, vec3_t light)
{
float dz, f, dot;
vec3_t normal;
f *= 128;
f += 16; // just to give it a haze so you can see the outline
f = bound(0, f, 255);
- return (qbyte) f;
+ return (unsigned char) f;
}
else
return 0;
}
-static void setuptex(int texnum, qbyte *data, qbyte *particletexturedata)
+static void setuptex(int texnum, unsigned char *data, unsigned char *particletexturedata)
{
int basex, basey, y;
basex = ((texnum >> 0) & 7) * PARTICLETEXTURESIZE;
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)
+void particletextureblotch(unsigned char *data, float radius, float red, float green, float blue, float alpha)
{
int x, y;
float cx, cy, dx, dy, f, iradius;
- qbyte *d;
+ unsigned char *d;
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;
}
}
-void particletextureclamp(qbyte *data, int minr, int ming, int minb, int maxr, int maxg, int maxb)
+void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int maxr, int maxg, int maxb)
{
int i;
for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
}
}
-void particletextureinvert(qbyte *data)
+void particletextureinvert(unsigned char *data)
{
int i;
for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
}
// Those loops are in a separate function to work around an optimization bug in Mac OS X's GCC
-static void R_InitBloodTextures (qbyte *particletexturedata)
+static void R_InitBloodTextures (unsigned char *particletexturedata)
{
int i, j, k, m;
- qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4];
+ unsigned char data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4];
// blood particles
for (i = 0;i < 8;i++)
{
int x, y, d, i, k, m;
float dx, dy, radius, f, f2;
- qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4], noise3[64][64], data2[64][16][4];
+ unsigned char data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4], noise3[64][64], data2[64][16][4];
vec3_t light;
- qbyte *particletexturedata;
+ unsigned char *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...
- particletexturedata = Mem_Alloc(tempmempool, PARTICLEFONTSIZE*PARTICLEFONTSIZE*4);
+ particletexturedata = (unsigned char *)Mem_Alloc(tempmempool, PARTICLEFONTSIZE*PARTICLEFONTSIZE*4);
memset(particletexturedata, 255, PARTICLEFONTSIZE*PARTICLEFONTSIZE*4);
// smoke
memset(&data[0][0][0], 255, sizeof(data));
do
{
- qbyte noise1[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise2[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2];
+ unsigned char noise1[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise2[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2];
fractalnoise(&noise1[0][0], PARTICLETEXTURESIZE*2, PARTICLETEXTURESIZE/8);
fractalnoise(&noise2[0][0], PARTICLETEXTURESIZE*2, PARTICLETEXTURESIZE/4);
d = d * (1-(dx*dx+dy*dy));
d = (d * noise1[y][x]) >> 7;
d = bound(0, d, 255);
- data[y][x][3] = (qbyte) d;
+ data[y][x][3] = (unsigned char) d;
if (m < d)
m = d;
}
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;
+ data[y][x][3] = (unsigned char) d;
}
}
setuptex(tex_particle, &data[0][0][0], particletexturedata);
{
dx = (x - 0.5f*16) / (16*0.5f-2);
d = (1 - sqrt(fabs(dx))) * noise3[y][x];
- data2[y][x][0] = data2[y][x][1] = data2[y][x][2] = (qbyte) bound(0, d, 255);
+ data2[y][x][0] = data2[y][x][1] = data2[y][x][2] = (unsigned char) bound(0, d, 255);
data2[y][x][3] = 255;
}
}
#else
void R_DrawParticleCallback(const void *calldata1, int calldata2)
{
- const particle_t *p = calldata1;
+ const particle_t *p = (particle_t *)calldata1;
rmeshstate_t m;
#endif
pblend_t blendmode;
- float org[3], up2[3], v[3], right[3], up[3], fog, ifog, fogvec[3], cr, cg, cb, ca, size;
+ float org[3], up2[3], v[3], right[3], up[3], fog, ifog, cr, cg, cb, ca, size;
particletexture_t *tex;
VectorCopy(p->org, org);
ca = 1;
}
#ifndef WORKINGLQUAKE
+ if (p->type->lighting)
+ {
+ float ambient[3], diffuse[3], diffusenormal[3];
+ R_CompleteLightPoint(ambient, diffuse, diffusenormal, org, true);
+ cr *= (ambient[0] + 0.5 * diffuse[0]);
+ cg *= (ambient[1] + 0.5 * diffuse[1]);
+ cb *= (ambient[2] + 0.5 * diffuse[2]);
+ }
if (fogenabled)
{
- VectorSubtract(org, r_vieworigin, fogvec);
- fog = exp(fogdensity/DotProduct(fogvec,fogvec));
+ fog = VERTEXFOGTABLE(VectorDistance(org, r_vieworigin));
ifog = 1 - fog;
cr = cr * ifog;
cg = cg * ifog;
cb = cb * ifog;
- if (blendmode == PBLEND_ADD)
+ if (blendmode == PBLEND_ALPHA)
{
cr += fogcolor[0] * fog;
cg += fogcolor[1] * fog;
{
R_CalcBeam_Vertex3f(particle_vertex3f, p->org, p->vel, size);
VectorSubtract(p->vel, p->org, up);
- VectorNormalizeFast(up);
+ VectorNormalize(up);
v[0] = DotProduct(p->org, up) * (1.0f / 64.0f);
v[1] = DotProduct(p->vel, up) * (1.0f / 64.0f);
particle_texcoord2f[0] = 1;particle_texcoord2f[1] = v[0];
particle_texcoord2f[6] = 1;particle_texcoord2f[7] = v[1];
}
else
- Host_Error("R_DrawParticles: unknown particle orientation %i\n", p->type->orientation);
+ {
+ Con_Printf("R_DrawParticles: unknown particle orientation %i\n", p->type->orientation);
+ return;
+ }
#if WORKINGLQUAKE
if (blendmode == PBLEND_ALPHA)
{
if (p->type)
{
- c_particles++;
+ renderstats.particles++;
if (DotProduct(p->org, r_viewforward) >= minparticledist || p->type->orientation == PARTICLE_BEAM)
{
if (p->type == particletype + pt_decal)