00001 /*************************************************************************** 00002 terrainscenemanager.cpp - description 00003 ------------------- 00004 begin : Mon Sep 23 2002 00005 copyright : (C) 2002 by Jon Anderson 00006 email : janders@users.sf.net 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU Lesser General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <OgreTerrainSceneManager.h> 00019 #include <OgreImage.h> 00020 #include <OgreConfigFile.h> 00021 #include <OgreMaterial.h> 00022 #include <OgreTechnique.h> 00023 #include <OgrePass.h> 00024 #include <OgreCamera.h> 00025 #include "OgreException.h" 00026 #include "OgreStringConverter.h" 00027 #include <OgreRenderSystem.h> 00028 #include <fstream> 00029 00030 namespace Ogre 00031 { 00032 00033 TerrainSceneManager::TerrainSceneManager() : OctreeSceneManager( ) 00034 { 00035 //setDisplaySceneNodes( true ); 00036 //setShowBoxes( true ); 00037 } 00038 00039 TerrainSceneManager::~TerrainSceneManager() 00040 { 00041 size_t size = mTiles.size(); 00042 00043 for ( size_t i = 0; i < size; i++ ) 00044 for ( size_t j = 0; j < size; j++ ) 00045 delete mTiles[ i ][ j ]; 00046 } 00047 00048 void TerrainSceneManager::setWorldGeometry( const String& filename ) 00049 { 00050 int i, j; 00051 00052 /* Set up the options */ 00053 ConfigFile config; 00054 TerrainOptions options; 00055 00056 config.load( filename ); 00057 00058 if ( config.getSetting( "DetailTile" ) != "" ) 00059 options.detail_tile = atoi( config.getSetting( "DetailTile" ) ); 00060 00061 options.max_mipmap = atoi( config.getSetting( "MaxMipMapLevel" ) ); 00062 00063 options.scalex = atof( config.getSetting( "ScaleX" ) ); 00064 00065 options.scaley = atof( config.getSetting( "ScaleY" ) ); 00066 00067 options.scalez = atof( config.getSetting( "ScaleZ" ) ); 00068 00069 options.max_pixel_error = atoi( config.getSetting( "MaxPixelError" ) ); 00070 00071 options.size = atoi( config.getSetting( "TileSize" ) ); 00072 00073 String terrain_filename = config.getSetting( "Terrain" ); 00074 00075 String detail_texture = config.getSetting( "DetailTexture" ); 00076 00077 String world_texture = config.getSetting( "WorldTexture" ); 00078 00079 if ( config.getSetting( "VertexColors" ) == "yes" ) 00080 options.colored = true; 00081 00082 if ( config.getSetting( "VertexNormals" ) == "yes" ) 00083 options.lit = true; 00084 00085 mScale = Vector3( options.scalex, options.scaley, options.scalez ); 00086 00087 mTileSize = options.size; 00088 00089 Image image; 00090 00091 image.load( terrain_filename ); 00092 00093 //check to make sure it's 2^n + 1 size. 00094 if ( image.getWidth() != image.getHeight() || 00095 ! _checkSize( image.getWidth() ) ) 00096 { 00097 String err = "Error: Invalid heightmap size : " + 00098 StringConverter::toString( image.getWidth() ) + 00099 "," + StringConverter::toString( image.getHeight() ) + 00100 ". Should be 2^n+1, 2^n+1"; 00101 Except( Exception::ERR_INVALIDPARAMS, err, "TerrainSceneManager::setWorldGeometry" ); 00102 } 00103 00104 if ( image.getFormat() != PF_L8 ) 00105 { 00106 Except( Exception::ERR_INVALIDPARAMS, "Error: Image is not a grayscale image.", 00107 "TerrainSceneManager::setWorldGeometry" ); 00108 } 00109 00110 const uchar *data = image. getData(); 00111 00112 int size = image.getWidth(); 00113 00114 // set up the octree size. 00115 float max_x = options.scalex * size; 00116 00117 float max_y = 255 * options.scaley; 00118 00119 float max_z = options.scalez * size; 00120 00121 resize( AxisAlignedBox( 0, 0, 0, max_x, max_y, max_z ) ); 00122 00123 00124 00125 options.data = data; 00126 00127 options.world_size = size; 00128 00129 mTerrainMaterial = createMaterial( "Terrain" ); 00130 00131 if ( world_texture != "" ) 00132 mTerrainMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( world_texture, 0 ); 00133 00134 if ( detail_texture != "" ) 00135 { 00136 mTerrainMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( detail_texture, 1 ); 00137 } 00138 00139 mTerrainMaterial -> setLightingEnabled( options.lit ); 00140 00141 mTerrainMaterial->load(); 00142 00143 00144 //create a root terrain node. 00145 mTerrainRoot = getRootSceneNode() -> createChildSceneNode( "Terrain" ); 00146 00147 //setup the tile array. 00148 int num_tiles = ( options.world_size - 1 ) / ( options.size - 1 ); 00149 00150 for ( i = 0; i < num_tiles; i++ ) 00151 { 00152 mTiles.push_back( TerrainRow() ); 00153 00154 for ( j = 0; j < num_tiles; j++ ) 00155 { 00156 mTiles[ i ].push_back( 0 ); 00157 } 00158 } 00159 00160 char name[ 24 ]; 00161 int p = 0; 00162 int q = 0; 00163 00164 for ( j = 0; j < options.world_size - 1; j += ( options.size - 1 ) ) 00165 { 00166 p = 0; 00167 00168 for ( i = 0; i < options.world_size - 1; i += ( options.size - 1 ) ) 00169 { 00170 options.startx = i; 00171 options.startz = j; 00172 sprintf( name, "tile[%d,%d]", p, q ); 00173 00174 SceneNode *c = mTerrainRoot -> createChildSceneNode( name ); 00175 TerrainRenderable *tile = new TerrainRenderable(); 00176 00177 tile -> setMaterial( mTerrainMaterial ); 00178 tile -> init( options ); 00179 00180 mTiles[ p ][ q ] = tile; 00181 00182 c -> attachObject( tile ); 00183 p++; 00184 } 00185 00186 q++; 00187 00188 } 00189 00190 00191 //setup the neighbor links. 00192 size = ( int ) mTiles.size(); 00193 00194 for ( j = 0; j < size; j++ ) 00195 { 00196 for ( i = 0; i < size; i++ ) 00197 { 00198 if ( j != size - 1 ) 00199 { 00200 mTiles[ i ][ j ] -> _setNeighbor( TerrainRenderable::SOUTH, mTiles[ i ][ j + 1 ] ); 00201 mTiles[ i ][ j + 1 ] -> _setNeighbor( TerrainRenderable::NORTH, mTiles[ i ][ j ] ); 00202 } 00203 00204 if ( i != size - 1 ) 00205 { 00206 mTiles[ i ][ j ] -> _setNeighbor( TerrainRenderable::EAST, mTiles[ i + 1 ][ j ] ); 00207 mTiles[ i + 1 ][ j ] -> _setNeighbor( TerrainRenderable::WEST, mTiles[ i ][ j ] ); 00208 } 00209 00210 } 00211 } 00212 00213 if(options.lit) 00214 { 00215 for ( j = 0; j < size; j++ ) 00216 { 00217 for ( i = 0; i < size; i++ ) 00218 { 00219 mTiles[ i ][ j ] -> _calculateNormals( ); 00220 // mTiles[ i ][ j ] -> _generateVertexLighting( Vector3( 255, 100, 255 ), ColourValue(.25,.25,.25) ); 00221 } 00222 } 00223 } 00224 00225 /* 00226 for ( j = 0; j < size; j++ ) 00227 { 00228 for ( i = 0; i < size; i++ ) 00229 { 00230 mTiles[ i ][ j ] -> _generateVertexLighting( Vector3( 255, 50, 255 ), ColourValue( .25, .25, .25 ) ); 00231 } 00232 } 00233 */ 00234 00235 00236 00237 // intersectSegment( Vector3(255, getHeightAt(255,255), 255), Vector3(255,50,255), 0 ); 00238 00239 00240 } 00241 00242 00243 void TerrainSceneManager::_updateSceneGraph( Camera * cam ) 00244 00245 { 00246 00247 //Vector3 c = cam -> getPosition(); 00248 //c.y = getHeightAt(c.x, c.z ) + 2; 00249 //cam -> setPosition( c ); 00250 00251 OctreeSceneManager::_updateSceneGraph( cam ); 00252 } 00253 00254 void TerrainSceneManager::_renderVisibleObjects( void ) 00255 { 00256 00257 for ( int i = 0; i < ( int ) mTiles.size(); i++ ) 00258 { 00259 for ( int j = 0; j < ( int ) mTiles.size(); j++ ) 00260 { 00261 mTiles[ i ][ j ] ->_alignNeighbors(); 00262 } 00263 } 00264 00265 mDestRenderSystem -> setLightingEnabled( false ); 00266 00267 OctreeSceneManager::_renderVisibleObjects(); 00268 00269 TerrainRenderable::mRenderedTris = 0; 00270 00271 } 00272 00273 void TerrainSceneManager::_findVisibleObjects ( Camera * cam ) 00274 { 00275 OctreeSceneManager::_findVisibleObjects( cam ); 00276 } 00277 00278 float TerrainSceneManager::getHeightAt( float x, float z ) 00279 { 00280 00281 00282 Vector3 pt( x, 0, z ); 00283 00284 TerrainRenderable * t = getTerrainTile( pt ); 00285 00286 if ( t == 0 ) 00287 { 00288 // printf( "No tile found for point\n" ); 00289 return -1; 00290 } 00291 00292 float h = t -> getHeightAt( x, z ); 00293 00294 // printf( "Height is %f\n", h ); 00295 return h; 00296 00297 } 00298 00299 TerrainRenderable * TerrainSceneManager::getTerrainTile( const Vector3 & pt ) 00300 { 00301 /* Since we don't know if the terrain is square, or has holes, we use a line trace 00302 to find the containing tile... 00303 */ 00304 00305 TerrainRenderable * tile = mTiles[ 0 ][ 0 ]; 00306 00307 while ( tile != 0 ) 00308 { 00309 AxisAlignedBox b = tile -> getBoundingBox(); 00310 const Vector3 *corners = b.getAllCorners(); 00311 00312 if ( pt.x < corners[ 0 ].x ) 00313 tile = tile -> _getNeighbor( TerrainRenderable::WEST ); 00314 else if ( pt.x > corners[ 4 ].x ) 00315 tile = tile -> _getNeighbor( TerrainRenderable::EAST ); 00316 else if ( pt.z < corners[ 0 ].z ) 00317 tile = tile -> _getNeighbor( TerrainRenderable::NORTH ); 00318 else if ( pt.z > corners[ 4 ].z ) 00319 tile = tile -> _getNeighbor( TerrainRenderable::SOUTH ); 00320 else 00321 return tile; 00322 } 00323 00324 return 0; 00325 } 00326 00327 00328 bool TerrainSceneManager::intersectSegment( const Vector3 & start, const Vector3 & end, Vector3 * result ) 00329 { 00330 00331 TerrainRenderable * t = getTerrainTile( start ); 00332 00333 if ( t == 0 ) 00334 { 00335 *result = Vector3( -1, -1, -1 ); 00336 return false; 00337 } 00338 00339 return t -> intersectSegment( start, end, result ); 00340 } 00341 00342 } //namespace
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:29 2004