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
38 #include "Displayer.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 ( )
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;
84 int c
= GarbageManager::garbage_count
;
85 for (int n
= 0; c
; n
++)
86 if (GarbageManager::storeMap
[n
]) {
87 Garbage
&garbage
= GarbageManager::garbageStore
[n
];
90 if (garbage
.y
> GC_SAFE_HEIGHT
) continue;
94 y
= garbage
.y
* DC_GRID_ELEMENT_LENGTH
95 + garbage
.f_y
* (DC_GRID_ELEMENT_LENGTH
/ (GLfloat
) GC_STEPS_PER_GRID
)
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
++) {
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
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
);
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
]);
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
167 glColor3fv(garbage_colors
[garbage
.pop_color
]);
169 // the small block is pre-rotated
170 glCallList(small_block_list
);
177 // don't draw a shell
180 glEnable(GL_TEXTURE_2D
);
184 // if we're about to awake; all sections have popped
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
++) {
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
);
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
230 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
233 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
235 // only push texture matrix once we know we're using it
236 glMatrixMode(GL_TEXTURE
);
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
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
);
257 alpha
= (DC_UNSHATTER_TIME
/ 4 - garbage
.alarm
+ Game::time_step
)
258 * (4.0f
/ (GLfloat
) DC_UNSHATTER_TIME
);
264 LightManager::setupGarbageLights(x
, y
, garbage
.height
,
267 glTranslatef(x
, y
, DC_PLAY_OFFSET_Z
);
269 // only push texture matrix once we know we're using it
270 glMatrixMode(GL_TEXTURE
);
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
) {
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]));
298 // then we clip plane away
300 #ifdef DC_CLIP_SHATTER
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
]);
317 glColor3fv(garbage_colors
[garbage
.flavor
]);
320 alpha
= (garbage
.alarm
- Game::time_step
)
321 * (1.0f
/ (GLfloat
) (DC_SHATTER_TIME
- DC_SHATTER_FLASH_TIME
));
323 glColor4f(garbage_colors
[garbage
.flavor
][0],
324 garbage_colors
[garbage
.flavor
][1],
325 garbage_colors
[garbage
.flavor
][2], alpha
);
329 glColor4f(garbage_colors
[garbage
.flavor
][0],
330 garbage_colors
[garbage
.flavor
][1],
331 garbage_colors
[garbage
.flavor
][2], alpha
);
333 glColor3fv(garbage_colors
[garbage
.flavor
]);
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
);
365 glCallList(garbage_small_list
);
373 glMatrixMode(GL_TEXTURE
);
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
);
403 glMatrixMode(GL_MODELVIEW
);
408 for (int h
= garbage
.height
- 1; --h
;) {
411 glMatrixMode(GL_TEXTURE
);
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
),
425 glMultMatrixf(xy_swap_matrix
);
426 glMatrixMode(GL_MODELVIEW
);
428 glCallList(garbage_thick_edge_list
);
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
);
452 glMatrixMode(GL_TEXTURE
);
454 glMatrixMode(GL_MODELVIEW
);
460 glMatrixMode(GL_TEXTURE
);
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
,
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
);
492 glMatrixMode(GL_MODELVIEW
);
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
);
506 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
508 glActiveTextureARB(GL_TEXTURE1_ARB
);
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
);
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
);
529 glActiveTextureARB(GL_TEXTURE0_ARB
);
530 glMatrixMode(GL_MODELVIEW
);
534 glBindTexture(GL_TEXTURE_2D
, garbage_lightmap
);
538 glPushAttrib(GL_LIGHTING_BIT
| GL_ENABLE_BIT
);
540 glMatrixMode(GL_TEXTURE
);
543 glBindTexture(GL_TEXTURE_2D
, garbage_texture
);
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
);
559 #ifndef NO_MULTITEXTURING
566 // turn off the clip plane
567 #ifdef DC_CLIP_SHATTER
571 glDisable(GL_CLIP_PLANE_SHATTERING
);
572 glEnable(GL_CULL_FACE
);
573 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_FALSE
);
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
);
588 glMatrixMode(GL_TEXTURE
);
590 glMatrixMode(GL_MODELVIEW
);