1 /*
2  * Sprites.cpp
3  * Copyright (C) 2007 by Bryan Duff <duff0097@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * 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
18  * USA
19  */
20 #include "Sprites.h"
21 #include "Globals.h"
22 
23 extern double multiplier;
24 extern bool slomo;
25 extern Fog fog;
26 extern bool blood;
27 //Functions
28 extern float sinefluct;
29 extern Environment environment;
30 extern Model gunmodels[10];
31 extern Camera camera;
32 
MakeSprite(int atype,float abrightness,float acolor1,float acolor2,float acolor3,XYZ alocation,XYZ avelocity,float asize)33 int Sprites::MakeSprite(int atype, float abrightness, float acolor1,
34                         float acolor2, float acolor3, XYZ alocation,
35                         XYZ avelocity, float asize)
36 {
37   type[howmanysprites] = atype;
38   rotation[howmanysprites] = Random() % 360;
39   brightness[howmanysprites] = abrightness;
40   color1[howmanysprites] = acolor1;
41   color2[howmanysprites] = acolor2;
42   color3[howmanysprites] = acolor3;
43   location[howmanysprites] = alocation;
44   oldlocation[howmanysprites] = alocation;
45   velocity[howmanysprites] = avelocity;
46   size[howmanysprites] = asize;
47   initialsize[howmanysprites] = asize;
48   initialbrightness[howmanysprites] = abrightness;
49   initialvelocity[howmanysprites] = avelocity;
50   alivetime[howmanysprites] = 0;
51   owner[howmanysprites] = 0;
52   if(howmanysprites < maxsprites) {
53     howmanysprites++;
54   }
55 
56   return 0;
57 }
58 
MakeSprite(int atype,float abrightness,float acolor1,float acolor2,float acolor3,XYZ alocation,XYZ avelocity,float asize,int aowner)59 int Sprites::MakeSprite(int atype, float abrightness, float acolor1,
60                         float acolor2, float acolor3, XYZ alocation,
61                         XYZ avelocity, float asize, int aowner)
62 {
63   type[howmanysprites] = atype;
64   rotation[howmanysprites] = Random() % 360;
65   brightness[howmanysprites] = abrightness;
66   color1[howmanysprites] = acolor1;
67   color2[howmanysprites] = acolor2;
68   color3[howmanysprites] = acolor3;
69   location[howmanysprites] = alocation;
70   oldlocation[howmanysprites] = alocation;
71   velocity[howmanysprites] = avelocity;
72   size[howmanysprites] = asize;
73   initialsize[howmanysprites] = asize;
74   initialbrightness[howmanysprites] = abrightness;
75   initialvelocity[howmanysprites] = avelocity;
76   alivetime[howmanysprites] = 0;
77   owner[howmanysprites] = aowner;
78   if(howmanysprites < maxsprites) {
79     howmanysprites++;
80   }
81 
82   return 0;
83 }
84 
DeleteSprite(int which)85 int Sprites::DeleteSprite(int which)
86 {
87   if(which >= 0) {
88     location[which] = location[howmanysprites - 1];
89     oldlocation[which] = oldlocation[howmanysprites - 1];
90     velocity[which] = velocity[howmanysprites - 1];
91     initialsize[which] = initialsize[howmanysprites - 1];
92     size[which] = size[howmanysprites - 1];
93     brightness[which] = brightness[howmanysprites - 1];
94     initialbrightness[which] = initialbrightness[howmanysprites - 1];
95     color1[which] = color1[howmanysprites - 1];
96     color2[which] = color2[howmanysprites - 1];
97     color3[which] = color3[howmanysprites - 1];
98     alivetime[which] = alivetime[howmanysprites - 1];
99     rotation[which] = rotation[howmanysprites - 1];
100     type[which] = type[howmanysprites - 1];
101     type[howmanysprites - 1] = 0;
102 
103     if(howmanysprites > 0) {
104       howmanysprites--;
105     }
106   }
107 
108   return 0;
109 }
110 
LoadFlareTexture(char * fileName)111 void Sprites::LoadFlareTexture(char *fileName)
112 {
113   TGAImageRec *tempTexture;
114   GLuint type;
115 
116   //Load Image
117   tempTexture = LoadTGA(fileName);
118   //Is it valid?
119   if(tempTexture) {
120     //Alpha channel?
121     if(tempTexture->bpp == 24)
122       type = GL_RGB;
123     else
124       type = GL_RGBA;
125 
126     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
127 
128     glGenTextures(1, &flaretextureptr);
129     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
130 
131     glBindTexture(GL_TEXTURE_2D, flaretextureptr);
132     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
133     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
134 
135     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
136                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
137                       tempTexture->data);
138     free(tempTexture->data);
139     free(tempTexture);
140   }
141 }
142 
LoadMuzzleFlareTexture(char * fileName)143 void Sprites::LoadMuzzleFlareTexture(char *fileName)
144 {
145   TGAImageRec *tempTexture;
146   GLuint type;
147 
148   //Load Image
149   tempTexture = LoadTGA(fileName);
150   //Is it valid?
151   if(tempTexture) {
152     //Alpha channel?
153     if(tempTexture->bpp == 24)
154       type = GL_RGB;
155     else
156       type = GL_RGBA;
157 
158     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
159 
160     glGenTextures(1, &muzzleflaretextureptr);
161     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
162 
163     glBindTexture(GL_TEXTURE_2D, muzzleflaretextureptr);
164     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
165     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
166 
167     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
168                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
169                       tempTexture->data);
170     free(tempTexture->data);
171     free(tempTexture);
172   }
173 }
174 
LoadSmokeTexture(char * fileName)175 void Sprites::LoadSmokeTexture(char *fileName)
176 {
177   TGAImageRec *tempTexture;
178   GLuint type;
179 
180   //Load Image
181   tempTexture = LoadTGA(fileName);
182   //Is it valid?
183   if(tempTexture) {
184     //Alpha channel?
185     if(tempTexture->bpp == 24)
186       type = GL_RGB;
187     else
188       type = GL_RGBA;
189 
190     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
191 
192     glGenTextures(1, &smoketextureptr);
193     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
194 
195     glBindTexture(GL_TEXTURE_2D, smoketextureptr);
196     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
197     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
198 
199     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
200                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
201                       tempTexture->data);
202     free(tempTexture->data);
203     free(tempTexture);
204   }
205 }
206 
LoadBloodTexture(char * fileName)207 void Sprites::LoadBloodTexture(char *fileName)
208 {
209   TGAImageRec *tempTexture;
210   GLuint type;
211 
212   //Load Image
213   tempTexture = LoadTGA(fileName);
214   //Is it valid?
215   if(tempTexture) {
216     //Alpha channel?
217     if(tempTexture->bpp == 24)
218       type = GL_RGB;
219     else
220       type = GL_RGBA;
221 
222     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
223 
224     glGenTextures(1, &bloodtextureptr);
225     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
226 
227     glBindTexture(GL_TEXTURE_2D, bloodtextureptr);
228     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
229     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
230 
231     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
232                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
233                       tempTexture->data);
234     free(tempTexture->data);
235     free(tempTexture);
236   }
237 }
238 
LoadRainTexture(char * fileName)239 void Sprites::LoadRainTexture(char *fileName)
240 {
241   TGAImageRec *tempTexture;
242   GLuint type;
243 
244   //Load Image
245   tempTexture = LoadTGA(fileName);
246   //Is it valid?
247   if(tempTexture) {
248     //Alpha channel?
249     if(tempTexture->bpp == 24)
250       type = GL_RGB;
251     else
252       type = GL_RGBA;
253 
254     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
255 
256     glGenTextures(1, &raintextureptr);
257     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
258 
259     glBindTexture(GL_TEXTURE_2D, raintextureptr);
260     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
261     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
262 
263     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
264                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
265                       tempTexture->data);
266     free(tempTexture->data);
267     free(tempTexture);
268   }
269 }
270 
LoadSnowTexture(char * fileName)271 void Sprites::LoadSnowTexture(char *fileName)
272 {
273   TGAImageRec *tempTexture;
274   GLuint type;
275 
276   //Load Image
277   tempTexture = LoadTGA(fileName);
278   //Is it valid?
279   if(tempTexture) {
280     //Alpha channel?
281     if(tempTexture->bpp == 24)
282       type = GL_RGB;
283     else
284       type = GL_RGBA;
285 
286     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
287 
288     glGenTextures(1, &snowtextureptr);
289     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
290 
291     glBindTexture(GL_TEXTURE_2D, snowtextureptr);
292     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
293     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
294 
295     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
296                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
297                       tempTexture->data);
298     free(tempTexture->data);
299     free(tempTexture);
300   }
301 }
302 
LoadBulletTexture(char * fileName)303 void Sprites::LoadBulletTexture(char *fileName)
304 {
305   TGAImageRec *tempTexture;
306   GLuint type;
307 
308   //Load Image
309   tempTexture = LoadTGA(fileName);
310   //Is it valid?
311   if(tempTexture) {
312     //Alpha channel?
313     if(tempTexture->bpp == 24)
314       type = GL_RGB;
315     else
316       type = GL_RGBA;
317 
318     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
319 
320     glGenTextures(1, &bullettextureptr);
321     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
322 
323     glBindTexture(GL_TEXTURE_2D, bullettextureptr);
324     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
325     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
326 
327     gluBuild2DMipmaps(GL_TEXTURE_2D, type, tempTexture->sizeX,
328                       tempTexture->sizeY, type, GL_UNSIGNED_BYTE,
329                       tempTexture->data);
330     free(tempTexture->data);
331     free(tempTexture);
332   }
333 }
334 
335 
DoStuff()336 void Sprites::DoStuff()
337 {
338   for(int i = 0; i < howmanysprites; i++) {
339     if(type[i] != bullet && type[i] != bulletinstant && type[i] != grenadesprite
340        && type[i] != pinsprite && type[i] != grenadesprite)
341       oldlocation[i] = location[i];
342     if(type[i] == muzzleflashsprite)
343       brightness[i] -= multiplier * 10;
344     if(type[i] == flashsprite)
345       brightness[i] -= multiplier * 10;
346     if(type[i] == smokesprite || type[i] == smokespritenoup
347        || type[i] == bloodspritedown || type[i] == particlesspritedown)
348       brightness[i] -= multiplier * .5;
349     if(type[i] == bloodspritenoup)
350       brightness[i] -= multiplier * .9;
351     if(type[i] == smokesprite)
352       size[i] = initialsize[i] * abs(fast_sqrt(fast_sqrt((float)abs(initialbrightness[i] - brightness[i]))));   //velocity[i].y+=multiplier*20;
353     if(type[i] == bloodspritenoup || type[i] == particlesspritedown)
354       size[i] = initialsize[i] * (initialbrightness[i] - brightness[i] + .4) * (initialbrightness[i] - brightness[i] + .4);     //velocity[i].y+=multiplier*20;
355     if(type[i] == bloodspritenoup || type[i] == particlesspritedown)
356       velocity[i] = initialvelocity[i] * brightness[i]; //velocity[i].y+=multiplier*20;
357     if(type[i] == bullet)
358       brightness[i] -= multiplier;
359     if(type[i] == snowsprite)
360       rotation[i] += multiplier * 50;
361     if(type[i] == smokesprite)
362       rotation[i] += multiplier * 30;
363     if(type[i] == smokespritenoup)
364       rotation[i] += multiplier * 30;
365     if(type[i] == bulletinstant) {
366       brightness[i] = 0;
367     }
368     if(type[i] == grenadesprite || type[i] == spoonsprite
369        || type[i] == pinsprite) {
370       if(findLengthfast(velocity[i]) > 0) {
371         velocity[i].y += gravity * multiplier;
372         rotation[i] += multiplier * 2;
373       }
374     }
375     if(type[i] == bloodspritedown || type[i] == particlesspritedown) {
376       velocity[i].y += gravity * multiplier;
377     }
378 
379     if(type[i] != bulletinstant && type[i] != bullet)
380       location[i] = location[i] + velocity[i] * multiplier;
381 
382     alivetime[i] += multiplier;
383     if(brightness[i] <= 0)
384       DeleteSprite(i);
385     if(type[i] == snowsprite
386        && (location[i].y < -.1 || environment.type != snowy_environment))
387       DeleteSprite(i);
388     if(type[i] == rainsprite
389        && (location[i].y < -.1 || environment.type != rainy_environment))
390       DeleteSprite(i);
391 
392     float precipitationhorz = environment.precipitationhorz;
393     float precipitationvert = environment.precipitationvert;
394     float precipitationdensity = environment.precipitationdensity;
395 
396     if(type[i] == snowsprite) {
397       if(location[i].x < camera.position.x - precipitationhorz) {
398         location[i].x += precipitationhorz * 2;
399       }
400       if(location[i].z < camera.position.z - precipitationhorz) {
401         location[i].z += precipitationhorz * 2;
402       }
403       if(location[i].y < camera.position.y - precipitationvert) {
404         location[i].y += precipitationvert * 2;
405         environment.snowdelay += 1 / precipitationdensity * 2;
406       }
407       if(location[i].x > camera.position.x + precipitationhorz) {
408         location[i].x -= precipitationhorz * 2;
409       }
410       if(location[i].z > camera.position.z + precipitationhorz) {
411         location[i].z -= precipitationhorz * 2;
412       }
413       if(location[i].y > camera.position.y + precipitationvert) {
414         location[i].y -= precipitationvert * 2;
415       }
416     }
417     if(type[i] == rainsprite) {
418       if(location[i].x < camera.position.x - precipitationhorz * .5) {
419         location[i].x += precipitationhorz;
420       }
421       if(location[i].z < camera.position.z - precipitationhorz * .5) {
422         location[i].z += precipitationhorz;
423       }
424       if(location[i].y < camera.position.y - precipitationvert) {
425         location[i].y += precipitationvert * 2;
426         environment.snowdelay += 1 / precipitationdensity / 4;
427       }
428       if(location[i].x > camera.position.x + precipitationhorz * .5) {
429         location[i].x -= precipitationhorz;
430       }
431       if(location[i].z > camera.position.z + precipitationhorz * .5) {
432         location[i].z -= precipitationhorz;
433       }
434       if(location[i].y > camera.position.y + precipitationvert) {
435         location[i].y -= precipitationvert * 2;
436       }
437     }
438   }
439 }
440 
draw()441 void Sprites::draw()
442 {
443   float M[16];
444   XYZ begProj, endProj, avgProj, persp;
445   float oolen, dx, dy;
446   float bulletsize;
447   XYZ point;
448   glAlphaFunc(GL_GREATER, 0.01);
449 
450   //glEnable(GL_POLYGON_OFFSET_FILL);
451 
452   glEnable(GL_BLEND);
453   glDisable(GL_CULL_FACE);
454   glEnable(GL_TEXTURE_2D);
455   glDisable(GL_LIGHTING);
456   glDepthMask(0);
457   glAlphaFunc(GL_GREATER, 0.01);
458 
459   for(int i = 0; i < howmanysprites; i++) {
460     if(type[i] == muzzleflashsprite) {
461       fog.TempFog(0, 0, 0);
462       glBindTexture(GL_TEXTURE_2D, muzzleflaretextureptr);
463       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
464     }
465     if(type[i] == flashsprite) {
466       fog.TempFog(0, 0, 0);
467       glBindTexture(GL_TEXTURE_2D, flaretextureptr);
468       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
469     }
470     if(type[i] == smokesprite || type[i] == smokespritenoup) {
471       fog.ResetFog();
472       glBindTexture(GL_TEXTURE_2D, smoketextureptr);
473       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
474     }
475     if(type[i] == bloodspritedown || type[i] == bloodspritenoup) {
476       fog.ResetFog();
477       glBindTexture(GL_TEXTURE_2D, smoketextureptr);
478       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
479     }
480     if(type[i] == particlesspritedown) {
481       fog.ResetFog();
482       glBindTexture(GL_TEXTURE_2D, bloodtextureptr);
483       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
484     }
485     if(type[i] == snowsprite) {
486       fog.ResetFog();
487       glBindTexture(GL_TEXTURE_2D, snowtextureptr);
488       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
489     }
490     if(type[i] == rainsprite) {
491       fog.ResetFog();
492       glBindTexture(GL_TEXTURE_2D, raintextureptr);
493       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
494     }
495     if(type[i] == bullet || type[i] == bulletinstant) {
496       fog.ResetFog();
497       glBindTexture(GL_TEXTURE_2D, bullettextureptr);
498       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
499     }
500 
501     glPushMatrix();
502     if(type[i] == muzzleflashsprite || type[i] == flashsprite
503        || type[i] == smokesprite || type[i] == smokespritenoup
504        || type[i] == snowsprite || type[i] == particlesspritedown
505        || ((type[i] == bloodspritenoup || type[i] == bloodspritedown)
506            && blood)) {
507       glColor4f(color1[i] * fog.fogcolor.r * 1.6,
508                 color2[i] * fog.fogcolor.g * 1.6,
509                 color3[i] * fog.fogcolor.b * 1.6, brightness[i]);
510       glTranslatef(location[i].x, location[i].y, location[i].z);
511       if(type[i] == snowsprite) {
512         glTranslatef(sinefluct * rotation[i] / 400, 0,
513                      sinefluct * rotation[i] / 400);
514       }
515       glGetFloatv(GL_MODELVIEW_MATRIX, M);
516       point.x = M[12];
517       point.y = M[13];
518       point.z = M[14];
519       glLoadIdentity();
520       glTranslatef(point.x, point.y, point.z);
521       glRotatef(rotation[i], 0, 0, 1);
522 
523       glBegin(GL_TRIANGLES);
524       glTexCoord2f(1.0f, 1.0f);
525       glVertex3f(.3f * size[i], .3f * size[i], 0.0f);
526       glTexCoord2f(0.0f, 1.0f);
527       glVertex3f(-.3f * size[i], .3f * size[i], 0.0f);
528       glTexCoord2f(1.0f, 0.0f);
529       glVertex3f(.3f * size[i], -.3f * size[i], 0.0f);
530       glTexCoord2f(0.0f, 0.0f);
531       glVertex3f(-.3f * size[i], -.3f * size[i], 0.0f);
532       glTexCoord2f(1.0f, 0.0f);
533       glVertex3f(.3f * size[i], -.3f * size[i], 0.0f);
534       glTexCoord2f(0.0f, 1.0f);
535       glVertex3f(-.3f * size[i], .3f * size[i], 0.0f);
536       glEnd();
537 
538     }
539 
540     if(type[i] == rainsprite) {
541       glColor4f(color1[i] * fog.fogcolor.r * 1.6,
542                 color2[i] * fog.fogcolor.g * 1.6,
543                 color3[i] * fog.fogcolor.b * 1.6, brightness[i]);
544       glTranslatef(location[i].x, location[i].y, location[i].z);
545       glGetFloatv(GL_MODELVIEW_MATRIX, M);
546       for(int k = 0; k < 3; k += 2)
547         for(int j = 0; j < 3; j++) {
548           if(k == j)
549             M[k * 4 + j] = 1.0;
550           else
551             M[k * 4 + j] = 0.0;
552         }
553 
554       glLoadMatrixf(M);
555       glScalef(.2, abs(velocity[i].y) * multiplier, .2);
556       glBegin(GL_TRIANGLES);
557       glTexCoord2f(1.0f, 1.0f);
558       glVertex3f(.3f * size[i], .3f * size[i], 0.0f);
559       glTexCoord2f(0.0f, 1.0f);
560       glVertex3f(-.3f * size[i], .3f * size[i], 0.0f);
561       glTexCoord2f(1.0f, 0.0f);
562       glVertex3f(.3f * size[i], -.3f * size[i], 0.0f);
563       glTexCoord2f(0.0f, 0.0f);
564       glVertex3f(-.3f * size[i], -.3f * size[i], 0.0f);
565       glTexCoord2f(1.0f, 0.0f);
566       glVertex3f(.3f * size[i], -.3f * size[i], 0.0f);
567       glTexCoord2f(0.0f, 1.0f);
568       glVertex3f(-.3f * size[i], .3f * size[i], 0.0f);
569       glEnd();
570     }
571 
572     if(type[i] == grenadesprite || type[i] == spoonsprite
573        || type[i] == pinsprite) {
574       glTranslatef(location[i].x, location[i].y + .2, location[i].z);
575       glDisable(GL_BLEND);
576       glEnable(GL_FOG);
577       glEnable(GL_CULL_FACE);
578       glDisable(GL_TEXTURE_2D);
579       glEnable(GL_LIGHTING);
580       glEnable(GL_COLOR_MATERIAL);
581       glDepthMask(1);
582       glRotatef(rotation[i], 1, .6, .3);
583 
584       if(type[i] == grenadesprite)
585         gunmodels[grenadebasemodel].draw();
586       if(type[i] == spoonsprite)
587         gunmodels[grenadespoonmodel].draw();
588       if(type[i] == pinsprite)
589         gunmodels[grenadepinmodel].draw();
590 
591       glEnable(GL_BLEND);
592       glDisable(GL_FOG);
593       glDisable(GL_CULL_FACE);
594       glEnable(GL_TEXTURE_2D);
595       glDisable(GL_LIGHTING);
596       glDisable(GL_COLOR_MATERIAL);
597       glDepthMask(0);
598     }
599 
600     if(type[i] == bullet || type[i] == bulletinstant) {
601       bulletsize = size[i];
602       glPushMatrix();
603       begProj = location[i];
604       endProj = velocity[i];
605       glPushMatrix();
606       glTranslatef(begProj.x, begProj.y, begProj.z);
607       glGetFloatv(GL_MODELVIEW_MATRIX, M);
608       begProj.x = M[12];
609       begProj.y = M[13];
610       begProj.z = M[14];
611       glPopMatrix();
612       glPushMatrix();
613       glTranslatef(endProj.x, endProj.y, endProj.z);
614       glGetFloatv(GL_MODELVIEW_MATRIX, M);
615       endProj.x = M[12];
616       endProj.y = M[13];
617       endProj.z = M[14];
618       glPopMatrix();
619       avgProj = (endProj + begProj) / 2;
620 
621       dx = endProj.x - begProj.x;
622       dy = endProj.y - begProj.y;
623       oolen = 1 / fast_sqrt(dx * dx + dy * dy) * 0.5;
624       persp = 0;
625       persp.x = -dy * oolen;
626       persp.y = dx * oolen;
627 
628       glColor4f(color1[i] * fog.fogcolor.r * 1.6,
629                 color2[i] * fog.fogcolor.g * 1.6,
630                 color3[i] * fog.fogcolor.b * 1.6, brightness[i]);
631 
632       glPushMatrix();
633       glLoadIdentity();
634       glBegin(GL_TRIANGLES);
635       glTexCoord2f(0.0f, 1.0f);
636       glVertex3f(endProj.x - persp.x * bulletsize / 2,
637                  endProj.y - persp.y * bulletsize / 2, endProj.z);
638       glTexCoord2f(1.0f, 0.0f);
639       glVertex3f(begProj.x + persp.x * bulletsize / 2,
640                  begProj.y + persp.y * bulletsize / 2, begProj.z);
641       glTexCoord2f(0.0f, 0.0f);
642       glVertex3f(begProj.x - persp.x * bulletsize / 2,
643                  begProj.y - persp.y * bulletsize / 2, begProj.z);
644       glTexCoord2f(1.0f, 0.0f);
645       glVertex3f(begProj.x + persp.x * bulletsize / 2,
646                  begProj.y + persp.y * bulletsize / 2, begProj.z);
647       glTexCoord2f(0.0f, 1.0f);
648       glVertex3f(endProj.x - persp.x * bulletsize / 2,
649                  endProj.y - persp.y * bulletsize / 2, endProj.z);
650       glTexCoord2f(1.0f, 1.0f);
651       glVertex3f(endProj.x + persp.x * bulletsize / 2,
652                  endProj.y + persp.y * bulletsize / 2, endProj.z);
653       glEnd();
654       glPopMatrix();
655       glPopMatrix();
656     }
657     glPopMatrix();
658   }
659   fog.ResetFog();
660   glDepthMask(1);
661   glDisable(GL_TEXTURE_2D);
662   glEnable(GL_CULL_FACE);
663 }
664