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

  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. // cg_marks.c -- wall marks
  4.  
  5. #include "cg_local.h"
  6.  
  7. /*
  8. ===================================================================
  9.  
  10. MARK POLYS
  11.  
  12. ===================================================================
  13. */
  14.  
  15.  
  16. markPoly_t    cg_activeMarkPolys;            // double linked list
  17. markPoly_t    *cg_freeMarkPolys;            // single linked list
  18. markPoly_t    cg_markPolys[MAX_MARK_POLYS];
  19.  
  20. /*
  21. ===================
  22. CG_InitMarkPolys
  23.  
  24. This is called at startup and for tournement restarts
  25. ===================
  26. */
  27. void    CG_InitMarkPolys( void ) {
  28.     int        i;
  29.  
  30.     memset( cg_markPolys, 0, sizeof(cg_markPolys) );
  31.  
  32.     cg_activeMarkPolys.nextMark = &cg_activeMarkPolys;
  33.     cg_activeMarkPolys.prevMark = &cg_activeMarkPolys;
  34.     cg_freeMarkPolys = cg_markPolys;
  35.     for ( i = 0 ; i < MAX_MARK_POLYS - 1 ; i++ ) {
  36.         cg_markPolys[i].nextMark = &cg_markPolys[i+1];
  37.     }
  38. }
  39.  
  40.  
  41. /*
  42. ==================
  43. CG_FreeMarkPoly
  44. ==================
  45. */
  46. void CG_FreeMarkPoly( markPoly_t *le ) {
  47.     if ( !le->prevMark ) {
  48.         CG_Error( "CG_FreeLocalEntity: not active" );
  49.     }
  50.  
  51.     // remove from the doubly linked active list
  52.     le->prevMark->nextMark = le->nextMark;
  53.     le->nextMark->prevMark = le->prevMark;
  54.  
  55.     // the free list is only singly linked
  56.     le->nextMark = cg_freeMarkPolys;
  57.     cg_freeMarkPolys = le;
  58. }
  59.  
  60. /*
  61. ===================
  62. CG_AllocMark
  63.  
  64. Will allways succeed, even if it requires freeing an old active mark
  65. ===================
  66. */
  67. markPoly_t    *CG_AllocMark( void ) {
  68.     markPoly_t    *le;
  69.     int time;
  70.  
  71.     if ( !cg_freeMarkPolys ) {
  72.         // no free entities, so free the one at the end of the chain
  73.         // remove the oldest active entity
  74.         time = cg_activeMarkPolys.prevMark->time;
  75.         while (cg_activeMarkPolys.prevMark && time == cg_activeMarkPolys.prevMark->time) {
  76.             CG_FreeMarkPoly( cg_activeMarkPolys.prevMark );
  77.         }
  78.     }
  79.  
  80.     le = cg_freeMarkPolys;
  81.     cg_freeMarkPolys = cg_freeMarkPolys->nextMark;
  82.  
  83.     memset( le, 0, sizeof( *le ) );
  84.  
  85.     // link into the active list
  86.     le->nextMark = cg_activeMarkPolys.nextMark;
  87.     le->prevMark = &cg_activeMarkPolys;
  88.     cg_activeMarkPolys.nextMark->prevMark = le;
  89.     cg_activeMarkPolys.nextMark = le;
  90.     return le;
  91. }
  92.  
  93.  
  94.  
  95. /*
  96. =================
  97. CG_ImpactMark
  98.  
  99. origin should be a point within a unit of the plane
  100. dir should be the plane normal
  101.  
  102. temporary marks will not be stored or randomly oriented, but immediately
  103. passed to the renderer.
  104. =================
  105. */
  106. #define    MAX_MARK_FRAGMENTS    128
  107. #define    MAX_MARK_POINTS        384
  108.  
  109. void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, 
  110.                    float orientation, float red, float green, float blue, float alpha,
  111.                    qboolean alphaFade, float radius, qboolean temporary ) {
  112.     vec3_t            axis[3];
  113.     float            texCoordScale;
  114.     vec3_t            originalPoints[4];
  115.     byte            colors[4];
  116.     int                i, j;
  117.     int                numFragments;
  118.     markFragment_t    markFragments[MAX_MARK_FRAGMENTS], *mf;
  119.     vec3_t            markPoints[MAX_MARK_POINTS];
  120.     vec3_t            projection;
  121.  
  122.     if ( !cg_addMarks.integer ) {
  123.         return;
  124.     }
  125.  
  126.     if ( radius <= 0 ) {
  127.         CG_Error( "CG_ImpactMark called with <= 0 radius" );
  128.     }
  129.  
  130.     // create the texture axis
  131.     VectorNormalize2( dir, axis[0] );
  132.     PerpendicularVector( axis[1], axis[0] );
  133.     RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
  134.     CrossProduct( axis[0], axis[2], axis[1] );
  135.  
  136.     texCoordScale = 0.5 * 1.0 / radius;
  137.  
  138.     // create the full polygon
  139.     for ( i = 0 ; i < 3 ; i++ ) {
  140.         originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
  141.         originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
  142.         originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
  143.         originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
  144.     }
  145.  
  146.     // get the fragments
  147.     VectorScale( dir, -20, projection );
  148.     numFragments = trap_CM_MarkFragments( 4, (void *)originalPoints,
  149.                     projection, MAX_MARK_POINTS, markPoints[0],
  150.                     MAX_MARK_FRAGMENTS, markFragments );
  151.  
  152.     colors[0] = red * 255;
  153.     colors[1] = green * 255;
  154.     colors[2] = blue * 255;
  155.     colors[3] = alpha * 255;
  156.  
  157.     for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) {
  158.         polyVert_t    *v;
  159.         polyVert_t    verts[MAX_VERTS_ON_POLY];
  160.         markPoly_t    *mark;
  161.  
  162.         // we have an upper limit on the complexity of polygons
  163.         // that we store persistantly
  164.         if ( mf->numPoints > MAX_VERTS_ON_POLY ) {
  165.             mf->numPoints = MAX_VERTS_ON_POLY;
  166.         }
  167.         for ( j = 0, v = verts ; j < mf->numPoints ; j++, v++ ) {
  168.             vec3_t        delta;
  169.  
  170.             VectorCopy( markPoints[mf->firstPoint + j], v->xyz );
  171.  
  172.             VectorSubtract( v->xyz, origin, delta );
  173.             v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
  174.             v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
  175.             *(int *)v->modulate = *(int *)colors;
  176.         }
  177.  
  178.         // if it is a temporary (shadow) mark, add it immediately and forget about it
  179.         if ( temporary ) {
  180.             trap_R_AddPolyToScene( markShader, mf->numPoints, verts );
  181.             continue;
  182.         }
  183.  
  184.         // otherwise save it persistantly
  185.         mark = CG_AllocMark();
  186.         mark->time = cg.time;
  187.         mark->alphaFade = alphaFade;
  188.         mark->markShader = markShader;
  189.         mark->poly.numVerts = mf->numPoints;
  190.         mark->color[0] = red;
  191.         mark->color[1] = green;
  192.         mark->color[2] = blue;
  193.         mark->color[3] = alpha;
  194.         memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
  195.     }
  196. }
  197.  
  198.  
  199. /*
  200. ===============
  201. CG_AddMarks
  202. ===============
  203. */
  204. #define    MARK_TOTAL_TIME        10000
  205. #define    MARK_FADE_TIME        1000
  206.  
  207. void CG_AddMarks( void ) {
  208.     int            j;
  209.     markPoly_t    *mp, *next;
  210.     int            t;
  211.     int            fade;
  212.  
  213.     if ( !cg_addMarks.integer ) {
  214.         return;
  215.     }
  216.  
  217.     mp = cg_activeMarkPolys.nextMark;
  218.     for ( ; mp != &cg_activeMarkPolys ; mp = next ) {
  219.         // grab next now, so if the local entity is freed we
  220.         // still have it
  221.         next = mp->nextMark;
  222.  
  223.         // see if it is time to completely remove it
  224.         if ( cg.time > mp->time + MARK_TOTAL_TIME ) {
  225.             CG_FreeMarkPoly( mp );
  226.             continue;
  227.         }
  228.  
  229.         // fade out the energy bursts
  230.         if ( mp->markShader == cgs.media.energyMarkShader ) {
  231.  
  232.             fade = 450 - 450 * ( (cg.time - mp->time ) / 3000.0 );
  233.             if ( fade < 255 ) {
  234.                 if ( fade < 0 ) {
  235.                     fade = 0;
  236.                 }
  237.                 if ( mp->verts[0].modulate[0] != 0 ) {
  238.                     for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
  239.                         mp->verts[j].modulate[0] = mp->color[0] * fade;
  240.                         mp->verts[j].modulate[1] = mp->color[1] * fade;
  241.                         mp->verts[j].modulate[2] = mp->color[2] * fade;
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.  
  247.         // fade all marks out with time
  248.         t = mp->time + MARK_TOTAL_TIME - cg.time;
  249.         if ( t < MARK_FADE_TIME ) {
  250.             fade = 255 * t / MARK_FADE_TIME;
  251.             if ( mp->alphaFade ) {
  252.                 for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
  253.                     mp->verts[j].modulate[3] = fade;
  254.                 }
  255.             } else {
  256.                 for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
  257.                     mp->verts[j].modulate[0] = mp->color[0] * fade;
  258.                     mp->verts[j].modulate[1] = mp->color[1] * fade;
  259.                     mp->verts[j].modulate[2] = mp->color[2] * fade;
  260.                 }
  261.             }
  262.         }
  263.  
  264.  
  265.         trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
  266.     }
  267. }
  268.  
  269.