diff options
Diffstat (limited to 'mod/src/cgame/cg_trails.c')
-rw-r--r-- | mod/src/cgame/cg_trails.c | 1489 |
1 files changed, 0 insertions, 1489 deletions
diff --git a/mod/src/cgame/cg_trails.c b/mod/src/cgame/cg_trails.c deleted file mode 100644 index 3ef19f00..00000000 --- a/mod/src/cgame/cg_trails.c +++ /dev/null @@ -1,1489 +0,0 @@ -// cg_trails.c -- the trail system - -/* - * Portions Copyright (C) 2000-2001 Tim Angus - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the OSML - Open Source Modification License v1.0 as - * described in the file COPYING which is distributed with this source - * code. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "cg_local.h" - -static baseTrailSystem_t baseTrailSystems[ MAX_BASETRAIL_SYSTEMS ]; -static baseTrailBeam_t baseTrailBeams[ MAX_BASETRAIL_BEAMS ]; -static int numBaseTrailSystems = 0; -static int numBaseTrailBeams = 0; - -static trailSystem_t trailSystems[ MAX_TRAIL_SYSTEMS ]; -static trailBeam_t trailBeams[ MAX_TRAIL_BEAMS ]; - -/* -=============== -CG_CalculateBeamNodeProperties - -Fills in trailBeamNode_t.textureCoord -=============== -*/ -static void CG_CalculateBeamNodeProperties( trailBeam_t *tb ) -{ - trailBeamNode_t *i = NULL; - trailSystem_t *ts; - baseTrailBeam_t *btb; - float nodeDistances[ MAX_TRAIL_BEAM_NODES ]; - float totalDistance = 0.0f, position = 0.0f; - int j, numNodes = 0; - float TCRange, widthRange, alphaRange; - vec3_t colorRange; - float fadeAlpha = 1.0f; - - if( !tb || !tb->nodes ) - return; - - ts = tb->parent; - btb = tb->class; - - if( ts->destroyTime > 0 && btb->fadeOutTime ) - { - fadeAlpha -= ( cg.time - ts->destroyTime ) / btb->fadeOutTime; - - if( fadeAlpha < 0.0f ) - fadeAlpha = 0.0f; - } - - TCRange = tb->class->backTextureCoord - - tb->class->frontTextureCoord; - widthRange = tb->class->backWidth - - tb->class->frontWidth; - alphaRange = tb->class->backAlpha - - tb->class->frontAlpha; - VectorSubtract( tb->class->backColor, - tb->class->frontColor, colorRange ); - - for( i = tb->nodes; i && i->next; i = i->next ) - { - nodeDistances[ numNodes++ ] = - Distance( i->position, i->next->position ); - } - - for( j = 0; j < numNodes; j++ ) - totalDistance += nodeDistances[ j ]; - - for( j = 0, i = tb->nodes; i; i = i->next, j++ ) - { - if( tb->class->textureType == TBTT_STRETCH ) - { - i->textureCoord = tb->class->frontTextureCoord + - ( ( position / totalDistance ) * TCRange ); - } - else if( tb->class->textureType == TBTT_REPEAT ) - { - if( tb->class->clampToBack ) - i->textureCoord = ( totalDistance - position ) / - tb->class->repeatLength; - else - i->textureCoord = position / tb->class->repeatLength; - } - - i->halfWidth = ( tb->class->frontWidth + - ( ( position / totalDistance ) * widthRange ) ) / 2.0f; - i->alpha = (byte)( (float)0xFF * ( tb->class->frontAlpha + - ( ( position / totalDistance ) * alphaRange ) ) * fadeAlpha ); - VectorMA( tb->class->frontColor, ( position / totalDistance ), - colorRange, i->color ); - - position += nodeDistances[ j ]; - } -} - -/* -=============== -CG_LightVertex - -Lights a particular vertex -=============== -*/ -static void CG_LightVertex( vec3_t point, byte alpha, byte *rgba ) -{ - int i; - vec3_t alight, dlight, lightdir; - - trap_R_LightForPoint( point, alight, dlight, lightdir ); - for( i = 0; i <= 2; i++ ) - rgba[ i ] = (int)alight[ i ]; - - rgba[ 3 ] = alpha; -} - -/* -=============== -CG_RenderBeam - -Renders a beam -=============== -*/ -static void CG_RenderBeam( trailBeam_t *tb ) -{ - trailBeamNode_t *i = NULL; - trailBeamNode_t *prev = NULL; - trailBeamNode_t *next = NULL; - vec3_t up; - polyVert_t verts[ ( MAX_TRAIL_BEAM_NODES - 1 ) * 4 ]; - int numVerts = 0; - baseTrailBeam_t *btb; - trailSystem_t *ts; - baseTrailSystem_t *bts; - - if( !tb || !tb->nodes ) - return; - - btb = tb->class; - ts = tb->parent; - bts = ts->class; - - if( bts->thirdPersonOnly && - ( CG_AttachmentCentNum( &ts->frontAttachment ) == cg.snap->ps.clientNum || - CG_AttachmentCentNum( &ts->backAttachment ) == cg.snap->ps.clientNum ) && - !cg.renderingThirdPerson ) - return; - - CG_CalculateBeamNodeProperties( tb ); - - i = tb->nodes; - - do - { - prev = i->prev; - next = i->next; - - if( prev && next ) - { - //this node has two neighbours - GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up ); - } - else if( !prev && next ) - { - //this is the front - GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up ); - } - else if( prev && !next ) - { - //this is the back - GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up ); - } - else - break; - - if( prev ) - { - VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); - verts[ numVerts ].st[ 0 ] = i->textureCoord; - verts[ numVerts ].st[ 1 ] = 1.0f; - - if( btb->realLight ) - CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); - else - { - VectorCopy( i->color, verts[ numVerts ].modulate ); - verts[ numVerts ].modulate[ 3 ] = i->alpha; - } - - numVerts++; - - VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); - verts[ numVerts ].st[ 0 ] = i->textureCoord; - verts[ numVerts ].st[ 1 ] = 0.0f; - - if( btb->realLight ) - CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); - else - { - VectorCopy( i->color, verts[ numVerts ].modulate ); - verts[ numVerts ].modulate[ 3 ] = i->alpha; - } - - numVerts++; - } - - if( next ) - { - VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); - verts[ numVerts ].st[ 0 ] = i->textureCoord; - verts[ numVerts ].st[ 1 ] = 0.0f; - - if( btb->realLight ) - CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); - else - { - VectorCopy( i->color, verts[ numVerts ].modulate ); - verts[ numVerts ].modulate[ 3 ] = i->alpha; - } - - numVerts++; - - VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); - verts[ numVerts ].st[ 0 ] = i->textureCoord; - verts[ numVerts ].st[ 1 ] = 1.0f; - - if( btb->realLight ) - CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate ); - else - { - VectorCopy( i->color, verts[ numVerts ].modulate ); - verts[ numVerts ].modulate[ 3 ] = i->alpha; - } - - numVerts++; - } - - i = i->next; - } while( i ); - - trap_R_AddPolysToScene( tb->class->shader, 4, &verts[ 0 ], numVerts / 4 ); -} - -/* -=============== -CG_AllocateBeamNode - -Allocates a trailBeamNode_t from a trailBeam_t's nodePool -=============== -*/ -static trailBeamNode_t *CG_AllocateBeamNode( trailBeam_t *tb ) -{ - baseTrailBeam_t *btb = tb->class; - int i; - trailBeamNode_t *tbn; - - for( i = 0; i < MAX_TRAIL_BEAM_NODES; i++ ) - { - tbn = &tb->nodePool[ i ]; - if( !tbn->used ) - { - tbn->timeLeft = btb->segmentTime; - tbn->prev = NULL; - tbn->next = NULL; - tbn->used = qtrue; - return tbn; - } - } - - // no space left - return NULL; -} - -/* -=============== -CG_DestroyBeamNode - -Removes a node from a beam -Returns the new head -=============== -*/ -static trailBeamNode_t *CG_DestroyBeamNode( trailBeamNode_t *tbn ) -{ - trailBeamNode_t *newHead = NULL; - - if( tbn->prev ) - { - if( tbn->next ) - { - // node is in the middle - tbn->prev->next = tbn->next; - tbn->next->prev = tbn->prev; - } - else // node is at the back - tbn->prev->next = NULL; - - // find the new head (shouldn't have changed) - newHead = tbn->prev; - - while( newHead->prev ) - newHead = newHead->prev; - } - else if( tbn->next ) - { - //node is at the front - tbn->next->prev = NULL; - newHead = tbn->next; - } - - tbn->prev = NULL; - tbn->next = NULL; - tbn->used = qfalse; - - return newHead; -} - -/* -=============== -CG_FindLastBeamNode - -Returns the last beam node in a beam -=============== -*/ -static trailBeamNode_t *CG_FindLastBeamNode( trailBeam_t *tb ) -{ - trailBeamNode_t *i = tb->nodes; - - while( i && i->next ) - i = i->next; - - return i; -} - -/* -=============== -CG_CountBeamNodes - -Returns the number of nodes in a beam -=============== -*/ -static int CG_CountBeamNodes( trailBeam_t *tb ) -{ - trailBeamNode_t *i = tb->nodes; - int numNodes = 0; - - while( i ) - { - numNodes++; - i = i->next; - } - - return numNodes; -} - -/* -=============== -CG_PrependBeamNode - -Prepend a new beam node to the front of a beam -Returns the new node -=============== -*/ -static trailBeamNode_t *CG_PrependBeamNode( trailBeam_t *tb ) -{ - trailBeamNode_t *i; - - if( tb->nodes ) - { - // prepend another node - i = CG_AllocateBeamNode( tb ); - - if( i ) - { - i->next = tb->nodes; - tb->nodes->prev = i; - tb->nodes = i; - } - } - else //add first node - { - i = CG_AllocateBeamNode( tb ); - - if( i ) - tb->nodes = i; - } - - return i; -} - -/* -=============== -CG_AppendBeamNode - -Append a new beam node to the back of a beam -Returns the new node -=============== -*/ -static trailBeamNode_t *CG_AppendBeamNode( trailBeam_t *tb ) -{ - trailBeamNode_t *last, *i; - - if( tb->nodes ) - { - // append another node - last = CG_FindLastBeamNode( tb ); - i = CG_AllocateBeamNode( tb ); - - if( i ) - { - last->next = i; - i->prev = last; - i->next = NULL; - } - } - else //add first node - { - i = CG_AllocateBeamNode( tb ); - - if( i ) - tb->nodes = i; - } - - return i; -} - -/* -=============== -CG_ApplyJitters -=============== -*/ -static void CG_ApplyJitters( trailBeam_t *tb ) -{ - trailBeamNode_t *i = NULL; - int j; - baseTrailBeam_t *btb; - trailSystem_t *ts; - trailBeamNode_t *start; - trailBeamNode_t *end; - - if( !tb || !tb->nodes ) - return; - - btb = tb->class; - ts = tb->parent; - - for( j = 0; j < btb->numJitters; j++ ) - { - if( tb->nextJitterTimes[ j ] <= cg.time ) - { - for( i = tb->nodes; i; i = i->next ) - { - i->jitters[ j ][ 0 ] = ( crandom( ) * btb->jitters[ j ].magnitude ); - i->jitters[ j ][ 1 ] = ( crandom( ) * btb->jitters[ j ].magnitude ); - } - - tb->nextJitterTimes[ j ] = cg.time + btb->jitters[ j ].period; - } - } - - start = tb->nodes; - end = CG_FindLastBeamNode( tb ); - - if( !btb->jitterAttachments ) - { - if( CG_Attached( &ts->frontAttachment ) && start->next ) - start = start->next; - - if( CG_Attached( &ts->backAttachment ) && end->prev ) - end = end->prev; - } - - for( i = start; i; i = i->next ) - { - vec3_t forward, right, up; - trailBeamNode_t *prev; - trailBeamNode_t *next; - float upJitter = 0.0f, rightJitter = 0.0f; - - prev = i->prev; - next = i->next; - - if( prev && next ) - { - //this node has two neighbours - GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up ); - VectorSubtract( next->position, prev->position, forward ); - } - else if( !prev && next ) - { - //this is the front - GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up ); - VectorSubtract( next->position, i->position, forward ); - } - else if( prev && !next ) - { - //this is the back - GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up ); - VectorSubtract( i->position, prev->position, forward ); - } - - VectorNormalize( forward ); - CrossProduct( forward, up, right ); - VectorNormalize( right ); - - for( j = 0; j < btb->numJitters; j++ ) - { - upJitter += i->jitters[ j ][ 0 ]; - rightJitter += i->jitters[ j ][ 1 ]; - } - - VectorMA( i->position, upJitter, up, i->position ); - VectorMA( i->position, rightJitter, right, i->position ); - - if( i == end ) - break; - } -} - -/* -=============== -CG_UpdateBeam - -Updates a beam -=============== -*/ -static void CG_UpdateBeam( trailBeam_t *tb ) -{ - baseTrailBeam_t *btb; - trailSystem_t *ts; - trailBeamNode_t *i; - int deltaTime; - int nodesToAdd; - int j; - int numNodes; - - if( !tb ) - return; - - btb = tb->class; - ts = tb->parent; - - deltaTime = cg.time - tb->lastEvalTime; - tb->lastEvalTime = cg.time; - - // first make sure this beam has enough nodes - if( ts->destroyTime <= 0 ) - { - nodesToAdd = btb->numSegments - CG_CountBeamNodes( tb ) + 1; - - while( nodesToAdd-- ) - { - i = CG_AppendBeamNode( tb ); - - if( !tb->nodes->next && CG_Attached( &ts->frontAttachment ) ) - { - // this is the first node to be added - if( !CG_AttachmentPoint( &ts->frontAttachment, i->refPosition ) ) - CG_DestroyTrailSystem( &ts ); - } - else - VectorCopy( i->prev->refPosition, i->refPosition ); - } - } - - numNodes = CG_CountBeamNodes( tb ); - - for( i = tb->nodes; i; i = i->next ) - VectorCopy( i->refPosition, i->position ); - - if( CG_Attached( &ts->frontAttachment ) && CG_Attached( &ts->backAttachment ) ) - { - // beam between two attachments - vec3_t dir, front, back; - - if( ts->destroyTime > 0 && ( cg.time - ts->destroyTime ) >= btb->fadeOutTime ) - { - tb->valid = qfalse; - return; - } - - if( !CG_AttachmentPoint( &ts->frontAttachment, front ) ) - CG_DestroyTrailSystem( &ts ); - - if( !CG_AttachmentPoint( &ts->backAttachment, back ) ) - CG_DestroyTrailSystem( &ts ); - - VectorSubtract( back, front, dir ); - - for( j = 0, i = tb->nodes; i; i = i->next, j++ ) - { - float scale = (float)j / (float)( numNodes - 1 ); - - VectorMA( front, scale, dir, i->position ); - } - } - else if( CG_Attached( &ts->frontAttachment ) ) - { - // beam from one attachment - - // cull the trail tail - i = CG_FindLastBeamNode( tb ); - - if( i && i->timeLeft >= 0 ) - { - i->timeLeft -= deltaTime; - - if( i->timeLeft < 0 ) - { - tb->nodes = CG_DestroyBeamNode( i ); - - if( !tb->nodes ) - { - tb->valid = qfalse; - return; - } - - // if the ts has been destroyed, stop creating new nodes - if( ts->destroyTime <= 0 ) - CG_PrependBeamNode( tb ); - } - else if( i->timeLeft >= 0 && i->prev ) - { - vec3_t dir; - float length; - - VectorSubtract( i->refPosition, i->prev->refPosition, dir ); - length = VectorNormalize( dir ) * - ( (float)i->timeLeft / (float)tb->class->segmentTime ); - - VectorMA( i->prev->refPosition, length, dir, i->position ); - } - } - - if( tb->nodes ) - { - if( !CG_AttachmentPoint( &ts->frontAttachment, tb->nodes->refPosition ) ) - CG_DestroyTrailSystem( &ts ); - - VectorCopy( tb->nodes->refPosition, tb->nodes->position ); - } - } - - CG_ApplyJitters( tb ); -} - -/* -=============== -CG_ParseTrailBeamColor -=============== -*/ -static qboolean CG_ParseTrailBeamColor( byte *c, char **text_p ) -{ - char *token; - int i; - - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - c[ i ] = (int)( (float)0xFF * atof_neg( token, qfalse ) ); - } - - return qtrue; -} - -/* -=============== -CG_ParseTrailBeam - -Parse a trail beam -=============== -*/ -static qboolean CG_ParseTrailBeam( baseTrailBeam_t *btb, char **text_p ) -{ - char *token; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "segments" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->numSegments = atoi_neg( token, qfalse ); - - if( btb->numSegments >= MAX_TRAIL_BEAM_NODES ) - { - btb->numSegments = MAX_TRAIL_BEAM_NODES - 1; - CG_Printf( S_COLOR_YELLOW "WARNING: too many segments in trail beam\n" ); - } - continue; - } - else if( !Q_stricmp( token, "width" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->frontWidth = atof_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "-" ) ) - btb->backWidth = btb->frontWidth; - else - btb->backWidth = atof_neg( token, qfalse ); - continue; - } - else if( !Q_stricmp( token, "alpha" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->frontAlpha = atof_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "-" ) ) - btb->backAlpha = btb->frontAlpha; - else - btb->backAlpha = atof_neg( token, qfalse ); - continue; - } - else if( !Q_stricmp( token, "color" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseTrailBeamColor( btb->frontColor, text_p ) ) - break; - - token = COM_Parse( text_p ); - if( Q_stricmp( token, "}" ) ) - { - CG_Printf( S_COLOR_RED "ERROR: missing '}'\n" ); - break; - } - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - btb->backColor[ 0 ] = btb->frontColor[ 0 ]; - btb->backColor[ 1 ] = btb->frontColor[ 1 ]; - btb->backColor[ 2 ] = btb->frontColor[ 2 ]; - } - else if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseTrailBeamColor( btb->backColor, text_p ) ) - break; - - token = COM_Parse( text_p ); - if( Q_stricmp( token, "}" ) ) - { - CG_Printf( S_COLOR_RED "ERROR: missing '}'\n" ); - break; - } - } - else - { - CG_Printf( S_COLOR_RED "ERROR: missing '{'\n" ); - break; - } - } - else - { - CG_Printf( S_COLOR_RED "ERROR: missing '{'\n" ); - break; - } - - continue; - } - else if( !Q_stricmp( token, "segmentTime" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->segmentTime = atoi_neg( token, qfalse ); - continue; - } - else if( !Q_stricmp( token, "fadeOutTime" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->fadeOutTime = atoi_neg( token, qfalse ); - continue; - } - else if( !Q_stricmp( token, "shader" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - Q_strncpyz( btb->shaderName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "textureType" ) ) - { - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "stretch" ) ) - { - btb->textureType = TBTT_STRETCH; - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->frontTextureCoord = atof_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->backTextureCoord = atof_neg( token, qfalse ); - } - else if( !Q_stricmp( token, "repeat" ) ) - { - btb->textureType = TBTT_REPEAT; - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "front" ) ) - btb->clampToBack = qfalse; - else if( !Q_stricmp( token, "back" ) ) - btb->clampToBack = qtrue; - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown textureType clamp \"%s\"\n", token ); - break; - } - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->repeatLength = atof_neg( token, qfalse ); - } - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown textureType \"%s\"\n", token ); - break; - } - - continue; - } - else if( !Q_stricmp( token, "realLight" ) ) - { - btb->realLight = qtrue; - - continue; - } - else if( !Q_stricmp( token, "jitter" ) ) - { - if( btb->numJitters == MAX_TRAIL_BEAM_JITTERS ) - { - CG_Printf( S_COLOR_RED "ERROR: too many jitters\n", token ); - break; - } - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->jitters[ btb->numJitters ].magnitude = atof_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !Q_stricmp( token, "" ) ) - break; - - btb->jitters[ btb->numJitters ].period = atoi_neg( token, qfalse ); - - btb->numJitters++; - - continue; - } - else if( !Q_stricmp( token, "jitterAttachments" ) ) - { - btb->jitterAttachments = qtrue; - - continue; - } - else if( !Q_stricmp( token, "}" ) ) - return qtrue; //reached the end of this trail beam - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in trail beam\n", token ); - return qfalse; - } - } - - return qfalse; -} - -/* -=============== -CG_InitialiseBaseTrailBeam -=============== -*/ -static void CG_InitialiseBaseTrailBeam( baseTrailBeam_t *btb ) -{ - memset( btb, 0, sizeof( baseTrailBeam_t ) ); - - btb->numSegments = 1; - btb->frontWidth = btb->backWidth = 1.0f; - btb->frontAlpha = btb->backAlpha = 1.0f; - memset( btb->frontColor, 0xFF, sizeof( btb->frontColor ) ); - memset( btb->backColor, 0xFF, sizeof( btb->backColor ) ); - - btb->segmentTime = 100; - - btb->textureType = TBTT_STRETCH; - btb->frontTextureCoord = 0.0f; - btb->backTextureCoord = 1.0f; -} - -/* -=============== -CG_ParseTrailSystem - -Parse a trail system section -=============== -*/ -static qboolean CG_ParseTrailSystem( baseTrailSystem_t *bts, char **text_p, const char *name ) -{ - char *token; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "{" ) ) - { - CG_InitialiseBaseTrailBeam( &baseTrailBeams[ numBaseTrailBeams ] ); - - if( !CG_ParseTrailBeam( &baseTrailBeams[ numBaseTrailBeams ], text_p ) ) - { - CG_Printf( S_COLOR_RED "ERROR: failed to parse trail beam\n" ); - return qfalse; - } - - if( bts->numBeams == MAX_BEAMS_PER_SYSTEM ) - { - CG_Printf( S_COLOR_RED "ERROR: trail system has > %d beams\n", MAX_BEAMS_PER_SYSTEM ); - return qfalse; - } - else if( numBaseTrailBeams == MAX_BASETRAIL_BEAMS ) - { - CG_Printf( S_COLOR_RED "ERROR: maximum number of trail beams (%d) reached\n", - MAX_BASETRAIL_BEAMS ); - return qfalse; - } - else - { - //start parsing beams again - bts->beams[ bts->numBeams ] = &baseTrailBeams[ numBaseTrailBeams ]; - bts->numBeams++; - numBaseTrailBeams++; - } - continue; - } - else if( !Q_stricmp( token, "thirdPersonOnly" ) ) - bts->thirdPersonOnly = qtrue; - else if( !Q_stricmp( token, "beam" ) ) //acceptable text - continue; - else if( !Q_stricmp( token, "}" ) ) - { - if( cg_debugTrails.integer >= 1 ) - CG_Printf( "Parsed trail system %s\n", name ); - - return qtrue; //reached the end of this trail system - } - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in trail system %s\n", token, bts->name ); - return qfalse; - } - } - - return qfalse; -} - -/* -=============== -CG_ParseTrailFile - -Load the trail systems from a trail file -=============== -*/ -static qboolean CG_ParseTrailFile( const char *fileName ) -{ - char *text_p; - int i; - int len; - char *token; - char text[ 32000 ]; - char tsName[ MAX_QPATH ]; - qboolean tsNameSet = qfalse; - fileHandle_t f; - - // load the file - len = trap_FS_FOpenFile( fileName, &f, FS_READ ); - if( len <= 0 ) - return qfalse; - - if( len >= sizeof( text ) - 1 ) - { - CG_Printf( S_COLOR_RED "ERROR: trail file %s too long\n", fileName ); - return qfalse; - } - - trap_FS_Read( text, len, f ); - text[ len ] = 0; - trap_FS_FCloseFile( f ); - - // parse the text - text_p = text; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( &text_p ); - - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "{" ) ) - { - if( tsNameSet ) - { - //check for name space clashes - for( i = 0; i < numBaseTrailSystems; i++ ) - { - if( !Q_stricmp( baseTrailSystems[ i ].name, tsName ) ) - { - CG_Printf( S_COLOR_RED "ERROR: a trail system is already named %s\n", tsName ); - return qfalse; - } - } - - Q_strncpyz( baseTrailSystems[ numBaseTrailSystems ].name, tsName, MAX_QPATH ); - - if( !CG_ParseTrailSystem( &baseTrailSystems[ numBaseTrailSystems ], &text_p, tsName ) ) - { - CG_Printf( S_COLOR_RED "ERROR: %s: failed to parse trail system %s\n", fileName, tsName ); - return qfalse; - } - - //start parsing trail systems again - tsNameSet = qfalse; - - if( numBaseTrailSystems == MAX_BASETRAIL_SYSTEMS ) - { - CG_Printf( S_COLOR_RED "ERROR: maximum number of trail systems (%d) reached\n", - MAX_BASETRAIL_SYSTEMS ); - return qfalse; - } - else - numBaseTrailSystems++; - - continue; - } - else - { - CG_Printf( S_COLOR_RED "ERROR: unamed trail system\n" ); - return qfalse; - } - } - - if( !tsNameSet ) - { - Q_strncpyz( tsName, token, sizeof( tsName ) ); - tsNameSet = qtrue; - } - else - { - CG_Printf( S_COLOR_RED "ERROR: trail system already named\n" ); - return qfalse; - } - } - - return qtrue; -} - -/* -=============== -CG_LoadTrailSystems - -Load trail system templates -=============== -*/ -void CG_LoadTrailSystems( void ) -{ - int i; - /*const char *s[ MAX_TRAIL_FILES ];*/ - - //clear out the old - numBaseTrailSystems = 0; - numBaseTrailBeams = 0; - - for( i = 0; i < MAX_BASETRAIL_SYSTEMS; i++ ) - { - baseTrailSystem_t *bts = &baseTrailSystems[ i ]; - memset( bts, 0, sizeof( baseTrailSystem_t ) ); - } - - for( i = 0; i < MAX_BASETRAIL_BEAMS; i++ ) - { - baseTrailBeam_t *btb = &baseTrailBeams[ i ]; - memset( btb, 0, sizeof( baseTrailBeam_t ) ); - } - - //and bring in the new -/* for( i = 0; i < MAX_TRAIL_FILES; i++ ) - { - s[ i ] = CG_ConfigString( CS_TRAIL_FILES + i ); - - if( strlen( s[ i ] ) > 0 ) - { - CG_Printf( "...loading '%s'\n", s[ i ] ); - CG_ParseTrailFile( s[ i ] ); - } - else - break; - }*/ - CG_Printf( "trail.trail: %d\n", CG_ParseTrailFile( "scripts/trail.trail" ) ); -} - -/* -=============== -CG_RegisterTrailSystem - -Load the media that a trail system needs -=============== -*/ -qhandle_t CG_RegisterTrailSystem( char *name ) -{ - int i, j; - baseTrailSystem_t *bts; - baseTrailBeam_t *btb; - - for( i = 0; i < MAX_BASETRAIL_SYSTEMS; i++ ) - { - bts = &baseTrailSystems[ i ]; - - if( !Q_stricmp( bts->name, name ) ) - { - //already registered - if( bts->registered ) - return i + 1; - - for( j = 0; j < bts->numBeams; j++ ) - { - btb = bts->beams[ j ]; - - btb->shader = trap_R_RegisterShader( btb->shaderName ); - } - - if( cg_debugTrails.integer >= 1 ) - CG_Printf( "Registered trail system %s\n", name ); - - bts->registered = qtrue; - - //avoid returning 0 - return i + 1; - } - } - - CG_Printf( S_COLOR_RED "ERROR: failed to register trail system %s\n", name ); - return 0; -} - - -/* -=============== -CG_SpawnNewTrailBeam - -Allocate a new trail beam -=============== -*/ -static trailBeam_t *CG_SpawnNewTrailBeam( baseTrailBeam_t *btb, - trailSystem_t *parent ) -{ - int i; - trailBeam_t *tb = NULL; - trailSystem_t *ts = parent; - - for( i = 0; i < MAX_TRAIL_BEAMS; i++ ) - { - tb = &trailBeams[ i ]; - - if( !tb->valid ) - { - memset( tb, 0, sizeof( trailBeam_t ) ); - - //found a free slot - tb->class = btb; - tb->parent = ts; - - tb->valid = qtrue; - - if( cg_debugTrails.integer >= 1 ) - CG_Printf( "TB %s created\n", ts->class->name ); - - break; - } - } - - return tb; -} - - -/* -=============== -CG_SpawnNewTrailSystem - -Spawns a new trail system -=============== -*/ -trailSystem_t *CG_SpawnNewTrailSystem( qhandle_t psHandle ) -{ - int i, j; - trailSystem_t *ts = NULL; - baseTrailSystem_t *bts = &baseTrailSystems[ psHandle - 1 ]; - - if( !bts->registered ) - { - CG_Printf( S_COLOR_RED "ERROR: a trail system has not been registered yet\n" ); - return NULL; - } - - for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ ) - { - ts = &trailSystems[ i ]; - - if( !ts->valid ) - { - memset( ts, 0, sizeof( trailSystem_t ) ); - - //found a free slot - ts->class = bts; - - ts->valid = qtrue; - ts->destroyTime = -1; - - for( j = 0; j < bts->numBeams; j++ ) - CG_SpawnNewTrailBeam( bts->beams[ j ], ts ); - - if( cg_debugTrails.integer >= 1 ) - CG_Printf( "TS %s created\n", bts->name ); - - break; - } - } - - return ts; -} - -/* -=============== -CG_DestroyTrailSystem - -Destroy a trail system -=============== -*/ -void CG_DestroyTrailSystem( trailSystem_t **ts ) -{ - (*ts)->destroyTime = cg.time; - - if( CG_Attached( &(*ts)->frontAttachment ) && - !CG_Attached( &(*ts)->backAttachment ) ) - { - vec3_t v; - - // attach the trail head to a static point - CG_AttachmentPoint( &(*ts)->frontAttachment, v ); - CG_SetAttachmentPoint( &(*ts)->frontAttachment, v ); - CG_AttachToPoint( &(*ts)->frontAttachment ); - - (*ts)->frontAttachment.centValid = qfalse; // a bit naughty - } - - ts = NULL; -} - -/* -=============== -CG_IsTrailSystemValid - -Test a trail system for validity -=============== -*/ -qboolean CG_IsTrailSystemValid( trailSystem_t **ts ) -{ - if( *ts == NULL || ( *ts && !(*ts)->valid ) ) - { - if( *ts && !(*ts)->valid ) - *ts = NULL; - - return qfalse; - } - - return qtrue; -} - -/* -=============== -CG_GarbageCollectTrailSystems - -Destroy inactive trail systems -=============== -*/ -static void CG_GarbageCollectTrailSystems( void ) -{ - int i, j, count; - trailSystem_t *ts; - trailBeam_t *tb; - int centNum; - - for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ ) - { - ts = &trailSystems[ i ]; - count = 0; - - //don't bother checking already invalid systems - if( !ts->valid ) - continue; - - for( j = 0; j < MAX_TRAIL_BEAMS; j++ ) - { - tb = &trailBeams[ j ]; - - if( tb->valid && tb->parent == ts ) - count++; - } - - if( !count ) - ts->valid = qfalse; - - //check systems where the parent cent has left the PVS - //( local player entity is always valid ) - if( ( centNum = CG_AttachmentCentNum( &ts->frontAttachment ) ) >= 0 && - centNum != cg.snap->ps.clientNum ) - { - trailSystem_t *tempTS = ts; - - if( !cg_entities[ centNum ].valid ) - CG_DestroyTrailSystem( &tempTS ); - } - - if( ( centNum = CG_AttachmentCentNum( &ts->backAttachment ) ) >= 0 && - centNum != cg.snap->ps.clientNum ) - { - trailSystem_t *tempTS = ts; - - if( !cg_entities[ centNum ].valid ) - CG_DestroyTrailSystem( &tempTS ); - } - - if( cg_debugTrails.integer >= 1 && !ts->valid ) - CG_Printf( "TS %s garbage collected\n", ts->class->name ); - } -} - -/* -=============== -CG_AddTrails - -Add trails to the scene -=============== -*/ -void CG_AddTrails( void ) -{ - int i; - trailBeam_t *tb; - int numTS = 0, numTB = 0; - - //remove expired trail systems - CG_GarbageCollectTrailSystems( ); - - for( i = 0; i < MAX_TRAIL_BEAMS; i++ ) - { - tb = &trailBeams[ i ]; - - if( tb->valid ) - { - CG_UpdateBeam( tb ); - CG_RenderBeam( tb ); - } - } - - if( cg_debugTrails.integer >= 2 ) - { - for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ ) - if( trailSystems[ i ].valid ) - numTS++; - - for( i = 0; i < MAX_TRAIL_BEAMS; i++ ) - if( trailBeams[ i ].valid ) - numTB++; - - CG_Printf( "TS: %d TB: %d\n", numTS, numTB ); - } -} - -static trailSystem_t *testTS; -static qhandle_t testTSHandle; - -/* -=============== -CG_DestroyTestTS_f - -Destroy the test a trail system -=============== -*/ -void CG_DestroyTestTS_f( void ) -{ - if( CG_IsTrailSystemValid( &testTS ) ) - CG_DestroyTrailSystem( &testTS ); -} - -/* -=============== -CG_TestTS_f - -Test a trail system -=============== -*/ -void CG_TestTS_f( void ) -{ - char tsName[ MAX_QPATH ]; - - if( trap_Argc( ) < 2 ) - return; - - Q_strncpyz( tsName, CG_Argv( 1 ), MAX_QPATH ); - testTSHandle = CG_RegisterTrailSystem( tsName ); - - if( testTSHandle ) - { - CG_DestroyTestTS_f( ); - - testTS = CG_SpawnNewTrailSystem( testTSHandle ); - - if( CG_IsTrailSystemValid( &testTS ) ) - { - CG_SetAttachmentCent( &testTS->frontAttachment, &cg_entities[ 0 ] ); - CG_AttachToCent( &testTS->frontAttachment ); - } - } -} |