2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #define MAX_PARTICLES 1024 // default max # of particles at one
26 #define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's
27 // on the command line
29 int ramp1
[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
30 int ramp2
[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
31 int ramp3
[8] = {0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
33 particle_t
*active_particles
, *free_particles
;
35 particle_t
*particles
;
38 vec3_t r_pright
, r_pup
, r_ppn
;
46 void R_InitParticles (void)
50 i
= COM_CheckParm ("-particles");
54 r_numparticles
= (int)(Q_atoi(com_argv
[i
+1]));
55 if (r_numparticles
< ABSOLUTE_MIN_PARTICLES
)
56 r_numparticles
= ABSOLUTE_MIN_PARTICLES
;
60 r_numparticles
= MAX_PARTICLES
;
63 particles
= (particle_t
*)
64 Hunk_AllocName (r_numparticles
* sizeof(particle_t
), "particles");
68 void R_DarkFieldParticles (entity_t
*ent
)
76 org
[0] = ent
->origin
[0];
77 org
[1] = ent
->origin
[1];
78 org
[2] = ent
->origin
[2];
79 for (i
=-16 ; i
<16 ; i
+=8)
80 for (j
=-16 ; j
<16 ; j
+=8)
81 for (k
=0 ; k
<32 ; k
+=8)
86 free_particles
= p
->next
;
87 p
->next
= active_particles
;
90 p
->die
= cl
.time
+ 0.2 + (rand()&7) * 0.02;
91 p
->color
= 150 + rand()%6;
92 p
->type
= pt_slowgrav
;
98 p
->org
[0] = org
[0] + i
+ (rand()&3);
99 p
->org
[1] = org
[1] + j
+ (rand()&3);
100 p
->org
[2] = org
[2] + k
+ (rand()&3);
102 VectorNormalize (dir
);
103 vel
= 50 + (rand()&63);
104 VectorScale (dir
, vel
, p
->vel
);
116 #define NUMVERTEXNORMALS 162
117 extern float r_avertexnormals
[NUMVERTEXNORMALS
][3];
118 vec3_t avelocities
[NUMVERTEXNORMALS
];
119 float beamlength
= 16;
120 vec3_t avelocity
= {23, 7, 3};
121 float partstep
= 0.01;
122 float timescale
= 0.01;
124 void R_EntityParticles (entity_t
*ent
)
130 float sr
, sp
, sy
, cr
, cp
, cy
;
137 if (!avelocities
[0][0])
139 for (i
=0 ; i
<NUMVERTEXNORMALS
*3 ; i
++)
140 avelocities
[0][i
] = (rand()&255) * 0.01;
144 for (i
=0 ; i
<NUMVERTEXNORMALS
; i
++)
146 angle
= cl
.time
* avelocities
[i
][0];
149 angle
= cl
.time
* avelocities
[i
][1];
152 angle
= cl
.time
* avelocities
[i
][2];
163 free_particles
= p
->next
;
164 p
->next
= active_particles
;
165 active_particles
= p
;
167 p
->die
= cl
.time
+ 0.01;
169 p
->type
= pt_explode
;
171 p
->org
[0] = ent
->origin
[0] + r_avertexnormals
[i
][0]*dist
+ forward
[0]*beamlength
;
172 p
->org
[1] = ent
->origin
[1] + r_avertexnormals
[i
][1]*dist
+ forward
[1]*beamlength
;
173 p
->org
[2] = ent
->origin
[2] + r_avertexnormals
[i
][2]*dist
+ forward
[2]*beamlength
;
183 void R_ClearParticles (void)
187 free_particles
= &particles
[0];
188 active_particles
= NULL
;
190 for (i
=0 ;i
<r_numparticles
; i
++)
191 particles
[i
].next
= &particles
[i
+1];
192 particles
[r_numparticles
-1].next
= NULL
;
196 void R_ReadPointFile_f (void)
203 char name
[MAX_OSPATH
];
205 sprintf (name
,"maps/%s.pts", sv
.name
);
207 COM_FOpenFile (name
, &f
);
210 Con_Printf ("couldn't open %s\n", name
);
214 Con_Printf ("Reading %s...\n", name
);
218 // Read the line into a string.
223 if (chars
>= (sizeof(line
) - 2))
225 Sys_Error("Line buffer overflow when reading point file");
228 if (!Sys_FileRead(f
, &line
[chars
++], 1) != 1)
233 while (line
[chars
- 1] != '\n');
236 r
= sscanf (line
, "%f %f %f\n", &org
[0], &org
[1], &org
[2]);
243 Con_Printf ("Not enough free particles\n");
247 free_particles
= p
->next
;
248 p
->next
= active_particles
;
249 active_particles
= p
;
254 VectorCopy (vec3_origin
, p
->vel
);
255 VectorCopy (org
, p
->org
);
259 Con_Printf ("%i points read\n", c
);
264 R_ParseParticleEffect
266 Parse an effect out of the server message
269 void R_ParseParticleEffect (void)
272 int i
, count
, msgcount
, color
;
274 for (i
=0 ; i
<3 ; i
++)
275 org
[i
] = MSG_ReadCoord ();
276 for (i
=0 ; i
<3 ; i
++)
277 dir
[i
] = MSG_ReadChar () * (1.0/16);
278 msgcount
= MSG_ReadByte ();
279 color
= MSG_ReadByte ();
286 R_RunParticleEffect (org
, dir
, color
, count
);
295 void R_ParticleExplosion (vec3_t org
)
300 for (i
=0 ; i
<1024 ; i
++)
305 free_particles
= p
->next
;
306 p
->next
= active_particles
;
307 active_particles
= p
;
309 p
->die
= cl
.time
+ 5;
314 p
->type
= pt_explode
;
315 for (j
=0 ; j
<3 ; j
++)
317 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
318 p
->vel
[j
] = (rand()%512)-256;
323 p
->type
= pt_explode2
;
324 for (j
=0 ; j
<3 ; j
++)
326 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
327 p
->vel
[j
] = (rand()%512)-256;
339 void R_ParticleExplosion2 (vec3_t org
, int colorStart
, int colorLength
)
345 for (i
=0; i
<512; i
++)
350 free_particles
= p
->next
;
351 p
->next
= active_particles
;
352 active_particles
= p
;
354 p
->die
= cl
.time
+ 0.3;
355 p
->color
= colorStart
+ (colorMod
% colorLength
);
359 for (j
=0 ; j
<3 ; j
++)
361 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
362 p
->vel
[j
] = (rand()%512)-256;
373 void R_BlobExplosion (vec3_t org
)
378 for (i
=0 ; i
<1024 ; i
++)
383 free_particles
= p
->next
;
384 p
->next
= active_particles
;
385 active_particles
= p
;
387 p
->die
= cl
.time
+ 1 + (rand()&8)*0.05;
392 p
->color
= 66 + rand()%6;
393 for (j
=0 ; j
<3 ; j
++)
395 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
396 p
->vel
[j
] = (rand()%512)-256;
402 p
->color
= 150 + rand()%6;
403 for (j
=0 ; j
<3 ; j
++)
405 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
406 p
->vel
[j
] = (rand()%512)-256;
418 void R_RunParticleEffect (vec3_t org
, vec3_t dir
, int color
, int count
)
423 for (i
=0 ; i
<count
; i
++)
428 free_particles
= p
->next
;
429 p
->next
= active_particles
;
430 active_particles
= p
;
433 { // rocket explosion
434 p
->die
= cl
.time
+ 5;
439 p
->type
= pt_explode
;
440 for (j
=0 ; j
<3 ; j
++)
442 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
443 p
->vel
[j
] = (rand()%512)-256;
448 p
->type
= pt_explode2
;
449 for (j
=0 ; j
<3 ; j
++)
451 p
->org
[j
] = org
[j
] + ((rand()%32)-16);
452 p
->vel
[j
] = (rand()%512)-256;
458 p
->die
= cl
.time
+ 0.1*(rand()%5);
459 p
->color
= (color
&~7) + (rand()&7);
460 p
->type
= pt_slowgrav
;
461 for (j
=0 ; j
<3 ; j
++)
463 p
->org
[j
] = org
[j
] + ((rand()&15)-8);
464 p
->vel
[j
] = dir
[j
]*15;// + (rand()%300)-150;
477 void R_LavaSplash (vec3_t org
)
484 for (i
=-16 ; i
<16 ; i
++)
485 for (j
=-16 ; j
<16 ; j
++)
486 for (k
=0 ; k
<1 ; k
++)
491 free_particles
= p
->next
;
492 p
->next
= active_particles
;
493 active_particles
= p
;
495 p
->die
= cl
.time
+ 2 + (rand()&31) * 0.02;
496 p
->color
= 224 + (rand()&7);
497 p
->type
= pt_slowgrav
;
499 dir
[0] = j
*8 + (rand()&7);
500 dir
[1] = i
*8 + (rand()&7);
503 p
->org
[0] = org
[0] + dir
[0];
504 p
->org
[1] = org
[1] + dir
[1];
505 p
->org
[2] = org
[2] + (rand()&63);
507 VectorNormalize (dir
);
508 vel
= 50 + (rand()&63);
509 VectorScale (dir
, vel
, p
->vel
);
519 void R_TeleportSplash (vec3_t org
)
526 for (i
=-16 ; i
<16 ; i
+=4)
527 for (j
=-16 ; j
<16 ; j
+=4)
528 for (k
=-24 ; k
<32 ; k
+=4)
533 free_particles
= p
->next
;
534 p
->next
= active_particles
;
535 active_particles
= p
;
537 p
->die
= cl
.time
+ 0.2 + (rand()&7) * 0.02;
538 p
->color
= 7 + (rand()&7);
539 p
->type
= pt_slowgrav
;
545 p
->org
[0] = org
[0] + i
+ (rand()&3);
546 p
->org
[1] = org
[1] + j
+ (rand()&3);
547 p
->org
[2] = org
[2] + k
+ (rand()&3);
549 VectorNormalize (dir
);
550 vel
= 50 + (rand()&63);
551 VectorScale (dir
, vel
, p
->vel
);
555 void R_RocketTrail (vec3_t start
, vec3_t end
, int type
)
562 static int tracercount
;
564 VectorSubtract (end
, start
, vec
);
565 len
= VectorNormalize (vec
);
581 free_particles
= p
->next
;
582 p
->next
= active_particles
;
583 active_particles
= p
;
585 VectorCopy (vec3_origin
, p
->vel
);
586 p
->die
= cl
.time
+ 2;
590 case 0: // rocket trail
591 p
->ramp
= (rand()&3);
592 p
->color
= ramp3
[(int)p
->ramp
];
594 for (j
=0 ; j
<3 ; j
++)
595 p
->org
[j
] = start
[j
] + ((rand()%6)-3);
598 case 1: // smoke smoke
599 p
->ramp
= (rand()&3) + 2;
600 p
->color
= ramp3
[(int)p
->ramp
];
602 for (j
=0 ; j
<3 ; j
++)
603 p
->org
[j
] = start
[j
] + ((rand()%6)-3);
608 p
->color
= 67 + (rand()&3);
609 for (j
=0 ; j
<3 ; j
++)
610 p
->org
[j
] = start
[j
] + ((rand()%6)-3);
615 p
->die
= cl
.time
+ 0.5;
618 p
->color
= 52 + ((tracercount
&4)<<1);
620 p
->color
= 230 + ((tracercount
&4)<<1);
624 VectorCopy (start
, p
->org
);
627 p
->vel
[0] = 30*vec
[1];
628 p
->vel
[1] = 30*-vec
[0];
632 p
->vel
[0] = 30*-vec
[1];
633 p
->vel
[1] = 30*vec
[0];
637 case 4: // slight blood
639 p
->color
= 67 + (rand()&3);
640 for (j
=0 ; j
<3 ; j
++)
641 p
->org
[j
] = start
[j
] + ((rand()%6)-3);
645 case 6: // voor trail
646 p
->color
= 9*16 + 8 + (rand()&3);
648 p
->die
= cl
.time
+ 0.3;
649 for (j
=0 ; j
<3 ; j
++)
650 p
->org
[j
] = start
[j
] + ((rand()&15)-8);
655 VectorAdd (start
, vec
, start
);
665 extern cvar_t sv_gravity
;
667 #define PART_BUFFER_SIZE 1024
669 void R_DrawParticles (void)
671 particle_t
*p
, *kill
;
681 #ifdef PSP_HARDWARE_VIDEO
683 int part_buffer_size
= PART_BUFFER_SIZE
;
684 psp_particle
* part_buffer
= NULL
;
685 part_buffer
= D_CreateBuffer(part_buffer_size
);
687 VectorScale (vup
, 1.25, up
);
688 VectorScale (vright
, 1.25, right
);
692 #ifdef PSP_HARDWARE_VIDEO
693 //VectorScale (vright, xscaleshrink, r_pright);
694 //VectorScale (vup, yscaleshrink, r_pup);
695 //VectorCopy (vright, r_pright);
696 //VectorCopy (vup, r_pup);
698 VectorScale (vright
, xscaleshrink
, r_pright
);
699 VectorScale (vup
, yscaleshrink
, r_pup
);
701 VectorCopy (vpn
, r_ppn
);
703 frametime
= cl
.time
- cl
.oldtime
;
704 time3
= frametime
* 15;
705 time2
= frametime
* 10; // 15;
706 time1
= frametime
* 5;
707 grav
= frametime
* sv_gravity
.value
* 0.05;
712 kill
= active_particles
;
713 if (kill
&& kill
->die
< cl
.time
)
715 active_particles
= kill
->next
;
716 kill
->next
= free_particles
;
717 free_particles
= kill
;
723 for (p
=active_particles
; p
; p
=p
->next
)
728 if (kill
&& kill
->die
< cl
.time
)
730 p
->next
= kill
->next
;
731 kill
->next
= free_particles
;
732 free_particles
= kill
;
738 #ifdef PSP_HARDWARE_VIDEO
739 // hack a scale up to keep particles from disapearing
740 scale
= (p
->org
[0] - r_origin
[0])*vpn
[0] + (p
->org
[1] - r_origin
[1])*vpn
[1]
741 + (p
->org
[2] - r_origin
[2])*vpn
[2];
745 scale
= 1 + scale
* 0.004;
747 // D_DrawParticle (p, up, right, scale);
748 int rv
= D_DrawParticleBuffered(part_buffer
,p
, up
, right
, scale
);
750 part_buffer
= D_CreateBuffer(part_buffer_size
);
755 p
->org
[0] += p
->vel
[0]*frametime
;
756 p
->org
[1] += p
->vel
[1]*frametime
;
757 p
->org
[2] += p
->vel
[2]*frametime
;
768 p
->color
= ramp3
[(int)p
->ramp
];
777 p
->color
= ramp1
[(int)p
->ramp
];
778 for (i
=0 ; i
<3 ; i
++)
779 p
->vel
[i
] += p
->vel
[i
]*dvel
;
788 p
->color
= ramp2
[(int)p
->ramp
];
789 for (i
=0 ; i
<3 ; i
++)
790 p
->vel
[i
] -= p
->vel
[i
]*frametime
;
795 for (i
=0 ; i
<3 ; i
++)
796 p
->vel
[i
] += p
->vel
[i
]*dvel
;
801 for (i
=0 ; i
<2 ; i
++)
802 p
->vel
[i
] -= p
->vel
[i
]*dvel
;
808 p
->vel
[2] -= grav
* 20;
816 #ifdef PSP_HARDWARE_VIDEO
817 D_DeleteBuffer(part_buffer
);