• 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 #ifdef QUAKE2
R_DarkFieldParticles(entity_t * ent)68 void R_DarkFieldParticles (entity_t *ent)
69 {
70 	int			i, j, k;
71 	particle_t	*p;
72 	float		vel;
73 	vec3_t		dir;
74 	vec3_t		org;
75 
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)
82 			{
83 				if (!free_particles)
84 					return;
85 				p = free_particles;
86 				free_particles = p->next;
87 				p->next = active_particles;
88 				active_particles = p;
89 
90 				p->die = cl.time + 0.2 + (rand()&7) * 0.02;
91 				p->color = 150 + rand()%6;
92 				p->type = pt_slowgrav;
93 
94 				dir[0] = j*8;
95 				dir[1] = i*8;
96 				dir[2] = k*8;
97 
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);
101 
102 				VectorNormalize (dir);
103 				vel = 50 + (rand()&63);
104 				VectorScale (dir, vel, p->vel);
105 			}
106 }
107 #endif
108 
109 
110 /*
111 ===============
112 R_EntityParticles
113 ===============
114 */
115 
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;
123 
R_EntityParticles(entity_t * ent)124 void R_EntityParticles (entity_t *ent)
125 {
126 	int			count;
127 	int			i;
128 	particle_t	*p;
129 	float		angle;
130 	float		sr, sp, sy, cr, cp, cy;
131 	vec3_t		forward;
132 	float		dist;
133 
134 	dist = 64;
135 	count = 50;
136 
137 if (!avelocities[0][0])
138 {
139 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
140 avelocities[i/3][i%3] = (rand()&255) * 0.01;
141 }
142 
143 
144 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
145 	{
146 		angle = cl.time * avelocities[i][0];
147 		sy = sin(angle);
148 		cy = cos(angle);
149 		angle = cl.time * avelocities[i][1];
150 		sp = sin(angle);
151 		cp = cos(angle);
152 		angle = cl.time * avelocities[i][2];
153 		sr = sin(angle);
154 		cr = cos(angle);
155 
156 		forward[0] = cp*cy;
157 		forward[1] = cp*sy;
158 		forward[2] = -sp;
159 
160 		if (!free_particles)
161 			return;
162 		p = free_particles;
163 		free_particles = p->next;
164 		p->next = active_particles;
165 		active_particles = p;
166 
167 		p->die = cl.time + 0.01;
168 		p->color = 0x6f;
169 		p->type = pt_explode;
170 
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;
174 	}
175 }
176 
177 
178 /*
179 ===============
180 R_ClearParticles
181 ===============
182 */
R_ClearParticles(void)183 void R_ClearParticles (void)
184 {
185 	int		i;
186 
187 	free_particles = &particles[0];
188 	active_particles = NULL;
189 
190 	for (i=0 ;i<r_numparticles ; i++)
191 		particles[i].next = &particles[i+1];
192 	particles[r_numparticles-1].next = NULL;
193 }
194 
195 
R_ReadPointFile_f(void)196 void R_ReadPointFile_f (void)
197 {
198 	FILE	*f;
199 	vec3_t	org;
200 	int		r;
201 	int		c;
202 	particle_t	*p;
203 	char	name[MAX_OSPATH];
204 
205 	sprintf (name,"maps/%s.pts", sv.name);
206 
207 	COM_FOpenFile (name, &f);
208 	if (!f)
209 	{
210 		Con_Printf ("couldn't open %s\n", name);
211 		return;
212 	}
213 
214 	Con_Printf ("Reading %s...\n", name);
215 	c = 0;
216 	for ( ;; )
217 	{
218 		r = fscanf (f,"%f %f %f\n", &org[0], &org[1], &org[2]);
219 		if (r != 3)
220 			break;
221 		c++;
222 
223 		if (!free_particles)
224 		{
225 			Con_Printf ("Not enough free particles\n");
226 			break;
227 		}
228 		p = free_particles;
229 		free_particles = p->next;
230 		p->next = active_particles;
231 		active_particles = p;
232 
233 		p->die = 99999;
234 		p->color = (-c)&15;
235 		p->type = pt_static;
236 		VectorCopy (vec3_origin, p->vel);
237 		VectorCopy (org, p->org);
238 	}
239 
240 	fclose (f);
241 	Con_Printf ("%i points read\n", c);
242 }
243 
244 /*
245 ===============
246 R_ParseParticleEffect
247 
248 Parse an effect out of the server message
249 ===============
250 */
R_ParseParticleEffect(void)251 void R_ParseParticleEffect (void)
252 {
253 	vec3_t		org, dir;
254 	int			i, count, msgcount, color;
255 
256 	for (i=0 ; i<3 ; i++)
257 		org[i] = MSG_ReadCoord ();
258 	for (i=0 ; i<3 ; i++)
259 		dir[i] = MSG_ReadChar () * (1.0/16);
260 	msgcount = MSG_ReadByte ();
261 	color = MSG_ReadByte ();
262 
263 if (msgcount == 255)
264 	count = 1024;
265 else
266 	count = msgcount;
267 
268 	R_RunParticleEffect (org, dir, color, count);
269 }
270 
271 /*
272 ===============
273 R_ParticleExplosion
274 
275 ===============
276 */
R_ParticleExplosion(vec3_t org)277 void R_ParticleExplosion (vec3_t org)
278 {
279 	int			i, j;
280 	particle_t	*p;
281 
282 	for (i=0 ; i<1024 ; i++)
283 	{
284 		if (!free_particles)
285 			return;
286 		p = free_particles;
287 		free_particles = p->next;
288 		p->next = active_particles;
289 		active_particles = p;
290 
291 		p->die = cl.time + 5;
292 		p->color = ramp1[0];
293 		p->ramp = rand()&3;
294 		if (i & 1)
295 		{
296 			p->type = pt_explode;
297 			for (j=0 ; j<3 ; j++)
298 			{
299 				p->org[j] = org[j] + ((rand()%32)-16);
300 				p->vel[j] = (rand()%512)-256;
301 			}
302 		}
303 		else
304 		{
305 			p->type = pt_explode2;
306 			for (j=0 ; j<3 ; j++)
307 			{
308 				p->org[j] = org[j] + ((rand()%32)-16);
309 				p->vel[j] = (rand()%512)-256;
310 			}
311 		}
312 	}
313 }
314 
315 /*
316 ===============
317 R_ParticleExplosion2
318 
319 ===============
320 */
R_ParticleExplosion2(vec3_t org,int colorStart,int colorLength)321 void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
322 {
323 	int			i, j;
324 	particle_t	*p;
325 	int			colorMod = 0;
326 
327 	for (i=0; i<512; i++)
328 	{
329 		if (!free_particles)
330 			return;
331 		p = free_particles;
332 		free_particles = p->next;
333 		p->next = active_particles;
334 		active_particles = p;
335 
336 		p->die = cl.time + 0.3;
337 		p->color = colorStart + (colorMod % colorLength);
338 		colorMod++;
339 
340 		p->type = pt_blob;
341 		for (j=0 ; j<3 ; j++)
342 		{
343 			p->org[j] = org[j] + ((rand()%32)-16);
344 			p->vel[j] = (rand()%512)-256;
345 		}
346 	}
347 }
348 
349 /*
350 ===============
351 R_BlobExplosion
352 
353 ===============
354 */
R_BlobExplosion(vec3_t org)355 void R_BlobExplosion (vec3_t org)
356 {
357 	int			i, j;
358 	particle_t	*p;
359 
360 	for (i=0 ; i<1024 ; i++)
361 	{
362 		if (!free_particles)
363 			return;
364 		p = free_particles;
365 		free_particles = p->next;
366 		p->next = active_particles;
367 		active_particles = p;
368 
369 		p->die = cl.time + 1 + (rand()&8)*0.05;
370 
371 		if (i & 1)
372 		{
373 			p->type = pt_blob;
374 			p->color = 66 + rand()%6;
375 			for (j=0 ; j<3 ; j++)
376 			{
377 				p->org[j] = org[j] + ((rand()%32)-16);
378 				p->vel[j] = (rand()%512)-256;
379 			}
380 		}
381 		else
382 		{
383 			p->type = pt_blob2;
384 			p->color = 150 + rand()%6;
385 			for (j=0 ; j<3 ; j++)
386 			{
387 				p->org[j] = org[j] + ((rand()%32)-16);
388 				p->vel[j] = (rand()%512)-256;
389 			}
390 		}
391 	}
392 }
393 
394 /*
395 ===============
396 R_RunParticleEffect
397 
398 ===============
399 */
R_RunParticleEffect(vec3_t org,vec3_t dir,int color,int count)400 void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
401 {
402 	int			i, j;
403 	particle_t	*p;
404 
405 	for (i=0 ; i<count ; i++)
406 	{
407 		if (!free_particles)
408 			return;
409 		p = free_particles;
410 		free_particles = p->next;
411 		p->next = active_particles;
412 		active_particles = p;
413 
414 		if (count == 1024)
415 		{	// rocket explosion
416 			p->die = cl.time + 5;
417 			p->color = ramp1[0];
418 			p->ramp = rand()&3;
419 			if (i & 1)
420 			{
421 				p->type = pt_explode;
422 				for (j=0 ; j<3 ; j++)
423 				{
424 					p->org[j] = org[j] + ((rand()%32)-16);
425 					p->vel[j] = (rand()%512)-256;
426 				}
427 			}
428 			else
429 			{
430 				p->type = pt_explode2;
431 				for (j=0 ; j<3 ; j++)
432 				{
433 					p->org[j] = org[j] + ((rand()%32)-16);
434 					p->vel[j] = (rand()%512)-256;
435 				}
436 			}
437 		}
438 		else
439 		{
440 			p->die = cl.time + 0.1*(rand()%5);
441 			p->color = (color&~7) + (rand()&7);
442 			p->type = pt_slowgrav;
443 			for (j=0 ; j<3 ; j++)
444 			{
445 				p->org[j] = org[j] + ((rand()&15)-8);
446 				p->vel[j] = dir[j]*15;// + (rand()%300)-150;
447 			}
448 		}
449 	}
450 }
451 
452 
453 /*
454 ===============
455 R_LavaSplash
456 
457 ===============
458 */
R_LavaSplash(vec3_t org)459 void R_LavaSplash (vec3_t org)
460 {
461 	int			i, j, k;
462 	particle_t	*p;
463 	float		vel;
464 	vec3_t		dir;
465 
466 	for (i=-16 ; i<16 ; i++)
467 		for (j=-16 ; j<16 ; j++)
468 			for (k=0 ; k<1 ; k++)
469 			{
470 				if (!free_particles)
471 					return;
472 				p = free_particles;
473 				free_particles = p->next;
474 				p->next = active_particles;
475 				active_particles = p;
476 
477 				p->die = cl.time + 2 + (rand()&31) * 0.02;
478 				p->color = 224 + (rand()&7);
479 				p->type = pt_slowgrav;
480 
481 				dir[0] = j*8 + (rand()&7);
482 				dir[1] = i*8 + (rand()&7);
483 				dir[2] = 256;
484 
485 				p->org[0] = org[0] + dir[0];
486 				p->org[1] = org[1] + dir[1];
487 				p->org[2] = org[2] + (rand()&63);
488 
489 				VectorNormalize (dir);
490 				vel = 50 + (rand()&63);
491 				VectorScale (dir, vel, p->vel);
492 			}
493 }
494 
495 /*
496 ===============
497 R_TeleportSplash
498 
499 ===============
500 */
R_TeleportSplash(vec3_t org)501 void R_TeleportSplash (vec3_t org)
502 {
503 	int			i, j, k;
504 	particle_t	*p;
505 	float		vel;
506 	vec3_t		dir;
507 
508 	for (i=-16 ; i<16 ; i+=4)
509 		for (j=-16 ; j<16 ; j+=4)
510 			for (k=-24 ; k<32 ; k+=4)
511 			{
512 				if (!free_particles)
513 					return;
514 				p = free_particles;
515 				free_particles = p->next;
516 				p->next = active_particles;
517 				active_particles = p;
518 
519 				p->die = cl.time + 0.2 + (rand()&7) * 0.02;
520 				p->color = 7 + (rand()&7);
521 				p->type = pt_slowgrav;
522 
523 				dir[0] = j*8;
524 				dir[1] = i*8;
525 				dir[2] = k*8;
526 
527 				p->org[0] = org[0] + i + (rand()&3);
528 				p->org[1] = org[1] + j + (rand()&3);
529 				p->org[2] = org[2] + k + (rand()&3);
530 
531 				VectorNormalize (dir);
532 				vel = 50 + (rand()&63);
533 				VectorScale (dir, vel, p->vel);
534 			}
535 }
536 
R_RocketTrail(vec3_t start,vec3_t end,int type)537 void R_RocketTrail (vec3_t start, vec3_t end, int type)
538 {
539 	vec3_t		vec;
540 	float		len;
541 	int			j;
542 	particle_t	*p;
543 	int			dec;
544 	static int	tracercount;
545 
546 	VectorSubtract (end, start, vec);
547 	len = VectorNormalize (vec);
548 	if (type < 128)
549 		dec = 3;
550 	else
551 	{
552 		dec = 1;
553 		type -= 128;
554 	}
555 
556 	while (len > 0)
557 	{
558 		len -= dec;
559 
560 		if (!free_particles)
561 			return;
562 		p = free_particles;
563 		free_particles = p->next;
564 		p->next = active_particles;
565 		active_particles = p;
566 
567 		VectorCopy (vec3_origin, p->vel);
568 		p->die = cl.time + 2;
569 
570 		switch (type)
571 		{
572 			case 0:	// rocket trail
573 				p->ramp = (rand()&3);
574 				p->color = ramp3[(int)p->ramp];
575 				p->type = pt_fire;
576 				for (j=0 ; j<3 ; j++)
577 					p->org[j] = start[j] + ((rand()%6)-3);
578 				break;
579 
580 			case 1:	// smoke smoke
581 				p->ramp = (rand()&3) + 2;
582 				p->color = ramp3[(int)p->ramp];
583 				p->type = pt_fire;
584 				for (j=0 ; j<3 ; j++)
585 					p->org[j] = start[j] + ((rand()%6)-3);
586 				break;
587 
588 			case 2:	// blood
589 				p->type = pt_grav;
590 				p->color = 67 + (rand()&3);
591 				for (j=0 ; j<3 ; j++)
592 					p->org[j] = start[j] + ((rand()%6)-3);
593 				break;
594 
595 			case 3:
596 			case 5:	// tracer
597 				p->die = cl.time + 0.5;
598 				p->type = pt_static;
599 				if (type == 3)
600 					p->color = 52 + ((tracercount&4)<<1);
601 				else
602 					p->color = 230 + ((tracercount&4)<<1);
603 
604 				tracercount++;
605 
606 				VectorCopy (start, p->org);
607 				if (tracercount & 1)
608 				{
609 					p->vel[0] = 30*vec[1];
610 					p->vel[1] = 30*-vec[0];
611 				}
612 				else
613 				{
614 					p->vel[0] = 30*-vec[1];
615 					p->vel[1] = 30*vec[0];
616 				}
617 				break;
618 
619 			case 4:	// slight blood
620 				p->type = pt_grav;
621 				p->color = 67 + (rand()&3);
622 				for (j=0 ; j<3 ; j++)
623 					p->org[j] = start[j] + ((rand()%6)-3);
624 				len -= 3;
625 				break;
626 
627 			case 6:	// voor trail
628 				p->color = 9*16 + 8 + (rand()&3);
629 				p->type = pt_static;
630 				p->die = cl.time + 0.3;
631 				for (j=0 ; j<3 ; j++)
632 					p->org[j] = start[j] + ((rand()&15)-8);
633 				break;
634 		}
635 
636 
637 		VectorAdd (start, vec, start);
638 	}
639 }
640 
641 
642 /*
643 ===============
644 R_DrawParticles
645 ===============
646 */
647 extern	cvar_t	sv_gravity;
648 
R_DrawParticles(void)649 void R_DrawParticles (void)
650 {
651 	particle_t		*p, *kill;
652 	float			grav;
653 	int				i;
654 	float			time2, time3;
655 	float			time1;
656 	float			dvel;
657 	float			frametime;
658 #ifdef USE_OPENGLES
659 	float*			pPos = gVertexBuffer;
660 	unsigned char*	pColor = (unsigned char*) gColorBuffer;
661 	unsigned char*  pUV = (unsigned char*) gTexCoordBuffer;
662 	int				particleIndex = 0;
663 	int				maxParticleIndex = (int) sizeof(gVertexBuffer) / (sizeof(float) * 3) - 3;
664 #endif
665 #ifdef GLQUAKE
666 	vec3_t			up, right;
667 	float			scale;
668 
669 	GL_Bind(particletexture);
670 
671 	glEnable (GL_BLEND);
672 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
673 
674 #ifdef USE_OPENGLES
675 	glEnableClientState(GL_COLOR_ARRAY);
676 	glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
677 	glTexCoordPointer(2, GL_BYTE, 0, gTexCoordBuffer);
678 	glColorPointer(4, GL_UNSIGNED_BYTE, 0, gColorBuffer);
679 	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
680 #else
681 	glBegin (GL_TRIANGLES);
682 #endif
683 
684 	VectorScale (vup, 1.5, up);
685 	VectorScale (vright, 1.5, right);
686 #else
687 	D_StartParticles ();
688 
689 	VectorScale (vright, xscaleshrink, r_pright);
690 	VectorScale (vup, yscaleshrink, r_pup);
691 	VectorCopy (vpn, r_ppn);
692 #endif
693 	frametime = cl.time - cl.oldtime;
694 	time3 = frametime * 15;
695 	time2 = frametime * 10; // 15;
696 	time1 = frametime * 5;
697 	grav = frametime * sv_gravity.value * 0.05;
698 	dvel = 4*frametime;
699 
700 	for ( ;; )
701 	{
702 		kill = active_particles;
703 		if (kill && kill->die < cl.time)
704 		{
705 			active_particles = kill->next;
706 			kill->next = free_particles;
707 			free_particles = kill;
708 			continue;
709 		}
710 		break;
711 	}
712 
713 	for (p=active_particles ; p ; p=p->next)
714 	{
715 		for ( ;; )
716 		{
717 			kill = p->next;
718 			if (kill && kill->die < cl.time)
719 			{
720 				p->next = kill->next;
721 				kill->next = free_particles;
722 				free_particles = kill;
723 				continue;
724 			}
725 			break;
726 		}
727 
728 #ifdef GLQUAKE
729 		// hack a scale up to keep particles from disapearing
730 		scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
731 			+ (p->org[2] - r_origin[2])*vpn[2];
732 		if (scale < 20)
733 			scale = 1;
734 		else
735 			scale = 1 + scale * 0.004;
736 #ifdef USE_OPENGLES
737 
738 		if(particleIndex >= maxParticleIndex)
739 		{
740 			glDrawArrays(GL_TRIANGLES, 0, particleIndex);
741 			particleIndex = 0;
742 			pPos = gVertexBuffer;
743 			pColor = (unsigned char*) gColorBuffer;
744 			pUV = (unsigned char*) gTexCoordBuffer;
745 		}
746 
747 		memcpy(pColor, (byte *)&d_8to24table[(int)p->color], 3);
748 		pColor[3] = 255;
749 		pColor += 4;
750 		*pUV++ = 0;
751 		*pUV++ = 0;
752 		*pPos++ = p->org[0];
753 		*pPos++ = p->org[1];
754 		*pPos++ = p->org[2];
755 
756 		memcpy(pColor, (byte *)&d_8to24table[(int)p->color], 3);
757 		pColor[3] = 255;
758 		pColor += 4;
759 		*pUV++ = 1;
760 		*pUV++ = 0;
761 		*pPos++ = p->org[0] + up[0]*scale;
762 		*pPos++ = p->org[1] + up[1]*scale;
763 		*pPos++ = p->org[2] + up[2]*scale;
764 
765 		memcpy(pColor, (byte *)&d_8to24table[(int)p->color], 3);
766 		pColor[3] = 255;
767 		pColor += 4;
768 		*pUV++ = 0;
769 		*pUV++ = 1;
770 		*pPos++ = p->org[0] + right[0]*scale;
771 		*pPos++ = p->org[1] + right[1]*scale;
772 		*pPos++ = p->org[2] + right[2]*scale;
773 
774 		particleIndex += 3;
775 
776 #else
777 		glColor3ubv ((byte *)&d_8to24table[(int)p->color]);
778 		glTexCoord2f (0,0);
779 		glVertex3fv (p->org);
780 		glTexCoord2f (1,0);
781 		glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale);
782 		glTexCoord2f (0,1);
783 		glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale);
784 #endif // !USE_OPENGLES
785 #else
786 		D_DrawParticle (p);
787 #endif
788 		p->org[0] += p->vel[0]*frametime;
789 		p->org[1] += p->vel[1]*frametime;
790 		p->org[2] += p->vel[2]*frametime;
791 
792 		switch (p->type)
793 		{
794 		case pt_static:
795 			break;
796 		case pt_fire:
797 			p->ramp += time1;
798 			if (p->ramp >= 6)
799 				p->die = -1;
800 			else
801 				p->color = ramp3[(int)p->ramp];
802 			p->vel[2] += grav;
803 			break;
804 
805 		case pt_explode:
806 			p->ramp += time2;
807 			if (p->ramp >=8)
808 				p->die = -1;
809 			else
810 				p->color = ramp1[(int)p->ramp];
811 			for (i=0 ; i<3 ; i++)
812 				p->vel[i] += p->vel[i]*dvel;
813 			p->vel[2] -= grav;
814 			break;
815 
816 		case pt_explode2:
817 			p->ramp += time3;
818 			if (p->ramp >=8)
819 				p->die = -1;
820 			else
821 				p->color = ramp2[(int)p->ramp];
822 			for (i=0 ; i<3 ; i++)
823 				p->vel[i] -= p->vel[i]*frametime;
824 			p->vel[2] -= grav;
825 			break;
826 
827 		case pt_blob:
828 			for (i=0 ; i<3 ; i++)
829 				p->vel[i] += p->vel[i]*dvel;
830 			p->vel[2] -= grav;
831 			break;
832 
833 		case pt_blob2:
834 			for (i=0 ; i<2 ; i++)
835 				p->vel[i] -= p->vel[i]*dvel;
836 			p->vel[2] -= grav;
837 			break;
838 
839 		case pt_grav:
840 #ifdef QUAKE2
841 			p->vel[2] -= grav * 20;
842 			break;
843 #endif
844 		case pt_slowgrav:
845 			p->vel[2] -= grav;
846 			break;
847 	    default:
848 	        break;
849 		}
850 	}
851 
852 #ifdef GLQUAKE
853 #ifdef USE_OPENGLES
854 	glDrawArrays(GL_TRIANGLES, 0, particleIndex);
855 	glDisableClientState(GL_COLOR_ARRAY);
856 	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
857 #else
858 	glEnd ();
859 #endif
860 	glDisable (GL_BLEND);
861 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
862 #else
863 	D_EndParticles ();
864 #endif
865 }
866 
867