HeightMap.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:13k
- //-----------------------------------------------------------------------------
- // File: heightmap.cpp
- //
- // Desc: Class to read a height map from a file or create one using a simple
- // function.
- //
- // Copyright (C) Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
- #include "stdafx.h"
- extern float g_fVar1;
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- CHeightMap::CHeightMap( CTerrainEngine* pTerrainEngine, float fWorldOffsetX, float fWorldOffsetZ )
- {
- m_nXSize = 0;
- m_nZSize = 0;
- m_fXSize = 0.0f;
- m_fZSize = 0.0f;
- m_pMap = NULL;
- g_pTerrainEngine = pTerrainEngine;
- m_fWorldOffsetX = fWorldOffsetX;
- m_fWorldOffsetZ = fWorldOffsetZ;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- CHeightMap::~CHeightMap()
- {
- SAFE_DELETE_ARRAY( m_pMap );
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CHeightMap::Create( int nXSize, int nZSize )
- {
- m_nXSize = nXSize;
- m_nZSize = nZSize;
- m_fXSize = (float) m_nXSize;
- m_fZSize = (float) m_nZSize;
- m_pMap = new FLOAT[ m_nXSize * m_nZSize ];
- if( m_pMap == NULL )
- return E_OUTOFMEMORY;
- ZeroMemory( m_pMap, m_nXSize * m_nZSize * sizeof(FLOAT) );
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CHeightMap::CreateTestMap( FLOAT fHeight )
- {
- for( int iZ=0; iZ<m_nZSize; iZ++ )
- {
- for( int iX=0; iX<m_nXSize; iX++ )
- {
- m_pMap[ iZ*m_nXSize + iX ] = fHeight;
- }
- }
- if( fHeight == 0.0f )
- {
- for( int iZ=5; iZ<40; iZ++ )
- {
- for( int iX=5; iX<40; iX++ )
- {
- m_pMap[ iZ*m_nXSize + iX ] = 10.0f;
- }
- }
- for( iZ=6; iZ<39; iZ++ )
- {
- for( int iX=6; iX<39; iX++ )
- {
- m_pMap[ iZ*m_nXSize + iX ] += 2.0f;
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CHeightMap::CreateMountain()
- {
- CreateSmallHills();
- int iCenterX = m_nXSize/2;
- int iCenterZ = m_nZSize/2;
- RaiseLand( iCenterX, iCenterZ, 9.0f, 1.0f );
- RaiseLand( iCenterX, iCenterZ, 7.0f, 2.0f );
- RaiseLand( iCenterX, iCenterZ, 5.0f, 4.0f );
- RaiseLand( iCenterX, iCenterZ, 4.0f, 1.0f );
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CHeightMap::RaiseLand( int iCenterX, int iCenterZ, float fRadius, float fHeight )
- {
- for( float fAngle=0.0f; fAngle<3.14f*2.0f; fAngle += 0.1f )
- {
- int fIncX = (int) (cos(fAngle) * fRadius);
- int fIncZ = (int) (sin(fAngle) * fRadius);
- int iX = iCenterX+fIncX;
- int iZ = iCenterZ+fIncZ;
- if( !IsOutOfRangeObj( iX, iZ ) )
- m_pMap[ iZ*m_nXSize + iX ] += fHeight;
- }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CHeightMap::CreateSmallHills()
- {
- int i;
- for( i=0; i<1500; i++ )
- {
- int iX = rand() % (m_nXSize-1);
- int iZ = rand() % (m_nZSize-1);
- float fIncSize = 2.0f;
- if( m_pMap[ iZ*m_nXSize + iX ] + fIncSize < MAX_HEIGHT_OF_MAP )
- m_pMap[ iZ*m_nXSize + iX ] += fIncSize;
- }
- for( i=0; i<500; i++ )
- {
- int iX = rand() % (m_nXSize-1);
- int iZ = rand() % (m_nZSize-1);
- float fIncSize = 1.0f;
- if( m_pMap[ iZ*m_nXSize + iX ] + fIncSize < MAX_HEIGHT_OF_MAP )
- m_pMap[ iZ*m_nXSize + iX ] += fIncSize;
- }
- SmoothSingleMap();
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CHeightMap::CreateFromFile( TCHAR* strFileName )
- {
- HRESULT hr;
- D3DSURFACE_DESC desc;
- IDirect3DTexture9* pTexture = NULL;
- // Create a D3DFMT_R5G6B5 texture -- use D3DPOOL_SCRATCH to
- // ensure that this will succeeded independent of the device
- hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFileName,
- ZONE_WIDTH, ZONE_HEIGHT, 1, 0,
- D3DFMT_R5G6B5, D3DPOOL_SCRATCH,
- D3DX_FILTER_NONE, D3DX_FILTER_NONE,
- 0, NULL, NULL, &pTexture );
- if( FAILED(hr) )
- return hr;
- pTexture->GetLevelDesc( 0, &desc );
- m_nXSize = desc.Width;
- m_nZSize = desc.Height;
- m_fXSize = (float) m_nXSize;
- m_fZSize = (float) m_nZSize;
- assert( desc.Format == D3DFMT_R5G6B5 );
- // create an array of floats to store the values of the bmp
- m_pMap = new FLOAT[ m_nXSize * m_nZSize ];
- if( m_pMap == NULL )
- {
- SAFE_RELEASE( pTexture );
- return E_OUTOFMEMORY;
- }
- ZeroMemory( m_pMap, m_nXSize * m_nZSize * sizeof(FLOAT) );
- D3DLOCKED_RECT lockedRect;
- hr = pTexture->LockRect( 0, &lockedRect, NULL, D3DLOCK_READONLY );
- if( SUCCEEDED(hr) )
- {
- WORD* pBuffer = (WORD*) lockedRect.pBits;
- for( DWORD iY=0; iY<desc.Height; iY++ )
- {
- pBuffer = (WORD*) ((BYTE*)lockedRect.pBits + lockedRect.Pitch * iY);
- for( DWORD iX=0; iX<desc.Width; iX++ )
- {
- // Normalize the values between 0.0f and 1.0f
- FLOAT fValue = (float)(*pBuffer) / (float) 0xFFFF;
- // Invert Y, so it appears the same as the bmp
- m_pMap[ (desc.Height-1-iY)*m_nXSize + iX] = fValue * 50.0f;
- pBuffer++;
- }
- }
- pTexture->UnlockRect( 0 );
- }
-
- SAFE_RELEASE( pTexture );
-
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CHeightMap::SmoothSingleMap()
- {
- // Smooth the map so its not so jaggy
- FLOAT* pSmoothMap = new FLOAT[ m_nXSize * m_nZSize ];
- if( pSmoothMap == NULL )
- return E_OUTOFMEMORY;
- for( float iZ=0.0f; iZ<m_nZSize; iZ++ )
- {
- for( float iX=0.0f; iX<m_nXSize; iX++ )
- {
- float fAvg;
- if( iZ==0.0f || iX==0.0f ||
- iZ==m_nZSize-1 || iX==m_nXSize-1 )
- {
- // Don't smoooth the edges cause they neighbor
- // maps haven't been created yet, and if we use 0 for
- // the 'off the map' values, it will change the height
- // around the border
- fAvg = GetCellHeightObj( iX, iZ );
- }
- else
- {
- // 3x3 smooth the middle
- FLOAT f11 = GetCellHeightObj( iX-1, iZ-1 );
- FLOAT f12 = GetCellHeightObj( iX-1, iZ-0 );
- FLOAT f13 = GetCellHeightObj( iX-1, iZ+1 );
- FLOAT f21 = GetCellHeightObj( iX-0, iZ-1 );
- FLOAT f22 = GetCellHeightObj( iX-0, iZ-0 );
- FLOAT f23 = GetCellHeightObj( iX-0, iZ+1 );
- FLOAT f31 = GetCellHeightObj( iX+1, iZ-1 );
- FLOAT f32 = GetCellHeightObj( iX+1, iZ-0 );
- FLOAT f33 = GetCellHeightObj( iX+1, iZ+1 );
- fAvg = (f22+f12+f21+f23+f32+f11+f13+f31+f33)/9.0f;
- }
- pSmoothMap[ (int) (iZ*m_nXSize + iX) ] = fAvg;
- }
- }
- SAFE_DELETE_ARRAY( m_pMap );
- m_pMap = pSmoothMap;
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CHeightMap::SmoothMap()
- {
- // Smooth the map so its not so jaggy
- m_pSmoothMap = new FLOAT[ m_nXSize * m_nZSize ];
- if( m_pSmoothMap == NULL )
- return E_OUTOFMEMORY;
- for( float iZ=m_fWorldOffsetZ; iZ<m_fWorldOffsetZ+m_nZSize; iZ++ )
- {
- for( float iX=m_fWorldOffsetX; iX<m_fWorldOffsetX+m_nXSize; iX++ )
- {
- float fAvg;
- // 3x3 -- use g_pTerrainEngine to have it ask the right map what the cell value is
- FLOAT f11 = g_pTerrainEngine->GetHeight( iX-1, iZ-1 );
- FLOAT f12 = g_pTerrainEngine->GetHeight( iX-1, iZ-0 );
- FLOAT f13 = g_pTerrainEngine->GetHeight( iX-1, iZ+1 );
- FLOAT f21 = g_pTerrainEngine->GetHeight( iX-0, iZ-1 );
- FLOAT f22 = g_pTerrainEngine->GetHeight( iX-0, iZ-0 );
- FLOAT f23 = g_pTerrainEngine->GetHeight( iX-0, iZ+1 );
- FLOAT f31 = g_pTerrainEngine->GetHeight( iX+1, iZ-1 );
- FLOAT f32 = g_pTerrainEngine->GetHeight( iX+1, iZ-0 );
- FLOAT f33 = g_pTerrainEngine->GetHeight( iX+1, iZ+1 );
- fAvg = (f22+f12+f21+f23+f32+f11+f13+f31+f33)/9.0f;
- m_pSmoothMap[ (int) ((iZ-m_fWorldOffsetZ)*m_nXSize + (iX-m_fWorldOffsetX)) ] = fAvg;
- }
- }
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CHeightMap::FinalizeSmooth()
- {
- SAFE_DELETE_ARRAY( m_pMap );
- m_pMap = m_pSmoothMap;
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- BOOL CHeightMap::IsOutOfRangeObj( float x, float z )
- {
- if( x < 0.0f ||
- z < 0.0f ||
- x >= m_fXSize ||
- z >= m_fZSize )
- return TRUE;
-
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- BOOL CHeightMap::IsOutOfRangeObj( int x, int z )
- {
- if( x < 0 ||
- z < 0 ||
- x >= m_nXSize ||
- z >= m_nZSize )
- return TRUE;
-
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- float CHeightMap::GetCellHeightObj( float x, float z )
- {
- // If we're trying to access out of range for this zone, then ask the engine
- // for the height of this coord, and it will find the zone that this coord lies
- // in and ask it.
- if( IsOutOfRangeObj( x, z ) )
- return 0;
- return m_pMap[ (int) (z*m_fXSize + x) ];
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- float CHeightMap::GetCellHeightObj( int x, int z )
- {
- if( IsOutOfRangeObj( x, z ) )
- return 0.0f;
- return m_pMap[ z*m_nXSize + x ];
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- FLOAT CHeightMap::GetHeightObj( float fObjCoordX, float fObjCoordZ )
- {
- // Do sub-cell calculation to find the exact height at this location
- float fXLow = (float) floor(fObjCoordX);
- float fXHigh = (float) ceil(fObjCoordX);
- float fZLow = (float) floor(fObjCoordZ);
- float fZHigh = (float) ceil(fObjCoordZ);
- if( fXLow == fXHigh && fZLow == fZHigh )
- {
- return GetCellHeightObj( fXHigh, fZHigh );
- }
- else
- {
- float fPtHH = GetCellHeightObj( fXHigh, fZHigh );
- float fPtHL = GetCellHeightObj( fXHigh, fZLow );
- float fPtLH = GetCellHeightObj( fXLow, fZHigh );
- float fPtLL = GetCellHeightObj( fXLow, fZLow );
- float fWeightX = fObjCoordX - fXLow;
- float fWeightZ = fObjCoordZ - fZLow;
- float fAvgZ_H = fPtHH*fWeightX + fPtLH*(1.0f-fWeightX); // avg( HH -> LH )
- float fAvgZ_L = fPtHL*fWeightX + fPtLL*(1.0f-fWeightX); // avg( HL -> LL )
- float fAvg = fAvgZ_H*fWeightZ + fAvgZ_L*(1.0f-fWeightZ); // avg( Z_H -> Z_L )
- return fAvg;
- }
- }