1 /*
2  * DrawGarbages.cxx
3  * Daniel Nelson - 9/1/0
4  *
5  * Copyright (C) 2000  Daniel Nelson
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * Daniel Nelson - aluminumangel.org
22  * 174 W. 18th Ave.
23  * Columbus, OH  43210
24  *
25  * Handle's the displaying of the garbage.
26  */
27 
28 #define GL_GLEXT_LEGACY
29 #define GL_GLEXT_PROTOTYPES
30 
31 #include <GL/glut.h>
32 #include <GL/glext.h>
33 
34 #include "glext.h"
35 
36 using namespace std;
37 
38 #include "Game.h"
39 #include "Block.h"
40 #include "Creep.h"
41 #include "Displayer.h"
42 #include "Garbage.h"
43 #include "GarbageManager.h"
44 #include "LightManager.h"
45 #include "GarbageFlavorImage.h"
46 
47 const GLfloat white[3]
48  = { 1.0f, 1.0f, 1.0f };
49 
50 const GLfloat Displayer::garbage_colors[GF_NUMBER][3]
51  = { { 1.0f, 0.0f, 0.0f },    // normal
52      { 0.4f, 0.4f, 0.4f },    // gray
53      { 0.05f, 0.05f, 0.05f }, // black
54      { 0.95f, 0.95f, 0.95f }, // white
55      { 0.73f, 0.0f, 0.73f },  // purple
56      { 0.2f, 0.2f, 0.8f },    // blue
57      { 0.0f, 0.6f, 0.05f },   // green
58      { 0.85f, 0.85f, 0.0f },  // yellow
59      { 1.0f, 0.4f, 0.0f } };  // orange
60 
61 const GLfloat xy_swap_matrix[]
62  = { 0.0f, 1.0f, 0.0f, 0.0f,
63      1.0f, 0.0f, 0.0f, 0.0f,
64      0.0f, 0.0f, -1.0f, 0.0f,
65      0.0f, 0.0f, 0.0f, 1.0f };
66 
67 GLdouble shatter_clip_plane[4]
68  = { 0.0, 1.0, 0.0, 0.0 };
69 
drawGarbage()70 void Displayer::drawGarbage (   )
71 {
72   GLfloat x, y;
73 
74   glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
75 
76   // blocks have already been drawn, so we use their material calls
77 
78   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
79 
80 #ifdef DC_CLIP_SHATTER
81   bool clipping = false;
82 #else
83   bool fading = false;
84   GLfloat alpha = 0.0f;
85 #endif
86 
87   int c = GarbageManager::garbage_count;
88   for (int n = 0; c; n++)
89     if (GarbageManager::storeMap[n]) {
90       Garbage &garbage = GarbageManager::garbageStore[n];
91       c--;
92 
93       if (garbage.y > GC_SAFE_HEIGHT) continue;
94 
95       glPushMatrix();
96 
97         y = garbage.y * DC_GRID_ELEMENT_LENGTH
98          + garbage.f_y * (DC_GRID_ELEMENT_LENGTH / (GLfloat) GC_STEPS_PER_GRID)
99          + play_offset_y;
100         x = garbage.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
101 
102         // awaking; it is assumed that awaking garbage is always grid wide
103         if (garbage.state & GS_AWAKING) {
104 
105           // if still popping our internal sections
106           if (garbage.alarm - Game::time_step > DC_UNSHATTER_TIME) {
107 
108             // no garbage lightmap for blocks
109             glDisable(GL_TEXTURE_2D);
110 
111             int popped = garbage.sections_popped;
112 
113             for (int h = 0; h < garbage.height; h++)
114               for (int w = 0; w < GC_PLAY_WIDTH; w++) {
115 
116                 glPushMatrix();
117 
118                 LightManager::setupBlockLights(x + w * DC_GRID_ELEMENT_LENGTH,
119                  y + h * DC_GRID_ELEMENT_LENGTH);
120                 glTranslatef(x + w * DC_GRID_ELEMENT_LENGTH,
121                  y + h * DC_GRID_ELEMENT_LENGTH, DC_PLAY_OFFSET_Z);
122 
123                 // if this section is about to pop; this code here mimics code
124                 // found in DrawBlocks.cxx
125                 if (popped == 0
126                  && garbage.pop_alarm - Game::time_step < DC_POP_ROTATE_TIME) {
127                   GLfloat p = (garbage.pop_alarm - Game::time_step)
128                    * (1.0f / (GLfloat) DC_POP_ROTATE_TIME);
129 
130                   // each block rotates a different direction
131                   if (garbage.pop_direction & BR_DIRECTION_1) {
132                     glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
133                     glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
134                   } else if (garbage.pop_direction & BR_DIRECTION_2) {
135                     glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
136                     glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
137                   } else if (garbage.pop_direction & BR_DIRECTION_3) {
138                     glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
139                     glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
140                   } else {
141                     glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
142                     glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
143                   }
144 
145                   GLfloat scale = 1.0f - 0.5f * p;
146                   glScalef(scale, scale, scale);
147 
148                   if (garbage.pop_color == garbage.flavor)
149                     glColor3fv(garbage_colors[garbage.flavor]);
150                   else
151                     glColor3f( (1.0f - p) * garbage_colors[garbage.flavor][0]
152                      + p * garbage_colors[garbage.pop_color][0],
153                      (1.0f - p) * garbage_colors[garbage.flavor][1]
154                      + p * garbage_colors[garbage.pop_color][1],
155                      (1.0f - p) * garbage_colors[garbage.flavor][2]
156                      + p * garbage_colors[garbage.pop_color][2]);
157 
158                   glEnable(rescale_method);
159                   glCallList(block_list);
160                   glDisable(rescale_method);
161 
162                 // if this section has popped
163                 } else if (popped > 0) {
164                   glColor3fv(garbage_colors[garbage.flavor]);
165 
166                   glCallList(block_list);
167 
168                 // if this section has not popped
169                 } else {
170                   glColor3fv(garbage_colors[garbage.pop_color]);
171 
172                   // the small block is pre-rotated
173                   glCallList(small_block_list);
174                 }
175 
176                 popped--;
177                 glPopMatrix();
178               }
179 
180             // don't draw a shell
181             glPopMatrix();
182 
183             glEnable(GL_TEXTURE_2D);
184 
185             continue;
186 
187           // if we're about to awake; all sections have popped
188           } else {
189             // crunch our sections back up
190 
191             // no garbage lightmap for blocks
192             glDisable(GL_TEXTURE_2D);
193 
194             GLfloat p = (DC_UNSHATTER_TIME - garbage.alarm + Game::time_step)
195              * (1.0f / (GLfloat) DC_UNSHATTER_TIME);
196             GLfloat scale = 1.0f - 0.5f * p;
197 
198             glColor3fv(garbage_colors[garbage.flavor]);
199 
200             glEnable(rescale_method);
201 
202             for (int h = 0; h < garbage.height; h++)
203               for (int w = 0; w < GC_PLAY_WIDTH; w++) {
204 
205                 glPushMatrix();
206 
207                 LightManager::setupBlockLights(x + w * DC_GRID_ELEMENT_LENGTH,
208                  y + h * DC_GRID_ELEMENT_LENGTH);
209                 glTranslatef(x + w * DC_GRID_ELEMENT_LENGTH,
210                  y + h * DC_GRID_ELEMENT_LENGTH, DC_PLAY_OFFSET_Z);
211 
212                 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
213                 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
214 
215                 glScalef(scale, scale, scale);
216 
217                 glCallList(block_list);
218 
219                 glPopMatrix();
220               }
221 
222             glDisable(rescale_method);
223 
224             glEnable(GL_TEXTURE_2D);
225 
226             // if we're in the first half of the unshatter
227             if (garbage.alarm - Game::time_step > DC_UNSHATTER_TIME / 4) {
228               // don't draw a shell
229               glPopMatrix();
230               continue;
231             }
232 
233             LightManager::setupGarbageLights(x, y, garbage.height,
234              garbage.width);
235 
236             glTranslatef(x, y, DC_PLAY_OFFSET_Z);
237 
238             // only push texture matrix once we know we're using it
239             glMatrixMode(GL_TEXTURE);
240             glPushMatrix();
241             glTranslatef(0.5f + x * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
242              0.5f + y * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
243             glMatrixMode(GL_MODELVIEW);
244 
245             // clip pane into existance
246 
247 #ifdef DC_CLIP_SHATTER
248             clipping = true;
249             glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
250             glDisable(GL_CULL_FACE);
251 
252             glEnable(GL_CLIP_PLANE_SHATTERING);
253             shatter_clip_plane[3] = -(garbage.alarm - Game::time_step)
254              * garbage.height * (DC_GRID_ELEMENT_LENGTH * 4.0f
255              / (GLfloat) DC_UNSHATTER_TIME)
256              + (DC_GRID_ELEMENT_LENGTH / 2.0f);
257             glClipPlane(GL_CLIP_PLANE_SHATTERING, shatter_clip_plane);
258 #else
259             fading = true;
260             alpha = (DC_UNSHATTER_TIME / 4 - garbage.alarm + Game::time_step)
261              * (4.0f / (GLfloat) DC_UNSHATTER_TIME);
262             glEnable(GL_BLEND);
263 #endif
264           }
265 
266         } else {
267           LightManager::setupGarbageLights(x, y, garbage.height,
268            garbage.width);
269 
270           glTranslatef(x, y, DC_PLAY_OFFSET_Z);
271 
272           // only push texture matrix once we know we're using it
273           glMatrixMode(GL_TEXTURE);
274           glPushMatrix();
275           glTranslatef(0.5f + x * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
276            0.5f + y * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
277           glMatrixMode(GL_MODELVIEW);
278         }
279 
280         // normal and shattering
281 
282         // if we're shattering
283         if (garbage.state & GS_SHATTERING) {
284 
285           // first we flash
286           if (Game::time_step - garbage.alarm
287            < (DC_SHATTER_FLASH_TIME - DC_SHATTER_TIME)) {
288 
289             GLfloat flash = ((GLfloat) DC_SHATTER_TIME - garbage.alarm
290              + Game::time_step) * (4.0f / (GLfloat) DC_SHATTER_FLASH_TIME);
291             if (flash > 2.0f) flash = 4.0f - flash;
292             if (flash > 1.0f) flash = 2.0f - flash;
293             glColor3f(garbage_colors[garbage.flavor][0] + flash
294              * (DC_FLASH_COLOR_RED - garbage_colors[garbage.flavor][0]),
295              garbage_colors[garbage.flavor][1] + flash
296              * (DC_FLASH_COLOR_GREEN - garbage_colors[garbage.flavor][1]),
297              garbage_colors[garbage.flavor][2] + flash
298              * (DC_FLASH_COLOR_BLUE - garbage_colors[garbage.flavor][2]));
299 
300           } else {
301             // then we clip plane away
302 
303 #ifdef DC_CLIP_SHATTER
304             clipping = true;
305             glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
306             glDisable(GL_CULL_FACE);
307 
308             glEnable(GL_CLIP_PLANE_SHATTERING);
309             shatter_clip_plane[3] = -((DC_SHATTER_TIME - DC_SHATTER_FLASH_TIME)
310              - garbage.alarm + Game::time_step) * garbage.height
311              * (DC_GRID_ELEMENT_LENGTH / (GLfloat) (DC_SHATTER_TIME
312              - DC_SHATTER_FLASH_TIME))
313              + (DC_GRID_ELEMENT_LENGTH / 2.0f);
314             glClipPlane(GL_CLIP_PLANE_SHATTERING, shatter_clip_plane);
315 
316             glColor3fv(garbage_colors[garbage.flavor]);
317           }
318 
319         } else
320           glColor3fv(garbage_colors[garbage.flavor]);
321 #else
322             fading = true;
323             alpha = (garbage.alarm - Game::time_step)
324              * (1.0f / (GLfloat) (DC_SHATTER_TIME - DC_SHATTER_FLASH_TIME));
325             glEnable(GL_BLEND);
326             glColor4f(garbage_colors[garbage.flavor][0],
327              garbage_colors[garbage.flavor][1],
328              garbage_colors[garbage.flavor][2], alpha);
329           }
330 
331         } else if (fading)
332           glColor4f(garbage_colors[garbage.flavor][0],
333            garbage_colors[garbage.flavor][1],
334            garbage_colors[garbage.flavor][2], alpha);
335         else
336           glColor3fv(garbage_colors[garbage.flavor]);
337 #endif
338 
339         // thin garbage
340         if (garbage.height == 1) {
341 
342           if (garbage.width != 1) {
343 
344             glCallList(garbage_thin_cap_list);
345             for (int w = garbage.width - 1; --w; ) {
346               glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
347 
348               glMatrixMode(GL_TEXTURE);
349               glTranslatef(DC_GRID_ELEMENT_LENGTH
350                * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
351               glMatrixMode(GL_MODELVIEW);
352 
353               glCallList(garbage_thin_middle_list);
354             }
355             glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
356             glScalef(-1.0f, 1.0f, -1.0f);
357 
358             glMatrixMode(GL_TEXTURE);
359             glTranslatef(DC_GRID_ELEMENT_LENGTH
360              * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
361             glScalef(-1.0f, 1.0f, -1.0f);
362             glMatrixMode(GL_MODELVIEW);
363 
364             glCallList(garbage_thin_cap_list);
365 
366           // tiny garbage
367           } else
368             glCallList(garbage_small_list);
369 
370         // thick garbage
371         } else {
372 
373           // draw the bottom
374           glPushMatrix();
375 
376           glMatrixMode(GL_TEXTURE);
377           glPushMatrix();
378 
379             glScalef(1.0f, -1.0f, -1.0f);
380             glMatrixMode(GL_MODELVIEW);
381 
382             glScalef(1.0f, -1.0f, -1.0f);
383 
384             glCallList(garbage_thick_corner_list);
385             for (int w = garbage.width - 1; --w; ) {
386               glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
387 
388               glMatrixMode(GL_TEXTURE);
389               glTranslatef(DC_GRID_ELEMENT_LENGTH
390                * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
391               glMatrixMode(GL_MODELVIEW);
392 
393               glCallList(garbage_thick_edge_list);
394             }
395             glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
396             glScalef(-1.0f, 1.0f, -1.0f);
397 
398             glMatrixMode(GL_TEXTURE);
399             glTranslatef(DC_GRID_ELEMENT_LENGTH
400              * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
401             glScalef(-1.0f, 1.0f, -1.0f);
402 
403             glCallList(garbage_thick_corner_list);
404 
405           glPopMatrix();
406           glMatrixMode(GL_MODELVIEW);
407 
408           glPopMatrix();
409 
410           // draw the middle
411           for (int h = garbage.height - 1; --h;) {
412             glPushMatrix();
413 
414             glMatrixMode(GL_TEXTURE);
415             glPushMatrix();
416             glMatrixMode(GL_MODELVIEW);
417 
418               int w = garbage.width - 1;
419               glTranslatef(w * DC_GRID_ELEMENT_LENGTH,
420                h * DC_GRID_ELEMENT_LENGTH, 0.0f);
421               glMultMatrixf(xy_swap_matrix);
422 
423               glMatrixMode(GL_TEXTURE);
424               glTranslatef(w * (DC_GRID_ELEMENT_LENGTH
425                * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER), h
426                * (DC_GRID_ELEMENT_LENGTH * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER),
427                0.0f);
428               glMultMatrixf(xy_swap_matrix);
429               glMatrixMode(GL_MODELVIEW);
430 
431               glCallList(garbage_thick_edge_list);
432               while (--w) {
433                 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH, 0.0f);
434 
435                 glMatrixMode(GL_TEXTURE);
436                 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH
437                  * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
438                 glMatrixMode(GL_MODELVIEW);
439 
440                 glCallList(garbage_thick_middle_list);
441               }
442               glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH, 0.0f);
443               glScalef(1.0f, -1.0f, -1.0f);
444 
445               glMatrixMode(GL_TEXTURE);
446               glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH
447                * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
448               glScalef(1.0f, -1.0f, -1.0f);
449               glMatrixMode(GL_MODELVIEW);
450 
451               glCallList(garbage_thick_edge_list);
452 
453             glPopMatrix();
454 
455             glMatrixMode(GL_TEXTURE);
456             glPopMatrix();
457             glMatrixMode(GL_MODELVIEW);
458           }
459 
460           // draw the top
461           glPushMatrix();
462 
463           glMatrixMode(GL_TEXTURE);
464           glPushMatrix();
465 
466             glTranslatef(0.0f, (garbage.height - 1) * (DC_GRID_ELEMENT_LENGTH
467              * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER), 0.0f);
468 
469             glMatrixMode(GL_MODELVIEW);
470             glTranslatef(0.0f, (garbage.height - 1) * DC_GRID_ELEMENT_LENGTH,
471              0.0f);
472 
473             glCallList(garbage_thick_corner_list);
474             for (int w = garbage.width - 1; --w; ) {
475               glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
476 
477               glMatrixMode(GL_TEXTURE);
478               glTranslatef(DC_GRID_ELEMENT_LENGTH
479                * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
480               glMatrixMode(GL_MODELVIEW);
481 
482               glCallList(garbage_thick_edge_list);
483             }
484             glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
485             glScalef(-1.0f, 1.0f, -1.0f);
486 
487             glMatrixMode(GL_TEXTURE);
488             glTranslatef(DC_GRID_ELEMENT_LENGTH
489              * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
490             glScalef(-1.0f, 1.0f, -1.0f);
491 
492             glCallList(garbage_thick_corner_list);
493 
494           glPopMatrix();
495           glMatrixMode(GL_MODELVIEW);
496 
497           glPopMatrix();
498 
499           if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS)) {
500             // draw flavor image; if any
501             if (GarbageFlavorImage::associated_garbage_id == garbage.id) {
502 #ifndef NO_MULTITEXTURING
503               if (state & DS_MULTITEXTURING) {
504                 glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
505 
506                   glMatrixMode(GL_TEXTURE);
507                   glLoadIdentity();
508 
509                   glBindTexture(GL_TEXTURE_2D, garbage_texture);
510 
511                   glActiveTextureARB(GL_TEXTURE1_ARB);
512                   glPushMatrix();
513                   glTranslatef(0.5f + (x + 2.0f * GarbageFlavorImage::x)
514                    * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
515                    0.5f + (y + 2.0f * GarbageFlavorImage::y)
516                    * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
517 
518                   glEnable(GL_TEXTURE_2D);
519                   glEnable(GL_BLEND);
520 
521                   glColor3fv(white);
522 
523                   glMatrixMode(GL_MODELVIEW);
524                   glTranslatef(GarbageFlavorImage::x * DC_GRID_ELEMENT_LENGTH,
525                    GarbageFlavorImage::y * DC_GRID_ELEMENT_LENGTH,
526                    DC_GARBAGE_FLAVOR_TEX_OFFSET_Z);
527 
528                   glCallList(garbage_flavor_list);
529 
530                   glMatrixMode(GL_TEXTURE);
531                   glPopMatrix();
532                   glActiveTextureARB(GL_TEXTURE0_ARB);
533                   glMatrixMode(GL_MODELVIEW);
534 
535                 glPopAttrib();
536 
537                 glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
538 
539               } else {
540 #endif
541                 glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
542 
543                   glMatrixMode(GL_TEXTURE);
544                   glLoadIdentity();
545 
546                   glBindTexture(GL_TEXTURE_2D, garbage_texture);
547 
548                   glEnable(GL_BLEND);
549 
550                   glColor3fv(white);
551 
552                   glMatrixMode(GL_MODELVIEW);
553                   glTranslatef(GarbageFlavorImage::x * DC_GRID_ELEMENT_LENGTH,
554                    GarbageFlavorImage::y * DC_GRID_ELEMENT_LENGTH,
555                    DC_GARBAGE_FLAVOR_TEX_OFFSET_Z);
556 
557                   glCallList(garbage_flavor_list);
558 
559                   glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
560 
561                 glPopAttrib();
562 #ifndef NO_MULTITEXTURING
563               }
564 #endif
565             }
566           }
567         }
568 
569         // turn off the clip plane
570 #ifdef DC_CLIP_SHATTER
571         if (clipping) {
572           clipping = false;
573 
574           glDisable(GL_CLIP_PLANE_SHATTERING);
575           glEnable(GL_CULL_FACE);
576           glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
577 #else
578         if (fading) {
579           fading = false;
580 
581           glDisable(GL_BLEND);
582 #endif
583 
584           // delete fully shattered garbage; note that we can't assume
585           // we'll display each time step
586           if (garbage.alarm <= Game::time_step)
587             GarbageManager::deleteGarbage(&garbage);
588         }
589 
590       glPopMatrix();
591       glMatrixMode(GL_TEXTURE);
592       glPopMatrix();
593       glMatrixMode(GL_MODELVIEW);
594     }
595 }
596