home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2000 March / maximum-cd-2000-03.iso / Quake3 Game Source / Q3AGameSource.exe / Main / cg_localents.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  13.3 KB  |  572 lines

  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3.  
  4. // cg_localents.c -- every frame, generate renderer commands for locally
  5. // processed entities, like smoke puffs, gibs, shells, etc.
  6.  
  7. #include "cg_local.h"
  8.  
  9. #define    MAX_LOCAL_ENTITIES    512
  10. localEntity_t    cg_localEntities[MAX_LOCAL_ENTITIES];
  11. localEntity_t    cg_activeLocalEntities;        // double linked list
  12. localEntity_t    *cg_freeLocalEntities;        // single linked list
  13.  
  14. /*
  15. ===================
  16. CG_InitLocalEntities
  17.  
  18. This is called at startup and for tournement restarts
  19. ===================
  20. */
  21. void    CG_InitLocalEntities( void ) {
  22.     int        i;
  23.  
  24.     memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
  25.     cg_activeLocalEntities.next = &cg_activeLocalEntities;
  26.     cg_activeLocalEntities.prev = &cg_activeLocalEntities;
  27.     cg_freeLocalEntities = cg_localEntities;
  28.     for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ ) {
  29.         cg_localEntities[i].next = &cg_localEntities[i+1];
  30.     }
  31. }
  32.  
  33.  
  34. /*
  35. ==================
  36. CG_FreeLocalEntity
  37. ==================
  38. */
  39. void CG_FreeLocalEntity( localEntity_t *le ) {
  40.     if ( !le->prev ) {
  41.         CG_Error( "CG_FreeLocalEntity: not active" );
  42.     }
  43.  
  44.     // remove from the doubly linked active list
  45.     le->prev->next = le->next;
  46.     le->next->prev = le->prev;
  47.  
  48.     // the free list is only singly linked
  49.     le->next = cg_freeLocalEntities;
  50.     cg_freeLocalEntities = le;
  51. }
  52.  
  53. /*
  54. ===================
  55. CG_AllocLocalEntity
  56.  
  57. Will allways succeed, even if it requires freeing an old active entity
  58. ===================
  59. */
  60. localEntity_t    *CG_AllocLocalEntity( void ) {
  61.     localEntity_t    *le;
  62.  
  63.     if ( !cg_freeLocalEntities ) {
  64.         // no free entities, so free the one at the end of the chain
  65.         // remove the oldest active entity
  66.         CG_FreeLocalEntity( cg_activeLocalEntities.prev );
  67.     }
  68.  
  69.     le = cg_freeLocalEntities;
  70.     cg_freeLocalEntities = cg_freeLocalEntities->next;
  71.  
  72.     memset( le, 0, sizeof( *le ) );
  73.  
  74.     // link into the active list
  75.     le->next = cg_activeLocalEntities.next;
  76.     le->prev = &cg_activeLocalEntities;
  77.     cg_activeLocalEntities.next->prev = le;
  78.     cg_activeLocalEntities.next = le;
  79.     return le;
  80. }
  81.  
  82.  
  83. /*
  84. ====================================================================================
  85.  
  86. FRAGMENT PROCESSING
  87.  
  88. A fragment localentity interacts with the environment in some way (hitting walls),
  89. or generates more localentities along a trail.
  90.  
  91. ====================================================================================
  92. */
  93.  
  94. /*
  95. ================
  96. CG_BloodTrail
  97.  
  98. Leave expanding blood puffs behind gibs
  99. ================
  100. */
  101. void CG_BloodTrail( localEntity_t *le ) {
  102.     int        t;
  103.     int        t2;
  104.     int        step;
  105.     vec3_t    newOrigin;
  106.     localEntity_t    *blood;
  107.  
  108.     step = 150;
  109.     t = step * ( (cg.time - cg.frametime + step ) / step );
  110.     t2 = step * ( cg.time / step );
  111.  
  112.     for ( ; t <= t2; t += step ) {
  113.         BG_EvaluateTrajectory( &le->pos, t, newOrigin );
  114.  
  115.         blood = CG_SmokePuff( newOrigin, vec3_origin, 
  116.                       20,        // radius
  117.                       1, 1, 1, 1,    // color
  118.                       2000,        // trailTime
  119.                       t,        // startTime
  120.                       0,        // flags
  121.                       cgs.media.bloodTrailShader );
  122.         // use the optimized version
  123.         blood->leType = LE_FALL_SCALE_FADE;
  124.         // drop a total of 40 units over its lifetime
  125.         blood->pos.trDelta[2] = 40;
  126.     }
  127. }
  128.  
  129.  
  130. /*
  131. ================
  132. CG_FragmentBounceMark
  133. ================
  134. */
  135. void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
  136.     int            radius;
  137.  
  138.     if ( le->leMarkType == LEMT_BLOOD ) {
  139.  
  140.         radius = 16 + (rand()&31);
  141.         CG_ImpactMark( cgs.media.bloodMarkShader, trace->endpos, trace->plane.normal, random()*360,
  142.             1,1,1,1, qtrue, radius, qfalse );
  143.     }
  144.  
  145.     // don't allow a fragment to make multiple marks, or they
  146.     // pile up while settling
  147.     le->leMarkType = LEMT_NONE;
  148. }
  149.  
  150. /*
  151. ================
  152. CG_FragmentBounceSound
  153. ================
  154. */
  155. void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace ) {
  156.     if ( le->leBounceSoundType == LEBS_BLOOD ) {
  157.         // half the gibs will make splat sounds
  158.         if ( rand() & 1 ) {
  159.             int r = rand()&3;
  160.             sfxHandle_t    s;
  161.  
  162.             if ( r < 2 ) {
  163.                 s = cgs.media.gibBounce1Sound;
  164.             } else if ( r == 2 ) {
  165.                 s = cgs.media.gibBounce2Sound;
  166.             } else {
  167.                 s = cgs.media.gibBounce3Sound;
  168.             }
  169.             trap_S_StartSound( trace->endpos, ENTITYNUM_WORLD, CHAN_AUTO, s );
  170.         }
  171.     } else if ( le->leBounceSoundType == LEBS_BRASS ) {
  172.  
  173.     }
  174.  
  175.     // don't allow a fragment to make multiple bounce sounds,
  176.     // or it gets too noisy as they settle
  177.     le->leBounceSoundType = LEBS_NONE;
  178. }
  179.  
  180.  
  181. /*
  182. ================
  183. CG_ReflectVelocity
  184. ================
  185. */
  186. void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
  187.     vec3_t    velocity;
  188.     float    dot;
  189.     int        hitTime;
  190.  
  191.     // reflect the velocity on the trace plane
  192.     hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
  193.     BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
  194.     dot = DotProduct( velocity, trace->plane.normal );
  195.     VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
  196.  
  197.     VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
  198.  
  199.     VectorCopy( trace->endpos, le->pos.trBase );
  200.     le->pos.trTime = cg.time;
  201.  
  202.  
  203.     // check for stop, making sure that even on low FPS systems it doesn't bobble
  204.     if ( trace->allsolid || 
  205.         ( trace->plane.normal[2] > 0 && 
  206.         ( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
  207.         le->pos.trType = TR_STATIONARY;
  208.     } else {
  209.  
  210.     }
  211. }
  212.  
  213. /*
  214. ================
  215. CG_AddFragment
  216. ================
  217. */
  218. void CG_AddFragment( localEntity_t *le ) {
  219.     vec3_t    newOrigin;
  220.     trace_t    trace;
  221.  
  222.     if ( le->pos.trType == TR_STATIONARY ) {
  223.         // sink into the ground if near the removal time
  224.         int        t;
  225.         float    oldZ;
  226.         
  227.         t = le->endTime - cg.time;
  228.         if ( t < SINK_TIME ) {
  229.             // we must use an explicit lighting origin, otherwise the
  230.             // lighting would be lost as soon as the origin went
  231.             // into the ground
  232.             VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
  233.             le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
  234.             oldZ = le->refEntity.origin[2];
  235.             le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
  236.             trap_R_AddRefEntityToScene( &le->refEntity );
  237.             le->refEntity.origin[2] = oldZ;
  238.         } else {
  239.             trap_R_AddRefEntityToScene( &le->refEntity );
  240.         }
  241.  
  242.         return;
  243.     }
  244.  
  245.     // calculate new position
  246.     BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
  247.  
  248.     // trace a line from previous position to new position
  249.     CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
  250.     if ( trace.fraction == 1.0 ) {
  251.         // still in free fall
  252.         VectorCopy( newOrigin, le->refEntity.origin );
  253.  
  254.         if ( le->leFlags & LEF_TUMBLE ) {
  255.             vec3_t angles;
  256.  
  257.             BG_EvaluateTrajectory( &le->angles, cg.time, angles );
  258.             AnglesToAxis( angles, le->refEntity.axis );
  259.         }
  260.  
  261.         trap_R_AddRefEntityToScene( &le->refEntity );
  262.  
  263.         // add a blood trail
  264.         if ( le->leBounceSoundType == LEBS_BLOOD ) {
  265.             CG_BloodTrail( le );
  266.         }
  267.  
  268.         return;
  269.     }
  270.  
  271.     // if it is in a nodrop zone, remove it
  272.     // this keeps gibs from waiting at the bottom of pits of death
  273.     // and floating levels
  274.     if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
  275.         CG_FreeLocalEntity( le );
  276.         return;
  277.     }
  278.  
  279.     // leave a mark
  280.     CG_FragmentBounceMark( le, &trace );
  281.  
  282.     // do a bouncy sound
  283.     CG_FragmentBounceSound( le, &trace );
  284.  
  285.     // reflect the velocity on the trace plane
  286.     CG_ReflectVelocity( le, &trace );
  287.  
  288.     trap_R_AddRefEntityToScene( &le->refEntity );
  289. }
  290.  
  291. /*
  292. =====================================================================
  293.  
  294. TRIVIAL LOCAL ENTITIES
  295.  
  296. These only do simple scaling or modulation before passing to the renderer
  297. =====================================================================
  298. */
  299.  
  300. /*
  301. ====================
  302. CG_AddFadeRGB
  303. ====================
  304. */
  305. void CG_AddFadeRGB( localEntity_t *le ) {
  306.     refEntity_t *re;
  307.     float c;
  308.  
  309.     re = &le->refEntity;
  310.  
  311.     c = ( le->endTime - cg.time ) * le->lifeRate;
  312.     c *= 0xff;
  313.  
  314.     re->shaderRGBA[0] = le->color[0] * c;
  315.     re->shaderRGBA[1] = le->color[1] * c;
  316.     re->shaderRGBA[2] = le->color[2] * c;
  317.     re->shaderRGBA[3] = le->color[3] * c;
  318.  
  319.     trap_R_AddRefEntityToScene( re );
  320. }
  321.  
  322. /*
  323. ==================
  324. CG_AddMoveScaleFade
  325. ==================
  326. */
  327. static void CG_AddMoveScaleFade( localEntity_t *le ) {
  328.     refEntity_t    *re;
  329.     float        c;
  330.     vec3_t        delta;
  331.     float        len;
  332.  
  333.     re = &le->refEntity;
  334.  
  335.     // fade / grow time
  336.     c = ( le->endTime - cg.time ) * le->lifeRate;
  337.  
  338.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  339.  
  340.     if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
  341.         re->radius = le->radius * ( 1.0 - c ) + 8;
  342.     }
  343.  
  344.     BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
  345.  
  346.     // if the view would be "inside" the sprite, kill the sprite
  347.     // so it doesn't add too much overdraw
  348.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  349.     len = VectorLength( delta );
  350.     if ( len < le->radius ) {
  351.         CG_FreeLocalEntity( le );
  352.         return;
  353.     }
  354.  
  355.     trap_R_AddRefEntityToScene( re );
  356. }
  357.  
  358.  
  359. /*
  360. ===================
  361. CG_AddScaleFade
  362.  
  363. For rocket smokes that hang in place, fade out, and are
  364. removed if the view passes through them.
  365. There are often many of these, so it needs to be simple.
  366. ===================
  367. */
  368. static void CG_AddScaleFade( localEntity_t *le ) {
  369.     refEntity_t    *re;
  370.     float        c;
  371.     vec3_t        delta;
  372.     float        len;
  373.  
  374.     re = &le->refEntity;
  375.  
  376.     // fade / grow time
  377.     c = ( le->endTime - cg.time ) * le->lifeRate;
  378.  
  379.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  380.     re->radius = le->radius * ( 1.0 - c ) + 8;
  381.  
  382.     // if the view would be "inside" the sprite, kill the sprite
  383.     // so it doesn't add too much overdraw
  384.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  385.     len = VectorLength( delta );
  386.     if ( len < le->radius ) {
  387.         CG_FreeLocalEntity( le );
  388.         return;
  389.     }
  390.  
  391.     trap_R_AddRefEntityToScene( re );
  392. }
  393.  
  394.  
  395. /*
  396. =================
  397. CG_AddFallScaleFade
  398.  
  399. This is just an optimized CG_AddMoveScaleFade
  400. For blood mists that drift down, fade out, and are
  401. removed if the view passes through them.
  402. There are often 100+ of these, so it needs to be simple.
  403. =================
  404. */
  405. static void CG_AddFallScaleFade( localEntity_t *le ) {
  406.     refEntity_t    *re;
  407.     float        c;
  408.     vec3_t        delta;
  409.     float        len;
  410.  
  411.     re = &le->refEntity;
  412.  
  413.     // fade time
  414.     c = ( le->endTime - cg.time ) * le->lifeRate;
  415.  
  416.     re->shaderRGBA[3] = 0xff * c * le->color[3];
  417.  
  418.     re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
  419.  
  420.     re->radius = le->radius * ( 1.0 - c ) + 16;
  421.  
  422.     // if the view would be "inside" the sprite, kill the sprite
  423.     // so it doesn't add too much overdraw
  424.     VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  425.     len = VectorLength( delta );
  426.     if ( len < le->radius ) {
  427.         CG_FreeLocalEntity( le );
  428.         return;
  429.     }
  430.  
  431.     trap_R_AddRefEntityToScene( re );
  432. }
  433.  
  434.  
  435.  
  436. /*
  437. ================
  438. CG_AddExplosion
  439. ================
  440. */
  441. static void CG_AddExplosion( localEntity_t *ex ) {
  442.     refEntity_t    *ent;
  443.  
  444.     ent = &ex->refEntity;
  445.  
  446.     // add the entity
  447.     trap_R_AddRefEntityToScene(ent);
  448.  
  449.     // add the dlight
  450.     if ( ex->light ) {
  451.         float        light;
  452.  
  453.         light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime );
  454.         if ( light < 0.5 ) {
  455.             light = 1.0;
  456.         } else {
  457.             light = 1.0 - ( light - 0.5 ) * 2;
  458.         }
  459.         light = ex->light * light;
  460.         trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] );
  461.     }
  462. }
  463.  
  464. /*
  465. ================
  466. CG_AddSpriteExplosion
  467. ================
  468. */
  469. static void CG_AddSpriteExplosion( localEntity_t *le ) {
  470.     refEntity_t    re;
  471.     float c;
  472.  
  473.     re = le->refEntity;
  474.  
  475.     c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime );
  476.     if ( c > 1 ) {
  477.         c = 1.0;    // can happen during connection problems
  478.     }
  479.  
  480.     re.shaderRGBA[0] = 0xff;
  481.     re.shaderRGBA[1] = 0xff;
  482.     re.shaderRGBA[2] = 0xff;
  483.     re.shaderRGBA[3] = 0xff * c * 0.33;
  484.  
  485.     re.reType = RT_SPRITE;
  486.     re.radius = 42 * ( 1.0 - c ) + 30;
  487.  
  488.     trap_R_AddRefEntityToScene( &re );
  489.  
  490.     // add the dlight
  491.     if ( le->light ) {
  492.         float        light;
  493.  
  494.         light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime );
  495.         if ( light < 0.5 ) {
  496.             light = 1.0;
  497.         } else {
  498.             light = 1.0 - ( light - 0.5 ) * 2;
  499.         }
  500.         light = le->light * light;
  501.         trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2] );
  502.     }
  503. }
  504.  
  505.  
  506. //==============================================================================
  507.  
  508. /*
  509. ===================
  510. CG_AddLocalEntities
  511.  
  512. ===================
  513. */
  514. void CG_AddLocalEntities( void ) {
  515.     localEntity_t    *le, *next;
  516.  
  517.     // walk the list backwards, so any new local entities generated
  518.     // (trails, marks, etc) will be present this frame
  519.     le = cg_activeLocalEntities.prev;
  520.     for ( ; le != &cg_activeLocalEntities ; le = next ) {
  521.         // grab next now, so if the local entity is freed we
  522.         // still have it
  523.         next = le->prev;
  524.  
  525.         if ( cg.time >= le->endTime ) {
  526.             CG_FreeLocalEntity( le );
  527.             continue;
  528.         }
  529.         switch ( le->leType ) {
  530.         default:
  531.             CG_Error( "Bad leType: %i", le->leType );
  532.             break;
  533.  
  534.         case LE_MARK:
  535.             break;
  536.  
  537.         case LE_SPRITE_EXPLOSION:
  538.             CG_AddSpriteExplosion( le );
  539.             break;
  540.  
  541.         case LE_EXPLOSION:
  542.             CG_AddExplosion( le );
  543.             break;
  544.  
  545.         case LE_FRAGMENT:            // gibs and brass
  546.             CG_AddFragment( le );
  547.             break;
  548.  
  549.         case LE_MOVE_SCALE_FADE:        // water bubbles
  550.             CG_AddMoveScaleFade( le );
  551.             break;
  552.  
  553.         case LE_FADE_RGB:                // teleporters, railtrails
  554.             CG_AddFadeRGB( le );
  555.             break;
  556.  
  557.         case LE_FALL_SCALE_FADE: // gib blood trails
  558.             CG_AddFallScaleFade( le );
  559.             break;
  560.  
  561.         case LE_SCALE_FADE:        // rocket trails
  562.             CG_AddScaleFade( le );
  563.             break;
  564.  
  565.         }
  566.     }
  567. }
  568.  
  569.  
  570.  
  571.  
  572.