00001
00008
00009
00010
00011
00012
00013 #if COMPILING_MODULE
00014 #ifndef MOD_SIM_TERRAIN_HEIGHTMAP_HH
00015 #define MOD_SIM_TERRAIN_HEIGHTMAP_HH 1
00016
00017 #include "eng_task.hh"
00018
00019 namespace mod_sim {
00020
00034 class Heightmap : public Shared
00035 {
00036
00037 friend class Terrain;
00038 friend class TileFactory;
00039 public:
00040 typedef uint8 Height;
00041 CLASS_CONST uint HEIGHT_INVALID = 0xff;
00042 CLASS_CONST uint HEIGHT_LIMIT = 0xfe;
00043
00044 public:
00050 class Elem
00051 {
00052 public:
00053
00054 Elem( void )
00055 {
00056
00057 }
00058
00059 ~Elem( void ) { }
00060
00062 fp GetHeight( void ) const
00063 {
00064 ASSERT( mHeight != Heightmap::HEIGHT_INVALID );
00065
00066 return fp(mHeight) / fp(Heightmap::HEIGHT_LIMIT);
00067 }
00068
00069 Heightmap::Height GetHeightDirect( void ) const
00070 {
00071 ASSERT( mHeight != Heightmap::HEIGHT_INVALID );
00072
00073 return mHeight;
00074 }
00075
00076 void SetHeight( Heightmap::Height height )
00077 {
00078
00079
00080
00081 mHeight = height;
00082 }
00083
00084 private:
00085 Heightmap::Height mHeight;
00086 };
00087
00088
00089
00090 public:
00091 struct InitArgs
00092 {
00093 InitArgs( const BoxVolume& boxVolume,
00094 const int heightmapWidth,
00095 const fp heightScale );
00096 #if DEBUG
00097 void Check( void ) const;
00098 #endif
00099
00100
00101 BoxVolume mBoxVolume;
00102 int mHeightmapWidth;
00103 fp mHeightScale;
00104 fp mWidthInWorld;
00105 };
00106
00107
00108
00109 public:
00110 struct NoiseArgs
00111 {
00112 NoiseArgs( fp inc, fp z ) : mInc(inc), mZ(z) { }
00113 fp mInc;
00114 fp mZ;
00115 };
00116
00117
00118
00119 private:
00120 class TextureTask : public Task::TaskFunctor
00121 {
00122 public:
00123 TextureTask( Heightmap& heightmap, Array2D<Texture::Texel32>& colormap )
00124 : mHeightmap(heightmap), mColormap(colormap)
00125 {
00126 }
00127 void operator()( void );
00128
00129 Heightmap& mHeightmap;
00130 Array2D<Texture::Texel32>& mColormap;
00131 };
00132 friend class TextureTask;
00133
00134
00135
00136
00137
00138
00139
00140 public:
00141 Heightmap( void );
00142 Heightmap( const InitArgs& initArgs );
00143 Heightmap( const InitArgs& initArgs, const NoiseArgs& noiseArgs );
00144 ~Heightmap();
00145
00146 private:
00147 void Init( const InitArgs& initArgs );
00148 void InitRandomNumbers( const InitArgs& initArgs );
00149 void ComputePalette( void );
00150
00151 public:
00152 void SetHeight( const int hmLat, const int hmLon, const Height height )
00153 {
00154 ASSERT2( mValid );
00155
00156 return mHeightmap.Get(hmLat,hmLon).SetHeight( height );
00157 }
00158
00160 fp GetHeight( const int hmLat, const int hmLon ) const
00161 {
00162 ASSERT2( mValid );
00163
00164
00165 return mHeightmap.Get(hmLat,hmLon).GetHeight();
00166 }
00167
00168 Heightmap::Height GetHeightDirect( const int hmLat, const int hmLon ) const
00169 {
00170 ASSERT2( mValid );
00171
00172
00173 return mHeightmap.Get(hmLat,hmLon).GetHeightDirect();
00174 }
00175
00177 fp GetHeightScaled( const int hmLat, const int hmLon ) const
00178 {
00179 ASSERT2( mValid );
00180 ASSERT2( mHeightScale > 0.0 );
00181
00182 return GetHeight(hmLat,hmLon) * mHeightScale;
00183 }
00184
00186 fp GetHeightScaledInterpolated( const fp worldLat, const fp worldLon ) const
00187 {
00188 ASSERT2( mValid );
00189 ASSERT2( mHeightmapWorldRatio != 0.0 );
00190 ASSERT2( IfInsideApprox(worldLat,worldLon) );
00191
00192
00193 int hmLat = int((worldLat - mBoxVolume.mMin.LAT_) * mHeightmapWorldRatio);
00194 int hmLon = int((worldLon - mBoxVolume.mMin.LON_) * mHeightmapWorldRatio);
00195
00196 return GetHeightScaled( hmLat, hmLon );
00197 }
00198
00199
00200 CLASS_METHOD Heightmap::Height
00201 GetHeightMedian( void );
00202
00203
00204 fp ScaleHeight( const Height height )
00205 {
00206 ASSERT2( mHeightScale > 0.0 );
00207 return fp(height) / fp(HEIGHT_LIMIT) * mHeightScale;
00208 }
00209
00211 WorldVertex GetPosition( const int hmLat, const int hmLon ) const
00212 {
00213 ASSERT2( mValid );
00214 ASSERT2( mWorldHeightmapRatio > 0.0 );
00215 ASSERT2( IfInsideApprox( hmLat * mWorldHeightmapRatio,
00216 hmLon * mWorldHeightmapRatio ) );
00217
00218
00219 return WorldVertex( LAT_LON_ALT( mBoxVolume.mMin.LAT_ + hmLat * mWorldHeightmapRatio,
00220 mBoxVolume.mMin.LON_ + hmLon * mWorldHeightmapRatio,
00221 GetHeightScaled(hmLat,hmLon) ) );
00222 }
00223
00225 uint GetIdx( const int hmLat, const int hmLon ) const
00226 {
00227 ASSERT2( mValid );
00228
00229
00230 return mHeightmap.GetIdx( hmLat, hmLon );
00231 }
00232
00233 SharedPtr<Texture> GetColormapTexture( void ) const
00234 {
00235 return mColormapTexture;
00236 }
00237
00238 TexCoord GetColormapTexCoord( const fp worldLat, const fp worldLon ) const
00239 {
00240
00241 const fp tx = Clamp1( (worldLat - mBoxVolume.mMin.LAT_) / mWidthInWorld );
00242 const fp ty = Clamp1( (worldLon - mBoxVolume.mMin.LON_) / mWidthInWorld );
00243
00244 return TexCoord( ty, tx );
00245 }
00246
00247 #if DEBUG
00248 bool IfInsideApprox( const fp worldLat, const fp worldLon ) const;
00249 #endif
00250
00251
00252 Elem& operator[]( uint i ) { return mHeightmap[i]; }
00253 const Elem& operator[]( uint i ) const { return mHeightmap[i]; }
00254
00255
00256
00257 class WaterTexture
00258 {
00259 public:
00260 WaterTexture( const uint heightmapWidth );
00261 ~WaterTexture();
00262
00266 inline uint
00267 CLAMP_WATER_COLOR( uint in )
00268 {
00269 if ( in < 0 )
00270 return 0;
00271 else if ( in > 150 )
00272 return 150;
00273 else
00274 return in;
00275 }
00276
00281 inline Texture::Texel32
00282 GetTexel( const uint lat, const uint lon )
00283 {
00284 uint bufIdx = uint((lat * mIdxRatio) + (lon * mIdxRatio * mBufWidth)) << 2;
00285 ASSERT( bufIdx+3 < mBufLen );
00286 const uint8* c = reinterpret_cast<const uint8*>( &mBuf[bufIdx] );
00287 return ( CLAMP_WATER_COLOR(c[BB]- 70) << TexelDefs::TEXEL32_BB_BIT_SHIFT )
00288 | ( CLAMP_WATER_COLOR(c[GG]-180) << TexelDefs::TEXEL32_GG_BIT_SHIFT )
00289 | ( CLAMP_WATER_COLOR(c[RR]-180) << TexelDefs::TEXEL32_RR_BIT_SHIFT )
00290 | ( c[AA] << TexelDefs::TEXEL32_AA_BIT_SHIFT );
00291
00292 }
00293
00294 private:
00295 Targa* mTarga;
00296 const uint8* mBuf;
00297 uint mBufLen;
00298 uint mBufWidth;
00299 fp mIdxRatio;
00300 };
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 private:
00319 CLASS_VAR int msHeightmapWidthMinus1;
00320 CLASS_VAR Array2D<fp> msRandomHeight;
00321 CLASS_VAR Array2D<uint> msRandomColor;
00322 CLASS_VAR vector<RGBA> msPalette;
00323 CLASS_VAR WaterTexture* msWaterTexture;
00324
00325 bool mValid;
00326
00327
00328 BoxVolume mBoxVolume;
00329 fp mWidthInWorld;
00330 fp mHeightScale;
00331 fp mHeightScaleHalf;
00332 fp mWorldHeightmapRatio;
00333 fp mHeightmapWorldRatio;
00334
00335
00336 typedef Array2D<Elem,Shared> HeightmapArray2D;
00337 HeightmapArray2D mHeightmap;
00338 int mHeightmapWidth;
00339
00340
00341 shptr<Texture> mColormapTexture;
00342
00343 #if DEBUG
00344 public:
00345 CLASS_VAR bool msDisableIfInsideApprox;
00346 #endif
00347 };
00348
00349 }
00350
00351 #endif // MOD_SIM_TERRAIN_HEIGHTMAP_HH
00352 #endif // COMPILING_MODULE