3 * Daniel Nelson - 9/1/0
5 * Copyright (C) 2000 Daniel Nelson
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
25 * Handle's the displaying of the garbage.
28 #define GL_GLEXT_LEGACY
29 #define GL_GLEXT_PROTOTYPES
44 #include "Displayer.h"
46 #include "GarbageManager.h"
47 #include "LightManager.h"
48 #include "GarbageFlavorImage.h"
50 const GLfloat white
[3]
51 = { 1.0f
, 1.0f
, 1.0f
};
53 const GLfloat
Displayer::garbage_colors
[GF_NUMBER
][3]
54 = { { 1.0f
, 0.0f
, 0.0f
}, // normal
55 { 0.4f
, 0.4f
, 0.4f
}, // gray
56 { 0.05f
, 0.05f
, 0.05f
}, // black
57 { 0.95f
, 0.95f
, 0.95f
}, // white
58 { 0.73f
, 0.0f
, 0.73f
}, // purple
59 { 0.2f
, 0.2f
, 0.8f
}, // blue
60 { 0.0f
, 0.6f
, 0.05f
}, // green
61 { 0.85f
, 0.85f
, 0.0f
}, // yellow
62 { 1.0f
, 0.4f
, 0.0f
} }; // orange
64 const GLfloat xy_swap_matrix
[]
65 = { 0.0f
, 1.0f
, 0.0f
, 0.0f
,
66 1.0f
, 0.0f
, 0.0f
, 0.0f
,
67 0.0f
, 0.0f
, -1.0f
, 0.0f
,
68 0.0f
, 0.0f
, 0.0f
, 1.0f
};
70 GLdouble shatter_clip_plane
[4]
71 = { 0.0, 1.0, 0.0, 0.0 };
73 void Displayer::drawGarbage ( )
77 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
79 // blocks have already been drawn, so we use their material calls
81 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
83 #ifdef DC_CLIP_SHATTER
84 bool clipping
= false;
90 int c
= GarbageManager::garbage_count
;
91 for (int n
= 0; c
; n
++)
92 if (GarbageManager::storeMap
[n
]) {
93 Garbage
&garbage
= GarbageManager::garbageStore
[n
];
96 if (garbage
.y
> GC_SAFE_HEIGHT
) continue;
100 y
= garbage
.y
* DC_GRID_ELEMENT_LENGTH
101 + garbage
.f_y
* (DC_GRID_ELEMENT_LENGTH
/ (GLfloat
) GC_STEPS_PER_GRID
)
103 x
= garbage
.x
* DC_GRID_ELEMENT_LENGTH
+ DC_PLAY_OFFSET_X
;
105 // awaking; it is assumed that awaking garbage is always grid wide
106 if (garbage
.state
& GS_AWAKING
) {
108 // if still popping our internal sections
109 if (garbage
.alarm
- Game::time_step
> DC_UNSHATTER_TIME
) {
111 // no garbage lightmap for blocks
112 glDisable(GL_TEXTURE_2D
);
114 int popped
= garbage
.sections_popped
;
116 for (int h
= 0; h
< garbage
.height
; h
++)
117 for (int w
= 0; w
< GC_PLAY_WIDTH
; w
++) {
121 LightManager::setupBlockLights(x
+ w
* DC_GRID_ELEMENT_LENGTH
,
122 y
+ h
* DC_GRID_ELEMENT_LENGTH
);
123 glTranslatef(x
+ w
* DC_GRID_ELEMENT_LENGTH
,
124 y
+ h
* DC_GRID_ELEMENT_LENGTH
, DC_PLAY_OFFSET_Z
);
126 // if this section is about to pop; this code here mimics code
127 // found in DrawBlocks.cxx
129 && garbage
.pop_alarm
- Game::time_step
< DC_POP_ROTATE_TIME
) {
130 GLfloat p
= (garbage
.pop_alarm
- Game::time_step
)
131 * (1.0f
/ (GLfloat
) DC_POP_ROTATE_TIME
);
133 // each block rotates a different direction
134 if (garbage
.pop_direction
& BR_DIRECTION_1
) {
135 glRotatef(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_2
) {
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 if (garbage
.pop_direction
& BR_DIRECTION_3
) {
141 glRotatef(90.0f
- 45.0f
* p
, 1.0f
, 0.0f
, 0.0f
);
142 glRotatef(-45.0f
* p
, 0.0f
, 1.0f
, 0.0f
);
144 glRotatef(45.0f
* p
, 1.0f
, 0.0f
, 0.0f
);
145 glRotatef(-45.0f
* p
, 0.0f
, 1.0f
, 0.0f
);
148 GLfloat scale
= 1.0f
- 0.5f
* p
;
149 glScalef(scale
, scale
, scale
);
151 if (garbage
.pop_color
== garbage
.flavor
)
152 glColor3fv(garbage_colors
[garbage
.flavor
]);
154 glColor3f( (1.0f
- p
) * garbage_colors
[garbage
.flavor
][0]
155 + p
* garbage_colors
[garbage
.pop_color
][0],
156 (1.0f
- p
) * garbage_colors
[garbage
.flavor
][1]
157 + p
* garbage_colors
[garbage
.pop_color
][1],
158 (1.0f
- p
) * garbage_colors
[garbage
.flavor
][2]
159 + p
* garbage_colors
[garbage
.pop_color
][2]);
161 glEnable(rescale_method
);
162 glCallList(block_list
);
163 glDisable(rescale_method
);
165 // if this section has popped
166 } else if (popped
> 0) {
167 glColor3fv(garbage_colors
[garbage
.flavor
]);
169 glCallList(block_list
);
171 // if this section has not popped
173 glColor3fv(garbage_colors
[garbage
.pop_color
]);
175 // the small block is pre-rotated
176 glCallList(small_block_list
);
183 // don't draw a shell
186 glEnable(GL_TEXTURE_2D
);
190 // if we're about to awake; all sections have popped
192 // crunch our sections back up
194 // no garbage lightmap for blocks
195 glDisable(GL_TEXTURE_2D
);
197 GLfloat p
= (DC_UNSHATTER_TIME
- garbage
.alarm
+ Game::time_step
)
198 * (1.0f
/ (GLfloat
) DC_UNSHATTER_TIME
);
199 GLfloat scale
= 1.0f
- 0.5f
* p
;
201 glColor3fv(garbage_colors
[garbage
.flavor
]);
203 glEnable(rescale_method
);
205 for (int h
= 0; h
< garbage
.height
; h
++)
206 for (int w
= 0; w
< GC_PLAY_WIDTH
; w
++) {
210 LightManager::setupBlockLights(x
+ w
* DC_GRID_ELEMENT_LENGTH
,
211 y
+ h
* DC_GRID_ELEMENT_LENGTH
);
212 glTranslatef(x
+ w
* DC_GRID_ELEMENT_LENGTH
,
213 y
+ h
* DC_GRID_ELEMENT_LENGTH
, DC_PLAY_OFFSET_Z
);
215 glRotatef(45.0f
* p
, 1.0f
, 0.0f
, 0.0f
);
216 glRotatef(45.0f
* p
, 0.0f
, 1.0f
, 0.0f
);
218 glScalef(scale
, scale
, scale
);
220 glCallList(block_list
);
225 glDisable(rescale_method
);
227 glEnable(GL_TEXTURE_2D
);
229 // if we're in the first half of the unshatter
230 if (garbage
.alarm
- Game::time_step
> DC_UNSHATTER_TIME
/ 4) {
231 // don't draw a shell
236 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
239 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
241 // only push texture matrix once we know we're using it
242 glMatrixMode(GL_TEXTURE
);
244 glTranslatef(0.5f
+ x
* DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
,
245 0.5f
+ y
* DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
246 glMatrixMode(GL_MODELVIEW
);
248 // clip pane into existance
250 #ifdef DC_CLIP_SHATTER
252 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
253 glDisable(GL_CULL_FACE
);
255 glEnable(GL_CLIP_PLANE_SHATTERING
);
256 shatter_clip_plane
[3] = -(garbage
.alarm
- Game::time_step
)
257 * garbage
.height
* (DC_GRID_ELEMENT_LENGTH
* 4.0f
258 / (GLfloat
) DC_UNSHATTER_TIME
)
259 + (DC_GRID_ELEMENT_LENGTH
/ 2.0f
);
260 glClipPlane(GL_CLIP_PLANE_SHATTERING
, shatter_clip_plane
);
263 alpha
= (DC_UNSHATTER_TIME
/ 4 - garbage
.alarm
+ Game::time_step
)
264 * (4.0f
/ (GLfloat
) DC_UNSHATTER_TIME
);
270 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
273 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
275 // only push texture matrix once we know we're using it
276 glMatrixMode(GL_TEXTURE
);
278 glTranslatef(0.5f
+ x
* DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
,
279 0.5f
+ y
* DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
280 glMatrixMode(GL_MODELVIEW
);
283 // normal and shattering
285 // if we're shattering
286 if (garbage
.state
& GS_SHATTERING
) {
289 if (Game::time_step
- garbage
.alarm
290 < (DC_SHATTER_FLASH_TIME
- DC_SHATTER_TIME
)) {
292 GLfloat flash
= ((GLfloat
) DC_SHATTER_TIME
- garbage
.alarm
293 + Game::time_step
) * (4.0f
/ (GLfloat
) DC_SHATTER_FLASH_TIME
);
294 if (flash
> 2.0f
) flash
= 4.0f
- flash
;
295 if (flash
> 1.0f
) flash
= 2.0f
- flash
;
296 glColor3f(garbage_colors
[garbage
.flavor
][0] + flash
297 * (DC_FLASH_COLOR_RED
- garbage_colors
[garbage
.flavor
][0]),
298 garbage_colors
[garbage
.flavor
][1] + flash
299 * (DC_FLASH_COLOR_GREEN
- garbage_colors
[garbage
.flavor
][1]),
300 garbage_colors
[garbage
.flavor
][2] + flash
301 * (DC_FLASH_COLOR_BLUE
- garbage_colors
[garbage
.flavor
][2]));
304 // then we clip plane away
306 #ifdef DC_CLIP_SHATTER
308 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
309 glDisable(GL_CULL_FACE
);
311 glEnable(GL_CLIP_PLANE_SHATTERING
);
312 shatter_clip_plane
[3] = -((DC_SHATTER_TIME
- DC_SHATTER_FLASH_TIME
)
313 - garbage
.alarm
+ Game::time_step
) * garbage
.height
314 * (DC_GRID_ELEMENT_LENGTH
/ (GLfloat
) (DC_SHATTER_TIME
315 - DC_SHATTER_FLASH_TIME
))
316 + (DC_GRID_ELEMENT_LENGTH
/ 2.0f
);
317 glClipPlane(GL_CLIP_PLANE_SHATTERING
, shatter_clip_plane
);
319 glColor3fv(garbage_colors
[garbage
.flavor
]);
323 glColor3fv(garbage_colors
[garbage
.flavor
]);
326 alpha
= (garbage
.alarm
- Game::time_step
)
327 * (1.0f
/ (GLfloat
) (DC_SHATTER_TIME
- DC_SHATTER_FLASH_TIME
));
329 glColor4f(garbage_colors
[garbage
.flavor
][0],
330 garbage_colors
[garbage
.flavor
][1],
331 garbage_colors
[garbage
.flavor
][2], alpha
);
335 glColor4f(garbage_colors
[garbage
.flavor
][0],
336 garbage_colors
[garbage
.flavor
][1],
337 garbage_colors
[garbage
.flavor
][2], alpha
);
339 glColor3fv(garbage_colors
[garbage
.flavor
]);
343 if (garbage
.height
== 1) {
345 if (garbage
.width
!= 1) {
347 glCallList(garbage_thin_cap_list
);
348 for (int w
= garbage
.width
- 1; --w
; ) {
349 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
351 glMatrixMode(GL_TEXTURE
);
352 glTranslatef(DC_GRID_ELEMENT_LENGTH
353 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
354 glMatrixMode(GL_MODELVIEW
);
356 glCallList(garbage_thin_middle_list
);
358 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
359 glScalef(-1.0f
, 1.0f
, -1.0f
);
361 glMatrixMode(GL_TEXTURE
);
362 glTranslatef(DC_GRID_ELEMENT_LENGTH
363 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
364 glScalef(-1.0f
, 1.0f
, -1.0f
);
365 glMatrixMode(GL_MODELVIEW
);
367 glCallList(garbage_thin_cap_list
);
371 glCallList(garbage_small_list
);
379 glMatrixMode(GL_TEXTURE
);
382 glScalef(1.0f
, -1.0f
, -1.0f
);
383 glMatrixMode(GL_MODELVIEW
);
385 glScalef(1.0f
, -1.0f
, -1.0f
);
387 glCallList(garbage_thick_corner_list
);
388 for (int w
= garbage
.width
- 1; --w
; ) {
389 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
391 glMatrixMode(GL_TEXTURE
);
392 glTranslatef(DC_GRID_ELEMENT_LENGTH
393 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
394 glMatrixMode(GL_MODELVIEW
);
396 glCallList(garbage_thick_edge_list
);
398 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
399 glScalef(-1.0f
, 1.0f
, -1.0f
);
401 glMatrixMode(GL_TEXTURE
);
402 glTranslatef(DC_GRID_ELEMENT_LENGTH
403 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
404 glScalef(-1.0f
, 1.0f
, -1.0f
);
406 glCallList(garbage_thick_corner_list
);
409 glMatrixMode(GL_MODELVIEW
);
414 for (int h
= garbage
.height
- 1; --h
;) {
417 glMatrixMode(GL_TEXTURE
);
419 glMatrixMode(GL_MODELVIEW
);
421 int w
= garbage
.width
- 1;
422 glTranslatef(w
* DC_GRID_ELEMENT_LENGTH
,
423 h
* DC_GRID_ELEMENT_LENGTH
, 0.0f
);
424 glMultMatrixf(xy_swap_matrix
);
426 glMatrixMode(GL_TEXTURE
);
427 glTranslatef(w
* (DC_GRID_ELEMENT_LENGTH
428 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
), h
429 * (DC_GRID_ELEMENT_LENGTH
* DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
),
431 glMultMatrixf(xy_swap_matrix
);
432 glMatrixMode(GL_MODELVIEW
);
434 glCallList(garbage_thick_edge_list
);
436 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
, 0.0f
);
438 glMatrixMode(GL_TEXTURE
);
439 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
440 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
441 glMatrixMode(GL_MODELVIEW
);
443 glCallList(garbage_thick_middle_list
);
445 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
, 0.0f
);
446 glScalef(1.0f
, -1.0f
, -1.0f
);
448 glMatrixMode(GL_TEXTURE
);
449 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
450 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
451 glScalef(1.0f
, -1.0f
, -1.0f
);
452 glMatrixMode(GL_MODELVIEW
);
454 glCallList(garbage_thick_edge_list
);
458 glMatrixMode(GL_TEXTURE
);
460 glMatrixMode(GL_MODELVIEW
);
466 glMatrixMode(GL_TEXTURE
);
469 glTranslatef(0.0f
, (garbage
.height
- 1) * (DC_GRID_ELEMENT_LENGTH
470 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
), 0.0f
);
472 glMatrixMode(GL_MODELVIEW
);
473 glTranslatef(0.0f
, (garbage
.height
- 1) * DC_GRID_ELEMENT_LENGTH
,
476 glCallList(garbage_thick_corner_list
);
477 for (int w
= garbage
.width
- 1; --w
; ) {
478 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
480 glMatrixMode(GL_TEXTURE
);
481 glTranslatef(DC_GRID_ELEMENT_LENGTH
482 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
483 glMatrixMode(GL_MODELVIEW
);
485 glCallList(garbage_thick_edge_list
);
487 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
488 glScalef(-1.0f
, 1.0f
, -1.0f
);
490 glMatrixMode(GL_TEXTURE
);
491 glTranslatef(DC_GRID_ELEMENT_LENGTH
492 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
493 glScalef(-1.0f
, 1.0f
, -1.0f
);
495 glCallList(garbage_thick_corner_list
);
498 glMatrixMode(GL_MODELVIEW
);
502 // draw flavor image; if any
503 if (GarbageFlavorImage::associated_garbage_id
== garbage
.id
) {
504 #ifndef NO_MULTITEXTURING
505 if (state
& DS_MULTITEXTURING
) {
506 glPushAttrib(GL_LIGHTING_BIT
| GL_ENABLE_BIT
);
508 glMatrixMode(GL_TEXTURE
);
511 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
513 glActiveTextureARB(GL_TEXTURE1_ARB
);
515 glTranslatef(0.5f
+ (x
+ 2.0f
* GarbageFlavorImage::x
)
516 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
,
517 0.5f
+ (y
+ 2.0f
* GarbageFlavorImage::y
)
518 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
520 glEnable(GL_TEXTURE_2D
);
525 glMatrixMode(GL_MODELVIEW
);
526 glTranslatef(GarbageFlavorImage::x
* DC_GRID_ELEMENT_LENGTH
,
527 GarbageFlavorImage::y
* DC_GRID_ELEMENT_LENGTH
,
528 DC_GARBAGE_FLAVOR_TEX_OFFSET_Z
);
530 glCallList(garbage_flavor_list
);
532 glMatrixMode(GL_TEXTURE
);
534 glActiveTextureARB(GL_TEXTURE0_ARB
);
535 glMatrixMode(GL_MODELVIEW
);
539 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
543 glPushAttrib(GL_LIGHTING_BIT
| GL_ENABLE_BIT
);
545 glMatrixMode(GL_TEXTURE
);
548 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
554 glMatrixMode(GL_MODELVIEW
);
555 glTranslatef(GarbageFlavorImage::x
* DC_GRID_ELEMENT_LENGTH
,
556 GarbageFlavorImage::y
* DC_GRID_ELEMENT_LENGTH
,
557 DC_GARBAGE_FLAVOR_TEX_OFFSET_Z
);
559 glCallList(garbage_flavor_list
);
561 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
564 #ifndef NO_MULTITEXTURING
570 // turn off the clip plane
571 #ifdef DC_CLIP_SHATTER
575 glDisable(GL_CLIP_PLANE_SHATTERING
);
576 glEnable(GL_CULL_FACE
);
577 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_FALSE
);
585 // delete fully shattered garbage; note that we can't assume
586 // we'll display each time step
587 if (garbage
.alarm
<= Game::time_step
)
588 GarbageManager::deleteGarbage(&garbage
);
592 glMatrixMode(GL_TEXTURE
);
594 glMatrixMode(GL_MODELVIEW
);