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

OgreHeightmapTerrainPageSource.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004 (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2004 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgreHeightmapTerrainPageSource.h"
00027 #include "OgreTerrainPage.h"
00028 #include "OgreException.h"
00029 #include "OgreStringConverter.h"
00030 #include "OgreTerrainSceneManager.h"
00031 #include "OgreResourceManager.h"
00032 #include "OgreLogManager.h"
00033 
00034 namespace Ogre {
00035 
00036     //-------------------------------------------------------------------------
00037     HeightmapTerrainPageSource::HeightmapTerrainPageSource()
00038         : mIsRaw(false), mFlipTerrain(false), mPage(0)
00039     {
00040     }
00041     //-------------------------------------------------------------------------
00042     HeightmapTerrainPageSource::~HeightmapTerrainPageSource()
00043     {
00044         shutdown();
00045     }
00046     //-------------------------------------------------------------------------
00047     void HeightmapTerrainPageSource::shutdown(void)
00048     {
00049         // Image / datachunk will destroy itself
00050         delete mPage;
00051         mPage = 0;
00052     }
00053     //-------------------------------------------------------------------------
00054     void HeightmapTerrainPageSource::loadHeightmap(void)
00055     {
00056         size_t imgSize;
00057         // Special-case RAW format
00058         if (mIsRaw)
00059         {
00060             // Image size comes from setting (since RAW is not self-describing)
00061             imgSize = mRawSize;
00062             
00063             // Load data
00064             mRawData.clear();
00065             ResourceManager::_findCommonResourceData(mSource, mRawData);
00066 
00067             // Validate size
00068             size_t numBytes = imgSize * imgSize * mRawBpp;
00069             if (mRawData.getSize() != numBytes)
00070             {
00071                 shutdown();
00072                 Except(Exception::ERR_INVALIDPARAMS, 
00073                     "RAW size (" + StringConverter::toString(mRawData.getSize()) + 
00074                     ") does not agree with configuration settings.", 
00075                     "HeightmapTerrainPageSource::loadHeightmap");
00076             }
00077         }
00078         else
00079         {
00080             mImage.load( mSource );
00081             // Must be square (dimensions checked later)
00082             if ( mImage.getWidth() != mImage.getHeight())
00083             {
00084                 shutdown();
00085                 Except(Exception::ERR_INVALIDPARAMS,
00086                     "Heightmap must be square",
00087                     "HeightmapTerrainPageSource::loadHeightmap");
00088             }
00089             imgSize = mImage.getWidth();
00090         }
00091         //check to make sure it's the expected size
00092         if ( imgSize != mPageSize)
00093         {
00094             shutdown();
00095             String err = "Error: Invalid heightmap size : " +
00096                 StringConverter::toString( imgSize ) +
00097                 ". Should be " + StringConverter::toString(mPageSize);
00098             Except( Exception::ERR_INVALIDPARAMS, err, 
00099                 "HeightmapTerrainPageSource::loadHeightmap" );
00100         }
00101 
00102     }
00103     //-------------------------------------------------------------------------
00104     void HeightmapTerrainPageSource::initialise(TerrainSceneManager* tsm, 
00105         ushort tileSize, ushort pageSize, bool asyncLoading, 
00106         TerrainPageSourceOptionList& optionList)
00107     {
00108         // Shutdown to clear any previous data
00109         shutdown();
00110 
00111         TerrainPageSource::initialise(tsm, tileSize, pageSize, asyncLoading, optionList);
00112 
00113         // Get source image
00114         TerrainPageSourceOptionList::iterator ti, tiend;
00115         tiend = optionList.end();
00116         bool imageFound = false;
00117         mIsRaw = false;
00118         bool rawSizeFound = false;
00119         bool rawBppFound = false;
00120         for (ti = optionList.begin(); ti != tiend; ++ti)
00121         {
00122             String val = ti->first;
00123             StringUtil::trim(val);
00124             if (StringUtil::startsWith(val, "Heightmap.image", false))
00125             {
00126                 mSource = ti->second;
00127                 imageFound = true;
00128                 // is it a raw?
00129                 if (StringUtil::endsWith(mSource, "raw"))
00130                 {
00131                     mIsRaw = true;
00132                 }
00133             }
00134             else if (StringUtil::startsWith(val, "Heightmap.raw.size", false))
00135             {
00136                 mRawSize = atoi(ti->second.c_str());
00137                 rawSizeFound = true;
00138             }
00139             else if (StringUtil::startsWith(val, "Heightmap.raw.bpp", false))
00140             {
00141                 mRawBpp = atoi(ti->second.c_str());
00142                 if (mRawBpp < 1 || mRawBpp > 2)
00143                 {
00144                     Except(Exception::ERR_INVALIDPARAMS, 
00145                         "Invalid value for 'Heightmap.raw.bpp', must be 1 or 2",
00146                         "HeightmapTerrainPageSource::initialise");
00147                 }
00148                 rawBppFound = true;
00149             }
00150             else if (StringUtil::startsWith(val, "Heightmap.flip", false))
00151             {
00152                 mFlipTerrain = StringConverter::parseBool(ti->second);
00153             }
00154             else
00155             {
00156                 LogManager::getSingleton().logMessage("Warning: ignoring unknown Heightmap option '"
00157                     + val + "'");
00158             }
00159         }
00160         if (!imageFound)
00161         {
00162             Except(Exception::ERR_ITEM_NOT_FOUND, 
00163                 "Missing option 'Heightmap.image'", 
00164                 "HeightmapTerrainPageSource::initialise");
00165         }
00166         if (mIsRaw && 
00167             (!rawSizeFound || !rawBppFound))
00168         {
00169             Except(Exception::ERR_ITEM_NOT_FOUND, 
00170                 "Options 'Heightmap.raw.size' and 'Heightmap.raw.bpp' must "
00171                 "be specified for RAW heightmap sources", 
00172                 "HeightmapTerrainPageSource::initialise");
00173         }
00174         // Load it!
00175         loadHeightmap();
00176     }
00177     //-------------------------------------------------------------------------
00178     void HeightmapTerrainPageSource::requestPage(ushort x, ushort y)
00179     {
00180         // Only 1 page provided
00181         if (x == 0 && y == 0 && !mPage)
00182         {
00183             // Convert the image data to unscaled floats
00184             ulong totalPageSize = mPageSize * mPageSize; 
00185             Real *heightData = new Real[totalPageSize];
00186             const uchar* pOrigSrc, *pSrc;
00187             Real* pDest = heightData;
00188             Real invScale;
00189             bool is16bit = false;
00190             
00191             if (mIsRaw)
00192             {
00193                 pOrigSrc = mRawData.getPtr();
00194                 is16bit = (mRawBpp == 2);
00195             }
00196             else
00197             {
00198                 PixelFormat pf = mImage.getFormat();
00199                 if (pf != PF_L8 && pf != PF_L16)
00200                 {
00201                     Except( Exception::ERR_INVALIDPARAMS, 
00202                         "Error: Image is not a grayscale image.",
00203                         "HeightmapTerrainPageSource::requestPage" );
00204                 }
00205 
00206                 pOrigSrc = mImage.getData();
00207                 is16bit = (pf == PF_L16);
00208             }
00209             // Determine mapping from fixed to floating
00210             ulong rowSize;
00211             if ( is16bit )
00212             {
00213                 invScale = 1.0f / 65535.0f; 
00214                 rowSize =  mPageSize * 2;
00215             }
00216             else 
00217             {
00218                 invScale = 1.0f / 255.0f; 
00219                 rowSize =  mPageSize;
00220             }
00221             // Read the data
00222             pSrc = pOrigSrc;
00223             for (ulong j = 0; j < mPageSize; ++j)
00224             {
00225                 if (mFlipTerrain)
00226                 {
00227                     // Work backwards 
00228                     pSrc = pOrigSrc + (rowSize * (mPageSize - j - 1));
00229                 }
00230                 for (ulong i = 0; i < mPageSize; ++i)
00231                 {
00232                     if (is16bit)
00233                     {
00234                         #if OGRE_ENDIAN == ENDIAN_BIG
00235                             ushort val = *pSrc++ << 8;
00236                             val += *pSrc++;
00237                         #else
00238                             ushort val = *pSrc++;
00239                             val += *pSrc++ << 8;
00240                         #endif
00241                         *pDest++ = Real(val) * invScale;
00242                     }
00243                     else
00244                     {
00245                         *pDest++ = Real(*pSrc++) * invScale;
00246                     }
00247                 }
00248             }
00249 
00250             // Call listeners
00251             firePageConstructed(0, 0, heightData);
00252             // Now turn into TerrainPage
00253             // Note that we're using a single material for now
00254             if (mSceneManager)
00255             {
00256                 mPage = buildPage(heightData, 
00257                     TerrainSceneManager::getOptions().terrainMaterial);
00258                 mSceneManager->attachPage(0, 0, mPage);
00259             }
00260 
00261             // Free temp store
00262             delete [] heightData;
00263         }
00264     }
00265     //-------------------------------------------------------------------------
00266     void HeightmapTerrainPageSource::expirePage(ushort x, ushort y)
00267     {
00268         // Single page
00269         if (x == 0 && y == 0 && mPage)
00270         {
00271             delete mPage;
00272             mPage = 0;
00273         }
00274 
00275     }
00276     //-------------------------------------------------------------------------
00277 
00278 
00279 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:29 2004