codemp/cgame/cg_marks.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 // cg_marks.c -- wall marks
00004 
00005 #include "cg_local.h"
00006 
00007 /*
00008 ===================================================================
00009 
00010 MARK POLYS
00011 
00012 ===================================================================
00013 */
00014 
00015 
00016 markPoly_t      cg_activeMarkPolys;                     // double linked list
00017 markPoly_t      *cg_freeMarkPolys;                      // single linked list
00018 markPoly_t      cg_markPolys[MAX_MARK_POLYS];
00019 static          int     markTotal;
00020 
00021 /*
00022 ===================
00023 CG_InitMarkPolys
00024 
00025 This is called at startup and for tournement restarts
00026 ===================
00027 */
00028 void    CG_InitMarkPolys( void ) {
00029         int             i;
00030 
00031         memset( cg_markPolys, 0, sizeof(cg_markPolys) );
00032 
00033         cg_activeMarkPolys.nextMark = &cg_activeMarkPolys;
00034         cg_activeMarkPolys.prevMark = &cg_activeMarkPolys;
00035         cg_freeMarkPolys = cg_markPolys;
00036         for ( i = 0 ; i < MAX_MARK_POLYS - 1 ; i++ ) {
00037                 cg_markPolys[i].nextMark = &cg_markPolys[i+1];
00038         }
00039 }
00040 
00041 
00042 /*
00043 ==================
00044 CG_FreeMarkPoly
00045 ==================
00046 */
00047 void CG_FreeMarkPoly( markPoly_t *le ) {
00048         if ( !le->prevMark ) {
00049                 CG_Error( "CG_FreeLocalEntity: not active" );
00050         }
00051 
00052         // remove from the doubly linked active list
00053         le->prevMark->nextMark = le->nextMark;
00054         le->nextMark->prevMark = le->prevMark;
00055 
00056         // the free list is only singly linked
00057         le->nextMark = cg_freeMarkPolys;
00058         cg_freeMarkPolys = le;
00059 }
00060 
00061 /*
00062 ===================
00063 CG_AllocMark
00064 
00065 Will allways succeed, even if it requires freeing an old active mark
00066 ===================
00067 */
00068 markPoly_t      *CG_AllocMark( void ) {
00069         markPoly_t      *le;
00070         int time;
00071 
00072         if ( !cg_freeMarkPolys ) {
00073                 // no free entities, so free the one at the end of the chain
00074                 // remove the oldest active entity
00075                 time = cg_activeMarkPolys.prevMark->time;
00076                 while (cg_activeMarkPolys.prevMark && time == cg_activeMarkPolys.prevMark->time) {
00077                         CG_FreeMarkPoly( cg_activeMarkPolys.prevMark );
00078                 }
00079         }
00080 
00081         le = cg_freeMarkPolys;
00082         cg_freeMarkPolys = cg_freeMarkPolys->nextMark;
00083 
00084         memset( le, 0, sizeof( *le ) );
00085 
00086         // link into the active list
00087         le->nextMark = cg_activeMarkPolys.nextMark;
00088         le->prevMark = &cg_activeMarkPolys;
00089         cg_activeMarkPolys.nextMark->prevMark = le;
00090         cg_activeMarkPolys.nextMark = le;
00091         return le;
00092 }
00093 
00094 
00095 
00096 /*
00097 =================
00098 CG_ImpactMark
00099 
00100 origin should be a point within a unit of the plane
00101 dir should be the plane normal
00102 
00103 temporary marks will not be stored or randomly oriented, but immediately
00104 passed to the renderer.
00105 =================
00106 */
00107 #define MAX_MARK_FRAGMENTS      128
00108 #define MAX_MARK_POINTS         384
00109 
00110 void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, 
00111                                    float orientation, float red, float green, float blue, float alpha,
00112                                    qboolean alphaFade, float radius, qboolean temporary ) {
00113         vec3_t                  axis[3];
00114         float                   texCoordScale;
00115         vec3_t                  originalPoints[4];
00116         byte                    colors[4];
00117         int                             i, j;
00118         int                             numFragments;
00119         markFragment_t  markFragments[MAX_MARK_FRAGMENTS], *mf;
00120         vec3_t                  markPoints[MAX_MARK_POINTS];
00121         vec3_t                  projection;
00122 
00123         assert(markShader);
00124 
00125         if ( !cg_addMarks.integer ) {
00126                 return;
00127         }
00128         else if (cg_addMarks.integer == 2)
00129         {
00130                 trap_R_AddDecalToScene(markShader, origin, dir, orientation, red, green, blue, alpha,
00131                         alphaFade, radius, temporary);
00132                 return;
00133         }
00134 
00135         if ( radius <= 0 ) {
00136                 CG_Error( "CG_ImpactMark called with <= 0 radius" );
00137         }
00138 
00139         //if ( markTotal >= MAX_MARK_POLYS ) {
00140         //      return;
00141         //}
00142 
00143         // create the texture axis
00144         VectorNormalize2( dir, axis[0] );
00145         PerpendicularVector( axis[1], axis[0] );
00146         RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
00147         CrossProduct( axis[0], axis[2], axis[1] );
00148 
00149         texCoordScale = 0.5 * 1.0 / radius;
00150 
00151         // create the full polygon
00152         for ( i = 0 ; i < 3 ; i++ ) {
00153                 originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
00154                 originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
00155                 originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
00156                 originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
00157         }
00158 
00159         // get the fragments
00160         VectorScale( dir, -20, projection );
00161         numFragments = trap_CM_MarkFragments( 4, (const vec3_t *) originalPoints,
00162                                         projection, MAX_MARK_POINTS, markPoints[0],
00163                                         MAX_MARK_FRAGMENTS, markFragments );
00164 
00165         colors[0] = red * 255;
00166         colors[1] = green * 255;
00167         colors[2] = blue * 255;
00168         colors[3] = alpha * 255;
00169 
00170         for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) {
00171                 polyVert_t      *v;
00172                 polyVert_t      verts[MAX_VERTS_ON_POLY];
00173                 markPoly_t      *mark;
00174 
00175                 // we have an upper limit on the complexity of polygons
00176                 // that we store persistantly
00177                 if ( mf->numPoints > MAX_VERTS_ON_POLY ) {
00178                         mf->numPoints = MAX_VERTS_ON_POLY;
00179                 }
00180                 for ( j = 0, v = verts ; j < mf->numPoints ; j++, v++ ) {
00181                         vec3_t          delta;
00182 
00183                         VectorCopy( markPoints[mf->firstPoint + j], v->xyz );
00184 
00185                         VectorSubtract( v->xyz, origin, delta );
00186                         v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
00187                         v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
00188                         *(int *)v->modulate = *(int *)colors;
00189                 }
00190 
00191                 // if it is a temporary (shadow) mark, add it immediately and forget about it
00192                 if ( temporary ) {
00193                         trap_R_AddPolyToScene( markShader, mf->numPoints, verts );
00194                         continue;
00195                 }
00196 
00197                 // otherwise save it persistantly
00198                 mark = CG_AllocMark();
00199                 mark->time = cg.time;
00200                 mark->alphaFade = alphaFade;
00201                 mark->markShader = markShader;
00202                 mark->poly.numVerts = mf->numPoints;
00203                 mark->color[0] = red;
00204                 mark->color[1] = green;
00205                 mark->color[2] = blue;
00206                 mark->color[3] = alpha;
00207                 memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
00208                 markTotal++;
00209         }
00210 }
00211 
00212 
00213 /*
00214 ===============
00215 CG_AddMarks
00216 ===============
00217 */
00218 #define MARK_TOTAL_TIME         10000
00219 #define MARK_FADE_TIME          1000
00220 
00221 void CG_AddMarks( void ) {
00222         int                     j;
00223         markPoly_t      *mp, *next;
00224         int                     t;
00225         int                     fade;
00226 
00227         if ( !cg_addMarks.integer ) {
00228                 return;
00229         }
00230 
00231         mp = cg_activeMarkPolys.nextMark;
00232         for ( ; mp != &cg_activeMarkPolys ; mp = next ) {
00233                 // grab next now, so if the local entity is freed we
00234                 // still have it
00235                 next = mp->nextMark;
00236 
00237                 // see if it is time to completely remove it
00238                 if ( cg.time > mp->time + MARK_TOTAL_TIME ) {
00239                         CG_FreeMarkPoly( mp );
00240                         continue;
00241                 }
00242 
00243                 // fade out the energy bursts
00244                 //if ( mp->markShader == cgs.media.energyMarkShader ) {
00245                 if (0) {
00246 
00247                         fade = 450 - 450 * ( (cg.time - mp->time ) / 3000.0 );
00248                         if ( fade < 255 ) {
00249                                 if ( fade < 0 ) {
00250                                         fade = 0;
00251                                 }
00252                                 if ( mp->verts[0].modulate[0] != 0 ) {
00253                                         for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
00254                                                 mp->verts[j].modulate[0] = mp->color[0] * fade;
00255                                                 mp->verts[j].modulate[1] = mp->color[1] * fade;
00256                                                 mp->verts[j].modulate[2] = mp->color[2] * fade;
00257                                         }
00258                                 }
00259                         }
00260                 }
00261 
00262                 // fade all marks out with time
00263                 t = mp->time + MARK_TOTAL_TIME - cg.time;
00264                 if ( t < MARK_FADE_TIME ) {
00265                         fade = 255 * t / MARK_FADE_TIME;
00266                         if ( mp->alphaFade ) {
00267                                 for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
00268                                         mp->verts[j].modulate[3] = fade;
00269                                 }
00270                         }
00271                         else 
00272                         {
00273                                 float f = (float)t / MARK_FADE_TIME;
00274                                 for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
00275                                         mp->verts[j].modulate[0] = mp->color[0] * f;
00276                                         mp->verts[j].modulate[1] = mp->color[1] * f;
00277                                         mp->verts[j].modulate[2] = mp->color[2] * f;
00278                                 }
00279                         }
00280                 }
00281                 else
00282                 {
00283                         for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
00284                                 mp->verts[j].modulate[0] = mp->color[0];
00285                                 mp->verts[j].modulate[1] = mp->color[1];
00286                                 mp->verts[j].modulate[2] = mp->color[2];
00287                         }
00288                 }
00289 
00290                 trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
00291         }
00292 }
00293 
00294 // cg_particles.c  
00295 
00296 #define BLOODRED        2
00297 #define EMISIVEFADE     3
00298 #define GREY75          4
00299 
00300 typedef struct particle_s
00301 {
00302         struct particle_s       *next;
00303 
00304         float           time;
00305         float           endtime;
00306 
00307         vec3_t          org;
00308         vec3_t          vel;
00309         vec3_t          accel;
00310         int                     color;
00311         float           colorvel;
00312         float           alpha;
00313         float           alphavel;
00314         int                     type;
00315         qhandle_t       pshader;
00316         
00317         float           height;
00318         float           width;
00319                                 
00320         float           endheight;
00321         float           endwidth;
00322         
00323         float           start;
00324         float           end;
00325 
00326         float           startfade;
00327         qboolean        rotate;
00328         int                     snum;
00329         
00330         qboolean        link;
00331 
00332         // Ridah
00333         int                     shaderAnim;
00334         int                     roll;
00335 
00336         int                     accumroll;
00337 
00338 } cparticle_t;
00339 
00340 typedef enum
00341 {
00342         P_NONE,
00343         P_WEATHER,
00344         P_FLAT,
00345         P_SMOKE,
00346         P_ROTATE,
00347         P_WEATHER_TURBULENT,
00348         P_ANIM, // Ridah
00349         P_BAT,
00350         P_BLEED,
00351         P_FLAT_SCALEUP,
00352         P_FLAT_SCALEUP_FADE,
00353         P_WEATHER_FLURRY,
00354         P_SMOKE_IMPACT,
00355         P_BUBBLE,
00356         P_BUBBLE_TURBULENT,
00357         P_SPRITE
00358 } particle_type_t;
00359 
00360 #define MAX_SHADER_ANIMS                32
00361 #define MAX_SHADER_ANIM_FRAMES  64
00362 
00363 static char *shaderAnimNames[MAX_SHADER_ANIMS] = {
00364         "explode1",
00365         NULL
00366 };
00367 static qhandle_t shaderAnims[MAX_SHADER_ANIMS][MAX_SHADER_ANIM_FRAMES];
00368 static int      shaderAnimCounts[MAX_SHADER_ANIMS] = {
00369         23
00370 };
00371 static float    shaderAnimSTRatio[MAX_SHADER_ANIMS] = {
00372         1.0f
00373 };
00374 static int      numShaderAnims;
00375 // done.
00376 
00377 #define         PARTICLE_GRAVITY        40
00378 #define         MAX_PARTICLES   1024
00379 
00380 cparticle_t     *active_particles, *free_particles;
00381 cparticle_t     particles[MAX_PARTICLES];
00382 int             cl_numparticles = MAX_PARTICLES;
00383 
00384 qboolean                initparticles = qfalse;
00385 vec3_t                  pvforward, pvright, pvup;
00386 vec3_t                  rforward, rright, rup;
00387 
00388 float                   oldtime;
00389 
00390 /*
00391 ===============
00392 CL_ClearParticles
00393 ===============
00394 */
00395 void CG_ClearParticles (void)
00396 {
00397         int             i;
00398 
00399         memset( particles, 0, sizeof(particles) );
00400 
00401         free_particles = &particles[0];
00402         active_particles = NULL;
00403 
00404         for (i=0 ;i<cl_numparticles ; i++)
00405         {
00406                 particles[i].next = &particles[i+1];
00407                 particles[i].type = 0;
00408         }
00409         particles[cl_numparticles-1].next = NULL;
00410 
00411         oldtime = cg.time;
00412 
00413         /*
00414         // Ridah, init the shaderAnims
00415         for (i=0; shaderAnimNames[i]; i++) {
00416                 int j;
00417 
00418                 for (j=0; j<shaderAnimCounts[i]; j++) {
00419                         shaderAnims[i][j] = trap_R_RegisterShader( va("%s%i", shaderAnimNames[i], j+1) );
00420                 }
00421         }
00422         numShaderAnims = i;
00423         */
00424         numShaderAnims = 0;
00425         // done.
00426 
00427         initparticles = qtrue;
00428 }
00429 
00430 
00431 /*
00432 =====================
00433 CG_AddParticleToScene
00434 =====================
00435 */
00436 void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha)
00437 {
00438 
00439         vec3_t          point;
00440         polyVert_t      verts[4];
00441         float           width;
00442         float           height;
00443         float           time, time2;
00444         float           ratio;
00445         float           invratio;
00446         vec3_t          color;
00447         polyVert_t      TRIverts[3];
00448         vec3_t          rright2, rup2;
00449 
00450         if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY
00451                 || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
00452         {// create a front facing polygon
00453                         
00454                 if (p->type != P_WEATHER_FLURRY)
00455                 {
00456                         if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
00457                         {
00458                                 if (org[2] > p->end)                    
00459                                 {       
00460                                         p->time = cg.time;      
00461                                         VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
00462                                                                         
00463                                         p->org[2] = ( p->start + crandom () * 4 );
00464                                         
00465                                         
00466                                         if (p->type == P_BUBBLE_TURBULENT)
00467                                         {
00468                                                 p->vel[0] = crandom() * 4;
00469                                                 p->vel[1] = crandom() * 4;
00470                                         }
00471                                 
00472                                 }
00473                         }
00474                         else
00475                         {
00476                                 if (org[2] < p->end)                    
00477                                 {       
00478                                         p->time = cg.time;      
00479                                         VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
00480                                                                         
00481                                         while (p->org[2] < p->end) 
00482                                         {
00483                                                 p->org[2] += (p->start - p->end); 
00484                                         }
00485                                         
00486                                         
00487                                         if (p->type == P_WEATHER_TURBULENT)
00488                                         {
00489                                                 p->vel[0] = crandom() * 16;
00490                                                 p->vel[1] = crandom() * 16;
00491                                         }
00492                                 
00493                                 }
00494                         }
00495                         
00496 
00497                         // Rafael snow pvs check
00498                         if (!p->link)
00499                                 return;
00500 
00501                         p->alpha = 1;
00502                 }
00503                 
00504                 // Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp
00505                 if (Distance( cg.snap->ps.origin, org ) > 1024) {
00506                         return;
00507                 }
00508                 // done.
00509         
00510                 if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
00511                 {
00512                         VectorMA (org, -p->height, pvup, point);        
00513                         VectorMA (point, -p->width, pvright, point);    
00514                         VectorCopy (point, verts[0].xyz);       
00515                         verts[0].st[0] = 0;     
00516                         verts[0].st[1] = 0;     
00517                         verts[0].modulate[0] = 255;     
00518                         verts[0].modulate[1] = 255;     
00519                         verts[0].modulate[2] = 255;     
00520                         verts[0].modulate[3] = 255 * p->alpha;  
00521 
00522                         VectorMA (org, -p->height, pvup, point);        
00523                         VectorMA (point, p->width, pvright, point);     
00524                         VectorCopy (point, verts[1].xyz);       
00525                         verts[1].st[0] = 0;     
00526                         verts[1].st[1] = 1;     
00527                         verts[1].modulate[0] = 255;     
00528                         verts[1].modulate[1] = 255;     
00529                         verts[1].modulate[2] = 255;     
00530                         verts[1].modulate[3] = 255 * p->alpha;  
00531 
00532                         VectorMA (org, p->height, pvup, point); 
00533                         VectorMA (point, p->width, pvright, point);     
00534                         VectorCopy (point, verts[2].xyz);       
00535                         verts[2].st[0] = 1;     
00536                         verts[2].st[1] = 1;     
00537                         verts[2].modulate[0] = 255;     
00538                         verts[2].modulate[1] = 255;     
00539                         verts[2].modulate[2] = 255;     
00540                         verts[2].modulate[3] = 255 * p->alpha;  
00541 
00542                         VectorMA (org, p->height, pvup, point); 
00543                         VectorMA (point, -p->width, pvright, point);    
00544                         VectorCopy (point, verts[3].xyz);       
00545                         verts[3].st[0] = 1;     
00546                         verts[3].st[1] = 0;     
00547                         verts[3].modulate[0] = 255;     
00548                         verts[3].modulate[1] = 255;     
00549                         verts[3].modulate[2] = 255;     
00550                         verts[3].modulate[3] = 255 * p->alpha;  
00551                 }
00552                 else
00553                 {
00554                         VectorMA (org, -p->height, pvup, point);        
00555                         VectorMA (point, -p->width, pvright, point);    
00556                         VectorCopy( point, TRIverts[0].xyz );
00557                         TRIverts[0].st[0] = 1;
00558                         TRIverts[0].st[1] = 0;
00559                         TRIverts[0].modulate[0] = 255;
00560                         TRIverts[0].modulate[1] = 255;
00561                         TRIverts[0].modulate[2] = 255;
00562                         TRIverts[0].modulate[3] = 255 * p->alpha;       
00563 
00564                         VectorMA (org, p->height, pvup, point); 
00565                         VectorMA (point, -p->width, pvright, point);    
00566                         VectorCopy (point, TRIverts[1].xyz);    
00567                         TRIverts[1].st[0] = 0;
00568                         TRIverts[1].st[1] = 0;
00569                         TRIverts[1].modulate[0] = 255;
00570                         TRIverts[1].modulate[1] = 255;
00571                         TRIverts[1].modulate[2] = 255;
00572                         TRIverts[1].modulate[3] = 255 * p->alpha;       
00573 
00574                         VectorMA (org, p->height, pvup, point); 
00575                         VectorMA (point, p->width, pvright, point);     
00576                         VectorCopy (point, TRIverts[2].xyz);    
00577                         TRIverts[2].st[0] = 0;
00578                         TRIverts[2].st[1] = 1;
00579                         TRIverts[2].modulate[0] = 255;
00580                         TRIverts[2].modulate[1] = 255;
00581                         TRIverts[2].modulate[2] = 255;
00582                         TRIverts[2].modulate[3] = 255 * p->alpha;       
00583                 }
00584         
00585         }
00586         else if (p->type == P_SPRITE)
00587         {
00588                 vec3_t  rr, ru;
00589                 vec3_t  rotate_ang;
00590 
00591                 VectorSet (color, 1.0, 1.0, 0.5);
00592                 time = cg.time - p->time;
00593                 time2 = p->endtime - p->time;
00594                 ratio = time / time2;
00595 
00596                 width = p->width + ( ratio * ( p->endwidth - p->width) );
00597                 height = p->height + ( ratio * ( p->endheight - p->height) );
00598 
00599                 if (p->roll) {
00600                         vectoangles( cg.refdef.viewaxis[0], rotate_ang );
00601                         rotate_ang[ROLL] += p->roll;
00602                         AngleVectors ( rotate_ang, NULL, rr, ru);
00603                 }
00604 
00605                 if (p->roll) {
00606                         VectorMA (org, -height, ru, point);     
00607                         VectorMA (point, -width, rr, point);    
00608                 } else {
00609                         VectorMA (org, -height, pvup, point);   
00610                         VectorMA (point, -width, pvright, point);       
00611                 }
00612                 VectorCopy (point, verts[0].xyz);       
00613                 verts[0].st[0] = 0;     
00614                 verts[0].st[1] = 0;     
00615                 verts[0].modulate[0] = 255;     
00616                 verts[0].modulate[1] = 255;     
00617                 verts[0].modulate[2] = 255;     
00618                 verts[0].modulate[3] = 255;
00619 
00620                 if (p->roll) {
00621                         VectorMA (point, 2*height, ru, point);  
00622                 } else {
00623                         VectorMA (point, 2*height, pvup, point);        
00624                 }
00625                 VectorCopy (point, verts[1].xyz);       
00626                 verts[1].st[0] = 0;     
00627                 verts[1].st[1] = 1;     
00628                 verts[1].modulate[0] = 255;     
00629                 verts[1].modulate[1] = 255;     
00630                 verts[1].modulate[2] = 255;     
00631                 verts[1].modulate[3] = 255;     
00632 
00633                 if (p->roll) {
00634                         VectorMA (point, 2*width, rr, point);   
00635                 } else {
00636                         VectorMA (point, 2*width, pvright, point);      
00637                 }
00638                 VectorCopy (point, verts[2].xyz);       
00639                 verts[2].st[0] = 1;     
00640                 verts[2].st[1] = 1;     
00641                 verts[2].modulate[0] = 255;     
00642                 verts[2].modulate[1] = 255;     
00643                 verts[2].modulate[2] = 255;     
00644                 verts[2].modulate[3] = 255;     
00645 
00646                 if (p->roll) {
00647                         VectorMA (point, -2*height, ru, point); 
00648                 } else {
00649                         VectorMA (point, -2*height, pvup, point);       
00650                 }
00651                 VectorCopy (point, verts[3].xyz);       
00652                 verts[3].st[0] = 1;     
00653                 verts[3].st[1] = 0;     
00654                 verts[3].modulate[0] = 255;     
00655                 verts[3].modulate[1] = 255;     
00656                 verts[3].modulate[2] = 255;     
00657                 verts[3].modulate[3] = 255;     
00658         }
00659         else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT)
00660         {// create a front rotating facing polygon
00661 
00662                 if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) {
00663                         return;
00664                 }
00665 
00666                 if (p->color == BLOODRED)
00667                         VectorSet (color, 0.22f, 0.0f, 0.0f);
00668                 else if (p->color == GREY75)
00669                 {
00670                         float   len;
00671                         float   greyit;
00672                         float   val;
00673                         len = Distance (cg.snap->ps.origin, org);
00674                         if (!len)
00675                                 len = 1;
00676 
00677                         val = 4096/len;
00678                         greyit = 0.25 * val;
00679                         if (greyit > 0.5)
00680                                 greyit = 0.5;
00681 
00682                         VectorSet (color, greyit, greyit, greyit);
00683                 }
00684                 else
00685                         VectorSet (color, 1.0, 1.0, 1.0);
00686 
00687                 time = cg.time - p->time;
00688                 time2 = p->endtime - p->time;
00689                 ratio = time / time2;
00690                 
00691                 if (cg.time > p->startfade)
00692                 {
00693                         invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) );
00694 
00695                         if (p->color == EMISIVEFADE)
00696                         {
00697                                 float fval;
00698                                 fval = (invratio * invratio);
00699                                 if (fval < 0)
00700                                         fval = 0;
00701                                 VectorSet (color, fval , fval , fval );
00702                         }
00703                         invratio *= p->alpha;
00704                 }
00705                 else 
00706                         invratio = 1 * p->alpha;
00707 
00708                 if (invratio > 1)
00709                         invratio = 1;
00710         
00711                 width = p->width + ( ratio * ( p->endwidth - p->width) );
00712                 height = p->height + ( ratio * ( p->endheight - p->height) );
00713 
00714                 if (p->type != P_SMOKE_IMPACT)
00715                 {
00716                         vec3_t temp;
00717 
00718                         vectoangles (rforward, temp);
00719                         p->accumroll += p->roll;
00720                         temp[ROLL] += p->accumroll * 0.1;
00721                         AngleVectors ( temp, NULL, rright2, rup2);
00722                 }
00723                 else
00724                 {
00725                         VectorCopy (rright, rright2);
00726                         VectorCopy (rup, rup2);
00727                 }
00728                 
00729                 if (p->rotate)
00730                 {
00731                         VectorMA (org, -height, rup2, point);   
00732                         VectorMA (point, -width, rright2, point);       
00733                 }
00734                 else
00735                 {
00736                         VectorMA (org, -p->height, pvup, point);        
00737                         VectorMA (point, -p->width, pvright, point);    
00738                 }
00739                 VectorCopy (point, verts[0].xyz);       
00740                 verts[0].st[0] = 0;     
00741                 verts[0].st[1] = 0;     
00742                 verts[0].modulate[0] = 255 * color[0];  
00743                 verts[0].modulate[1] = 255 * color[1];  
00744                 verts[0].modulate[2] = 255 * color[2];  
00745                 verts[0].modulate[3] = 255 * invratio;  
00746 
00747                 if (p->rotate)
00748                 {
00749                         VectorMA (org, -height, rup2, point);   
00750                         VectorMA (point, width, rright2, point);        
00751                 }
00752                 else
00753                 {
00754                         VectorMA (org, -p->height, pvup, point);        
00755                         VectorMA (point, p->width, pvright, point);     
00756                 }
00757                 VectorCopy (point, verts[1].xyz);       
00758                 verts[1].st[0] = 0;     
00759                 verts[1].st[1] = 1;     
00760                 verts[1].modulate[0] = 255 * color[0];  
00761                 verts[1].modulate[1] = 255 * color[1];  
00762                 verts[1].modulate[2] = 255 * color[2];  
00763                 verts[1].modulate[3] = 255 * invratio;  
00764 
00765                 if (p->rotate)
00766                 {
00767                         VectorMA (org, height, rup2, point);    
00768                         VectorMA (point, width, rright2, point);        
00769                 }
00770                 else
00771                 {
00772                         VectorMA (org, p->height, pvup, point); 
00773                         VectorMA (point, p->width, pvright, point);     
00774                 }
00775                 VectorCopy (point, verts[2].xyz);       
00776                 verts[2].st[0] = 1;     
00777                 verts[2].st[1] = 1;     
00778                 verts[2].modulate[0] = 255 * color[0];  
00779                 verts[2].modulate[1] = 255 * color[1];  
00780                 verts[2].modulate[2] = 255 * color[2];  
00781                 verts[2].modulate[3] = 255 * invratio;  
00782 
00783                 if (p->rotate)
00784                 {
00785                         VectorMA (org, height, rup2, point);    
00786                         VectorMA (point, -width, rright2, point);       
00787                 }
00788                 else
00789                 {
00790                         VectorMA (org, p->height, pvup, point); 
00791                         VectorMA (point, -p->width, pvright, point);    
00792                 }
00793                 VectorCopy (point, verts[3].xyz);       
00794                 verts[3].st[0] = 1;     
00795                 verts[3].st[1] = 0;     
00796                 verts[3].modulate[0] = 255 * color[0];  
00797                 verts[3].modulate[1] = 255 * color[1];  
00798                 verts[3].modulate[2] = 255 * color[2];  
00799                 verts[3].modulate[3] = 255  * invratio; 
00800                 
00801         }
00802         else if (p->type == P_BLEED)
00803         {
00804                 vec3_t  rr, ru;
00805                 vec3_t  rotate_ang;
00806                 float   alpha;
00807 
00808                 alpha = p->alpha;
00809                 
00810                 if (p->roll) 
00811                 {
00812                         vectoangles( cg.refdef.viewaxis[0], rotate_ang );
00813                         rotate_ang[ROLL] += p->roll;
00814                         AngleVectors ( rotate_ang, NULL, rr, ru);
00815                 }
00816                 else
00817                 {
00818                         VectorCopy (pvup, ru);
00819                         VectorCopy (pvright, rr);
00820                 }
00821 
00822                 VectorMA (org, -p->height, ru, point);  
00823                 VectorMA (point, -p->width, rr, point); 
00824                 VectorCopy (point, verts[0].xyz);       
00825                 verts[0].st[0] = 0;     
00826                 verts[0].st[1] = 0;     
00827                 verts[0].modulate[0] = 111;     
00828                 verts[0].modulate[1] = 19;      
00829                 verts[0].modulate[2] = 9;       
00830                 verts[0].modulate[3] = 255 * alpha;     
00831 
00832                 VectorMA (org, -p->height, ru, point);  
00833                 VectorMA (point, p->width, rr, point);  
00834                 VectorCopy (point, verts[1].xyz);       
00835                 verts[1].st[0] = 0;     
00836                 verts[1].st[1] = 1;     
00837                 verts[1].modulate[0] = 111;     
00838                 verts[1].modulate[1] = 19;      
00839                 verts[1].modulate[2] = 9;       
00840                 verts[1].modulate[3] = 255 * alpha;     
00841 
00842                 VectorMA (org, p->height, ru, point);   
00843                 VectorMA (point, p->width, rr, point);  
00844                 VectorCopy (point, verts[2].xyz);       
00845                 verts[2].st[0] = 1;     
00846                 verts[2].st[1] = 1;     
00847                 verts[2].modulate[0] = 111;     
00848                 verts[2].modulate[1] = 19;      
00849                 verts[2].modulate[2] = 9;       
00850                 verts[2].modulate[3] = 255 * alpha;     
00851 
00852                 VectorMA (org, p->height, ru, point);   
00853                 VectorMA (point, -p->width, rr, point); 
00854                 VectorCopy (point, verts[3].xyz);       
00855                 verts[3].st[0] = 1;     
00856                 verts[3].st[1] = 0;     
00857                 verts[3].modulate[0] = 111;     
00858                 verts[3].modulate[1] = 19;      
00859                 verts[3].modulate[2] = 9;       
00860                 verts[3].modulate[3] = 255 * alpha;     
00861 
00862         }
00863         else if (p->type == P_FLAT_SCALEUP)
00864         {
00865                 float width, height;
00866                 float sinR, cosR;
00867 
00868                 if (p->color == BLOODRED)
00869                         VectorSet (color, 1, 1, 1);
00870                 else
00871                         VectorSet (color, 0.5, 0.5, 0.5);
00872                 
00873                 time = cg.time - p->time;
00874                 time2 = p->endtime - p->time;
00875                 ratio = time / time2;
00876 
00877                 width = p->width + ( ratio * ( p->endwidth - p->width) );
00878                 height = p->height + ( ratio * ( p->endheight - p->height) );
00879 
00880                 if (width > p->endwidth)
00881                         width = p->endwidth;
00882 
00883                 if (height > p->endheight)
00884                         height = p->endheight;
00885 
00886                 sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2.0f);
00887                 cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2.0f);
00888 
00889                 VectorCopy (org, verts[0].xyz); 
00890                 verts[0].xyz[0] -= sinR;
00891                 verts[0].xyz[1] -= cosR;
00892                 verts[0].st[0] = 0;     
00893                 verts[0].st[1] = 0;     
00894                 verts[0].modulate[0] = 255 * color[0];  
00895                 verts[0].modulate[1] = 255 * color[1];  
00896                 verts[0].modulate[2] = 255 * color[2];  
00897                 verts[0].modulate[3] = 255;     
00898 
00899                 VectorCopy (org, verts[1].xyz); 
00900                 verts[1].xyz[0] -= cosR;        
00901                 verts[1].xyz[1] += sinR;        
00902                 verts[1].st[0] = 0;     
00903                 verts[1].st[1] = 1;     
00904                 verts[1].modulate[0] = 255 * color[0];  
00905                 verts[1].modulate[1] = 255 * color[1];  
00906                 verts[1].modulate[2] = 255 * color[2];  
00907                 verts[1].modulate[3] = 255;     
00908 
00909                 VectorCopy (org, verts[2].xyz); 
00910                 verts[2].xyz[0] += sinR;        
00911                 verts[2].xyz[1] += cosR;        
00912                 verts[2].st[0] = 1;     
00913                 verts[2].st[1] = 1;     
00914                 verts[2].modulate[0] = 255 * color[0];  
00915                 verts[2].modulate[1] = 255 * color[1];  
00916                 verts[2].modulate[2] = 255 * color[2];  
00917                 verts[2].modulate[3] = 255;     
00918 
00919                 VectorCopy (org, verts[3].xyz); 
00920                 verts[3].xyz[0] += cosR;        
00921                 verts[3].xyz[1] -= sinR;        
00922                 verts[3].st[0] = 1;     
00923                 verts[3].st[1] = 0;     
00924                 verts[3].modulate[0] = 255 * color[0];  
00925                 verts[3].modulate[1] = 255 * color[1];  
00926                 verts[3].modulate[2] = 255 * color[2];  
00927                 verts[3].modulate[3] = 255;             
00928         }
00929         else if (p->type == P_FLAT)
00930         {
00931 
00932                 VectorCopy (org, verts[0].xyz); 
00933                 verts[0].xyz[0] -= p->height;   
00934                 verts[0].xyz[1] -= p->width;    
00935                 verts[0].st[0] = 0;     
00936                 verts[0].st[1] = 0;     
00937                 verts[0].modulate[0] = 255;     
00938                 verts[0].modulate[1] = 255;     
00939                 verts[0].modulate[2] = 255;     
00940                 verts[0].modulate[3] = 255;     
00941 
00942                 VectorCopy (org, verts[1].xyz); 
00943                 verts[1].xyz[0] -= p->height;   
00944                 verts[1].xyz[1] += p->width;    
00945                 verts[1].st[0] = 0;     
00946                 verts[1].st[1] = 1;     
00947                 verts[1].modulate[0] = 255;     
00948                 verts[1].modulate[1] = 255;     
00949                 verts[1].modulate[2] = 255;     
00950                 verts[1].modulate[3] = 255;     
00951 
00952                 VectorCopy (org, verts[2].xyz); 
00953                 verts[2].xyz[0] += p->height;   
00954                 verts[2].xyz[1] += p->width;    
00955                 verts[2].st[0] = 1;     
00956                 verts[2].st[1] = 1;     
00957                 verts[2].modulate[0] = 255;     
00958                 verts[2].modulate[1] = 255;     
00959                 verts[2].modulate[2] = 255;     
00960                 verts[2].modulate[3] = 255;     
00961 
00962                 VectorCopy (org, verts[3].xyz); 
00963                 verts[3].xyz[0] += p->height;   
00964                 verts[3].xyz[1] -= p->width;    
00965                 verts[3].st[0] = 1;     
00966                 verts[3].st[1] = 0;     
00967                 verts[3].modulate[0] = 255;     
00968                 verts[3].modulate[1] = 255;     
00969                 verts[3].modulate[2] = 255;     
00970                 verts[3].modulate[3] = 255;     
00971 
00972         }
00973         // Ridah
00974         else if (p->type == P_ANIM) {
00975                 vec3_t  rr, ru;
00976                 vec3_t  rotate_ang;
00977                 int i, j;
00978 
00979                 time = cg.time - p->time;
00980                 time2 = p->endtime - p->time;
00981                 ratio = time / time2;
00982                 if (ratio >= 1.0f) {
00983                         ratio = 0.9999f;
00984                 }
00985 
00986                 width = p->width + ( ratio * ( p->endwidth - p->width) );
00987                 height = p->height + ( ratio * ( p->endheight - p->height) );
00988 
00989                 // if we are "inside" this sprite, don't draw
00990                 if (Distance( cg.snap->ps.origin, org ) < width/1.5) {
00991                         return;
00992                 }
00993 
00994                 i = p->shaderAnim;
00995                 j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]);
00996                 p->pshader = shaderAnims[i][j];
00997 
00998                 if (p->roll) {
00999                         vectoangles( cg.refdef.viewaxis[0], rotate_ang );
01000                         rotate_ang[ROLL] += p->roll;
01001                         AngleVectors ( rotate_ang, NULL, rr, ru);
01002                 }
01003 
01004                 if (p->roll) {
01005                         VectorMA (org, -height, ru, point);     
01006                         VectorMA (point, -width, rr, point);    
01007                 } else {
01008                         VectorMA (org, -height, pvup, point);   
01009                         VectorMA (point, -width, pvright, point);       
01010                 }
01011                 VectorCopy (point, verts[0].xyz);       
01012                 verts[0].st[0] = 0;     
01013                 verts[0].st[1] = 0;     
01014                 verts[0].modulate[0] = 255;     
01015                 verts[0].modulate[1] = 255;     
01016                 verts[0].modulate[2] = 255;     
01017                 verts[0].modulate[3] = 255;
01018 
01019                 if (p->roll) {
01020                         VectorMA (point, 2*height, ru, point);  
01021                 } else {
01022                         VectorMA (point, 2*height, pvup, point);        
01023                 }
01024                 VectorCopy (point, verts[1].xyz);       
01025                 verts[1].st[0] = 0;     
01026                 verts[1].st[1] = 1;     
01027                 verts[1].modulate[0] = 255;     
01028                 verts[1].modulate[1] = 255;     
01029                 verts[1].modulate[2] = 255;     
01030                 verts[1].modulate[3] = 255;     
01031 
01032                 if (p->roll) {
01033                         VectorMA (point, 2*width, rr, point);   
01034                 } else {
01035                         VectorMA (point, 2*width, pvright, point);      
01036                 }
01037                 VectorCopy (point, verts[2].xyz);       
01038                 verts[2].st[0] = 1;     
01039                 verts[2].st[1] = 1;     
01040                 verts[2].modulate[0] = 255;     
01041                 verts[2].modulate[1] = 255;     
01042                 verts[2].modulate[2] = 255;     
01043                 verts[2].modulate[3] = 255;     
01044 
01045                 if (p->roll) {
01046                         VectorMA (point, -2*height, ru, point); 
01047                 } else {
01048                         VectorMA (point, -2*height, pvup, point);       
01049                 }
01050                 VectorCopy (point, verts[3].xyz);       
01051                 verts[3].st[0] = 1;     
01052                 verts[3].st[1] = 0;     
01053                 verts[3].modulate[0] = 255;     
01054                 verts[3].modulate[1] = 255;     
01055                 verts[3].modulate[2] = 255;     
01056                 verts[3].modulate[3] = 255;     
01057         }
01058         // done.
01059         
01060         if (!p->pshader) {
01061 // (SA) temp commented out for DM
01062 //              CG_Printf ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type);
01063                 return;
01064         }
01065 
01066         if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY)
01067                 trap_R_AddPolyToScene( p->pshader, 3, TRIverts );
01068         else
01069                 trap_R_AddPolyToScene( p->pshader, 4, verts );
01070 
01071 }
01072 
01073 // Ridah, made this static so it doesn't interfere with other files
01074 static float roll = 0.0;
01075 
01076 /*
01077 ===============
01078 CG_AddParticles
01079 ===============
01080 */
01081 void CG_AddParticles (void)
01082 {
01083         cparticle_t             *p, *next;
01084         float                   alpha;
01085         float                   time, time2;
01086         vec3_t                  org;
01087         int                             color;
01088         cparticle_t             *active, *tail;
01089         int                             type;
01090         vec3_t                  rotate_ang;
01091 
01092         if (!initparticles)
01093                 CG_ClearParticles ();
01094 
01095         VectorCopy( cg.refdef.viewaxis[0], pvforward );
01096         VectorCopy( cg.refdef.viewaxis[1], pvright );
01097         VectorCopy( cg.refdef.viewaxis[2], pvup );
01098 
01099         vectoangles( cg.refdef.viewaxis[0], rotate_ang );
01100         roll += ((cg.time - oldtime) * 0.1) ;
01101         rotate_ang[ROLL] += (roll*0.9);
01102         AngleVectors ( rotate_ang, rforward, rright, rup);
01103         
01104         oldtime = cg.time;
01105 
01106         active = NULL;
01107         tail = NULL;
01108 
01109         for (p=active_particles ; p ; p=next)
01110         {
01111 
01112                 next = p->next;
01113 
01114                 time = (cg.time - p->time)*0.001;
01115 
01116                 alpha = p->alpha + time*p->alphavel;
01117                 if (alpha <= 0)
01118                 {       // faded out
01119                         p->next = free_particles;
01120                         free_particles = p;
01121                         p->type = 0;
01122                         p->color = 0;
01123                         p->alpha = 0;
01124                         continue;
01125                 }
01126 
01127                 if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT)
01128                 {
01129                         if (cg.time > p->endtime)
01130                         {
01131                                 p->next = free_particles;
01132                                 free_particles = p;
01133                                 p->type = 0;
01134                                 p->color = 0;
01135                                 p->alpha = 0;
01136                         
01137                                 continue;
01138                         }
01139 
01140                 }
01141 
01142                 if (p->type == P_WEATHER_FLURRY)
01143                 {
01144                         if (cg.time > p->endtime)
01145                         {
01146                                 p->next = free_particles;
01147                                 free_particles = p;
01148                                 p->type = 0;
01149                                 p->color = 0;
01150                                 p->alpha = 0;
01151                         
01152                                 continue;
01153                         }
01154                 }
01155 
01156 
01157                 if (p->type == P_FLAT_SCALEUP_FADE)
01158                 {
01159                         if (cg.time > p->endtime)
01160                         {
01161                                 p->next = free_particles;
01162                                 free_particles = p;
01163                                 p->type = 0;
01164                                 p->color = 0;
01165                                 p->alpha = 0;
01166                                 continue;
01167                         }
01168 
01169                 }
01170 
01171                 if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) {
01172                         // temporary sprite
01173                         CG_AddParticleToScene (p, p->org, alpha);
01174                         p->next = free_particles;
01175                         free_particles = p;
01176                         p->type = 0;
01177                         p->color = 0;
01178                         p->alpha = 0;
01179                         continue;
01180                 }
01181 
01182                 p->next = NULL;
01183                 if (!tail)
01184                         active = tail = p;
01185                 else
01186                 {
01187                         tail->next = p;
01188                         tail = p;
01189                 }
01190 
01191                 if (alpha > 1.0)
01192                         alpha = 1;
01193 
01194                 color = p->color;
01195 
01196                 time2 = time*time;
01197 
01198                 org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2;
01199                 org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2;
01200                 org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2;
01201 
01202                 type = p->type;
01203 
01204                 CG_AddParticleToScene (p, org, alpha);
01205         }
01206 
01207         active_particles = active;
01208 }
01209 
01210 /*
01211 ======================
01212 CG_AddParticles
01213 ======================
01214 */
01215 void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent)
01216 {
01217         cparticle_t     *p;
01218         qboolean turb = qtrue;
01219 
01220         if (!pshader)
01221                 CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n");
01222 
01223         if (!free_particles)
01224                 return;
01225         p = free_particles;
01226         free_particles = p->next;
01227         p->next = active_particles;
01228         active_particles = p;
01229         p->time = cg.time;
01230         p->color = 0;
01231         p->alpha = 0.90f;
01232         p->alphavel = 0;
01233 
01234         p->start = cent->currentState.origin2[0];
01235         p->end = cent->currentState.origin2[1];
01236         
01237         p->endtime = cg.time + cent->currentState.time;
01238         p->startfade = cg.time + cent->currentState.time2;
01239         
01240         p->pshader = pshader;
01241         
01242         if (rand()%100 > 90)
01243         {
01244                 p->height = 32;
01245                 p->width = 32;
01246                 p->alpha = 0.10f;
01247         }
01248         else
01249         {
01250                 p->height = 1;
01251                 p->width = 1;
01252         }
01253 
01254         p->vel[2] = -20;
01255 
01256         p->type = P_WEATHER_FLURRY;
01257         
01258         if (turb)
01259                 p->vel[2] = -10;
01260         
01261         VectorCopy(cent->currentState.origin, p->org);
01262 
01263         p->org[0] = p->org[0];
01264         p->org[1] = p->org[1];
01265         p->org[2] = p->org[2];
01266 
01267         p->vel[0] = p->vel[1] = 0;
01268         
01269         p->accel[0] = p->accel[1] = p->accel[2] = 0;
01270 
01271         p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16);
01272         p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16);
01273         p->vel[2] += cent->currentState.angles[2];
01274 
01275         if (turb)
01276         {
01277                 p->accel[0] = crandom () * 16;
01278                 p->accel[1] = crandom () * 16;
01279         }
01280 
01281 }
01282 
01283 void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum)
01284 {
01285         cparticle_t     *p;
01286 
01287         if (!pshader)
01288                 CG_Printf ("CG_ParticleSnow pshader == ZERO!\n");
01289 
01290         if (!free_particles)
01291                 return;
01292         p = free_particles;
01293         free_particles = p->next;
01294         p->next = active_particles;
01295         active_particles = p;
01296         p->time = cg.time;
01297         p->color = 0;
01298         p->alpha = 0.40f;
01299         p->alphavel = 0;
01300         p->start = origin[2];
01301         p->end = origin2[2];
01302         p->pshader = pshader;
01303         p->height = 1;
01304         p->width = 1;
01305         
01306         p->vel[2] = -50;
01307 
01308         if (turb)
01309         {
01310                 p->type = P_WEATHER_TURBULENT;
01311                 p->vel[2] = -50 * 1.3;
01312         }
01313         else
01314         {
01315                 p->type = P_WEATHER;
01316         }
01317         
01318         VectorCopy(origin, p->org);
01319 
01320         p->org[0] = p->org[0] + ( crandom() * range);
01321         p->org[1] = p->org[1] + ( crandom() * range);
01322         p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); 
01323 
01324         p->vel[0] = p->vel[1] = 0;
01325         
01326         p->accel[0] = p->accel[1] = p->accel[2] = 0;
01327 
01328         if (turb)
01329         {
01330                 p->vel[0] = crandom() * 16;
01331                 p->vel[1] = crandom() * 16;
01332         }
01333 
01334         // Rafael snow pvs check
01335         p->snum = snum;
01336         p->link = qtrue;
01337 
01338 }
01339 
01340 void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int<