HeightMap.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:13k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: heightmap.cpp
  3. //
  4. // Desc: Class to read a height map from a file or create one using a simple
  5. //       function.
  6. //
  7. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9. #include "stdafx.h"
  10. extern float g_fVar1;
  11. //-----------------------------------------------------------------------------
  12. // Name: 
  13. // Desc: 
  14. //-----------------------------------------------------------------------------
  15. CHeightMap::CHeightMap( CTerrainEngine* pTerrainEngine, float fWorldOffsetX, float fWorldOffsetZ )
  16. {
  17.     m_nXSize = 0;
  18.     m_nZSize = 0;
  19.     m_fXSize = 0.0f;
  20.     m_fZSize = 0.0f;
  21.     m_pMap   = NULL;
  22.     g_pTerrainEngine = pTerrainEngine;
  23.     m_fWorldOffsetX  = fWorldOffsetX;
  24.     m_fWorldOffsetZ  = fWorldOffsetZ;
  25. }
  26. //-----------------------------------------------------------------------------
  27. // Name: 
  28. // Desc: 
  29. //-----------------------------------------------------------------------------
  30. CHeightMap::~CHeightMap()
  31. {
  32.     SAFE_DELETE_ARRAY( m_pMap );
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Name: 
  36. // Desc: 
  37. //-----------------------------------------------------------------------------
  38. HRESULT CHeightMap::Create( int nXSize, int nZSize )
  39. {
  40.     m_nXSize = nXSize;
  41.     m_nZSize = nZSize;
  42.     m_fXSize = (float) m_nXSize;
  43.     m_fZSize = (float) m_nZSize;
  44.     m_pMap   = new FLOAT[ m_nXSize * m_nZSize ];
  45.     if( m_pMap == NULL )
  46.         return E_OUTOFMEMORY;
  47.     ZeroMemory( m_pMap, m_nXSize * m_nZSize * sizeof(FLOAT) );
  48.     return S_OK;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Name: 
  52. // Desc: 
  53. //-----------------------------------------------------------------------------
  54. VOID CHeightMap::CreateTestMap( FLOAT fHeight )
  55. {
  56.     for( int iZ=0; iZ<m_nZSize; iZ++ )
  57.     {
  58.         for( int iX=0; iX<m_nXSize; iX++ )
  59.         {
  60.             m_pMap[ iZ*m_nXSize + iX ] = fHeight;
  61.         }
  62.     }
  63.     if( fHeight == 0.0f )
  64.     {
  65.         for( int iZ=5; iZ<40; iZ++ )
  66.         {
  67.             for( int iX=5; iX<40; iX++ )
  68.             {
  69.                 m_pMap[ iZ*m_nXSize + iX ] = 10.0f;
  70.             }
  71.         }
  72.         for( iZ=6; iZ<39; iZ++ )
  73.         {
  74.             for( int iX=6; iX<39; iX++ )
  75.             {
  76.                 m_pMap[ iZ*m_nXSize + iX ] += 2.0f;
  77.             }
  78.         }
  79.     }
  80. }
  81. //-----------------------------------------------------------------------------
  82. // Name: 
  83. // Desc: 
  84. //-----------------------------------------------------------------------------
  85. VOID CHeightMap::CreateMountain()
  86. {
  87.     CreateSmallHills();
  88.     int iCenterX = m_nXSize/2;
  89.     int iCenterZ = m_nZSize/2;
  90.     RaiseLand( iCenterX, iCenterZ, 9.0f, 1.0f );
  91.     RaiseLand( iCenterX, iCenterZ, 7.0f, 2.0f );
  92.     RaiseLand( iCenterX, iCenterZ, 5.0f, 4.0f );
  93.     RaiseLand( iCenterX, iCenterZ, 4.0f, 1.0f );
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Name: 
  97. // Desc: 
  98. //-----------------------------------------------------------------------------
  99. VOID CHeightMap::RaiseLand( int iCenterX, int iCenterZ, float fRadius, float fHeight )
  100. {
  101.     for( float fAngle=0.0f; fAngle<3.14f*2.0f; fAngle += 0.1f )
  102.     {
  103.         int fIncX = (int) (cos(fAngle) * fRadius);
  104.         int fIncZ = (int) (sin(fAngle) * fRadius);
  105.         int iX = iCenterX+fIncX;
  106.         int iZ = iCenterZ+fIncZ;
  107.         if( !IsOutOfRangeObj( iX, iZ ) )
  108.             m_pMap[ iZ*m_nXSize + iX ] += fHeight;
  109.     }
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Name: 
  113. // Desc: 
  114. //-----------------------------------------------------------------------------
  115. VOID CHeightMap::CreateSmallHills()
  116. {
  117.     int i;
  118.     for( i=0; i<1500; i++ )
  119.     {
  120.         int iX = rand() % (m_nXSize-1);
  121.         int iZ = rand() % (m_nZSize-1);
  122.         float fIncSize = 2.0f;
  123.         if( m_pMap[ iZ*m_nXSize + iX ] + fIncSize < MAX_HEIGHT_OF_MAP )
  124.             m_pMap[ iZ*m_nXSize + iX ] += fIncSize;
  125.     }
  126.     for( i=0; i<500; i++ )
  127.     {
  128.         int iX = rand() % (m_nXSize-1);
  129.         int iZ = rand() % (m_nZSize-1);
  130.         float fIncSize = 1.0f;
  131.         if( m_pMap[ iZ*m_nXSize + iX ] + fIncSize < MAX_HEIGHT_OF_MAP )
  132.             m_pMap[ iZ*m_nXSize + iX ] += fIncSize;
  133.     }
  134.     SmoothSingleMap();
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Name: 
  138. // Desc: 
  139. //-----------------------------------------------------------------------------
  140. HRESULT CHeightMap::CreateFromFile( TCHAR* strFileName )
  141. {
  142.     HRESULT hr;
  143.     D3DSURFACE_DESC desc;
  144.     IDirect3DTexture9* pTexture = NULL;
  145.     // Create a D3DFMT_R5G6B5 texture -- use D3DPOOL_SCRATCH to 
  146.     // ensure that this will succeeded independent of the device
  147.     hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFileName, 
  148.                                  ZONE_WIDTH, ZONE_HEIGHT, 1, 0, 
  149.                                  D3DFMT_R5G6B5, D3DPOOL_SCRATCH, 
  150.                                  D3DX_FILTER_NONE, D3DX_FILTER_NONE,
  151.                                  0, NULL, NULL, &pTexture );
  152.     if( FAILED(hr) )
  153.         return hr;
  154.     pTexture->GetLevelDesc( 0, &desc ); 
  155.     m_nXSize = desc.Width;
  156.     m_nZSize = desc.Height;
  157.     m_fXSize = (float) m_nXSize;
  158.     m_fZSize = (float) m_nZSize;
  159.     assert( desc.Format == D3DFMT_R5G6B5 );
  160.     // create an array of floats to store the values of the bmp
  161.     m_pMap = new FLOAT[ m_nXSize * m_nZSize ];
  162.     if( m_pMap == NULL )
  163.     {
  164.         SAFE_RELEASE( pTexture );
  165.         return E_OUTOFMEMORY;
  166.     }
  167.     ZeroMemory( m_pMap, m_nXSize * m_nZSize * sizeof(FLOAT) );
  168.     D3DLOCKED_RECT lockedRect;
  169.     hr = pTexture->LockRect( 0, &lockedRect, NULL, D3DLOCK_READONLY );
  170.     if( SUCCEEDED(hr) )
  171.     {
  172.         WORD* pBuffer = (WORD*) lockedRect.pBits;
  173.         for( DWORD iY=0; iY<desc.Height; iY++ )
  174.         {
  175.             pBuffer = (WORD*) ((BYTE*)lockedRect.pBits + lockedRect.Pitch * iY);
  176.             for( DWORD iX=0; iX<desc.Width; iX++ )
  177.             {
  178.                 // Normalize the values between 0.0f and 1.0f
  179.                 FLOAT fValue = (float)(*pBuffer) / (float) 0xFFFF;
  180.                 // Invert Y, so it appears the same as the bmp
  181.                 m_pMap[ (desc.Height-1-iY)*m_nXSize + iX] = fValue * 50.0f;
  182.                 pBuffer++;
  183.             }
  184.         }
  185.         pTexture->UnlockRect( 0 );
  186.     }
  187.                                  
  188.     SAFE_RELEASE( pTexture );
  189.     
  190.     return S_OK;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Name: 
  194. // Desc: 
  195. //-----------------------------------------------------------------------------
  196. HRESULT CHeightMap::SmoothSingleMap()
  197. {
  198.     // Smooth the map so its not so jaggy
  199.     FLOAT* pSmoothMap = new FLOAT[ m_nXSize * m_nZSize ];
  200.     if( pSmoothMap == NULL )
  201.         return E_OUTOFMEMORY;
  202.     for( float iZ=0.0f; iZ<m_nZSize; iZ++ )
  203.     {
  204.         for( float iX=0.0f; iX<m_nXSize; iX++ )
  205.         {
  206.             float fAvg;
  207.             if( iZ==0.0f || iX==0.0f || 
  208.                 iZ==m_nZSize-1 || iX==m_nXSize-1 )
  209.             {
  210.                 // Don't smoooth the edges cause they neighbor 
  211.                 // maps haven't been created yet, and if we use 0 for
  212.                 // the 'off the map' values, it will change the height
  213.                 // around the border
  214.                 fAvg = GetCellHeightObj( iX, iZ );
  215.             }
  216.             else
  217.             {
  218.                 // 3x3 smooth the middle
  219.                 FLOAT f11 = GetCellHeightObj( iX-1, iZ-1 );
  220.                 FLOAT f12 = GetCellHeightObj( iX-1, iZ-0 );
  221.                 FLOAT f13 = GetCellHeightObj( iX-1, iZ+1 );
  222.                 FLOAT f21 = GetCellHeightObj( iX-0, iZ-1 );
  223.                 FLOAT f22 = GetCellHeightObj( iX-0, iZ-0 );
  224.                 FLOAT f23 = GetCellHeightObj( iX-0, iZ+1 );
  225.                 FLOAT f31 = GetCellHeightObj( iX+1, iZ-1 );
  226.                 FLOAT f32 = GetCellHeightObj( iX+1, iZ-0 );
  227.                 FLOAT f33 = GetCellHeightObj( iX+1, iZ+1 );
  228.                 fAvg = (f22+f12+f21+f23+f32+f11+f13+f31+f33)/9.0f;
  229.             }
  230.             pSmoothMap[ (int) (iZ*m_nXSize + iX) ] = fAvg;
  231.         }
  232.     }
  233.     SAFE_DELETE_ARRAY( m_pMap );
  234.     m_pMap = pSmoothMap;
  235.     return S_OK;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Name: 
  239. // Desc: 
  240. //-----------------------------------------------------------------------------
  241. HRESULT CHeightMap::SmoothMap()
  242. {
  243.     // Smooth the map so its not so jaggy
  244.     m_pSmoothMap = new FLOAT[ m_nXSize * m_nZSize ];
  245.     if( m_pSmoothMap == NULL )
  246.         return E_OUTOFMEMORY;
  247.     for( float iZ=m_fWorldOffsetZ; iZ<m_fWorldOffsetZ+m_nZSize; iZ++ )
  248.     {
  249.         for( float iX=m_fWorldOffsetX; iX<m_fWorldOffsetX+m_nXSize; iX++ )
  250.         {
  251.             float fAvg;
  252.             // 3x3 -- use g_pTerrainEngine to have it ask the right map what the cell value is
  253.             FLOAT f11 = g_pTerrainEngine->GetHeight( iX-1, iZ-1 );
  254.             FLOAT f12 = g_pTerrainEngine->GetHeight( iX-1, iZ-0 );
  255.             FLOAT f13 = g_pTerrainEngine->GetHeight( iX-1, iZ+1 );
  256.             FLOAT f21 = g_pTerrainEngine->GetHeight( iX-0, iZ-1 );
  257.             FLOAT f22 = g_pTerrainEngine->GetHeight( iX-0, iZ-0 );
  258.             FLOAT f23 = g_pTerrainEngine->GetHeight( iX-0, iZ+1 );
  259.             FLOAT f31 = g_pTerrainEngine->GetHeight( iX+1, iZ-1 );
  260.             FLOAT f32 = g_pTerrainEngine->GetHeight( iX+1, iZ-0 );
  261.             FLOAT f33 = g_pTerrainEngine->GetHeight( iX+1, iZ+1 );
  262.             fAvg = (f22+f12+f21+f23+f32+f11+f13+f31+f33)/9.0f;
  263.             m_pSmoothMap[ (int) ((iZ-m_fWorldOffsetZ)*m_nXSize + (iX-m_fWorldOffsetX)) ] = fAvg;
  264.         }
  265.     }
  266.     return S_OK;
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Name: 
  270. // Desc: 
  271. //-----------------------------------------------------------------------------
  272. HRESULT CHeightMap::FinalizeSmooth()
  273. {
  274.     SAFE_DELETE_ARRAY( m_pMap );
  275.     m_pMap = m_pSmoothMap;
  276.     return S_OK;  
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Name: 
  280. // Desc: 
  281. //-----------------------------------------------------------------------------
  282. BOOL CHeightMap::IsOutOfRangeObj( float x, float z )
  283. {
  284.     if( x < 0.0f        || 
  285.         z < 0.0f        ||
  286.         x >= m_fXSize   || 
  287.         z >= m_fZSize )
  288.         return TRUE;
  289.     
  290.     return FALSE;
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Name: 
  294. // Desc: 
  295. //-----------------------------------------------------------------------------
  296. BOOL CHeightMap::IsOutOfRangeObj( int x, int z )
  297. {
  298.     if( x < 0           || 
  299.         z < 0           ||
  300.         x >= m_nXSize   || 
  301.         z >= m_nZSize )
  302.         return TRUE;
  303.     
  304.     return FALSE;
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Name: 
  308. // Desc: 
  309. //-----------------------------------------------------------------------------
  310. float CHeightMap::GetCellHeightObj( float x, float z )
  311. {
  312.     // If we're trying to access out of range for this zone, then ask the engine 
  313.     // for the height of this coord, and it will find the zone that this coord lies 
  314.     // in and ask it.
  315.     if( IsOutOfRangeObj( x, z ) )
  316.         return 0;
  317.     return m_pMap[ (int) (z*m_fXSize + x) ]; 
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Name: 
  321. // Desc: 
  322. //-----------------------------------------------------------------------------
  323. float CHeightMap::GetCellHeightObj( int x, int z )
  324. {
  325.     if( IsOutOfRangeObj( x, z ) )
  326.         return 0.0f;
  327.     return m_pMap[ z*m_nXSize + x ]; 
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Name: 
  331. // Desc: 
  332. //-----------------------------------------------------------------------------
  333. FLOAT CHeightMap::GetHeightObj( float fObjCoordX, float fObjCoordZ ) 
  334.     // Do sub-cell calculation to find the exact height at this location 
  335.     float fXLow   = (float) floor(fObjCoordX);
  336.     float fXHigh  = (float) ceil(fObjCoordX);
  337.     float fZLow   = (float) floor(fObjCoordZ);
  338.     float fZHigh  = (float) ceil(fObjCoordZ);
  339.     if( fXLow == fXHigh && fZLow == fZHigh )
  340.     {
  341.         return GetCellHeightObj( fXHigh, fZHigh );
  342.     }
  343.     else
  344.     {
  345.         float fPtHH = GetCellHeightObj( fXHigh, fZHigh );
  346.         float fPtHL = GetCellHeightObj( fXHigh, fZLow ); 
  347.         float fPtLH = GetCellHeightObj( fXLow,  fZHigh ); 
  348.         float fPtLL = GetCellHeightObj( fXLow,  fZLow ); 
  349.         float fWeightX  = fObjCoordX - fXLow;
  350.         float fWeightZ  = fObjCoordZ - fZLow;
  351.         float fAvgZ_H   = fPtHH*fWeightX + fPtLH*(1.0f-fWeightX);       // avg( HH -> LH )
  352.         float fAvgZ_L   = fPtHL*fWeightX + fPtLL*(1.0f-fWeightX);       // avg( HL -> LL )
  353.         float fAvg      = fAvgZ_H*fWeightZ + fAvgZ_L*(1.0f-fWeightZ);   // avg( Z_H -> Z_L )
  354.         return fAvg;
  355.     }
  356. }