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