Back to index

extremetuxracer  0.5beta
course_render.cpp
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  */
00021 
00022 #include "course_load.h"
00023 #include "course_render.h"
00024 #include "textures.h"
00025 #include "phys_sim.h"
00026 #include "hier_util.h"
00027 #include "gl_util.h"
00028 #include "render_util.h"
00029 #include "fog.h"
00030 #include "course_quad.h"
00031 #include "viewfrustum.h"
00032 #include "track_marks.h"
00033 
00034 #include "game_config.h"
00035 
00036 #include "ppgltk/alg/defs.h"
00037 
00038 
00039 /* 
00040  *  Constants 
00041  */
00042  
00043 
00044 /* How long to make the flat part at the bottom of the course, as a
00045    fraction of the total length of the course */
00046 #define FLAT_SEGMENT_FRACTION 0.2
00047 
00048 /* Aspect ratio of background texture */
00049 #define BACKGROUND_TEXTURE_ASPECT 3.0
00050 
00051 
00052 /*
00053  * Statics 
00054  */
00055 
00056 /* The course normal vectors */
00057 static pp::Vec3d *nmls = NULL;
00058 
00059 /* Should we activate clipping when drawing the course? */
00060 static bool clip_course = false;
00061 
00062 /* If clipping is active, it will be based on a camera located here */
00063 static pp::Vec3d eye_pt;
00064 
00065 
00066 /* Macros for converting indices in height map to world coordinates */
00067 #define XCD(x) (  (double)(x) / (nx-1.) * courseWidth )
00068 #define ZCD(y) ( -(double)(y) / (ny-1.) * courseLength )
00069 
00070 #define NORMAL(x, y) ( nmls[ (x) + nx * (y) ] )
00071 
00072 
00073 /*
00074  * Function definitions
00075  */
00076 
00077 void set_course_clipping( bool state ) { clip_course = state; }
00078 void set_course_eye_point( pp::Vec3d pt ) { eye_pt = pt; }
00079 
00080 pp::Vec3d* get_course_normals() { return nmls; } 
00081 
00082 void calc_normals()
00083 {
00084     float *elevation;
00085     float courseWidth, courseLength;
00086     int nx, ny;
00087     int x,y;
00088     pp::Vec3d p0, p1, p2;
00089     pp::Vec3d n, nml, v1, v2;
00090 
00091     elevation = get_course_elev_data();
00092     get_course_dimensions( &courseWidth, &courseLength );
00093     get_course_divisions( &nx, &ny );
00094 
00095     if ( nmls != NULL ) {
00096         free( nmls );
00097     } 
00098 
00099     nmls = (pp::Vec3d *)malloc( sizeof(pp::Vec3d)*nx*ny ); 
00100     if ( nmls == NULL ) {
00101        handle_system_error( 1, "malloc failed" );
00102     }
00103 
00104     for ( y=0; y<ny; y++) {
00105         for ( x=0; x<nx; x++) {
00106             nml = pp::Vec3d( 0., 0., 0. );
00107 
00108             p0 = pp::Vec3d( XCD(x), ELEV(x,y), ZCD(y) );
00109 
00110            /* The terrain is meshed as follows:
00111                     ...
00112                  +-+-+-+-+            x<---+
00113                  |\|/|\|/|                 |
00114               ...+-+-+-+-+...              V
00115                  |/|\|/|\|                 y
00116                  +-+-+-+-+
00117                    ...
00118 
00119               So there are two types of vertices: those surrounded by
00120               four triangles (x+y is odd), and those surrounded by
00121               eight (x+y is even).
00122            */
00123 
00124 #define POINT(x,y) pp::Vec3d( XCD(x), ELEV(x,y), ZCD(y) )
00125 
00126            if ( (x + y) % 2 == 0 ) {
00127               if ( x > 0 && y > 0 ) {
00128                   p1 = POINT(x,  y-1);
00129                   p2 = POINT(x-1,y-1);
00130                   v1 = p1-p0;
00131                   v2 = p2-p0;
00132                   n = v2^v1;
00133 
00134                   check_assertion( n.y > 0, "course normal points down" );
00135 
00136                   n.normalize();
00137                   nml = nml+n;
00138 
00139                   p1 = POINT(x-1,y-1);
00140                   p2 = POINT(x-1,y  );
00141                   v1 = p1-p0;
00142                   v2 = p2-p0;
00143                   n = v2^v1;
00144 
00145                   check_assertion( n.y > 0, "course normal points down" );
00146 
00147                   n.normalize();
00148                   nml = nml+n;
00149               } 
00150               if ( x > 0 && y < ny-1 ) {
00151                   p1 = POINT(x-1,y  );
00152                   p2 = POINT(x-1,y+1);
00153                   v1 = p1-p0;
00154                   v2 = p2-p0;
00155                   n = v2^v1;
00156 
00157                   check_assertion( n.y > 0, "course normal points down" );
00158 
00159                   n.normalize();
00160                   nml = nml+n;
00161 
00162                   p1 = POINT(x-1,y+1);
00163                   p2 = POINT(x  ,y+1);
00164                   v1 = p1-p0;
00165                   v2 = p2-p0;
00166                   n = v2^v1;
00167 
00168                   check_assertion( n.y > 0, "course normal points down" );
00169 
00170                   n.normalize();
00171                   nml = nml+n;
00172               } 
00173               if ( x < nx-1 && y > 0 ) {
00174                   p1 = POINT(x+1,y  );
00175                   p2 = POINT(x+1,y-1);
00176                   v1 = p1-p0;
00177                   v2 = p2-p0;
00178                   n = v2^v1;
00179 
00180                   check_assertion( n.y > 0, "course normal points down" );
00181 
00182                   n.normalize();
00183                   nml = nml+n;
00184 
00185                   p1 = POINT(x+1,y-1);
00186                   p2 = POINT(x  ,y-1);
00187                   v1 = p1-p0;
00188                   v2 = p2-p0;
00189                   n = v2^v1;
00190 
00191                   check_assertion( n.y > 0, "course normal points down" );
00192 
00193                   n.normalize();
00194                   nml = nml+n;
00195               } 
00196               if ( x < nx-1 && y < ny-1 ) {
00197                   p1 = POINT(x+1,y  );
00198                   p2 = POINT(x+1,y+1);
00199                   v1 = p1-p0;
00200                   v2 = p2-p0;
00201                   n = v1^v2;
00202 
00203                   check_assertion( n.y > 0, "course normal points down" );
00204 
00205                   n.normalize();
00206                   nml = nml+n;
00207 
00208                   p1 = POINT(x+1,y+1);
00209                   p2 = POINT(x  ,y+1);
00210                   v1 = p1-p0;
00211                   v2 = p2-p0;
00212                   n = v1^v2;
00213 
00214                   check_assertion( n.y > 0, "course normal points down" );
00215 
00216                   n.normalize();
00217                   nml = nml+n;
00218 
00219               } 
00220            } else {
00221               /* x + y is odd */
00222               if ( x > 0 && y > 0 ) {
00223                   p1 = POINT(x,  y-1);
00224                   p2 = POINT(x-1,y  );
00225                   v1 = p1-p0;
00226                   v2 = p2-p0;
00227                   n = v2^v1;
00228 
00229                   check_assertion( n.y > 0, "course normal points down" );
00230 
00231                   n.normalize();
00232                   nml = nml+n;
00233               } 
00234               if ( x > 0 && y < ny-1 ) {
00235                   p1 = POINT(x-1,y  );
00236                   p2 = POINT(x  ,y+1);
00237                   v1 = p1-p0;
00238                   v2 = p2-p0;
00239                   n = v2^v1;
00240 
00241                   check_assertion( n.y > 0, "course normal points down" );
00242 
00243                   n.normalize();
00244                   nml = nml+n;
00245               } 
00246               if ( x < nx-1 && y > 0 ) {
00247                   p1 = POINT(x+1,y  );
00248                   p2 = POINT(x  ,y-1);
00249                   v1 = p1-p0;
00250                   v2 = p2-p0;
00251                   n = v2^v1;
00252 
00253                   check_assertion( n.y > 0, "course normal points down" );
00254 
00255                   n.normalize();
00256                   nml = nml+n;
00257               } 
00258               if ( x < nx-1 && y < ny-1 ) {
00259                   p1 = POINT(x+1,y  );
00260                   p2 = POINT(x  ,y+1);
00261                   v1 = p1-p0;
00262                   v2 = p2-p0;
00263                   n = v1^v2;
00264 
00265                   check_assertion( n.y > 0, "course normal points down" );
00266 
00267                   n.normalize();
00268                   nml = nml+n;
00269               } 
00270            }
00271 
00272             nml.normalize();
00273             NORMAL(x,y) = nml;
00274             continue;
00275         } 
00276 #undef POINT
00277     } 
00278 } 
00279 
00280 void setup_course_tex_gen()
00281 {
00282     static GLfloat xplane[4] = { 1.0 / TEX_SCALE, 0.0, 0.0, 0.0 };
00283     static GLfloat zplane[4] = { 0.0, 0.0, 1.0 / TEX_SCALE, 0.0 };
00284     glTexGenfv( GL_S, GL_OBJECT_PLANE, xplane );
00285     glTexGenfv( GL_T, GL_OBJECT_PLANE, zplane );
00286 }
00287 
00288 #define DRAW_POINT \
00289     glNormal3f( nml.x, nml.y, nml.z ); \
00290     glVertex3f( pt.x, pt.y, pt.z ); 
00291 
00292 
00293 void render_course()
00294 {
00295     int nx, ny;
00296 
00297     get_course_divisions(&nx, &ny);
00298     set_gl_options( COURSE );
00299 
00300     setup_course_tex_gen();
00301 
00302     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00303     set_material( pp::Color::white, pp::Color::black, 1.0 );
00304     
00305     update_course_quadtree( eye_pt, getparam_course_detail_level() );
00306 
00307 
00308     render_course_quadtree( );
00309        
00310     draw_track_marks();
00311 }
00312 
00313 void draw_sky(pp::Vec3d pos)
00314 {
00315   GLuint texture_id[6];
00316 
00317   set_gl_options( SKY );
00318 
00319   if (!(get_texture_binding( "sky_front", &texture_id[0] ) && 
00320         get_texture_binding( "sky_top", &texture_id[1] ) && 
00321         get_texture_binding( "sky_bottom", &texture_id[2] ) && 
00322         get_texture_binding( "sky_left", &texture_id[3] ) && 
00323         get_texture_binding( "sky_right", &texture_id[4] ) && 
00324         get_texture_binding( "sky_back", &texture_id[5] ) ) ) {
00325     return;
00326   } 
00327 
00328   glColor4f( 1.0, 1.0, 1.0, 1.0 );
00329 
00330   glPushMatrix();
00331 
00332   glTranslatef(pos.x, pos.y, pos.z);
00333 
00334   glBindTexture( GL_TEXTURE_2D, texture_id[0] );
00335   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00336 
00337   glBegin(GL_QUADS);
00338   glTexCoord2f( 0.0, 0.0 );
00339   glVertex3f( -1, -1, -1);
00340   glTexCoord2f( 1.0, 0.0 );
00341   glVertex3f(  1, -1, -1);
00342   glTexCoord2f( 1.0, 1.0 );
00343   glVertex3f(  1,  1, -1);
00344   glTexCoord2f( 0.0, 1.0 );
00345   glVertex3f( -1,  1, -1);
00346   glEnd();
00347 
00348   glBindTexture( GL_TEXTURE_2D, texture_id[1] );
00349   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00350 
00351   glBegin(GL_QUADS);
00352   glTexCoord2f( 0.0, 0.0 );
00353   glVertex3f( -1,  1, -1);
00354   glTexCoord2f( 1.0, 0.0 );
00355   glVertex3f(  1,  1, -1);
00356   glTexCoord2f( 1.0, 1.0 );
00357   glVertex3f(  1,  1,  1);
00358   glTexCoord2f( 0.0, 1.0 );
00359   glVertex3f( -1,  1,  1);
00360   glEnd();
00361 
00362   glBindTexture( GL_TEXTURE_2D, texture_id[2] );
00363   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00364 
00365   glBegin(GL_QUADS);
00366   glTexCoord2f( 0.0, 0.0 );
00367   glVertex3f( -1, -1,  1);
00368   glTexCoord2f( 1.0, 0.0 );
00369   glVertex3f(  1, -1,  1);
00370   glTexCoord2f( 1.0, 1.0 );
00371   glVertex3f(  1, -1, -1);
00372   glTexCoord2f( 0.0, 1.0 );
00373   glVertex3f( -1, -1, -1);
00374   glEnd();
00375 
00376 
00377   glBindTexture( GL_TEXTURE_2D, texture_id[3] );
00378   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00379 
00380   glBegin(GL_QUADS);
00381   glTexCoord2f( 0.0, 0.0 );
00382   glVertex3f( -1, -1,  1);
00383   glTexCoord2f( 1.0, 0.0 );
00384   glVertex3f( -1, -1, -1);
00385   glTexCoord2f( 1.0, 1.0 );
00386   glVertex3f( -1,  1, -1);
00387   glTexCoord2f( 0.0, 1.0 );
00388   glVertex3f( -1,  1,  1);
00389   glEnd();
00390 
00391 
00392   glBindTexture( GL_TEXTURE_2D, texture_id[4] );
00393   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00394 
00395   glBegin(GL_QUADS);
00396   glTexCoord2f( 0.0, 0.0 );
00397   glVertex3f(  1, -1, -1);
00398   glTexCoord2f( 1.0, 0.0 );
00399   glVertex3f(  1, -1,  1);
00400   glTexCoord2f( 1.0, 1.0 );
00401   glVertex3f(  1,  1,  1);
00402   glTexCoord2f( 0.0, 1.0 );
00403   glVertex3f(  1,  1, -1);
00404   glEnd();
00405 
00406 
00407   glBindTexture( GL_TEXTURE_2D, texture_id[5] );
00408   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
00409 
00410   glBegin(GL_QUADS);
00411   glTexCoord2f( 0.0, 0.0 );
00412   glVertex3f(  1, -1,  1);
00413   glTexCoord2f( 1.0, 0.0 );
00414   glVertex3f( -1, -1,  1);
00415   glTexCoord2f( 1.0, 1.0 );
00416   glVertex3f( -1,  1,  1);
00417   glTexCoord2f( 0.0, 1.0 );
00418   glVertex3f(  1,  1,  1);
00419   glEnd();
00420 
00421 
00422   glPopMatrix();
00423 
00424 }
00425 
00426 void draw_trees() 
00427 {
00428     Tree    *treeLocs;
00429     int       numTrees;
00430     //double  treeRadius;
00431     //double  treeHeight;
00432     int       i;
00433     GLuint    texture_id;
00434     pp::Vec3d  normal;
00435     double  fwd_clip_limit, bwd_clip_limit, fwd_tree_detail_limit;
00436 
00437     int tree_type = -1;
00438     const char *tree_name = 0;
00439 
00440     Item    *itemLocs;
00441     int       numItems;
00442     double  itemRadius;
00443     double  itemHeight;
00444     int       item_type = -1;
00445     const char *    item_name = 0;
00446     item_type_t *item_types;
00447 
00448     treeLocs = get_tree_locs();
00449     numTrees = get_num_trees();
00450     item_types = get_item_types();
00451 
00452     fwd_clip_limit = getparam_forward_clip_distance();
00453     bwd_clip_limit = getparam_backward_clip_distance();
00454     fwd_tree_detail_limit = getparam_tree_detail_distance();
00455 
00456     set_gl_options( TREES );
00457 
00458     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00459     set_material( pp::Color::white, pp::Color::black, 1.0 );
00460     
00461     for (i = 0; i< numTrees; i++ ) {
00462 
00463               if ( clip_course ) {
00464                      if ( eye_pt.z - treeLocs[i].ray.pt.z > fwd_clip_limit ) 
00465                      continue;
00466            
00467               if ( treeLocs[i].ray.pt.z - eye_pt.z > bwd_clip_limit )
00468                      continue;
00469               }
00470 
00471               // verify that the correct texture is bound
00472               if (treeLocs[i].type != tree_type) {
00473                   tree_type = treeLocs[i].type;
00474                   tree_name = get_tree_name(tree_type);
00475               }
00476 
00477         glPushMatrix();
00478         
00479               glTranslatef( treeLocs[i].ray.pt.x,
00480                             treeLocs[i].ray.pt.y, 
00481                      treeLocs[i].ray.pt.z );
00482 
00483               normal = eye_pt - treeLocs[i].ray.pt;
00484               normal.normalize();
00485 
00486               glNormal3f( normal.x, normal.y, normal.z );
00487               //glCallList( treeLocs[i].getDisplayList() );    
00488               
00489               treeLocs[i].getModel()->draw();
00490               
00491         glPopMatrix();
00492     } 
00493 
00494     itemLocs = get_item_locs();
00495     numItems = get_num_items();
00496 
00497     for (i = 0; i< numItems; i++ ) {
00498 
00499        if ( !itemLocs[i].isDrawable() ) {
00500               continue;
00501        }
00502 
00503        if ( clip_course ) {
00504            if ( eye_pt.z - itemLocs[i].ray.pt.z > fwd_clip_limit ) 
00505               continue;
00506            
00507            if ( itemLocs[i].ray.pt.z - eye_pt.z > bwd_clip_limit )
00508               continue;
00509        }
00510 
00511        /* verify that the correct texture is bound */
00512        if (itemLocs[i].type != item_type) {
00513            item_type = itemLocs[i].type;
00514            item_name = get_item_name(item_type);
00515            if (!get_texture_binding( item_name, &texture_id ) ) {
00516               texture_id = 0;
00517            }
00518            glBindTexture( GL_TEXTURE_2D, texture_id );
00519        }
00520 
00521         glPushMatrix();
00522        {
00523            glTranslatef( itemLocs[i].ray.pt.x, itemLocs[i].ray.pt.y, 
00524                        itemLocs[i].ray.pt.z );
00525 
00526            itemRadius = itemLocs[i].diam/2.;
00527            itemHeight = itemLocs[i].height;
00528 
00529            if ( item_types[item_type].use_normal ) {
00530               normal = item_types[item_type].normal;
00531            } else {
00532               normal = eye_pt - itemLocs[i].ray.pt;
00533               normal.normalize();
00534            }
00535 
00536            if (normal.y == 1.0) {
00537               continue;
00538            }
00539 
00540            glNormal3f( normal.x, normal.y, normal.z );
00541 
00542            normal.y = 0.0;
00543            normal.normalize();
00544 
00545            glBegin( GL_QUADS );
00546            {
00547               glTexCoord2f( 0., 0. );
00548               glVertex3f( -itemRadius*normal.z, 
00549                          0.0, 
00550                          itemRadius*normal.x );
00551               glTexCoord2f( 1., 0. );
00552               glVertex3f( itemRadius*normal.z, 
00553                          0.0, 
00554                          -itemRadius*normal.x );
00555               glTexCoord2f( 1., 1. );
00556               glVertex3f( itemRadius*normal.z, 
00557                          itemHeight, 
00558                          -itemRadius*normal.x );
00559               glTexCoord2f( 0., 1. );
00560               glVertex3f( -itemRadius*normal.z, 
00561                          itemHeight, 
00562                          itemRadius*normal.x );
00563            }
00564            glEnd();
00565        }
00566         glPopMatrix();
00567     } 
00568 
00569 } 
00570 
00580 void draw_fog_plane()
00581 {
00582     pp::Plane left_edge_plane, right_edge_plane;
00583     pp::Plane left_clip_plane, right_clip_plane;
00584     pp::Plane far_clip_plane;
00585     pp::Plane bottom_clip_plane;
00586     pp::Plane bottom_plane, top_plane;
00587 
00588     float course_width, course_length;
00589     double course_angle, slope;
00590 
00591     pp::Vec3d left_pt, right_pt, pt;
00592     pp::Vec3d top_left_pt, top_right_pt;
00593     pp::Vec3d bottom_left_pt, bottom_right_pt;
00594     pp::Vec3d left_vec, right_vec;
00595     double height;
00596 
00597     GLfloat *fogColor;
00598 
00599     if ( fogPlane.isEnabled() == false ) {
00600        return;
00601     }
00602 
00603     //set_gl_options( FOG_PLANE );
00604 
00605     get_course_dimensions( &course_width, &course_length );
00606     course_angle = get_course_angle();
00607     slope = tan( ANGLES_TO_RADIANS( course_angle ) );
00608 
00609     left_edge_plane = pp::Plane( 1.0, 0.0, 0.0, 0.0 );
00610 
00611     right_edge_plane = pp::Plane( -1.0, 0.0, 0.0, course_width );
00612 
00613     far_clip_plane = get_far_clip_plane();
00614     left_clip_plane = get_left_clip_plane();
00615     right_clip_plane = get_right_clip_plane();
00616     bottom_clip_plane = get_bottom_clip_plane();
00617 
00618 
00619     // Find the bottom plane 
00620     bottom_plane.nml = pp::Vec3d( 0.0, 1, -slope );
00621     height = get_terrain_base_height( 0 );
00622 
00623     bottom_plane.d = -height * bottom_plane.nml.y;
00624 
00625     // Find the top plane 
00626     top_plane.nml = bottom_plane.nml;
00627     height = get_terrain_max_height( 0 );
00628     top_plane.d = -height * top_plane.nml.y;
00629 
00630     // Now find the bottom left and right points of the fog plane 
00631     if ( !pp::Plane::intersect( bottom_plane, far_clip_plane, left_clip_plane,
00632                          &left_pt ) )
00633     {
00634        return;
00635     }
00636 
00637     if ( !pp::Plane::intersect( bottom_plane, far_clip_plane, right_clip_plane,
00638                          &right_pt ) )
00639     {
00640        return;
00641     }
00642 
00643     if ( !pp::Plane::intersect( top_plane, far_clip_plane, left_clip_plane,
00644                          &top_left_pt ) )
00645     {
00646        return;
00647     }
00648 
00649     if ( !pp::Plane::intersect( top_plane, far_clip_plane, right_clip_plane,
00650                          &top_right_pt ) )
00651     {
00652        return;
00653     }
00654 
00655     if ( !pp::Plane::intersect( bottom_clip_plane, far_clip_plane, 
00656                          left_clip_plane, &bottom_left_pt ) )
00657     {
00658        return;
00659     }
00660 
00661     if ( !pp::Plane::intersect( bottom_clip_plane, far_clip_plane, 
00662                          right_clip_plane, &bottom_right_pt ) )
00663     {
00664        return;
00665     }
00666 
00667     left_vec = top_left_pt - left_pt;
00668     right_vec = top_right_pt - right_pt;
00669 
00670 
00671     // Now draw the fog plane 
00672 
00673     set_gl_options( FOG_PLANE );
00674 
00675     fogColor = fogPlane.getColor();
00676 
00677     glColor4fv( fogColor );
00678 
00679     glBegin( GL_QUAD_STRIP );
00680 
00681     glVertex3f( bottom_left_pt.x, bottom_left_pt.y, bottom_left_pt.z );
00682     glVertex3f( bottom_right_pt.x, bottom_right_pt.y, bottom_right_pt.z );
00683     glVertex3f( left_pt.x, left_pt.y, left_pt.z );
00684     glVertex3f( right_pt.x, right_pt.y, right_pt.z );
00685 
00686     glColor4f( fogColor[0], fogColor[1], fogColor[2], 0.9 );
00687     glVertex3f( top_left_pt.x, top_left_pt.y, top_left_pt.z );
00688     glVertex3f( top_right_pt.x, top_right_pt.y, top_right_pt.z );
00689 
00690     glColor4f( fogColor[0], fogColor[1], fogColor[2], 0.3 );
00691     pt = top_left_pt + left_vec ;
00692     glVertex3f( pt.x, pt.y, pt.z );
00693     pt = top_right_pt + right_vec;
00694     glVertex3f( pt.x, pt.y, pt.z );
00695               
00696     glColor4f( fogColor[0], fogColor[1], fogColor[2], 0.0 );
00697     pt = top_left_pt + left_vec*3.0;
00698     glVertex3f( pt.x, pt.y, pt.z );
00699     pt = top_right_pt + right_vec*3.0;
00700     glVertex3f( pt.x, pt.y, pt.z );
00701 
00702     glEnd();
00703 }