1 /*
2 sw32_rpart.c
3
4 24 bit color software renderer particle effects.
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #define NH_DEFINE
32 #include "namehack.h"
33
34 #include <stdlib.h>
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41
42 #include "QF/cvar.h"
43 #include "QF/mersenne.h"
44 #include "QF/qargs.h"
45 #include "QF/quakefs.h"
46 #include "QF/render.h"
47 #include "QF/sys.h"
48 #include "QF/va.h"
49
50 #include "compat.h"
51 #include "r_internal.h"
52
53 static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 };
54 //static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 };
55 static int ramp3[8] = { 0x6d, 0x6b, 6, 5, 4, 3 };
56
57 static mtstate_t mt; // private PRNG state
58
59
60 void
sw32_R_InitParticles(void)61 sw32_R_InitParticles (void)
62 {
63 mtwist_seed (&mt, 0xdeadbeef);
64 }
65
66 void
sw32_R_ClearParticles(void)67 sw32_R_ClearParticles (void)
68 {
69 unsigned int i;
70
71 free_particles = &particles[0];
72 active_particles = NULL;
73
74 for (i = 0; i < r_maxparticles; i++)
75 particles[i].next = &particles[i + 1];
76 if (r_maxparticles)
77 particles[r_maxparticles - 1].next = NULL;
78 }
79
80 void
sw32_R_ReadPointFile_f(void)81 sw32_R_ReadPointFile_f (void)
82 {
83 QFile *f;
84 vec3_t org;
85 int r;
86 int c;
87 particle_t *p;
88 const char *name;
89 char *mapname;
90
91 mapname = strdup (r_worldentity.model->name);
92 if (!mapname)
93 Sys_Error ("Can't duplicate mapname!");
94 QFS_StripExtension (mapname, mapname);
95
96 name = va ("maps/%s.pts", mapname);
97 free (mapname);
98
99 QFS_FOpenFile (name, &f);
100 if (!f) {
101 Sys_Printf ("couldn't open %s\n", name);
102 return;
103 }
104
105 Sys_Printf ("Reading %s...\n", name);
106 c = 0;
107 for (;;) {
108 char buf[64];
109
110 Qgets (f, buf, sizeof (buf));
111 r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]);
112 if (r != 3)
113 break;
114 c++;
115
116 if (!free_particles) {
117 Sys_Printf ("Not enough free particles\n");
118 break;
119 }
120 p = free_particles;
121 free_particles = p->next;
122 p->next = active_particles;
123 active_particles = p;
124
125 p->die = 99999;
126 p->color = (-c) & 15;
127 p->type = pt_static;
128 p->phys = R_ParticlePhysics (p->type);
129 VectorZero (p->vel);
130 VectorCopy (org, p->org);
131 }
132
133 Qclose (f);
134 Sys_Printf ("%i points read\n", c);
135 }
136
137 static void
R_ParticleExplosion_QF(const vec3_t org)138 R_ParticleExplosion_QF (const vec3_t org)
139 {
140 int i, j;
141 particle_t *p;
142
143 if (!r_particles->int_val)
144 return;
145
146 for (i = 0; i < 1024; i++) {
147 if (!free_particles)
148 return;
149 p = free_particles;
150 free_particles = p->next;
151 p->next = active_particles;
152 active_particles = p;
153
154 p->die = vr_data.realtime + 5;
155 p->color = ramp1[0];
156 p->ramp = mtwist_rand (&mt) & 3;
157 if (i & 1) {
158 p->type = pt_explode;
159 for (j = 0; j < 3; j++) {
160 p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16);
161 p->vel[j] = (mtwist_rand (&mt) % 512) - 256;
162 }
163 } else {
164 p->type = pt_explode2;
165 for (j = 0; j < 3; j++) {
166 p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16);
167 p->vel[j] = (mtwist_rand (&mt) % 512) - 256;
168 }
169 }
170 p->phys = R_ParticlePhysics (p->type);
171 }
172 }
173
174 static void
R_ParticleExplosion2_QF(const vec3_t org,int colorStart,int colorLength)175 R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength)
176 {
177 int i, j;
178 particle_t *p;
179 int colorMod = 0;
180
181 for (i=0; i<512; i++)
182 {
183 if (!free_particles)
184 return;
185 p = free_particles;
186 free_particles = p->next;
187 p->next = active_particles;
188 active_particles = p;
189
190 p->die = vr_data.realtime + 0.3;
191 p->color = colorStart + (colorMod % colorLength);
192 colorMod++;
193
194 p->type = pt_blob;
195 p->phys = R_ParticlePhysics (p->type);
196 for (j=0 ; j<3 ; j++)
197 {
198 p->org[j] = org[j] + ((mtwist_rand (&mt)%32)-16);
199 p->vel[j] = (mtwist_rand (&mt)%512)-256;
200 }
201 }
202 }
203
204 static void
R_BlobExplosion_QF(const vec3_t org)205 R_BlobExplosion_QF (const vec3_t org)
206 {
207 int i, j;
208 particle_t *p;
209
210 if (!r_particles->int_val)
211 return;
212
213 for (i = 0; i < 1024; i++) {
214 if (!free_particles)
215 return;
216 p = free_particles;
217 free_particles = p->next;
218 p->next = active_particles;
219 active_particles = p;
220
221 p->die = vr_data.realtime + 1 + (mtwist_rand (&mt) & 8) * 0.05;
222
223 if (i & 1) {
224 p->type = pt_blob;
225 p->color = 66 + mtwist_rand (&mt) % 6;
226 for (j = 0; j < 3; j++) {
227 p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16);
228 p->vel[j] = (mtwist_rand (&mt) % 512) - 256;
229 }
230 } else {
231 p->type = pt_blob2;
232 p->color = 150 + mtwist_rand (&mt) % 6;
233 for (j = 0; j < 3; j++) {
234 p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16);
235 p->vel[j] = (mtwist_rand (&mt) % 512) - 256;
236 }
237 }
238 p->phys = R_ParticlePhysics (p->type);
239 }
240 }
241
242 static void
R_LavaSplash_QF(const vec3_t org)243 R_LavaSplash_QF (const vec3_t org)
244 {
245 int i, j, k;
246 particle_t *p;
247 float vel;
248 vec3_t dir;
249
250 if (!r_particles->int_val)
251 return;
252
253 for (i = -16; i < 16; i++)
254 for (j = -16; j < 16; j++)
255 for (k = 0; k < 1; k++) {
256 if (!free_particles)
257 return;
258 p = free_particles;
259 free_particles = p->next;
260 p->next = active_particles;
261 active_particles = p;
262
263 p->die = vr_data.realtime + 2 + (mtwist_rand (&mt) & 31) * 0.02;
264 p->color = 224 + (mtwist_rand (&mt) & 7);
265 p->type = pt_grav;
266 p->phys = R_ParticlePhysics (p->type);
267
268 dir[0] = j * 8 + (mtwist_rand (&mt) & 7);
269 dir[1] = i * 8 + (mtwist_rand (&mt) & 7);
270 dir[2] = 256;
271
272 p->org[0] = org[0] + dir[0];
273 p->org[1] = org[1] + dir[1];
274 p->org[2] = org[2] + (mtwist_rand (&mt) & 63);
275
276 VectorNormalize (dir);
277 vel = 50 + (mtwist_rand (&mt) & 63);
278 VectorScale (dir, vel, p->vel);
279 }
280 }
281
282 static void
R_TeleportSplash_QF(const vec3_t org)283 R_TeleportSplash_QF (const vec3_t org)
284 {
285 float vel;
286 int i, j, k;
287 particle_t *p;
288 vec3_t dir;
289
290 if (!r_particles->int_val)
291 return;
292
293 for (i = -16; i < 16; i += 4) {
294 for (j = -16; j < 16; j += 4) {
295 for (k = -24; k < 32; k += 4) {
296 if (!free_particles)
297 return;
298 p = free_particles;
299 free_particles = p->next;
300 p->next = active_particles;
301 active_particles = p;
302
303 p->die = vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02;
304 p->color = 7 + (mtwist_rand (&mt) & 7);
305 p->type = pt_grav;
306 p->phys = R_ParticlePhysics (p->type);
307
308 dir[0] = j * 8;
309 dir[1] = i * 8;
310 dir[2] = k * 8;
311
312 p->org[0] = org[0] + i + (mtwist_rand (&mt) & 3);
313 p->org[1] = org[1] + j + (mtwist_rand (&mt) & 3);
314 p->org[2] = org[2] + k + (mtwist_rand (&mt) & 3);
315
316 VectorNormalize (dir);
317 vel = 50 + (mtwist_rand (&mt) & 63);
318 VectorScale (dir, vel, p->vel);
319 }
320 }
321 }
322 }
323
324 static void
R_DarkFieldParticles_ID(const entity_t * ent)325 R_DarkFieldParticles_ID (const entity_t *ent)
326 {
327 int i, j, k;
328 unsigned int rnd;
329 float vel;
330 particle_t *p;
331 vec3_t dir, org;
332
333 org[0] = ent->origin[0];
334 org[1] = ent->origin[1];
335 org[2] = ent->origin[2];
336 for (i = -16; i < 16; i += 8) {
337 for (j = -16; j < 16; j += 8) {
338 for (k = 0; k < 32; k += 8) {
339 if (!free_particles)
340 return;
341 p = free_particles;
342 free_particles = p->next;
343 p->next = active_particles;
344 active_particles = p;
345
346 rnd = mtwist_rand (&mt);
347
348 p->die = vr_data.realtime + 0.2 + (rnd & 7) * 0.02;
349 p->color = 150 + mtwist_rand (&mt) % 6;
350 p->type = pt_slowgrav;
351 p->phys = R_ParticlePhysics (p->type);
352
353 dir[0] = j * 8;
354 dir[1] = i * 8;
355 dir[2] = k * 8;
356
357 p->org[0] = org[0] + i + ((rnd >> 3) & 3);
358 p->org[1] = org[1] + j + ((rnd >> 5) & 3);
359 p->org[2] = org[2] + k + ((rnd >> 7) & 3);
360
361 VectorNormalize (dir);
362 vel = 50 + ((rnd >> 9) & 63);
363 VectorScale (dir, vel, p->vel);
364 }
365 }
366 }
367 }
368
369 static vec3_t avelocities[NUMVERTEXNORMALS];
370
371 static void
R_EntityParticles_ID(const entity_t * ent)372 R_EntityParticles_ID (const entity_t *ent)
373 {
374 int i;
375 float angle, sp, sy, cp, cy; // cr, sr
376 float beamlength = 16.0, dist = 64.0;
377 particle_t *p;
378 vec3_t forward;
379
380 if (!avelocities[0][0]) {
381 for (i = 0; i < NUMVERTEXNORMALS * 3; i++)
382 avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01;
383 }
384
385 for (i = 0; i < NUMVERTEXNORMALS; i++) {
386 angle = vr_data.realtime * avelocities[i][0];
387 cy = cos (angle);
388 sy = sin (angle);
389 angle = vr_data.realtime * avelocities[i][1];
390 cp = cos (angle);
391 sp = sin (angle);
392 // Next 3 lines results aren't currently used, may be in future. --Despair
393 // angle = vr_data.realtime * avelocities[i][2];
394 // sr = sin (angle);
395 // cr = cos (angle);
396
397 forward[0] = cp * cy;
398 forward[1] = cp * sy;
399 forward[2] = -sp;
400
401 if (!free_particles)
402 return;
403 p = free_particles;
404 free_particles = p->next;
405 p->next = active_particles;
406 active_particles = p;
407
408 p->die = vr_data.realtime + 0.01;
409 p->color = 0x6f;
410 p->type = pt_explode;
411 p->phys = R_ParticlePhysics (p->type);
412
413 p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist +
414 forward[0] * beamlength;
415 p->org[1] = ent->origin[1] + r_avertexnormals[i][1] * dist +
416 forward[1] * beamlength;
417 p->org[2] = ent->origin[2] + r_avertexnormals[i][2] * dist +
418 forward[2] * beamlength;
419 }
420 }
421
422 static void
R_RunParticleEffect_QF(const vec3_t org,const vec3_t dir,int color,int count)423 R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color,
424 int count)
425 {
426 int i, j;
427 particle_t *p;
428
429 if (!r_particles->int_val)
430 return;
431
432 for (i = 0; i < count; i++) {
433 if (!free_particles)
434 return;
435 p = free_particles;
436 free_particles = p->next;
437 p->next = active_particles;
438 active_particles = p;
439
440 p->die = vr_data.realtime + 0.1 * (mtwist_rand (&mt) % 5);
441 p->color = (color & ~7) + (mtwist_rand (&mt) & 7);
442 p->type = pt_slowgrav;
443 p->phys = R_ParticlePhysics (p->type);
444 for (j = 0; j < 3; j++) {
445 p->org[j] = org[j] + ((mtwist_rand (&mt) & 15) - 8);
446 p->vel[j] = dir[j]; // + (mtwist_rand (&mt)%300)-150;
447 }
448 }
449 }
450
451 static void
R_SpikeEffect_QF(const vec3_t org)452 R_SpikeEffect_QF (const vec3_t org)
453 {
454 R_RunParticleEffect_QF (org, vec3_origin, 0, 10);
455 }
456
457 static void
R_SuperSpikeEffect_QF(const vec3_t org)458 R_SuperSpikeEffect_QF (const vec3_t org)
459 {
460 R_RunParticleEffect_QF (org, vec3_origin, 0, 20);
461 }
462
463 static void
R_KnightSpikeEffect_QF(const vec3_t org)464 R_KnightSpikeEffect_QF (const vec3_t org)
465 {
466 R_RunParticleEffect_QF (org, vec3_origin, 226, 20);
467 }
468
469 static void
R_WizSpikeEffect_QF(const vec3_t org)470 R_WizSpikeEffect_QF (const vec3_t org)
471 {
472 R_RunParticleEffect_QF (org, vec3_origin, 20, 30);
473 }
474
475 static void
R_BloodPuffEffect_QF(const vec3_t org,int count)476 R_BloodPuffEffect_QF (const vec3_t org, int count)
477 {
478 R_RunParticleEffect_QF (org, vec3_origin, 73, count);
479 }
480
481 static void
R_GunshotEffect_QF(const vec3_t org,int count)482 R_GunshotEffect_QF (const vec3_t org, int count)
483 {
484 R_RunParticleEffect_QF (org, vec3_origin, 0, count);
485 }
486
487 static void
R_LightningBloodEffect_QF(const vec3_t org)488 R_LightningBloodEffect_QF (const vec3_t org)
489 {
490 R_RunParticleEffect_QF (org, vec3_origin, 225, 50);
491 }
492
493 static void
R_RocketTrail_QF(const entity_t * ent)494 R_RocketTrail_QF (const entity_t *ent)
495 {
496 float len;
497 int j;
498 particle_t *p;
499 vec3_t old_origin, vec;
500
501 if (!r_particles->int_val)
502 return;
503
504 VectorCopy (ent->old_origin, old_origin);
505 VectorSubtract (ent->origin, ent->old_origin, vec);
506 len = VectorNormalize (vec);
507
508 while (len > 0) {
509 len -= 3;
510
511 if (!free_particles)
512 return;
513 p = free_particles;
514 free_particles = p->next;
515 p->next = active_particles;
516 active_particles = p;
517
518 VectorZero (p->vel);
519
520 p->die = vr_data.realtime + 2;
521 p->ramp = (mtwist_rand (&mt) & 3);
522 p->color = ramp3[(int) p->ramp];
523 p->type = pt_fire;
524 p->phys = R_ParticlePhysics (p->type);
525 for (j = 0; j < 3; j++)
526 p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3);
527
528 VectorAdd (old_origin, vec, old_origin);
529 }
530 }
531
532 static void
R_GrenadeTrail_QF(const entity_t * ent)533 R_GrenadeTrail_QF (const entity_t *ent)
534 {
535 float len;
536 int j;
537 particle_t *p;
538 vec3_t old_origin, vec;
539
540 if (!r_particles->int_val)
541 return;
542
543 VectorCopy (ent->old_origin, old_origin);
544 VectorSubtract (ent->origin, old_origin, vec);
545 len = VectorNormalize (vec);
546
547 while (len > 0) {
548 len -= 3;
549
550 if (!free_particles)
551 return;
552 p = free_particles;
553 free_particles = p->next;
554 p->next = active_particles;
555 active_particles = p;
556
557 VectorZero (p->vel);
558
559 p->die = vr_data.realtime + 2;
560 p->ramp = (mtwist_rand (&mt) & 3) + 2;
561 p->color = ramp3[(int) p->ramp];
562 p->type = pt_fire;
563 p->phys = R_ParticlePhysics (p->type);
564 for (j = 0; j < 3; j++)
565 p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3);
566
567 VectorAdd (old_origin, vec, old_origin);
568 }
569 }
570
571 static void
R_BloodTrail_QF(const entity_t * ent)572 R_BloodTrail_QF (const entity_t *ent)
573 {
574 float len;
575 int j;
576 particle_t *p;
577 vec3_t old_origin, vec;
578
579 if (!r_particles->int_val)
580 return;
581
582 VectorCopy (ent->old_origin, old_origin);
583 VectorSubtract (ent->origin, old_origin, vec);
584 len = VectorNormalize (vec);
585
586 while (len > 0) {
587 len -= 3;
588
589 if (!free_particles)
590 return;
591 p = free_particles;
592 free_particles = p->next;
593 p->next = active_particles;
594 active_particles = p;
595
596 VectorZero (p->vel);
597
598 p->die = vr_data.realtime + 2;
599 p->type = pt_slowgrav;
600 p->phys = R_ParticlePhysics (p->type);
601 p->color = 67 + (mtwist_rand (&mt) & 3);
602 for (j = 0; j < 3; j++)
603 p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3);
604 break;
605
606 VectorAdd (old_origin, vec, old_origin);
607 }
608 }
609
610 static void
R_SlightBloodTrail_QF(const entity_t * ent)611 R_SlightBloodTrail_QF (const entity_t *ent)
612 {
613 float len;
614 int j;
615 particle_t *p;
616 vec3_t old_origin, vec;
617
618 if (!r_particles->int_val)
619 return;
620
621 VectorCopy (ent->old_origin, old_origin);
622 VectorSubtract (ent->origin, old_origin, vec);
623 len = VectorNormalize (vec);
624
625 while (len > 0) {
626 len -= 6;
627
628 if (!free_particles)
629 return;
630 p = free_particles;
631 free_particles = p->next;
632 p->next = active_particles;
633 active_particles = p;
634
635 VectorZero (p->vel);
636
637 p->die = vr_data.realtime + 2;
638 p->type = pt_slowgrav;
639 p->phys = R_ParticlePhysics (p->type);
640 p->color = 67 + (mtwist_rand (&mt) & 3);
641 for (j = 0; j < 3; j++)
642 p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3);
643
644 VectorAdd (old_origin, vec, old_origin);
645 }
646 }
647
648 static void
R_WizTrail_QF(const entity_t * ent)649 R_WizTrail_QF (const entity_t *ent)
650 {
651 float len;
652 particle_t *p;
653 vec3_t old_origin, vec;
654
655 if (!r_particles->int_val)
656 return;
657
658 VectorCopy (ent->old_origin, old_origin);
659 VectorSubtract (ent->origin, old_origin, vec);
660 len = VectorNormalize (vec);
661
662 while (len > 0) {
663 static int tracercount;
664
665 len -= 3;
666
667 if (!free_particles)
668 return;
669 p = free_particles;
670 free_particles = p->next;
671 p->next = active_particles;
672 active_particles = p;
673
674 p->die = vr_data.realtime + 0.5;
675 p->type = pt_static;
676 p->phys = R_ParticlePhysics (p->type);
677 p->color = 52 + ((tracercount & 4) << 1);
678
679 tracercount++;
680
681 VectorCopy (old_origin, p->org);
682 if (tracercount & 1) {
683 p->vel[0] = 30.0 * vec[1];
684 p->vel[1] = 30.0 * -vec[0];
685 } else {
686 p->vel[0] = 30.0 * -vec[1];
687 p->vel[1] = 30.0 * vec[0];
688 }
689 p->vel[2] = 0.0;
690
691 VectorAdd (old_origin, vec, old_origin);
692 }
693 }
694
695 static void
R_FlameTrail_QF(const entity_t * ent)696 R_FlameTrail_QF (const entity_t *ent)
697 {
698 float len;
699 particle_t *p;
700 vec3_t old_origin, vec;
701
702 if (!r_particles->int_val)
703 return;
704
705 VectorCopy (ent->old_origin, old_origin);
706 VectorSubtract (ent->origin, old_origin, vec);
707 len = VectorNormalize (vec);
708
709 while (len > 0) {
710 static int tracercount;
711
712 len -= 3;
713
714 if (!free_particles)
715 return;
716 p = free_particles;
717 free_particles = p->next;
718 p->next = active_particles;
719 active_particles = p;
720
721 p->die = vr_data.realtime + 0.5;
722 p->type = pt_static;
723 p->phys = R_ParticlePhysics (p->type);
724 p->color = 230 + ((tracercount & 4) << 1);
725
726 tracercount++;
727
728 VectorCopy (old_origin, p->org);
729 if (tracercount & 1) {
730 p->vel[0] = 30.0 * vec[1];
731 p->vel[1] = 30.0 * -vec[0];
732 } else {
733 p->vel[0] = 30.0 * -vec[1];
734 p->vel[1] = 30.0 * vec[0];
735 }
736 p->vel[2] = 0.0;
737
738 VectorAdd (old_origin, vec, old_origin);
739 }
740 }
741
742 static void
R_VoorTrail_QF(const entity_t * ent)743 R_VoorTrail_QF (const entity_t *ent)
744 {
745 float len;
746 int j;
747 particle_t *p;
748 vec3_t old_origin, vec;
749
750 if (!r_particles->int_val)
751 return;
752
753 VectorCopy (ent->old_origin, old_origin);
754 VectorSubtract (ent->origin, old_origin, vec);
755 len = VectorNormalize (vec);
756
757 while (len > 0) {
758 len -= 3;
759
760 if (!free_particles)
761 return;
762 p = free_particles;
763 free_particles = p->next;
764 p->next = active_particles;
765 active_particles = p;
766
767 VectorZero (p->vel);
768
769 p->die = vr_data.realtime + 0.3;
770 p->type = pt_static;
771 p->phys = R_ParticlePhysics (p->type);
772 p->color = 9 * 16 + 8 + (mtwist_rand (&mt) & 3);
773 for (j = 0; j < 3; j++)
774 p->org[j] = old_origin[j] + ((mtwist_rand (&mt) & 15) - 8);
775
776 VectorAdd (old_origin, vec, old_origin);
777 }
778 }
779
780 void
sw32_R_DrawParticles(void)781 sw32_R_DrawParticles (void)
782 {
783 particle_t *p, **particle;
784
785 VectorScale (vright, sw32_xscaleshrink, r_pright);
786 VectorScale (vup, sw32_yscaleshrink, r_pup);
787 VectorCopy (vpn, r_ppn);
788
789 for (particle = &active_particles; *particle;) {
790 if ((*particle)->die < vr_data.realtime) {
791 p = (*particle)->next;
792 (*particle)->next = free_particles;
793 free_particles = (*particle);
794 (*particle) = p;
795 } else {
796 p = *particle;
797 particle = &(*particle)->next;
798
799 sw32_D_DrawParticle (p);
800
801 p->phys (p);
802 }
803 }
804 }
805
806 void
sw32_r_easter_eggs_f(cvar_t * var)807 sw32_r_easter_eggs_f (cvar_t *var)
808 {
809 }
810
811 void
sw32_r_particles_style_f(cvar_t * var)812 sw32_r_particles_style_f (cvar_t *var)
813 {
814 }
815
816 static vid_particle_funcs_t particles_QF = {
817 R_RocketTrail_QF,
818 R_GrenadeTrail_QF,
819 R_BloodTrail_QF,
820 R_SlightBloodTrail_QF,
821 R_WizTrail_QF,
822 R_FlameTrail_QF,
823 R_VoorTrail_QF,
824 0,//R_GlowTrail_QF,
825 R_RunParticleEffect_QF,
826 R_BloodPuffEffect_QF,
827 R_GunshotEffect_QF,
828 R_LightningBloodEffect_QF,
829 R_SpikeEffect_QF,
830 R_KnightSpikeEffect_QF,
831 R_SuperSpikeEffect_QF,
832 R_WizSpikeEffect_QF,
833 R_BlobExplosion_QF,
834 R_ParticleExplosion_QF,
835 R_ParticleExplosion2_QF,
836 R_LavaSplash_QF,
837 R_TeleportSplash_QF,
838 R_DarkFieldParticles_ID,
839 R_EntityParticles_ID,
840 R_Particle_New,
841 R_Particle_NewRandom,
842 };
843
844 static void
R_ParticleFunctionInit(void)845 R_ParticleFunctionInit (void)
846 {
847 sw32_vid_render_funcs.particles = &particles_QF;
848 }
849
850 static void
r_particles_nearclip_f(cvar_t * var)851 r_particles_nearclip_f (cvar_t *var)
852 {
853 Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value,
854 r_farclip->value));
855 }
856
857 static void
r_particles_f(cvar_t * var)858 r_particles_f (cvar_t *var)
859 {
860 R_MaxParticlesCheck (var, r_particles_max);
861 }
862
863 static void
r_particles_max_f(cvar_t * var)864 r_particles_max_f (cvar_t *var)
865 {
866 R_MaxParticlesCheck (r_particles, var);
867 }
868
869 void
sw32_R_Particles_Init_Cvars(void)870 sw32_R_Particles_Init_Cvars (void)
871 {
872 easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f,
873 "Enables easter eggs.");
874 r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f,
875 "Toggles drawing of particles.");
876 r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE,
877 r_particles_max_f, "Maximum amount of "
878 "particles to display. No maximum, minimum "
879 "is 0.");
880 r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32",
881 CVAR_ARCHIVE, r_particles_nearclip_f,
882 "Distance of the particle near clipping "
883 "plane from the player.");
884 r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE,
885 r_particles_style_f, "Sets particle style. "
886 "0 for Id, 1 for QF.");
887 R_ParticleFunctionInit ();
888 }
889
890 void
sw32_R_Particle_New(ptype_t type,int texnum,const vec3_t org,float scale,const vec3_t vel,float die,int color,float alpha,float ramp)891 sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale,
892 const vec3_t vel, float die, int color, float alpha,
893 float ramp)
894 {
895 particle_t *p;
896
897 if (!free_particles)
898 return;
899 p = free_particles;
900 free_particles = p->next;
901 p->next = active_particles;
902 active_particles = p;
903
904 VectorCopy (org, p->org);
905 p->color = color;
906 p->tex = texnum;
907 p->scale = scale;
908 p->alpha = alpha;
909 VectorCopy (vel, p->vel);
910 p->type = type;
911 p->phys = R_ParticlePhysics (p->type);
912 p->die = die;
913 p->ramp = ramp;
914 }
915
916 void
sw32_R_Particle_NewRandom(ptype_t type,int texnum,const vec3_t org,int org_fuzz,float scale,int vel_fuzz,float die,int color,float alpha,float ramp)917 sw32_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org,
918 int org_fuzz, float scale, int vel_fuzz, float die,
919 int color, float alpha, float ramp)
920 {
921 float o_fuzz = org_fuzz, v_fuzz = vel_fuzz;
922 int rnd;
923 vec3_t porg, pvel;
924
925 rnd = mtwist_rand (&mt);
926 porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0];
927 porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1];
928 porg[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2];
929 rnd = mtwist_rand (&mt);
930 pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0;
931 pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0;
932 pvel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0;
933
934 sw32_R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp);
935 }
936