Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreTerrainSceneManager.cpp

Go to the documentation of this file.
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