Back to index

extremetuxracer  0.5beta
course_quad.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 "quadtree.h"
00024 
00025 #include "ppgltk/alg/defs.h"
00026 
00027 #define CULL_DETAIL_FACTOR 25
00028 
00029 static quadsquare *root = (quadsquare*) NULL;
00030 static quadcornerdata root_corner_data = { (quadcornerdata*)NULL };
00031 
00032 
00033 void reset_course_quadtree()
00034 {
00035     delete root;
00036     root = (quadsquare*)NULL;
00037 }
00038 
00039 static int get_root_level( int nx, int nz )
00040 {
00041     int xlev, zlev;
00042 
00043     check_assertion( nx > 0, "heightmap has x dimension of 0 size" );
00044     check_assertion( nz > 0, "heightmap has z dimension of 0 size" );
00045 
00046     xlev = (int) ( log((double) nx ) / log ((double) 2.0 ) );
00047     zlev = (int) ( log((double) nz ) / log ((double) 2.0 ) );
00048 
00049     /* Check to see if nx, nz are powers of 2 
00050      */
00051 
00052     if ( ( nx >> xlev ) << xlev == nx ) {
00053        /* do nothing */
00054     } else {
00055        nx += 1;
00056     }
00057 
00058     if ( ( nz >> zlev ) << zlev == nz ) {
00059        /* do nothing */
00060     } else {
00061        nz += 1;
00062     }
00063 
00064     return MAX( xlev, zlev );
00065 }
00066 
00067 static void Vec3fo_float_array( float dest[3], pp::Vec3d src )
00068 {
00069     dest[0] = src.x;
00070     dest[1] = src.y;
00071     dest[2] = src.z;
00072 }
00073 
00074 
00075 void init_course_quadtree( float *elevation, int nx, int nz, 
00076                         double scalex, double scalez,
00077                         pp::Vec3d view_pos, double detail )
00078 {
00079     HeightMapInfo hm;
00080     int i;
00081 
00082     hm.Data = elevation;
00083     hm.XOrigin = 0;
00084     hm.ZOrigin = 0;
00085     hm.XSize = nx;
00086     hm.ZSize = nz;
00087     hm.RowWidth = hm.XSize;
00088     hm.Scale = 0;
00089 
00090     root_corner_data.Square = (quadsquare*)NULL;
00091     root_corner_data.ChildIndex = 0;
00092     root_corner_data.Level = get_root_level( nx, nz );
00093     root_corner_data.xorg = 0;
00094     root_corner_data.zorg = 0;
00095 
00096     for (i=0; i<4; i++) {
00097        root_corner_data.Verts[i] = 0;
00098        root_corner_data.Verts[i] = 0;
00099     }
00100 
00101     root = new quadsquare( &root_corner_data );
00102 
00103     root->AddHeightMap( root_corner_data, hm );
00104     root->SetScale( scalex, scalez );
00105     root->SetTerrain( get_course_terrain_data() );
00106 
00107     // Debug info.
00108     //print_debug( DEBUG_QUADTREE, "nodes = %d\n", root->CountNodes());
00109     print_debug( DEBUG_QUADTREE, "max error = %g\n", 
00110                root->RecomputeError(root_corner_data));
00111 
00112     // Get rid of unnecessary nodes in flat-ish areas.
00113     print_debug( DEBUG_QUADTREE, 
00114                "Culling unnecessary nodes (detail factor = %d)...\n",
00115                CULL_DETAIL_FACTOR);
00116     root->StaticCullData(root_corner_data, CULL_DETAIL_FACTOR);
00117 
00118     // Post-cull debug info.
00119     print_debug( DEBUG_QUADTREE, "nodes = %d\n", root->CountNodes());
00120     print_debug( DEBUG_QUADTREE, "max error = %g\n", 
00121                root->RecomputeError(root_corner_data));
00122 
00123 
00124     // Run the update function a few times before we start rendering
00125     // to disable unnecessary quadsquares, so the first frame won't
00126     // be overloaded with tons of triangles.
00127 
00128     float ViewerLoc[3];
00129     Vec3fo_float_array( ViewerLoc, view_pos );
00130 
00131     for (i = 0; i < 10; i++) {
00132        root->Update(root_corner_data, (const float*) ViewerLoc, 
00133                    detail);
00134     }
00135 }
00136 
00137 
00138 void update_course_quadtree( const pp::Vec3d view_pos, const float detail )
00139 {
00140     float ViewerLoc[3];
00141 
00142     Vec3fo_float_array( ViewerLoc, view_pos );
00143 
00144     root->Update( root_corner_data, ViewerLoc, detail );
00145 }
00146 
00147 void render_course_quadtree()
00148 {
00149     GLubyte *vnc_array;
00150 
00151     get_gl_arrays( &vnc_array );
00152 
00153     root->Render( root_corner_data, vnc_array );
00154 }