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 float TerrainSceneManager::getHeightAt( float x, float z ) 00274 { 00275 00276 00277 Vector3 pt( x, 0, z ); 00278 00279 TerrainRenderable * t = getTerrainTile( pt ); 00280 00281 if ( t == 0 ) 00282 { 00283 // printf( "No tile found for point\n" ); 00284 return -1; 00285 } 00286 00287 float h = t -> getHeightAt( x, z ); 00288 00289 // printf( "Height is %f\n", h ); 00290 return h; 00291 00292 } 00293 00294 TerrainRenderable * TerrainSceneManager::getTerrainTile( const Vector3 & pt ) 00295 { 00296 /* Since we don't know if the terrain is square, or has holes, we use a line trace 00297 to find the containing tile... 00298 */ 00299 00300 TerrainRenderable * tile = mTiles[ 0 ][ 0 ]; 00301 00302 while ( tile != 0 ) 00303 { 00304 AxisAlignedBox b = tile -> getBoundingBox(); 00305 const Vector3 *corners = b.getAllCorners(); 00306 00307 if ( pt.x < corners[ 0 ].x ) 00308 tile = tile -> _getNeighbor( TerrainRenderable::WEST ); 00309 else if ( pt.x > corners[ 4 ].x ) 00310 tile = tile -> _getNeighbor( TerrainRenderable::EAST ); 00311 else if ( pt.z < corners[ 0 ].z ) 00312 tile = tile -> _getNeighbor( TerrainRenderable::NORTH ); 00313 else if ( pt.z > corners[ 4 ].z ) 00314 tile = tile -> _getNeighbor( TerrainRenderable::SOUTH ); 00315 else 00316 return tile; 00317 } 00318 00319 return 0; 00320 } 00321 00322 00323 bool TerrainSceneManager::intersectSegment( const Vector3 & start, const Vector3 & end, Vector3 * result ) 00324 { 00325 00326 TerrainRenderable * t = getTerrainTile( start ); 00327 00328 if ( t == 0 ) 00329 { 00330 *result = Vector3( -1, -1, -1 ); 00331 return false; 00332 } 00333 00334 return t -> intersectSegment( start, end, result ); 00335 } 00336 00337 } //namespace
Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:51 2004