From 31a215ac503e8181d0ae2b95e0b70f912aa035dc Mon Sep 17 00:00:00 2001 From: /dev/humancontroller Date: Sun, 13 Jul 2014 16:10:27 +0200 Subject: allow particles of child particle systems to be launched with (dynamic) normals new particle script constructs (in particle blocks): {velocityType | accelerationType} {last_normal | opportunistic_normal} the base vector in case of opportunistic_normal is (0,0,0) if the particle is flying, and is a surface normal vector if the particle is in/on a map surface. the base vector in case of last_normal is always a valid direction, though sometimes an arbitrary one (the up direction). in both cases, the initial value of the last/opportunistic normal vector is propagated from the parent particle. the last/opportunistic vector is a new particle system variable, and the original normal vector is not touched, so this change retains backward-compatibility. --- src/cgame/cg_local.h | 10 +++++- src/cgame/cg_particles.c | 80 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 5 deletions(-) (limited to 'src/cgame') diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 53841e45..54477662 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -203,7 +203,9 @@ typedef enum PMT_STATIC_TRANSFORM, PMT_TAG, PMT_CENT_ANGLES, - PMT_NORMAL + PMT_NORMAL, + PMT_LAST_NORMAL, + PMT_OPPORTUNISTIC_NORMAL } pMoveType_t; typedef enum @@ -357,6 +359,9 @@ typedef struct particleSystem_s //for PMT_NORMAL qboolean normalValid; vec3_t normal; + //for PMT_LAST_NORMAL and PMT_OPPORTUNISTIC_NORMAL + qboolean lastNormalIsCurrent; + vec3_t lastNormal; int charge; } particleSystem_t; @@ -384,6 +389,8 @@ typedef struct particle_s baseParticle_t *class; particleEjector_t *parent; + particleSystem_t *childParticleSystem; + int birthTime; int lifeTime; @@ -1814,6 +1821,7 @@ qboolean CG_IsParticleSystemInfinite( particleSystem_t *ps ); qboolean CG_IsParticleSystemValid( particleSystem_t **ps ); void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal ); +void CG_SetParticleSystemLastNormal( particleSystem_t *ps, const float *normal ); void CG_AddParticles( void ); diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c index 0c60ed4c..f3a63efd 100644 --- a/src/cgame/cg_particles.c +++ b/src/cgame/cg_particles.c @@ -261,6 +261,21 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p VectorNormalize( p->velocity ); VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin ); break; + + case PMT_LAST_NORMAL: + VectorCopy( ps->lastNormal, p->velocity ); + VectorNormalize( p->velocity ); + VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin ); + break; + + case PMT_OPPORTUNISTIC_NORMAL: + if( ps->lastNormalIsCurrent ) + { + VectorCopy( ps->lastNormal, p->velocity ); + VectorNormalize( p->velocity ); + VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin ); + } + break; } VectorNormalize( p->velocity ); @@ -283,12 +298,18 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p //this particle has a child particle system attached if( bp->childSystemName[ 0 ] != '\0' ) { - particleSystem_t *ps = CG_SpawnNewParticleSystem( bp->childSystemHandle ); + particleSystem_t *chps = CG_SpawnNewParticleSystem( bp->childSystemHandle ); - if( CG_IsParticleSystemValid( &ps ) ) + if( CG_IsParticleSystemValid( &chps ) ) { - CG_SetAttachmentParticle( &ps->attachment, p ); - CG_AttachToParticle( &ps->attachment ); + CG_SetAttachmentParticle( &chps->attachment, p ); + CG_AttachToParticle( &chps->attachment ); + p->childParticleSystem = chps; + + if( ps->lastNormalIsCurrent ) + CG_SetParticleSystemLastNormal( chps, ps->lastNormal ); + else + VectorCopy( ps->lastNormal, chps->lastNormal ); } } @@ -467,6 +488,9 @@ particleSystem_t *CG_SpawnNewParticleSystem( qhandle_t psHandle ) ps->valid = qtrue; ps->lazyRemove = qfalse; + // use "up" as an arbitrary (non-null) "last" normal + VectorSet( ps->lastNormal, 0, 0, 1 ); + for( j = 0; j < bps->numEjectors; j++ ) CG_SpawnNewParticleEjector( bps->ejectors[ j ], ps ); @@ -675,6 +699,10 @@ static qboolean CG_ParseType( pMoveType_t *pmt, char **text_p ) *pmt = PMT_CENT_ANGLES; else if( !Q_stricmp( token, "normal" ) ) *pmt = PMT_NORMAL; + else if( !Q_stricmp( token, "last_normal" ) ) + *pmt = PMT_LAST_NORMAL; + else if( !Q_stricmp( token, "opportunistic_normal" ) ) + *pmt = PMT_OPPORTUNISTIC_NORMAL; return qtrue; } @@ -1676,6 +1704,31 @@ void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal ) ps->normalValid = qtrue; VectorCopy( normal, ps->normal ); VectorNormalize( ps->normal ); + + CG_SetParticleSystemLastNormal( ps, normal ); +} + +/* +=============== +CG_SetParticleSystemLastNormal +=============== +*/ +void CG_SetParticleSystemLastNormal( particleSystem_t *ps, const float *normal ) +{ + if( ps == NULL || !ps->valid ) + { + CG_Printf( S_COLOR_YELLOW "WARNING: tried to modify a NULL particle system\n" ); + return; + } + + if( normal ) + { + ps->lastNormalIsCurrent = qtrue; + VectorCopy( normal, ps->lastNormal ); + VectorNormalize( ps->lastNormal ); + } + else + ps->lastNormalIsCurrent = qfalse; } @@ -1922,6 +1975,17 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) VectorCopy( ps->normal, acceleration ); break; + + case PMT_LAST_NORMAL: + VectorCopy( ps->lastNormal, acceleration ); + break; + + case PMT_OPPORTUNISTIC_NORMAL: + if( ps->lastNormalIsCurrent ) + VectorCopy( ps->lastNormal, acceleration ); + else + VectorClear( acceleration ); + break; } #define MAX_ACC_RADIUS 1000.0f @@ -1989,6 +2053,8 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) if( trace.fraction == 1.0f || bounce == 0.0f ) { VectorCopy( newOrigin, p->origin ); + if( CG_IsParticleSystemValid( &p->childParticleSystem ) ) + CG_SetParticleSystemLastNormal( p->childParticleSystem, NULL ); return; } @@ -2030,6 +2096,12 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) } VectorCopy( trace.endpos, p->origin ); + + if( !trace.allsolid ) + { + if( CG_IsParticleSystemValid( &p->childParticleSystem ) ) + CG_SetParticleSystemLastNormal( p->childParticleSystem, trace.plane.normal ); + } } -- cgit