new trailstate system

te_lightning? and similar, and trail emit is no longer fps dependent
timelimit particle field added
te_*_end is still frame dependent and needs a resonable fix


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1062 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
TimeServ 2005-05-30 04:34:47 +00:00
parent 181a88c471
commit 86f3912654
7 changed files with 250 additions and 71 deletions

View file

@ -1568,15 +1568,7 @@ void CL_LinkPacketEntities (void)
}
if (i == cl_oldnumvisedicts)
{
trailstate_t *t;
t = &cl.lerpents[s1->number].trailstate;
t->lastdist = 0;
if (t->lastbeam)
{
t->lastbeam->flags &= ~BS_LASTSEG;
t->lastbeam->flags |= BS_NODRAW;
}
t->lastbeam = NULL;
P_DelinkTrailstate(&(cl.lerpents[s1->number].trailstate));
continue; // not in last message
}

View file

@ -123,6 +123,7 @@ typedef struct
float alpha;
vec3_t start, end;
int particleeffect;
trailstate_t *trailstate;
} beam_t;
beam_t cl_beams[MAX_BEAMS];
@ -1978,8 +1979,15 @@ void CL_UpdateBeams (void)
// update lightning
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
{
if (!b->model || b->endtime < cl.time)
if (!b->model)
continue;
if (b->endtime < cl.time)
{
P_DelinkTrailstate(&b->trailstate);
b->model = NULL;
continue;
}
// if coming from the player, update the start position
if (b->flags & 1 && b->entity == (autocam[0]?spec_track[0]:(cl.playernum[0]+1))) // entity 0 is the world
@ -2059,7 +2067,7 @@ void CL_UpdateBeams (void)
// if (part_type[rt_lightning1].loaded)
// if (!P_ParticleTrail(b->start, b->end, rt_lightning1, NULL))
// continue;
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, NULL))
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, &b->trailstate))
continue;
// add new entities for the lightning

View file

