1 // Description:
2 // Block View GL smooth rotation
3 //
4 // Copyright (C) 2003 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2 of the License, or (at your option) any later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include "SDL.h"
16 #include <gl++.hpp>
17
18 #include <Trace.hpp>
19 #include <Point.hpp>
20 #include <Config.hpp>
21
22 #include <FPS.hpp>
23
24 #include <GameState.hpp>
25 #include <Constants.hpp>
26 #include <FontManager.hpp>
27 #include <ResourceManager.hpp>
28 #include <zrwops.hpp>
29
30 #include "BlockViewGLSmooth.hpp"
31
32 const int VIDEO_ORTHO_WIDTH=1000;
33 const int VIDEO_ORTHO_HEIGHT=750;
34
35 const float GAMEOVERROTSPEED = 1.0f;
36
BlockViewGLSmooth(BlockModel & model)37 BlockViewGLSmooth::BlockViewGLSmooth( BlockModel &model):
38 BlockViewGL(model),
39 _useAALines(false),
40 _gameOverAngle(0.0),
41 _blockFace(0)
42 {
43 XTRACE();
44
45 ConfigS::instance()->getBoolean( "aalines", _useAALines);
46
47 FontManagerS::instance()->reload();
48 }
49
~BlockViewGLSmooth()50 BlockViewGLSmooth::~BlockViewGLSmooth()
51 {
52 XTRACE();
53 delete _blockFace;
54 }
55
init(void)56 bool BlockViewGLSmooth::init( void)
57 {
58 bool status = BlockViewGL::init();
59
60 if( status)
61 {
62 _smallFont = FontManagerS::instance()->getFont( "bitmaps/arial-small");
63 if( !_smallFont)
64 {
65 LOG_ERROR << "Unable to get font... (arial-small)" << endl;
66 SDL_QuitSubSystem( SDL_INIT_VIDEO);
67 status = false;
68 }
69
70 if( !ResourceManagerS::instance()->selectResource(
71 // string("bitmaps/Biohazard3.png")))
72 string("bitmaps/biohazard.png")))
73 {
74 LOG_WARNING << "blockPic1.png not found." << endl;
75 return false;
76 }
77 ziStream &bminfile1 = ResourceManagerS::instance()->getInputStream();
78 SDL_RWops *src = RWops_from_ziStream( bminfile1);
79 SDL_Surface *img1 = IMG_LoadPNG_RW( src);
80 _blockFace = new GLTexture( GL_TEXTURE_2D, img1, false);
81 SDL_FreeRW(src);
82 }
83
84 return status;
85 }
86
close(void)87 void BlockViewGLSmooth::close( void)
88 {
89 FontManagerS::cleanup();
90 BlockViewGL::close();
91 }
92
update(void)93 void BlockViewGLSmooth::update( void)
94 {
95 if( GameState::isAlive)
96 {
97 BlockViewSmooth::update();
98 }
99 else
100 {
101 _gameOverAngle += GAMEOVERROTSPEED;
102 }
103 }
104
draw(void)105 void BlockViewGLSmooth::draw( void)
106 {
107 int blockView = min(_width, _height);
108 glViewport(0,0, blockView, blockView);
109
110 glEnable( GL_DEPTH_TEST);
111 glEnable( GL_LIGHTING);
112 glEnable( GL_LIGHT0);
113 glShadeModel(GL_SMOOTH);
114
115 glEnable( GL_NORMALIZE);
116
117 glEnable(GL_BLEND);
118 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
119 glEnable( GL_COLOR_MATERIAL );
120
121 glClearColor(0.0, 0.0, 0.0, 0.0);
122 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
123
124 glMatrixMode(GL_PROJECTION);
125 glLoadIdentity();
126
127 const float fov = 53.13;
128 glFrustum(
129 (3.0/3.0)*(-2.0*tan(fov * M_PI / 360.0)), //xmin
130 (3.0/3.0)*( 2.0*tan(fov * M_PI / 360.0)), //xmax
131 -2.0*tan(fov * M_PI / 360.0), //ymin
132 2.0*tan(fov * M_PI / 360.0), //ymax
133 2.0, //znear
134 2000.0); //zfar
135
136 glMatrixMode(GL_MODELVIEW);
137 glLoadIdentity();
138
139 // glTranslatef( -_cameraX, -_cameraY, -_cameraZ );
140 glTranslatef( 0, 0,-100);
141
142 GLfloat light_position[] = { -100.0, 100.0, 100.0, 1.0 };
143 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
144 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
145
146 #if 0
147 //show light position
148 glColor4f( 1.0, 1.0, 1.0, 1.0 );
149 glBegin(GL_QUADS);
150 glNormal3f( 0,0,1);
151 glVertex3f( 40.0, 40.0, -150.0);
152 glVertex3f( 40.0, 60.0, -150.0);
153 glVertex3f( 60.0, 60.0, -150.0);
154 glVertex3f( 60.0, 40.0, -150.0);
155 glEnd();
156 #endif
157
158 int w = _model.getWidth();
159 int h = _model.getHeight();
160 int d = _model.getDepth();
161
162 _squaresize = 200.0f / (float)(max(w,h));
163 float bottom = -120.0f -((float)d *_squaresize);
164
165 if( _useAALines)
166 {
167 //AA lines
168 glHint(GL_NICEST,GL_LINE_SMOOTH_HINT);
169 glEnable( GL_LINE_SMOOTH);
170 }
171
172 // -- Draw the shaft
173 glDisable(GL_DEPTH_TEST);
174 drawShaft();
175 glEnable(GL_DEPTH_TEST);
176
177 // -- Draw all the locked elements
178 glPushMatrix();
179
180 if( !GameState::isAlive)
181 {
182 float gf = GameState::frameFraction;
183 float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf);
184 glRotatef( interpAngle, 0,0,1);
185 }
186
187 ElementList::iterator i;
188
189 glTranslatef(
190 0-_squaresize*(w-1)/2.0f,
191 0-_squaresize*(h-1)/2.0f,
192 0+bottom + _squaresize/2.0f);
193
194 ElementList &lockedElementList = _model.getLockedElementList();
195 for( i=lockedElementList.begin(); i!=lockedElementList.end(); i++)
196 {
197 Point3Di *p = *i;
198 drawElement( p, true);
199 }
200 glPopMatrix();
201
202 if( GameState::isAlive)
203 {
204 // -- Draw the block
205 glPushMatrix();
206 // glDisable( GL_LIGHTING);
207
208 Point3D &interpOffset = getInterpolatedOffset();
209 glTranslatef(
210 interpOffset.x*_squaresize-_squaresize*(w-1)/2.0f,
211 interpOffset.y*_squaresize-_squaresize*(h-1)/2.0f,
212 interpOffset.z*_squaresize+bottom + _squaresize/2.0f);
213
214 Point3D ¤tAxis = getCurrentAxis();
215 Point3D &prevAxis = getPrevAxis();
216 glRotatef( getInterpolatedAngle(), currentAxis.x, currentAxis.y, currentAxis.z);
217 glRotatef( getPrevAngle(), prevAxis.x, prevAxis.y, prevAxis.z);
218
219 ElementList &elementList = _model.getElementListNorm();
220 for( i=elementList.begin(); i!=elementList.end(); i++)
221 {
222 Point3Di *p = *i;
223 drawElement( p, false);
224 }
225 // glEnable( GL_LIGHTING);
226 glPopMatrix();
227 }
228 else
229 {
230 float gf = GameState::frameFraction;
231 float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf);
232 glRotatef( interpAngle, 0,1,0);
233
234 glDisable( GL_LIGHTING);
235 glColor4f(1.0,1.0,1.0,1.0);
236 string gameOver = "Game Over!";
237 _smallFont->DrawString( gameOver.c_str() , -40, 10.0, 0.4, 0.4);
238 string getOut = "Press ESC to exit";
239 _smallFont->DrawString( getOut.c_str() , -14, 0.0, 0.1, 0.1);
240 glEnable( GL_LIGHTING);
241 }
242
243 //---
244 glViewport(blockView,0, _width-blockView, blockView);
245
246 glMatrixMode(GL_PROJECTION);
247 glLoadIdentity();
248 glFrustum(
249 (1.0/4.0)*(-2.0*tan(fov * M_PI / 360.0)), //xmin
250 (1.0/4.0)*( 2.0*tan(fov * M_PI / 360.0)), //xmax
251 -2.0*tan(fov * M_PI / 360.0), //ymin
252 2.0*tan(fov * M_PI / 360.0), //ymax
253 2.0, //znear
254 2000.0); //zfar
255 glMatrixMode(GL_MODELVIEW);
256 glLoadIdentity();
257 drawIndicator();
258 //---
259
260 glDisable(GL_DEPTH_TEST);
261 glDisable(GL_LIGHTING);
262
263 glMatrixMode(GL_PROJECTION);
264 glLoadIdentity();
265 glOrtho(-0.5,VIDEO_ORTHO_WIDTH/4+0.5,-0.5,VIDEO_ORTHO_HEIGHT+0.5, -1000.0, 1000.0);
266
267 glMatrixMode(GL_MODELVIEW);
268 glLoadIdentity();
269
270 FPS::Update();
271 glColor4f(1.0,1.0,1.0,1.0);
272 _smallFont->DrawString( FPS::GetFPSString(), 0, 20, 1.0, 1.0);
273
274 char num[30];
275 sprintf( num, "Score: %d", _model.getScore());
276 _smallFont->DrawString( num, 0, 70, 0.6, 1.0);
277
278 sprintf( num, "Blocks: %d", _model.getElementCount());
279 _smallFont->DrawString( num, 0, 120, 0.6, 1.0);
280
281 sprintf( num, "Level: %d", _model.getLevel());
282 _smallFont->DrawString( num, 0, 170, 0.6, 1.0);
283
284 glColor4f(1.0,1.0,1.0,0.5);
285 string cr = "Copyright (C) 2004 by Frank Becker";
286 _smallFont->DrawString( cr.c_str() , 0, VIDEO_ORTHO_HEIGHT-20.0, 0.4, 0.4);
287
288 glColor4f(1.0,1.0,1.0,0.5);
289 string gVersion = "v"+GAMEVERSION;
290 float width = _smallFont->GetWidth( gVersion.c_str(), 0.6);
291 _smallFont->DrawString( gVersion.c_str() , (VIDEO_ORTHO_WIDTH/4)-width, 5.0, 0.6, 0.4);
292
293 SDL_GL_SwapBuffers( );
294 }
295
drawIndicator(void)296 void BlockViewGLSmooth::drawIndicator( void)
297 {
298 #if 0
299 static float r=0;
300 r+= 0.1;
301 glTranslatef( -10, -10,-100);
302 glRotatef( r, 0,1,0);
303 #else
304 glTranslatef( -5, -7,-50);
305 #endif
306
307 for( int i=0; i<_model.getDepth(); i++)
308 {
309 int count = _model.numBlocksInPlane( i);
310
311 if( !count) glColor4f( 0.2, 0.2, 0.2, 1.0 );
312 else setColor( i);
313
314 glBegin(GL_QUADS);
315 glNormal3f(-1, 1, 1); glVertex3f(-1, (float)i*2.5+1.0, 1);
316 glNormal3f( 1, 1,-1); glVertex3f( 1, (float)i*2.5+1.0, 1);
317 glNormal3f( 1,-1,-1); glVertex3f( 1, (float)i*2.5-1.0, 1);
318 glNormal3f(-1,-1, 1); glVertex3f(-1, (float)i*2.5-1.0, 1);
319 #if 0
320 glNormal3f(-1, 1, 1); glVertex3f(-1, i*3+1, 1);
321 glNormal3f( 1, 1, 1); glVertex3f( 1, i*3+1, 1);
322 glNormal3f( 1,-1, 1); glVertex3f( 1, i*3-1, 1);
323 glNormal3f(-1,-1, 1); glVertex3f(-1, i*3-1, 1);
324
325 glNormal3f( 1, 1, 1); glVertex3f( 1, i*3+1, 1);
326 glNormal3f( 1,-1, 1); glVertex3f( 1, i*3-1, 1);
327 glNormal3f( 1,-1,-1); glVertex3f( 1, i*3-1,-1);
328 glNormal3f( 1, 1,-1); glVertex3f( 1, i*3+1,-1);
329
330 glNormal3f( 1, 1,-1); glVertex3f( 1, i*3+1,-1);
331 glNormal3f(-1, 1,-1); glVertex3f(-1, i*3+1,-1);
332 glNormal3f(-1,-1,-1); glVertex3f(-1, i*3-1,-1);
333 glNormal3f( 1,-1,-1); glVertex3f( 1, i*3-1,-1);
334
335 glNormal3f(-1, 1,-1); glVertex3f(-1, i*3+1,-1);
336 glNormal3f(-1, 1, 1); glVertex3f(-1, i*3+1, 1);
337 glNormal3f(-1,-1, 1); glVertex3f(-1, i*3-1, 1);
338 glNormal3f(-1,-1,-1); glVertex3f(-1, i*3-1,-1);
339 #endif
340 glEnd();
341 }
342 }
343
drawShaft(void)344 void BlockViewGLSmooth::drawShaft( void)
345 {
346 int w = _model.getWidth();
347 int h = _model.getHeight();
348 int d = _model.getDepth();
349
350 float tilesize = _squaresize*0.80f;
351 float halfgapsize = (_squaresize-tilesize)/2.0f;
352 float bottom = -120.0f -((float)d *_squaresize);
353
354 glPushMatrix();
355
356 if( !GameState::isAlive)
357 {
358 float gf = GameState::frameFraction;
359 float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf);
360 glRotatef( interpAngle, 0,0,1);
361 }
362
363 glTranslatef( 0,0,bottom);
364
365 glBegin(GL_QUADS);
366 glColor4f( 0.0, 1.0, 0.0, 0.5 );
367 for( int x=0; x<w; x++)
368 {
369 float xp = x*_squaresize - _squaresize*w/2.0f + halfgapsize;
370 for( int y=0; y<h; y++)
371 {
372 float yp = y*_squaresize - _squaresize*h/2.0f + halfgapsize;
373 glNormal3f( 2,1,1);
374 glVertex3f( xp , yp , 0);
375 glNormal3f( 1,2,1);
376 glVertex3f( xp+tilesize, yp , 0);
377 glNormal3f( 1,2,1);
378 glVertex3f( xp+tilesize, yp+tilesize, 0);
379 glNormal3f( 2,1,1);
380 glVertex3f( xp , yp+tilesize, 0);
381 }
382 }
383
384 glColor4f( 0.0, 0.0, 1.0, 0.5 );
385 for( int x=0; x<w; x++)
386 {
387 float xp = x*_squaresize - _squaresize*w/2.0f + halfgapsize;
388 float yp = _squaresize*h/2.0f;
389 for( int z=0; z<d; z++)
390 {
391 float zp = z*_squaresize;
392 glNormal3f( 1, 1,2);
393 glVertex3f( xp+tilesize,-yp, zp);
394 glNormal3f( 2, 1,1);
395 glVertex3f( xp ,-yp, zp);
396 glNormal3f( 2, 1,1);
397 glVertex3f( xp ,-yp, zp+tilesize);
398 glNormal3f( 1, 1,2);
399 glVertex3f( xp+tilesize,-yp, zp+tilesize);
400
401 glNormal3f( 1,-1,2);
402 glVertex3f( xp+tilesize, yp, zp+tilesize);
403 glNormal3f( 2,-1,1);
404 glVertex3f( xp , yp, zp+tilesize);
405 glNormal3f( 2,-1,1);
406 glVertex3f( xp , yp, zp);
407 glNormal3f( 1,-1,2);
408 glVertex3f( xp+tilesize, yp, zp);
409 }
410 }
411
412 glColor4f( 1.0, 0.0, 0.0, 0.5 );
413 for( int y=0; y<h; y++)
414 {
415 float xp = _squaresize*w/2.0f;
416 float yp = y*_squaresize - _squaresize*h/2.0f + halfgapsize;
417 for( int z=0; z<d; z++)
418 {
419 float zp = z*_squaresize;
420 glNormal3f( 1,0,0);
421 glVertex3f(-xp, yp , zp);
422 glVertex3f(-xp, yp+tilesize, zp);
423 glVertex3f(-xp, yp+tilesize, zp+tilesize);
424 glVertex3f(-xp, yp , zp+tilesize);
425
426 glNormal3f(-1,0,0);
427 glVertex3f( xp, yp , zp+tilesize);
428 glVertex3f( xp, yp+tilesize, zp+tilesize);
429 glVertex3f( xp, yp+tilesize, zp);
430 glVertex3f( xp, yp , zp);
431 }
432 }
433 glEnd();
434
435 glPopMatrix();
436 }
437
setColor(int p)438 void BlockViewGLSmooth::setColor( int p)
439 {
440 switch( p % 7)
441 {
442 case 0:
443 glColor4f( 0.0, 0.0, 1.0, 1.0 );
444 break;
445 case 1:
446 glColor4f( 0.0, 1.0, 0.0, 1.0 );
447 break;
448 case 2:
449 glColor4f( 0.0, 1.0, 1.0, 1.0 );
450 break;
451 case 3:
452 glColor4f( 1.0, 0.0, 0.0, 1.0 );
453 break;
454 case 4:
455 glColor4f( 1.0, 0.0, 1.0, 1.0 );
456 break;
457 case 5:
458 glColor4f( 1.0, 0.7, 0.0, 1.0 );
459 break;
460 case 6:
461 glColor4f( 0.5, 0.5, 0.5, 1.0 );
462 break;
463 }
464 }
465
drawElement(Point3Di * p,bool isLocked)466 void BlockViewGLSmooth::drawElement( Point3Di *p, bool isLocked)
467 {
468 float xp = (p->x)*_squaresize;
469 float yp = (p->y)*_squaresize;
470 float zp = (p->z)*_squaresize;
471
472 float halftilesize = (_squaresize*0.80f)/2.0f;
473 float xpm = xp-halftilesize;
474 float xpp = xp+halftilesize;
475 float ypm = yp-halftilesize;
476 float ypp = yp+halftilesize;
477 float zpm = zp-halftilesize;
478 float zpp = zp+halftilesize;
479
480 float halfmtilesize = (_squaresize*0.60f)/2.0f;
481 float xpmm = xp-halfmtilesize;
482 float xpmp = xp+halfmtilesize;
483 float ypmm = yp-halfmtilesize;
484 float ypmp = yp+halfmtilesize;
485 float zpmm = zp-halfmtilesize;
486 float zpmp = zp+halfmtilesize;
487
488 if( isLocked)
489 {
490 setColor( p->z);
491 }
492
493 if( isLocked)
494 {
495 glBegin(GL_QUADS);
496 glNormal3f(-1,-1,1);
497 glVertex3f( xpm, ypm, zpm);
498 glNormal3f( 1,-1,1);
499 glVertex3f( xpp, ypm, zpm);
500 glNormal3f( 1, 1,1);
501 glVertex3f( xpp, ypp, zpm);
502 glNormal3f(-1, 1,1);
503 glVertex3f( xpm, ypp, zpm);
504
505 glNormal3f(-1, 1,-1);
506 glVertex3f( xpm, ypp, zpp);
507 glNormal3f( 1, 1,-1);
508 glVertex3f( xpp, ypp, zpp);
509 glNormal3f( 1,-1,-1);
510 glVertex3f( xpp, ypm, zpp);
511 glNormal3f(-1,-1,-1);
512 glVertex3f( xpm, ypm, zpp);
513
514 glEnd();
515 }
516 else
517 {
518 // glDisable( GL_DEPTH_TEST);
519 glColor4f( 1.0, 1.0, 0.3, 0.8 );
520
521 float dx= 1.0/512.0;
522 _blockFace->bind();
523
524 glEnable(GL_TEXTURE_2D);
525
526 glBegin(GL_QUADS);
527 glNormal3f( 0,0,1);
528 glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmm, zpmm);
529 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmm, zpmm);
530 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmp, zpmm);
531 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmp, zpmm);
532
533 glNormal3f( 0,0,-1);
534 glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmp, zpmp);
535 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmp, zpmp);
536 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmm, zpmp);
537 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmm, zpmp);
538
539 glNormal3f( 0, 1,0);
540 glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmm, zpmm);
541 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmm, zpmm);
542 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmm, zpmp);
543 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmm, zpmp);
544
545 glNormal3f( 0,-1,0);
546 glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmp, zpmp);
547 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmp, zpmp);
548 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmp, zpmm);
549 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmp, zpmm);
550
551 glNormal3f( 1,0,0);
552 glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmm, zpmm);
553 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmp, zpmm);
554 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmp, zpmp);
555 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmm, zpmp);
556
557 glNormal3f(-1,0,0);
558 glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmm, zpmp);
559 glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmp, zpmp);
560 glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmp, zpmm);
561 glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmm, zpmm);
562 glEnd();
563
564 glDisable(GL_TEXTURE_2D);
565
566 // glEnable( GL_DEPTH_TEST);
567 }
568
569 if( !isLocked)
570 {
571 glDisable( GL_LIGHTING);
572
573 // glLineWidth(2.0f);
574 glColor4f( 1.0, 1.0, 0.0, 1.0 );
575
576 glBegin(GL_LINE_LOOP);
577 glNormal3f( 0,0,1);
578 glVertex3f( xpm, ypm, zpm);
579 glVertex3f( xpp, ypm, zpm);
580 glVertex3f( xpp, ypp, zpm);
581 glVertex3f( xpm, ypp, zpm);
582 glEnd();
583
584 glBegin(GL_LINE_LOOP);
585 glNormal3f( 0,0,-1);
586 glVertex3f( xpm, ypm, zpp);
587 glVertex3f( xpp, ypm, zpp);
588 glVertex3f( xpp, ypp, zpp);
589 glVertex3f( xpm, ypp, zpp);
590 glEnd();
591
592 glBegin(GL_LINE_LOOP);
593 glNormal3f( 0, 1,0);
594 glVertex3f( xpp, ypm, zpm);
595 glVertex3f( xpm, ypm, zpm);
596 glVertex3f( xpm, ypm, zpp);
597 glVertex3f( xpp, ypm, zpp);
598 glEnd();
599
600 glBegin(GL_LINE_LOOP);
601 glNormal3f( 0,-1,0);
602 glVertex3f( xpp, ypp, zpp);
603 glVertex3f( xpm, ypp, zpp);
604 glVertex3f( xpm, ypp, zpm);
605 glVertex3f( xpp, ypp, zpm);
606 glEnd();
607
608 glEnable( GL_LIGHTING);
609 }
610 }
611