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 &currentAxis = 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