Fixes for datatype size on amd64.
[crack-attack.git] / src / DrawGarbage.cxx
blobc405d96ff26f2006e891f4ffbfe0a9b3019dcd1e
1 /*
2 * DrawGarbages.cxx
3 * Daniel Nelson - 9/1/0
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.
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.
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.
21 * Daniel Nelson - aluminumangel.org
22 * 174 W. 18th Ave.
23 * Columbus, OH 43210
25 * Handle's the displaying of the garbage.
28 #define GL_GLEXT_LEGACY
29 #define GL_GLEXT_PROTOTYPES
31 #include <GL/glut.h>
33 #include "glext.h"
35 #include "Game.h"
36 #include "Block.h"
37 #include "Creep.h"
38 #include "Displayer.h"
39 #include "Garbage.h"
40 #include "GarbageManager.h"
41 #include "LightManager.h"
42 #include "GarbageFlavorImage.h"
44 const GLfloat white[3]
45 = { 1.0f, 1.0f, 1.0f };
47 const GLfloat Displayer::garbage_colors[GF_NUMBER][3]
48 = { { 1.0f, 0.0f, 0.0f }, // normal
49 { 0.4f, 0.4f, 0.4f }, // gray
50 { 0.05f, 0.05f, 0.05f }, // black
51 { 0.95f, 0.95f, 0.95f }, // white
52 { 0.73f, 0.0f, 0.73f }, // purple
53 { 0.2f, 0.2f, 0.8f }, // blue
54 { 0.0f, 0.6f, 0.05f }, // green
55 { 0.85f, 0.85f, 0.0f }, // yellow
56 { 1.0f, 0.4f, 0.0f } }; // orange
58 const GLfloat xy_swap_matrix[]
59 = { 0.0f, 1.0f, 0.0f, 0.0f,
60 1.0f, 0.0f, 0.0f, 0.0f,
61 0.0f, 0.0f, -1.0f, 0.0f,
62 0.0f, 0.0f, 0.0f, 1.0f };
64 GLdouble shatter_clip_plane[4]
65 = { 0.0, 1.0, 0.0, 0.0 };
67 void Displayer::drawGarbage ( )
69 GLfloat x, y;
71 glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
73 // blocks have already been drawn, so we use their material calls
75 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
77 #ifdef DC_CLIP_SHATTER
78 bool clipping = false;
79 #else
80 bool fading = false;
81 GLfloat alpha = 0.0f;
82 #endif
84 int c = GarbageManager::garbage_count;
85 for (int n = 0; c; n++)
86 if (GarbageManager::storeMap[n]) {
87 Garbage &garbage = GarbageManager::garbageStore[n];
88 c--;
90 if (garbage.y > GC_SAFE_HEIGHT) continue;
92 glPushMatrix();
94 y = garbage.y * DC_GRID_ELEMENT_LENGTH
95 + garbage.f_y * (DC_GRID_ELEMENT_LENGTH / (GLfloat) GC_STEPS_PER_GRID)
96 + play_offset_y;
97 x = garbage.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
99 // awaking; it is assumed that awaking garbage is always grid wide
100 if (garbage.state & GS_AWAKING) {
102 // if still popping our internal sections
103 if (garbage.alarm - Game::time_step > DC_UNSHATTER_TIME) {
105 // no garbage lightmap for blocks
106 glDisable(GL_TEXTURE_2D);
108 int popped = garbage.sections_popped;
110 for (int h = 0; h < garbage.height; h++)
111 for (int w = 0; w < GC_PLAY_WIDTH; w++) {
113 glPushMatrix();
115 LightManager::setupBlockLights(x + w * DC_GRID_ELEMENT_LENGTH,
116 y + h * DC_GRID_ELEMENT_LENGTH);
117 glTranslatef(x + w * DC_GRID_ELEMENT_LENGTH,
118 y + h * DC_GRID_ELEMENT_LENGTH, DC_PLAY_OFFSET_Z);
120 // if this section is about to pop; this code here mimics code
121 // found in DrawBlocks.cxx
122 if (popped == 0
123 && garbage.pop_alarm - Game::time_step < DC_POP_ROTATE_TIME) {
124 GLfloat p = (garbage.pop_alarm - Game::time_step)
125 * (1.0f / (GLfloat) DC_POP_ROTATE_TIME);
127 // each block rotates a different direction
128 if (garbage.pop_direction & BR_DIRECTION_1) {
129 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
130 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
131 } else if (garbage.pop_direction & BR_DIRECTION_2) {
132 glRotatef(90.0f - 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_3) {
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 {
138 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
139 glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
142 GLfloat scale = 1.0f - 0.5f * p;
143 glScalef(scale, scale, scale);
145 if (garbage.pop_color == garbage.flavor)
146 glColor3fv(garbage_colors[garbage.flavor]);
147 else
148 glColor3f( (1.0f - p) * garbage_colors[garbage.flavor][0]
149 + p * garbage_colors[garbage.pop_color][0],
150 (1.0f - p) * garbage_colors[garbage.flavor][1]
151 + p * garbage_colors[garbage.pop_color][1],
152 (1.0f - p) * garbage_colors[garbage.flavor][2]
153 + p * garbage_colors[garbage.pop_color][2]);
155 glEnable(rescale_method);
156 glCallList(block_list);
157 glDisable(rescale_method);
159 // if this section has popped
160 } else if (popped > 0) {
161 glColor3fv(garbage_colors[garbage.flavor]);
163 glCallList(block_list);
165 // if this section has not popped
166 } else {
167 glColor3fv(garbage_colors[garbage.pop_color]);
169 // the small block is pre-rotated
170 glCallList(small_block_list);
173 popped--;
174 glPopMatrix();
177 // don't draw a shell
178 glPopMatrix();
180 glEnable(GL_TEXTURE_2D);
182 continue;
184 // if we're about to awake; all sections have popped
185 } else {
186 // crunch our sections back up
188 // no garbage lightmap for blocks
189 glDisable(GL_TEXTURE_2D);
191 GLfloat p = (DC_UNSHATTER_TIME - garbage.alarm + Game::time_step)
192 * (1.0f / (GLfloat) DC_UNSHATTER_TIME);
193 GLfloat scale = 1.0f - 0.5f * p;
195 glColor3fv(garbage_colors[garbage.flavor]);
197 glEnable(rescale_method);
199 for (int h = 0; h < garbage.height; h++)
200 for (int w = 0; w < GC_PLAY_WIDTH; w++) {
202 glPushMatrix();
204 LightManager::setupBlockLights(x + w * DC_GRID_ELEMENT_LENGTH,
205 y + h * DC_GRID_ELEMENT_LENGTH);
206 glTranslatef(x + w * DC_GRID_ELEMENT_LENGTH,
207 y + h * DC_GRID_ELEMENT_LENGTH, DC_PLAY_OFFSET_Z);
209 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
210 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
212 glScalef(scale, scale, scale);
214 glCallList(block_list);
216 glPopMatrix();
219 glDisable(rescale_method);
221 glEnable(GL_TEXTURE_2D);
223 // if we're in the first half of the unshatter
224 if (garbage.alarm - Game::time_step > DC_UNSHATTER_TIME / 4) {
225 // don't draw a shell
226 glPopMatrix();
227 continue;
230 LightManager::setupGarbageLights(x, y, garbage.height,
231 garbage.width);
233 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
235 // only push texture matrix once we know we're using it
236 glMatrixMode(GL_TEXTURE);
237 glPushMatrix();
238 glTranslatef(0.5f + x * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
239 0.5f + y * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
240 glMatrixMode(GL_MODELVIEW);
242 // clip pane into existance
244 #ifdef DC_CLIP_SHATTER
245 clipping = true;
246 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
247 glDisable(GL_CULL_FACE);
249 glEnable(GL_CLIP_PLANE_SHATTERING);
250 shatter_clip_plane[3] = -(garbage.alarm - Game::time_step)
251 * garbage.height * (DC_GRID_ELEMENT_LENGTH * 4.0f
252 / (GLfloat) DC_UNSHATTER_TIME)
253 + (DC_GRID_ELEMENT_LENGTH / 2.0f);
254 glClipPlane(GL_CLIP_PLANE_SHATTERING, shatter_clip_plane);
255 #else
256 fading = true;
257 alpha = (DC_UNSHATTER_TIME / 4 - garbage.alarm + Game::time_step)
258 * (4.0f / (GLfloat) DC_UNSHATTER_TIME);
259 glEnable(GL_BLEND);
260 #endif
263 } else {
264 LightManager::setupGarbageLights(x, y, garbage.height,
265 garbage.width);
267 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
269 // only push texture matrix once we know we're using it
270 glMatrixMode(GL_TEXTURE);
271 glPushMatrix();
272 glTranslatef(0.5f + x * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
273 0.5f + y * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
274 glMatrixMode(GL_MODELVIEW);
277 // normal and shattering
279 // if we're shattering
280 if (garbage.state & GS_SHATTERING) {
282 // first we flash
283 if (Game::time_step - garbage.alarm
284 < (DC_SHATTER_FLASH_TIME - DC_SHATTER_TIME)) {
286 GLfloat flash = ((GLfloat) DC_SHATTER_TIME - garbage.alarm
287 + Game::time_step) * (4.0f / (GLfloat) DC_SHATTER_FLASH_TIME);
288 if (flash > 2.0f) flash = 4.0f - flash;
289 if (flash > 1.0f) flash = 2.0f - flash;
290 glColor3f(garbage_colors[garbage.flavor][0] + flash
291 * (DC_FLASH_COLOR_RED - garbage_colors[garbage.flavor][0]),
292 garbage_colors[garbage.flavor][1] + flash
293 * (DC_FLASH_COLOR_GREEN - garbage_colors[garbage.flavor][1]),
294 garbage_colors[garbage.flavor][2] + flash
295 * (DC_FLASH_COLOR_BLUE - garbage_colors[garbage.flavor][2]));
297 } else {
298 // then we clip plane away
300 #ifdef DC_CLIP_SHATTER
301 clipping = true;
302 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
303 glDisable(GL_CULL_FACE);
305 glEnable(GL_CLIP_PLANE_SHATTERING);
306 shatter_clip_plane[3] = -((DC_SHATTER_TIME - DC_SHATTER_FLASH_TIME)
307 - garbage.alarm + Game::time_step) * garbage.height
308 * (DC_GRID_ELEMENT_LENGTH / (GLfloat) (DC_SHATTER_TIME
309 - DC_SHATTER_FLASH_TIME))
310 + (DC_GRID_ELEMENT_LENGTH / 2.0f);
311 glClipPlane(GL_CLIP_PLANE_SHATTERING, shatter_clip_plane);
313 glColor3fv(garbage_colors[garbage.flavor]);
316 } else
317 glColor3fv(garbage_colors[garbage.flavor]);
318 #else
319 fading = true;
320 alpha = (garbage.alarm - Game::time_step)
321 * (1.0f / (GLfloat) (DC_SHATTER_TIME - DC_SHATTER_FLASH_TIME));
322 glEnable(GL_BLEND);
323 glColor4f(garbage_colors[garbage.flavor][0],
324 garbage_colors[garbage.flavor][1],
325 garbage_colors[garbage.flavor][2], alpha);
328 } else if (fading)
329 glColor4f(garbage_colors[garbage.flavor][0],
330 garbage_colors[garbage.flavor][1],
331 garbage_colors[garbage.flavor][2], alpha);
332 else
333 glColor3fv(garbage_colors[garbage.flavor]);
334 #endif
336 // thin garbage
337 if (garbage.height == 1) {
339 if (garbage.width != 1) {
341 glCallList(garbage_thin_cap_list);
342 for (int w = garbage.width - 1; --w; ) {
343 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
345 glMatrixMode(GL_TEXTURE);
346 glTranslatef(DC_GRID_ELEMENT_LENGTH
347 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
348 glMatrixMode(GL_MODELVIEW);
350 glCallList(garbage_thin_middle_list);
352 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
353 glScalef(-1.0f, 1.0f, -1.0f);
355 glMatrixMode(GL_TEXTURE);
356 glTranslatef(DC_GRID_ELEMENT_LENGTH
357 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
358 glScalef(-1.0f, 1.0f, -1.0f);
359 glMatrixMode(GL_MODELVIEW);
361 glCallList(garbage_thin_cap_list);
363 // tiny garbage
364 } else
365 glCallList(garbage_small_list);
367 // thick garbage
368 } else {
370 // draw the bottom
371 glPushMatrix();
373 glMatrixMode(GL_TEXTURE);
374 glPushMatrix();
376 glScalef(1.0f, -1.0f, -1.0f);
377 glMatrixMode(GL_MODELVIEW);
379 glScalef(1.0f, -1.0f, -1.0f);
381 glCallList(garbage_thick_corner_list);
382 for (int w = garbage.width - 1; --w; ) {
383 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
385 glMatrixMode(GL_TEXTURE);
386 glTranslatef(DC_GRID_ELEMENT_LENGTH
387 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
388 glMatrixMode(GL_MODELVIEW);
390 glCallList(garbage_thick_edge_list);
392 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
393 glScalef(-1.0f, 1.0f, -1.0f);
395 glMatrixMode(GL_TEXTURE);
396 glTranslatef(DC_GRID_ELEMENT_LENGTH
397 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
398 glScalef(-1.0f, 1.0f, -1.0f);
400 glCallList(garbage_thick_corner_list);
402 glPopMatrix();
403 glMatrixMode(GL_MODELVIEW);
405 glPopMatrix();
407 // draw the middle
408 for (int h = garbage.height - 1; --h;) {
409 glPushMatrix();
411 glMatrixMode(GL_TEXTURE);
412 glPushMatrix();
413 glMatrixMode(GL_MODELVIEW);
415 int w = garbage.width - 1;
416 glTranslatef(w * DC_GRID_ELEMENT_LENGTH,
417 h * DC_GRID_ELEMENT_LENGTH, 0.0f);
418 glMultMatrixf(xy_swap_matrix);
420 glMatrixMode(GL_TEXTURE);
421 glTranslatef(w * (DC_GRID_ELEMENT_LENGTH
422 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER), h
423 * (DC_GRID_ELEMENT_LENGTH * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER),
424 0.0f);
425 glMultMatrixf(xy_swap_matrix);
426 glMatrixMode(GL_MODELVIEW);
428 glCallList(garbage_thick_edge_list);
429 while (--w) {
430 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH, 0.0f);
432 glMatrixMode(GL_TEXTURE);
433 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH
434 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
435 glMatrixMode(GL_MODELVIEW);
437 glCallList(garbage_thick_middle_list);
439 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH, 0.0f);
440 glScalef(1.0f, -1.0f, -1.0f);
442 glMatrixMode(GL_TEXTURE);
443 glTranslatef(0.0f, -DC_GRID_ELEMENT_LENGTH
444 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
445 glScalef(1.0f, -1.0f, -1.0f);
446 glMatrixMode(GL_MODELVIEW);
448 glCallList(garbage_thick_edge_list);
450 glPopMatrix();
452 glMatrixMode(GL_TEXTURE);
453 glPopMatrix();
454 glMatrixMode(GL_MODELVIEW);
457 // draw the top
458 glPushMatrix();
460 glMatrixMode(GL_TEXTURE);
461 glPushMatrix();
463 glTranslatef(0.0f, (garbage.height - 1) * (DC_GRID_ELEMENT_LENGTH
464 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER), 0.0f);
466 glMatrixMode(GL_MODELVIEW);
467 glTranslatef(0.0f, (garbage.height - 1) * DC_GRID_ELEMENT_LENGTH,
468 0.0f);
470 glCallList(garbage_thick_corner_list);
471 for (int w = garbage.width - 1; --w; ) {
472 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
474 glMatrixMode(GL_TEXTURE);
475 glTranslatef(DC_GRID_ELEMENT_LENGTH
476 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
477 glMatrixMode(GL_MODELVIEW);
479 glCallList(garbage_thick_edge_list);
481 glTranslatef(DC_GRID_ELEMENT_LENGTH, 0.0f, 0.0f);
482 glScalef(-1.0f, 1.0f, -1.0f);
484 glMatrixMode(GL_TEXTURE);
485 glTranslatef(DC_GRID_ELEMENT_LENGTH
486 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f, 0.0f);
487 glScalef(-1.0f, 1.0f, -1.0f);
489 glCallList(garbage_thick_corner_list);
491 glPopMatrix();
492 glMatrixMode(GL_MODELVIEW);
494 glPopMatrix();
496 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS)) {
497 // draw flavor image; if any
498 if (GarbageFlavorImage::associated_garbage_id == garbage.id) {
499 #ifndef NO_MULTITEXTURING
500 if (state & DS_MULTITEXTURING) {
501 glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
503 glMatrixMode(GL_TEXTURE);
504 glLoadIdentity();
506 glBindTexture(GL_TEXTURE_2D, garbage_texture);
508 glActiveTextureARB(GL_TEXTURE1_ARB);
509 glPushMatrix();
510 glTranslatef(0.5f + (x + 2.0f * GarbageFlavorImage::x)
511 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER,
512 0.5f + (y + 2.0f * GarbageFlavorImage::y)
513 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER, 0.0f);
515 glEnable(GL_TEXTURE_2D);
516 glEnable(GL_BLEND);
518 glColor3fv(white);
520 glMatrixMode(GL_MODELVIEW);
521 glTranslatef(GarbageFlavorImage::x * DC_GRID_ELEMENT_LENGTH,
522 GarbageFlavorImage::y * DC_GRID_ELEMENT_LENGTH,
523 DC_GARBAGE_FLAVOR_TEX_OFFSET_Z);
525 glCallList(garbage_flavor_list);
527 glMatrixMode(GL_TEXTURE);
528 glPopMatrix();
529 glActiveTextureARB(GL_TEXTURE0_ARB);
530 glMatrixMode(GL_MODELVIEW);
532 glPopAttrib();
534 glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
536 } else {
537 #endif
538 glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
540 glMatrixMode(GL_TEXTURE);
541 glLoadIdentity();
543 glBindTexture(GL_TEXTURE_2D, garbage_texture);
545 glEnable(GL_BLEND);
547 glColor3fv(white);
549 glMatrixMode(GL_MODELVIEW);
550 glTranslatef(GarbageFlavorImage::x * DC_GRID_ELEMENT_LENGTH,
551 GarbageFlavorImage::y * DC_GRID_ELEMENT_LENGTH,
552 DC_GARBAGE_FLAVOR_TEX_OFFSET_Z);
554 glCallList(garbage_flavor_list);
556 glBindTexture(GL_TEXTURE_2D, garbage_lightmap);
558 glPopAttrib();
559 #ifndef NO_MULTITEXTURING
561 #endif
566 // turn off the clip plane
567 #ifdef DC_CLIP_SHATTER
568 if (clipping) {
569 clipping = false;
571 glDisable(GL_CLIP_PLANE_SHATTERING);
572 glEnable(GL_CULL_FACE);
573 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
574 #else
575 if (fading) {
576 fading = false;
578 glDisable(GL_BLEND);
579 #endif
581 // delete fully shattered garbage; note that we can't assume
582 // we'll display each time step
583 if (garbage.alarm <= Game::time_step)
584 GarbageManager::deleteGarbage(&garbage);
587 glPopMatrix();
588 glMatrixMode(GL_TEXTURE);
589 glPopMatrix();
590 glMatrixMode(GL_MODELVIEW);