@ -389,7 +389,7 @@ typedef struct {
float lerprate; //inverse rate...
vec3_t origin;
vec3_t angles;
trailstate_t trailstate; //when to next throw out a trail
trailstate_t *trailstate; //when to next throw out a trail
unsigned short frame;
unsigned short tagent;
unsigned short tagindex;

View file

@ -86,7 +86,7 @@ typedef struct q2centity_s
int serverframe; // if not current, this ent isn't in the frame
trailstate_t trailstate;
trailstate_t *trailstate;
// float trailcount; // for diminishing grenade trails
vec3_t lerp_origin; // for trails (variable hz)
@ -823,7 +823,9 @@ void CLQ2_DeltaEntity (q2frame_t *frame, int newnum, entity_state_t *old, int bi
if (ent->serverframe != cl.q2frame.serverframe - 1)
{ // wasn't in last update, so initialize some things
ent->trailstate.lastdist = 0; // for diminishing rocket / grenade trails
// clear trailstate
P_DelinkTrailstate(&ent->trailstate);
// duplicate the current state so lerping doesn't hurt anything
ent->prev = *state;
if (state->event == Q2EV_OTHER_TELEPORT)

View file

@ -87,10 +87,11 @@ void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest);
void P_ReadPointFile_f (void);
#define MAX_BEAMS 2048 // default max # of beam segments
#define MAX_BEAMSEGS 2048 // default max # of beam segments
#define MAX_PARTICLES 32768 // default max # of particles at one
// time
#define MAX_DECALS 4096 // this is going to be expensive
#define MAX_TRAILSTATES 512 // default max # of trailstates
//int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
//int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
@ -108,6 +109,10 @@ clippeddecal_t *free_decals;
clippeddecal_t *decals;
int r_numdecals;
trailstate_t *trailstates;
int ts_cycle; // current cyclic index of trailstates
int r_numtrailstates;
vec3_t r_pright, r_pup, r_ppn;
extern cvar_t r_bouncysparks;
@ -163,6 +168,9 @@ typedef struct part_type_s {
float offsetspreadvert;
float randomvelvert;
float randscale;
float timelimit;
enum {PT_NORMAL, PT_BEAM, PT_DECAL} type;
enum {BM_MERGE, BM_ADD, BM_SUBTRACT} blendmode;
@ -661,6 +669,8 @@ void P_ParticleEffect_f(void)
Con_DPrintf("isbeam is deprechiated, use type beam\n");
ptype->type = PT_BEAM;
}
else if (!strcmp(var, "timelimit"))
ptype->timelimit = atof(value);
else if (!strcmp(var, "cliptype"))
{
assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types
@ -1086,18 +1096,24 @@ void P_InitParticles (void)
r_numparticles = MAX_PARTICLES;
}
r_numbeams = MAX_BEAMS;
r_numbeams = MAX_BEAMSEGS;
r_numdecals = MAX_DECALS;
r_numtrailstates = MAX_TRAILSTATES;
particles = (particle_t *)
Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
beams = (beamseg_t *)
Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beams");
Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beamsegs");
decals = (clippeddecal_t *)
Hunk_AllocName (r_numdecals * sizeof(clippeddecal_t), "decals");
trailstates = (trailstate_t *)
Hunk_AllocName (r_numtrailstates * sizeof(trailstate_t), "trailstates");
ts_cycle = 0;
Cmd_AddCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :)
@ -1898,6 +1914,8 @@ int P_RunParticleEffectType (vec3_t org, vec3_t dir, float count, int typenum)
p->alpha = ptype->alpha;
p->color = 0;
p->nextemit = particletime + ptype->emitstart - p->die;
if (ptype->emittime < 0)
p->trailstate = NULL;
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
@ -2296,15 +2314,81 @@ void CLQ2_RailTrail (vec3_t start, vec3_t end)
P_ParticleTrail(start, end, rt_railtrail, NULL);
}
int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
// Trailstate functions
void P_CleanTrailstate(trailstate_t *ts)
{
vec3_t vec, right, up, start;
// clear LASTSEG flag from lastbeam so it can be reused
if (ts->lastbeam)
{
ts->lastbeam->flags &= ~BS_LASTSEG;
ts->lastbeam->flags |= BS_NODRAW;
}
// clean structure
memset(ts, 0, sizeof(trailstate_t));
}
void P_DelinkTrailstate(trailstate_t **tsk)
{
trailstate_t *ts;
trailstate_t *assoc;
if (*tsk == NULL)
return; // not linked to a trailstate
ts = *tsk;
if (ts->key != tsk)
return; // prevent overwrite
assoc = ts->assoc; // store assoc
P_CleanTrailstate(ts); // clean directly linked trailstate
// clean trailstates assoc linked
while (assoc)
{
ts = assoc->assoc;
P_CleanTrailstate(assoc);
assoc = ts;
}
*tsk = NULL; // erase pointer
}
trailstate_t *P_NewTrailstate(trailstate_t **key)
{
trailstate_t *ts;
// bounds check here in case r_numtrailstates changed
if (ts_cycle >= r_numtrailstates)
ts_cycle = 0;
// get trailstate
ts = trailstates + ts_cycle;
// clear trailstate
P_CleanTrailstate(ts);
// set key
ts->key = key;
// advance index cycle
ts_cycle++;
// return clean trailstate
return ts;
}
int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk)
{
vec3_t vec, vstep, right, up, start;
float len;
int tcount;
particle_t *p;
part_type_t *ptype = &part_type[type];
beamseg_t *b;
beamseg_t *bfirst;
trailstate_t *ts;
float veladd = -ptype->veladd;
float randvel = ptype->randomvel;
@ -2316,21 +2400,51 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
return 1;
VectorCopy(startpos, start);
if (ptype->assoc>=0)
// trailstate allocation/deallocation
if (tsk)
{
VectorCopy(start, vec);
if (ts)
// if *tsk = NULL get a new one
if (*tsk == NULL)
{
trailstate_t nts;
memcpy(&nts, ts, sizeof(nts));
P_ParticleTrail(vec, end, ptype->assoc, &nts);
ts = P_NewTrailstate(tsk);
*tsk = ts;
}
else
P_ParticleTrail(vec, end, ptype->assoc, NULL);
}
else if (!ptype->die)
{
ts = *tsk;
if (ts->key != tsk) // trailstate was overwritten
{
ts = P_NewTrailstate(tsk); // so get a new one
*tsk = ts;
}
}
}
else
ts = NULL;
if (ptype->assoc>=0)
{
if (ts)
P_ParticleTrail(start, end, ptype->assoc, &(ts->assoc));
else
P_ParticleTrail(start, end, ptype->assoc, NULL);
}
// time limit for trails
if (ptype->timelimit && ts)
{
if (ts->statetime > particletime)
return 0; // timelimit still in effect
ts->statetime = particletime + ptype->timelimit; // record old time
ts = NULL; // clear trailstate so we don't save length/lastseg
}
if (!ptype->die)
ts = NULL;
step = 1/ptype->count;
if (step < 0.01)
@ -2338,6 +2452,7 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
VectorSubtract (end, start, vec);
len = VectorNormalize (vec);
VectorScale(vec, step, vstep);
// add offset
start[2] += ptype->offsetup;
@ -2351,16 +2466,11 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
tdegree = 2*M_PI/ptype->spawnparam1; /* distance per rotation inversed */
}
// store last stop here for lack of a better solution besides vectors
if (ts)
{
stop = ts->lastdist + len; //when to stop
ts->laststop = stop = ts->laststop + len; //when to stop
len = ts->lastdist;
if (!len)
{
len = particletime;
stop += len;
}
}
else
{
@ -2456,6 +2566,8 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
VectorCopy (vec3_origin, p->vel);
p->nextemit = particletime + ptype->emitstart - p->die;
if (ptype->emittime < 0)
p->trailstate = NULL; // init trailstate
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
@ -2520,7 +2632,7 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
break;
}
VectorMA (start, step, vec, start);
VectorAdd (start, vstep, start);
p->die = particletime + ptype->die - p->die;
}
@ -3392,6 +3504,22 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
if (type->type == PT_NORMAL)
RQ_AddDistReorder(pdraw, p, type, p->org);
// make sure emitter runs at least once
if (type->emit >= 0 && type->emitstart <= 0)
P_RunParticleEffectType(p->org, p->vel, 1, type->emit);
// make sure stain effect runs
if (type->stains && r_bloodstains.value)
{
if (traces-->0&&tr(oldorg, p->org, stop, normal))
{
R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10),
(p->rgb[0]*-10+p->rgb[2]*-10),
(p->rgb[0]*-10+p->rgb[1]*-10),
30*p->alpha*type->stains);
}
}
type->particles = p->next;
// p->next = free_particles;
// free_particles = p;
@ -3452,36 +3580,15 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
}
//kill off early ones.
for ( ;; )
if (type->emittime < 0)
{
kill = type->particles;
if (kill && kill->die < particletime)
for ( ;; )
{
type->particles = kill->next;
// kill->next = free_particles;
// free_particles = kill;
kill->next = kill_list;
kill_list = kill;
if (!kill_first)
kill_first = kill;
continue;
}
break;
}
grav = type->gravity*pframetime;
VectorScale(type->friction, pframetime, friction);
for (p=type->particles ; p ; p=p->next)
{
for ( ;; )
{
kill = p->next;
kill = type->particles;
if (kill && kill->die < particletime)
{
p->next = kill->next;
// kill->next = free_particles;
// free_particles = kill;
P_DelinkTrailstate(&kill->trailstate);
type->particles = kill->next;
kill->next = kill_list;
kill_list = kill;
if (!kill_first)
@ -3490,6 +3597,66 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
}
break;
}
}
else
{
for ( ;; )
{
kill = type->particles;
if (kill && kill->die < particletime)
{
type->particles = kill->next;
kill->next = kill_list;
kill_list = kill;
if (!kill_first)
kill_first = kill;
continue;
}
break;
}
}
grav = type->gravity*pframetime;
VectorScale(type->friction, pframetime, friction);
for (p=type->particles ; p ; p=p->next)
{
if (type->emittime < 0)
{
for ( ;; )
{
kill = p->next;
if (kill && kill->die < particletime)
{
P_DelinkTrailstate(&kill->trailstate);
p->next = kill->next;
kill->next = kill_list;
kill_list = kill;
if (!kill_first)
kill_first = kill;
continue;
}
break;
}
}
else
{
for ( ;; )
{
kill = p->next;
if (kill && kill->die < particletime)
{
p->next = kill->next;
kill->next = kill_list;
kill_list = kill;
if (!kill_first)
kill_first = kill;
continue;
}
break;
}
}
VectorCopy(p->org, oldorg);
if (type->flags & PT_VELOCITY)
{
@ -3535,7 +3702,7 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
if (type->emit >= 0)
{
if (type->emittime < 0)
P_ParticleTrail(oldorg, p->org, type->emit, NULL);
P_ParticleTrail(oldorg, p->org, type->emit, &p->trailstate);
else if (p->nextemit < particletime)
{
p->nextemit = particletime + type->emittime + frandom()*type->emitrand;

View file

@ -279,7 +279,6 @@ void CLQ2_BfgParticles(entity_t *ent);
struct q2centity_s;
void CLQ2_FlyEffect(struct q2centity_s *ent, vec3_t org);
void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects);
void CLQ2_BlasterTrail(vec3_t oldorg, vec3_t neworg);
void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg);
void WritePCXfile (char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.

View file

@ -59,6 +59,19 @@ extern int rt_rocket_trail,
rt_bubbletrail;
*/
struct beamseg_s;
typedef struct trailstate_s {
struct trailstate_s **key; // key to check if ts has been overwriten
struct trailstate_s *assoc; // assoc linked trail
struct beamseg_s *lastbeam; // last beam pointer (flagged with BS_LASTSEG)
union {
float lastdist; // last distance used with particle effect
float statetime; // time to emit effect again
};
float laststop; // last stopping point for particle effect
} trailstate_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
@ -74,8 +87,10 @@ typedef struct particle_s
vec3_t vel; //renderer uses for sparks
float angle;
float nextemit;
union {
float nextemit;
trailstate_t *trailstate;
};
// drivers never touch the following fields
float rotationspeed;
} particle_t;
@ -146,12 +161,8 @@ void P_BlobExplosion (vec3_t org); //tarbaby explosion or TF emp.
void P_ParticleExplosion (vec3_t org); //rocket explosion (sprite is allocated seperatly :( )
void P_LavaSplash (vec3_t org); //cthon dying, or a gas grenade.
typedef struct {
float lastdist;
struct beamseg_s *lastbeam; // last beam point
} trailstate_t;
//the core spawn function for trails. (trailstate can be null)
int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t *trailstate);
int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t **trailstate);
void P_DefaultTrail (struct model_s *model); //fills in the default particle properties for a loaded model. Should already have the model flags set.