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