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
41 #include "Displayer.h"
43 #include "GarbageManager.h"
44 #include "LightManager.h"
45 #include "GarbageFlavorImage.h"
47 const GLfloat white
[3]
48 = { 1.0f
, 1.0f
, 1.0f
};
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
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
};
67 GLdouble shatter_clip_plane
[4]
68 = { 0.0, 1.0, 0.0, 0.0 };
70 void Displayer::drawGarbage ( )
74 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
76 // blocks have already been drawn, so we use their material calls
78 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
80 #ifdef DC_CLIP_SHATTER
81 bool clipping
= false;
87 int c
= GarbageManager::garbage_count
;
88 for (int n
= 0; c
; n
++)
89 if (GarbageManager::storeMap
[n
]) {
90 Garbage
&garbage
= GarbageManager::garbageStore
[n
];
93 if (garbage
.y
> GC_SAFE_HEIGHT
) continue;
97 y
= garbage
.y
* DC_GRID_ELEMENT_LENGTH
98 + garbage
.f_y
* (DC_GRID_ELEMENT_LENGTH
/ (GLfloat
) GC_STEPS_PER_GRID
)
100 x
= garbage
.x
* DC_GRID_ELEMENT_LENGTH
+ DC_PLAY_OFFSET_X
;
102 // awaking; it is assumed that awaking garbage is always grid wide
103 if (garbage
.state
& GS_AWAKING
) {
105 // if still popping our internal sections
106 if (garbage
.alarm
- Game::time_step
> DC_UNSHATTER_TIME
) {
108 // no garbage lightmap for blocks
109 glDisable(GL_TEXTURE_2D
);
111 int popped
= garbage
.sections_popped
;
113 for (int h
= 0; h
< garbage
.height
; h
++)
114 for (int w
= 0; w
< GC_PLAY_WIDTH
; w
++) {
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
);
123 // if this section is about to pop; this code here mimics code
124 // found in DrawBlocks.cxx
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
);
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
);
141 glRotatef(45.0f
* p
, 1.0f
, 0.0f
, 0.0f
);
142 glRotatef(-45.0f
* p
, 0.0f
, 1.0f
, 0.0f
);
145 GLfloat scale
= 1.0f
- 0.5f
* p
;
146 glScalef(scale
, scale
, scale
);
148 if (garbage
.pop_color
== garbage
.flavor
)
149 glColor3fv(garbage_colors
[garbage
.flavor
]);
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]);
158 glEnable(rescale_method
);
159 glCallList(block_list
);
160 glDisable(rescale_method
);
162 // if this section has popped
163 } else if (popped
> 0) {
164 glColor3fv(garbage_colors
[garbage
.flavor
]);
166 glCallList(block_list
);
168 // if this section has not popped
170 glColor3fv(garbage_colors
[garbage
.pop_color
]);
172 // the small block is pre-rotated
173 glCallList(small_block_list
);
180 // don't draw a shell
183 glEnable(GL_TEXTURE_2D
);
187 // if we're about to awake; all sections have popped
189 // crunch our sections back up
191 // no garbage lightmap for blocks
192 glDisable(GL_TEXTURE_2D
);
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
;
198 glColor3fv(garbage_colors
[garbage
.flavor
]);
200 glEnable(rescale_method
);
202 for (int h
= 0; h
< garbage
.height
; h
++)
203 for (int w
= 0; w
< GC_PLAY_WIDTH
; w
++) {
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
);
212 glRotatef(45.0f
* p
, 1.0f
, 0.0f
, 0.0f
);
213 glRotatef(45.0f
* p
, 0.0f
, 1.0f
, 0.0f
);
215 glScalef(scale
, scale
, scale
);
217 glCallList(block_list
);
222 glDisable(rescale_method
);
224 glEnable(GL_TEXTURE_2D
);
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
233 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
236 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
238 // only push texture matrix once we know we're using it
239 glMatrixMode(GL_TEXTURE
);
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
);
245 // clip pane into existance
247 #ifdef DC_CLIP_SHATTER
249 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
250 glDisable(GL_CULL_FACE
);
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
);
260 alpha
= (DC_UNSHATTER_TIME
/ 4 - garbage
.alarm
+ Game::time_step
)
261 * (4.0f
/ (GLfloat
) DC_UNSHATTER_TIME
);
267 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
270 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
272 // only push texture matrix once we know we're using it
273 glMatrixMode(GL_TEXTURE
);
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
);
280 // normal and shattering
282 // if we're shattering
283 if (garbage
.state
& GS_SHATTERING
) {
286 if (Game::time_step
- garbage
.alarm
287 < (DC_SHATTER_FLASH_TIME
- DC_SHATTER_TIME
)) {
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]));
301 // then we clip plane away
303 #ifdef DC_CLIP_SHATTER
305 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
306 glDisable(GL_CULL_FACE
);
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
);
316 glColor3fv(garbage_colors
[garbage
.flavor
]);
320 glColor3fv(garbage_colors
[garbage
.flavor
]);
323 alpha
= (garbage
.alarm
- Game::time_step
)
324 * (1.0f
/ (GLfloat
) (DC_SHATTER_TIME
- DC_SHATTER_FLASH_TIME
));
326 glColor4f(garbage_colors
[garbage
.flavor
][0],
327 garbage_colors
[garbage
.flavor
][1],
328 garbage_colors
[garbage
.flavor
][2], alpha
);
332 glColor4f(garbage_colors
[garbage
.flavor
][0],
333 garbage_colors
[garbage
.flavor
][1],
334 garbage_colors
[garbage
.flavor
][2], alpha
);
336 glColor3fv(garbage_colors
[garbage
.flavor
]);
340 if (garbage
.height
== 1) {
342 if (garbage
.width
!= 1) {
344 glCallList(garbage_thin_cap_list
);
345 for (int w
= garbage
.width
- 1; --w
; ) {
346 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
348 glMatrixMode(GL_TEXTURE
);
349 glTranslatef(DC_GRID_ELEMENT_LENGTH
350 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
351 glMatrixMode(GL_MODELVIEW
);
353 glCallList(garbage_thin_middle_list
);
355 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
356 glScalef(-1.0f
, 1.0f
, -1.0f
);
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
);
364 glCallList(garbage_thin_cap_list
);
368 glCallList(garbage_small_list
);
376 glMatrixMode(GL_TEXTURE
);
379 glScalef(1.0f
, -1.0f
, -1.0f
);
380 glMatrixMode(GL_MODELVIEW
);
382 glScalef(1.0f
, -1.0f
, -1.0f
);
384 glCallList(garbage_thick_corner_list
);
385 for (int w
= garbage
.width
- 1; --w
; ) {
386 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
388 glMatrixMode(GL_TEXTURE
);
389 glTranslatef(DC_GRID_ELEMENT_LENGTH
390 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
391 glMatrixMode(GL_MODELVIEW
);
393 glCallList(garbage_thick_edge_list
);
395 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
396 glScalef(-1.0f
, 1.0f
, -1.0f
);
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
);
403 glCallList(garbage_thick_corner_list
);
406 glMatrixMode(GL_MODELVIEW
);
411 for (int h
= garbage
.height
- 1; --h
;) {
414 glMatrixMode(GL_TEXTURE
);
416 glMatrixMode(GL_MODELVIEW
);
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
);
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
),
428 glMultMatrixf(xy_swap_matrix
);
429 glMatrixMode(GL_MODELVIEW
);
431 glCallList(garbage_thick_edge_list
);
433 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
, 0.0f
);
435 glMatrixMode(GL_TEXTURE
);
436 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
437 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
);
438 glMatrixMode(GL_MODELVIEW
);
440 glCallList(garbage_thick_middle_list
);
442 glTranslatef(0.0f
, -DC_GRID_ELEMENT_LENGTH
, 0.0f
);
443 glScalef(1.0f
, -1.0f
, -1.0f
);
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
);
451 glCallList(garbage_thick_edge_list
);
455 glMatrixMode(GL_TEXTURE
);
457 glMatrixMode(GL_MODELVIEW
);
463 glMatrixMode(GL_TEXTURE
);
466 glTranslatef(0.0f
, (garbage
.height
- 1) * (DC_GRID_ELEMENT_LENGTH
467 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
), 0.0f
);
469 glMatrixMode(GL_MODELVIEW
);
470 glTranslatef(0.0f
, (garbage
.height
- 1) * DC_GRID_ELEMENT_LENGTH
,
473 glCallList(garbage_thick_corner_list
);
474 for (int w
= garbage
.width
- 1; --w
; ) {
475 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
477 glMatrixMode(GL_TEXTURE
);
478 glTranslatef(DC_GRID_ELEMENT_LENGTH
479 * DC_GARBAGE_LIGHTMAP_COORD_CONVERTER
, 0.0f
, 0.0f
);
480 glMatrixMode(GL_MODELVIEW
);
482 glCallList(garbage_thick_edge_list
);
484 glTranslatef(DC_GRID_ELEMENT_LENGTH
, 0.0f
, 0.0f
);
485 glScalef(-1.0f
, 1.0f
, -1.0f
);
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
);
492 glCallList(garbage_thick_corner_list
);
495 glMatrixMode(GL_MODELVIEW
);
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
);
506 glMatrixMode(GL_TEXTURE
);
509 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
511 glActiveTextureARB(GL_TEXTURE1_ARB
);
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
);
518 glEnable(GL_TEXTURE_2D
);
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
);
528 glCallList(garbage_flavor_list
);
530 glMatrixMode(GL_TEXTURE
);
532 glActiveTextureARB(GL_TEXTURE0_ARB
);
533 glMatrixMode(GL_MODELVIEW
);
537 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
541 glPushAttrib(GL_LIGHTING_BIT
| GL_ENABLE_BIT
);
543 glMatrixMode(GL_TEXTURE
);
546 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
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
);
557 glCallList(garbage_flavor_list
);
559 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
562 #ifndef NO_MULTITEXTURING
569 // turn off the clip plane
570 #ifdef DC_CLIP_SHATTER
574 glDisable(GL_CLIP_PLANE_SHATTERING
);
575 glEnable(GL_CULL_FACE
);
576 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_FALSE
);
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
);
591 glMatrixMode(GL_TEXTURE
);
593 glMatrixMode(GL_MODELVIEW
);