void CL_DrawParticles( void ) { particle_t *p, *kill; float frametime; static int framecount = -1; if( !cl_draw_particles->integer ) return; // HACKHACK: don't evaluate particles when executes many times at same frame // e.g. mirror rendering if( framecount != tr.realframecount ) { frametime = cl.time - cl.oldtime; framecount = tr.realframecount; } else frametime = 0.0f; if( tracerred->modified || tracergreen->modified || tracerblue->modified ) { gTracerColors[4][0] = (byte)(tracerred->value * 255); gTracerColors[4][1] = (byte)(tracergreen->value * 255); gTracerColors[4][2] = (byte)(tracerblue->value * 255); tracerred->modified = tracergreen->modified = tracerblue->modified = false; } while( 1 ) { // free time-expired particles kill = cl_active_particles; if( kill && kill->die < cl.time ) { cl_active_particles = kill->next; CL_FreeParticle( kill ); continue; } break; } for( p = cl_active_particles; p; p = p->next ) { while( 1 ) { kill = p->next; if( kill && kill->die < cl.time ) { p->next = kill->next; CL_FreeParticle( kill ); continue; } break; } CL_UpdateParticle( p, frametime ); } }
/* =============== CL_AddParticles =============== */ void CL_AddParticles (void) { cparticle_t *p, *next; float alpha; float time, time2; vec3_t org; int color; cparticle_t *active, *tail; int contents; float grav; active = NULL; tail = NULL; if (!cl_drawParticles->integer) return; // allow gravity tweaks by the server grav = Cvar_VariableValue("sv_gravity"); if (!grav) grav = 1; else grav /= 800; for (p = active_particles; p; p = next) { next = p->next; // set alpha // PMM - added INSTANT_PARTICLE handling if (p->alphavel != INSTANT_PARTICLE) { time = (cl.time - p->time) * 0.001; alpha = p->alpha + time * p->alphavel; if (alpha <= 0) { // faded out CL_FreeParticle (p); continue; } else if (alpha <= 0.3f && p->color == 240) // this is HACK central... { // do blood decals if (rand() & 4) { trace_t tr; time2 = time * time; org[0] = p->org[0] + p->vel[0] * time + p->accel[0] * time2; org[1] = p->org[1] + p->vel[1] * time + p->accel[1] * time2; org[2] = p->org[2] + p->vel[2] * time + p->accel[2] * time2; tr = CL_Trace(p->org, org, 0, MASK_SOLID); if (tr.fraction != 1.0f) { if (!VectorCompare(tr.plane.normal, vec3_origin) && !(CM_PointContents(p->org, 0) & MASK_WATER)) // no blood splatters underwater... { vec4_t color; Vector4Set(color, 1.0, 0.0, 0.0, 1.0f); RE_AddDecal(tr.endpos, tr.plane.normal, color, 16 + ((rand() % 21 * 0.05f) - 0.5f), DECAL_BLOOD + (rand() & 4), 0, frand() * 360); } } } } } else { alpha = p->alpha; } if (alpha > 1.0) alpha = 1; // set color color = p->color; // backup old position VectorCopy (p->org, p->oldOrg); // calculate new position time2 = time * time; org[0] = p->org[0] + p->vel[0] * time + p->accel[0] * time2; org[1] = p->org[1] + p->vel[1] * time + p->accel[1] * time2; org[2] = p->org[2] + p->vel[2] * time + p->accel[2] * time2; // gravity modulation //if (!p->ignoreGrav) // org[2] += time2 * -PARTICLE_GRAVITY; // collision test if (cl_particleCollision->integer) { if (p->bounceFactor) { trace_t trace; vec3_t vel; int hitTime; float time; trace = CL_Trace(p->oldOrg, org, 0, CONTENTS_SOLID); if (trace.fraction > 0 && trace.fraction < 1) { // reflect the velocity on the trace plane hitTime = cl.time - cls.rframetime + cls.rframetime * trace.fraction; time = ((float)hitTime - p->time) * 0.001; Vector3Set (vel, p->vel[0], p->vel[1], p->vel[2] + p->accel[2] * time * grav); VectorReflect (vel, trace.plane.normal, p->vel); VectorScale (p->vel, p->bounceFactor, p->vel); // check for stop, making sure that even on low FPS systems it doesn't bobble if (trace.allsolid || (trace.plane.normal[2] > 0 && (p->vel[2] < 40 || p->vel[2] < -cls.rframetime * p->vel[2]))) { VectorClear(p->vel); VectorClear(p->accel); p->bounceFactor = 0.0f; } VectorCopy (trace.endpos, org); // reset particle p->time = cl.time; VectorCopy (org, p->org); } } } // kill all particles in solid contents = CM_PointContents (org, 0); if (contents & MASK_SOLID) { CL_FreeParticle (p); continue; } // have this always below CL_FreeParticle(p); ! p->next = NULL; if (!tail) { active = tail = p; } else { tail->next = p; tail = p; } // add to scene V_AddParticle (org, color, alpha); // PMM if (p->alphavel == INSTANT_PARTICLE) { p->alphavel = 0.0; p->alpha = 0.0; } } active_particles = active; }