X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cl_particles.c;h=2e5d5259c6cdd0160499f71b9301243440d5994d;hp=543d41476c11d8601e9a58424808e0074641ce5b;hb=929495474f9cc099a83a4a884d85272791c5e7c3;hpb=ffa890cabf7fd917a496ba17b548c628f27d4d4c diff --git a/cl_particles.c b/cl_particles.c index 543d4147..2e5d5259 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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; #define cl_stainmaps.integer 0 @@ -46,16 +45,16 @@ void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width) 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]; @@ -145,14 +144,14 @@ void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up) 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; @@ -167,9 +166,7 @@ float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int #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" @@ -200,30 +197,31 @@ typedef struct particletype_s { 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 @@ -240,12 +238,10 @@ typedef struct particle_s 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 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; @@ -324,10 +320,6 @@ cvar_t cl_decals = {CVAR_SAVE, "cl_decals", "0"}; 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; @@ -383,8 +375,7 @@ void CL_Particles_Init (void) #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(); } @@ -393,8 +384,6 @@ void CL_Particles_Shutdown (void) { #ifdef WORKINGLQUAKE // No clue what to do here... -#else - Mem_FreePool (&cl_part_mempool); #endif } @@ -459,7 +448,7 @@ particle_t *particle(particletype_t *ptype, int pcolor1, int pcolor2, int ptex, 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) @@ -470,9 +459,9 @@ void CL_SpawnDecalParticleForSurface(void *hitent, const vec3_t org, const vec3_ 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 } @@ -482,24 +471,21 @@ void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, { 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) @@ -665,6 +651,7 @@ CL_ParticleExplosion void CL_ParticleExplosion (vec3_t org) { int i; + trace_t trace; //vec3_t v; //vec3_t v2; if (cl_stainmaps.integer) @@ -698,13 +685,14 @@ void CL_ParticleExplosion (vec3_t org) 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); } } @@ -806,8 +794,9 @@ void CL_SparkShower (vec3_t org, vec3_t dir, int count, vec_t gravityscale) 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; @@ -820,8 +809,8 @@ void CL_Smoke (vec3_t org, vec3_t dir, int count) 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); } } } @@ -844,7 +833,8 @@ static float bloodcount = 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; @@ -859,8 +849,8 @@ void CL_BloodPuff (vec3_t org, vec3_t vel, int count) 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; } } @@ -915,6 +905,7 @@ void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int color { 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;} @@ -950,9 +941,11 @@ void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int color { 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: @@ -983,7 +976,7 @@ void CL_Stardust (vec3_t mins, vec3_t maxs, int count) 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); @@ -1147,7 +1140,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *en 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) @@ -1158,7 +1151,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *en // 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; @@ -1244,7 +1237,7 @@ void CL_Tei_Smoke(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) * 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) @@ -1259,7 +1252,7 @@ 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) @@ -1276,12 +1269,9 @@ void CL_MoveParticles (void) { 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) @@ -1326,17 +1316,17 @@ void CL_MoveParticles (void) 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; @@ -1346,12 +1336,16 @@ void CL_MoveParticles (void) 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) { @@ -1360,19 +1354,15 @@ void CL_MoveParticles (void) } 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; @@ -1381,9 +1371,10 @@ void CL_MoveParticles (void) } 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; @@ -1391,8 +1382,8 @@ void CL_MoveParticles (void) } 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); } @@ -1475,9 +1466,9 @@ void CL_MoveParticles (void) { // 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); @@ -1488,17 +1479,17 @@ void CL_MoveParticles (void) #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) ? (p->alpha / cl_decals_fadetime.value) : 0; + 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; @@ -1637,11 +1628,43 @@ void particletextureinvert(qbyte *data) } } +// 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) +{ + int i, j, k, m; + qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4]; + + // blood particles + 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], 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); + } + + // blood decals + for (i = 0;i < 8;i++) + { + memset(&data[0][0][0], 255, sizeof(data)); + 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); + } + +} + static void R_InitParticleTexture (void) { - int x, y, d, i, j, k, m; + int x, y, d, i, k, m; float dx, dy, radius, f, f2; - qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4], noise1[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise2[PARTICLETEXTURESIZE*2][PARTICLETEXTURESIZE*2], noise3[64][64], data2[64][16][4]; + qbyte data[PARTICLETEXTURESIZE][PARTICLETEXTURESIZE][4], noise3[64][64], data2[64][16][4]; vec3_t light; qbyte *particletexturedata; @@ -1663,6 +1686,8 @@ static void R_InitParticleTexture (void) memset(&data[0][0][0], 255, sizeof(data)); do { + qbyte 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); m = 0; @@ -1759,29 +1784,8 @@ static void R_InitParticleTexture (void) } setuptex(tex_bubble, &data[0][0][0], particletexturedata); - // blood particles - 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], 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); - } - - // blood decals - for (i = 0;i < 8;i++) - { - memset(&data[0][0][0], 255, sizeof(data)); - 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); - } + // Blood particles and blood decals + R_InitBloodTextures (particletexturedata); // bullet decals for (i = 0;i < 8;i++) @@ -1911,7 +1915,15 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) ca = 1; } #ifndef WORKINGLQUAKE - else if (fogenabled) + 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)); @@ -1919,7 +1931,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) 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; @@ -1998,7 +2010,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) { 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]; @@ -2024,7 +2036,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2) glTexCoord2f(particle_texcoord2f[6], particle_texcoord2f[7]);glVertex3f(particle_vertex3f[ 9], particle_vertex3f[10], particle_vertex3f[11]); glEnd(); #else - R_Mesh_Draw(4, 2, polygonelements); + R_Mesh_Draw(0, 4, 2, polygonelements); #endif }