• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
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.
8 
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.
12 
13 See the GNU General Public License for more details.
14 
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.
18 
19 */
20 
21 #include "quakedef.h"
22 #include "r_local.h"
23 
24 #define MAX_PARTICLES			2048	// default max # of particles at one
25 										//  time
26 #define ABSOLUTE_MIN_PARTICLES	512		// no fewer than this no matter what's
27 										//  on the command line
28 
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, 6, 5, 4, 3};
32 
33 particle_t	*active_particles, *free_particles;
34 
35 particle_t	*particles;
36 int			r_numparticles;
37 
38 vec3_t			r_pright, r_pup, r_ppn;
39 
40 
41 /*
42 ===============
43 R_InitParticles
44 ===============
45 */
R_InitParticles(void)46 void R_InitParticles (void)
47 {
48 	int		i;
49 
50 	i = COM_CheckParm ("-particles");
51 
52 	if (i)
53 	{
54 		r_numparticles = (int)(Q_atoi(com_argv[i+1]));
55 		if (r_numparticles < ABSOLUTE_MIN_PARTICLES)
56 			r_numparticles = ABSOLUTE_MIN_PARTICLES;
57 	}
58 	else
59 	{
60 		r_numparticles = MAX_PARTICLES;
61 	}
62 
63 	particles = (particle_t *)
64 			Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
65 }
66 
67 
68 /*
69 ===============
70 R_ClearParticles
71 ===============
72 */
R_ClearParticles(void)73 void R_ClearParticles (void)
74 {
75 	int		i;
76 
77 	free_particles = &particles[0];
78 	active_particles = NULL;
79 
80 	for (i=0 ;i<r_numparticles ; i++)
81 		particles[i].next = &particles[i+1];
82 	particles[r_numparticles-1].next = NULL;
83 }
84 
85 
R_ReadPointFile_f(void)86 void R_ReadPointFile_f (void)
87 {
88 	FILE	*f;
89 	vec3_t	org;
90 	int		r;
91 	int		c;
92 	particle_t	*p;
93 	char	name[MAX_OSPATH];
94 
95 // FIXME	sprintf (name,"maps/%s.pts", sv.name);
96 
97 	COM_FOpenFile (name, &f);
98 	if (!f)
99 	{
100 		Con_Printf ("couldn't open %s\n", name);
101 		return;
102 	}
103 
104 	Con_Printf ("Reading %s...\n", name);
105 	c = 0;
106 	for ( ;; )
107 	{
108 		r = fscanf (f,"%f %f %f\n", &org[0], &org[1], &org[2]);
109 		if (r != 3)
110 			break;
111 		c++;
112 
113 		if (!free_particles)
114 		{
115 			Con_Printf ("Not enough free particles\n");
116 			break;
117 		}
118 		p = free_particles;
119 		free_particles = p->next;
120 		p->next = active_particles;
121 		active_particles = p;
122 
123 		p->die = 99999;
124 		p->color = (-c)&15;
125 		p->type = pt_static;
126 		VectorCopy (vec3_origin, p->vel);
127 		VectorCopy (org, p->org);
128 	}
129 
130 	fclose (f);
131 	Con_Printf ("%i points read\n", c);
132 }
133 
134 /*
135 ===============
136 R_ParticleExplosion
137 
138 ===============
139 */
R_ParticleExplosion(vec3_t org)140 void R_ParticleExplosion (vec3_t org)
141 {
142 	int			i, j;
143 	particle_t	*p;
144 
145 	for (i=0 ; i<1024 ; i++)
146 	{
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 = cl.time + 5;
155 		p->color = ramp1[0];
156 		p->ramp = rand()&3;
157 		if (i & 1)
158 		{
159 			p->type = pt_explode;
160 			for (j=0 ; j<3 ; j++)
161 			{
162 				p->org[j] = org[j] + ((rand()%32)-16);
163 				p->vel[j] = (rand()%512)-256;
164 			}
165 		}
166 		else
167 		{
168 			p->type = pt_explode2;
169 			for (j=0 ; j<3 ; j++)
170 			{
171 				p->org[j] = org[j] + ((rand()%32)-16);
172 				p->vel[j] = (rand()%512)-256;
173 			}
174 		}
175 	}
176 }
177 
178 /*
179 ===============
180 R_BlobExplosion
181 
182 ===============
183 */
R_BlobExplosion(vec3_t org)184 void R_BlobExplosion (vec3_t org)
185 {
186 	int			i, j;
187 	particle_t	*p;
188 
189 	for (i=0 ; i<1024 ; i++)
190 	{
191 		if (!free_particles)
192 			return;
193 		p = free_particles;
194 		free_particles = p->next;
195 		p->next = active_particles;
196 		active_particles = p;
197 
198 		p->die = cl.time + 1 + (rand()&8)*0.05;
199 
200 		if (i & 1)
201 		{
202 			p->type = pt_blob;
203 			p->color = 66 + rand()%6;
204 			for (j=0 ; j<3 ; j++)
205 			{
206 				p->org[j] = org[j] + ((rand()%32)-16);
207 				p->vel[j] = (rand()%512)-256;
208 			}
209 		}
210 		else
211 		{
212 			p->type = pt_blob2;
213 			p->color = 150 + rand()%6;
214 			for (j=0 ; j<3 ; j++)
215 			{
216 				p->org[j] = org[j] + ((rand()%32)-16);
217 				p->vel[j] = (rand()%512)-256;
218 			}
219 		}
220 	}
221 }
222 
223 /*
224 ===============
225 R_RunParticleEffect
226 
227 ===============
228 */
R_RunParticleEffect(vec3_t org,vec3_t dir,int color,int count)229 void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
230 {
231 	int			i, j;
232 	particle_t	*p;
233 	int			scale;
234 
235 	if (count > 130)
236 		scale = 3;
237 	else if (count > 20)
238 		scale = 2;
239 	else
240 		scale = 1;
241 
242 	for (i=0 ; i<count ; i++)
243 	{
244 		if (!free_particles)
245 			return;
246 		p = free_particles;
247 		free_particles = p->next;
248 		p->next = active_particles;
249 		active_particles = p;
250 
251 		p->die = cl.time + 0.1*(rand()%5);
252 		p->color = (color&~7) + (rand()&7);
253 		p->type = pt_grav;
254 		for (j=0 ; j<3 ; j++)
255 		{
256 			p->org[j] = org[j] + scale*((rand()&15)-8);
257 			p->vel[j] = dir[j]*15;// + (rand()%300)-150;
258 		}
259 	}
260 }
261 
262 
263 /*
264 ===============
265 R_LavaSplash
266 
267 ===============
268 */
R_LavaSplash(vec3_t org)269 void R_LavaSplash (vec3_t org)
270 {
271 	int			i, j, k;
272 	particle_t	*p;
273 	float		vel;
274 	vec3_t		dir;
275 
276 	for (i=-16 ; i<16 ; i++)
277 		for (j=-16 ; j<16 ; j++)
278 			for (k=0 ; k<1 ; k++)
279 			{
280 				if (!free_particles)
281 					return;
282 				p = free_particles;
283 				free_particles = p->next;
284 				p->next = active_particles;
285 				active_particles = p;
286 
287 				p->die = cl.time + 2 + (rand()&31) * 0.02;
288 				p->color = 224 + (rand()&7);
289 				p->type = pt_grav;
290 
291 				dir[0] = j*8 + (rand()&7);
292 				dir[1] = i*8 + (rand()&7);
293 				dir[2] = 256;
294 
295 				p->org[0] = org[0] + dir[0];
296 				p->org[1] = org[1] + dir[1];
297 				p->org[2] = org[2] + (rand()&63);
298 
299 				VectorNormalize (dir);
300 				vel = 50 + (rand()&63);
301 				VectorScale (dir, vel, p->vel);
302 			}
303 }
304 
305 /*
306 ===============
307 R_TeleportSplash
308 
309 ===============
310 */
R_TeleportSplash(vec3_t org)311 void R_TeleportSplash (vec3_t org)
312 {
313 	int			i, j, k;
314 	particle_t	*p;
315 	float		vel;
316 	vec3_t		dir;
317 
318 	for (i=-16 ; i<16 ; i+=4)
319 		for (j=-16 ; j<16 ; j+=4)
320 			for (k=-24 ; k<32 ; k+=4)
321 			{
322 				if (!free_particles)
323 					return;
324 				p = free_particles;
325 				free_particles = p->next;
326 				p->next = active_particles;
327 				active_particles = p;
328 
329 				p->die = cl.time + 0.2 + (rand()&7) * 0.02;
330 				p->color = 7 + (rand()&7);
331 				p->type = pt_grav;
332 
333 				dir[0] = j*8;
334 				dir[1] = i*8;
335 				dir[2] = k*8;
336 
337 				p->org[0] = org[0] + i + (rand()&3);
338 				p->org[1] = org[1] + j + (rand()&3);
339 				p->org[2] = org[2] + k + (rand()&3);
340 
341 				VectorNormalize (dir);
342 				vel = 50 + (rand()&63);
343 				VectorScale (dir, vel, p->vel);
344 			}
345 }
346 
R_RocketTrail(vec3_t start,vec3_t end,int type)347 void R_RocketTrail (vec3_t start, vec3_t end, int type)
348 {
349 	vec3_t	vec;
350 	float	len;
351 	int			j;
352 	particle_t	*p;
353 
354 	VectorSubtract (end, start, vec);
355 	len = VectorNormalize (vec);
356 	while (len > 0)
357 	{
358 		len -= 3;
359 
360 		if (!free_particles)
361 			return;
362 		p = free_particles;
363 		free_particles = p->next;
364 		p->next = active_particles;
365 		active_particles = p;
366 
367 		VectorCopy (vec3_origin, p->vel);
368 		p->die = cl.time + 2;
369 
370 		if (type == 4)
371 		{	// slight blood
372 			p->type = pt_slowgrav;
373 			p->color = 67 + (rand()&3);
374 			for (j=0 ; j<3 ; j++)
375 				p->org[j] = start[j] + ((rand()%6)-3);
376 			len -= 3;
377 		}
378 		else if (type == 2)
379 		{	// blood
380 			p->type = pt_slowgrav;
381 			p->color = 67 + (rand()&3);
382 			for (j=0 ; j<3 ; j++)
383 				p->org[j] = start[j] + ((rand()%6)-3);
384 		}
385 		else if (type == 6)
386 		{	// voor trail
387 			p->color = 9*16 + 8 + (rand()&3);
388 			p->type = pt_static;
389 			p->die = cl.time + 0.3;
390 			for (j=0 ; j<3 ; j++)
391 				p->org[j] = start[j] + ((rand()&15)-8);
392 		}
393 		else if (type == 1)
394 		{	// smoke smoke
395 			p->ramp = (rand()&3) + 2;
396 			p->color = ramp3[(int)p->ramp];
397 			p->type = pt_fire;
398 			for (j=0 ; j<3 ; j++)
399 				p->org[j] = start[j] + ((rand()%6)-3);
400 		}
401 		else if (type == 0)
402 		{	// rocket trail
403 			p->ramp = (rand()&3);
404 			p->color = ramp3[(int)p->ramp];
405 			p->type = pt_fire;
406 			for (j=0 ; j<3 ; j++)
407 				p->org[j] = start[j] + ((rand()%6)-3);
408 		}
409 		else if (type == 3 || type == 5)
410 		{	// tracer
411 			static int tracercount;
412 
413 			p->die = cl.time + 0.5;
414 			p->type = pt_static;
415 			if (type == 3)
416 				p->color = 52 + ((tracercount&4)<<1);
417 			else
418 				p->color = 230 + ((tracercount&4)<<1);
419 
420 			tracercount++;
421 
422 			VectorCopy (start, p->org);
423 			if (tracercount & 1)
424 			{
425 				p->vel[0] = 30*vec[1];
426 				p->vel[1] = 30*-vec[0];
427 			}
428 			else
429 			{
430 				p->vel[0] = 30*-vec[1];
431 				p->vel[1] = 30*vec[0];
432 			}
433 
434 		}
435 
436 
437 		VectorAdd (start, vec, start);
438 	}
439 }
440 
441 
442 /*
443 ===============
444 R_DrawParticles
445 ===============
446 */
R_DrawParticles(void)447 void R_DrawParticles (void)
448 {
449 	particle_t		*p, *kill;
450 	float			grav;
451 	int				i;
452 	float			time2, time3;
453 	float			time1;
454 	float			dvel;
455 	float			frametime;
456 #ifdef GLQUAKE
457 	unsigned char	*at;
458 	unsigned char	theAlpha;
459 	vec3_t			up, right;
460 	float			scale;
461 	qboolean		alphaTestEnabled;
462 
463 	GL_Bind(particletexture);
464 #ifdef USE_OPENGLES
465 	// !!! Implement this
466 	alphaTestEnabled = false;
467 #else
468 	alphaTestEnabled = glIsEnabled(GL_ALPHA_TEST);
469 #endif
470 
471 	if (alphaTestEnabled)
472 		glDisable(GL_ALPHA_TEST);
473 	glEnable (GL_BLEND);
474 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
475 
476 #ifdef USE_OPENGLES
477 	// !!! Implement this
478 #else
479 	glBegin (GL_TRIANGLES);
480 #endif
481 
482 	VectorScale (vup, 1.5, up);
483 	VectorScale (vright, 1.5, right);
484 #else
485 	D_StartParticles ();
486 
487 	VectorScale (vright, xscaleshrink, r_pright);
488 	VectorScale (vup, yscaleshrink, r_pup);
489 	VectorCopy (vpn, r_ppn);
490 #endif
491 
492 	frametime = host_frametime;
493 	time3 = frametime * 15;
494 	time2 = frametime * 10; // 15;
495 	time1 = frametime * 5;
496 	grav = frametime * 800 * 0.05;
497 	dvel = 4*frametime;
498 
499 	for ( ;; )
500 	{
501 		kill = active_particles;
502 		if (kill && kill->die < cl.time)
503 		{
504 			active_particles = kill->next;
505 			kill->next = free_particles;
506 			free_particles = kill;
507 			continue;
508 		}
509 		break;
510 	}
511 
512 	for (p=active_particles ; p ; p=p->next)
513 	{
514 		for ( ;; )
515 		{
516 			kill = p->next;
517 			if (kill && kill->die < cl.time)
518 			{
519 				p->next = kill->next;
520 				kill->next = free_particles;
521 				free_particles = kill;
522 				continue;
523 			}
524 			break;
525 		}
526 
527 #ifdef GLQUAKE
528 		// hack a scale up to keep particles from disapearing
529 		scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
530 			+ (p->org[2] - r_origin[2])*vpn[2];
531 		if (scale < 20)
532 			scale = 1;
533 		else
534 			scale = 1 + scale * 0.004;
535 		at = (byte *)&d_8to24table[(int)p->color];
536 		if (p->type==pt_fire)
537 			theAlpha = 255*(6-p->ramp)/6;
538 //			theAlpha = 192;
539 //		else if (p->type==pt_explode || p->type==pt_explode2)
540 //			theAlpha = 255*(8-p->ramp)/8;
541 		else
542 			theAlpha = 255;
543 
544 #ifdef USE_OPENGLES
545 	// !!! Implement this
546 #else
547 		glColor4ub (*at, *(at+1), *(at+2), theAlpha);
548 //		glColor3ubv (at);
549 //		glColor3ubv ((byte *)&d_8to24table[(int)p->color]);
550 		glTexCoord2f (0,0);
551 		glVertex3fv (p->org);
552 		glTexCoord2f (1,0);
553 		glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale);
554 		glTexCoord2f (0,1);
555 		glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale);
556 #endif
557 
558 #else
559 		D_DrawParticle (p);
560 #endif
561 
562 		p->org[0] += p->vel[0]*frametime;
563 		p->org[1] += p->vel[1]*frametime;
564 		p->org[2] += p->vel[2]*frametime;
565 
566 		switch (p->type)
567 		{
568 		case pt_static:
569 			break;
570 		case pt_fire:
571 			p->ramp += time1;
572 			if (p->ramp >= 6)
573 				p->die = -1;
574 			else
575 				p->color = ramp3[(int)p->ramp];
576 			p->vel[2] += grav;
577 			break;
578 
579 		case pt_explode:
580 			p->ramp += time2;
581 			if (p->ramp >=8)
582 				p->die = -1;
583 			else
584 				p->color = ramp1[(int)p->ramp];
585 			for (i=0 ; i<3 ; i++)
586 				p->vel[i] += p->vel[i]*dvel;
587 			p->vel[2] -= grav;
588 			break;
589 
590 		case pt_explode2:
591 			p->ramp += time3;
592 			if (p->ramp >=8)
593 				p->die = -1;
594 			else
595 				p->color = ramp2[(int)p->ramp];
596 			for (i=0 ; i<3 ; i++)
597 				p->vel[i] -= p->vel[i]*frametime;
598 			p->vel[2] -= grav;
599 			break;
600 
601 		case pt_blob:
602 			for (i=0 ; i<3 ; i++)
603 				p->vel[i] += p->vel[i]*dvel;
604 			p->vel[2] -= grav;
605 			break;
606 
607 		case pt_blob2:
608 			for (i=0 ; i<2 ; i++)
609 				p->vel[i] -= p->vel[i]*dvel;
610 			p->vel[2] -= grav;
611 			break;
612 
613 		case pt_slowgrav:
614 		case pt_grav:
615 			p->vel[2] -= grav;
616 			break;
617 		}
618 	}
619 
620 #ifdef GLQUAKE
621 #ifdef USE_OPENGLES
622 	// !!! Implement this
623 #else
624 	glEnd ();
625 #endif
626 	glDisable (GL_BLEND);
627 	if (alphaTestEnabled)
628 		glEnable(GL_ALPHA_TEST);
629 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
630 #else
631 	D_EndParticles ();
632 #endif
633 }
634 
635