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