www.pudn.com > 3D_Tank.rar > Terrain.cpp


#include "Terrain.h" 
 
CTerrain::CTerrain() 
{} 
 
CTerrain::~CTerrain() 
{} 
 
VOID CTerrain::InitTerrainFromHeightmap(const CComPtr &device,  
										LPCTSTR pSrcRawFile,  
										int nCxPixel, int nCzPixel, 
										int nCxLength, int nCzLength) 
{ 
    m_pDevice = device; 
 
	m_MapInfo.InitTerrainInfo(pSrcRawFile, nCxPixel, nCzPixel, nCxLength, nCzLength); 
 
    ID3DXMesh *mesh; 
             
	D3DXCreateMeshFVF(m_MapInfo.GetPolygonCount(), m_MapInfo.GetVertexCount(),  
					  0, TerrainVertex::FVF, m_pDevice.Get(), &mesh); 
 
	m_pTerrain.Reset(mesh); 
 
	TerrainVertex *vTemp; 
	m_pTerrain->LockVertexBuffer(0, reinterpret_cast(&vTemp)); 
 
	int x  = m_MapInfo.GetCxVertexCount(); 
	int z  = m_MapInfo.GetCzVertexCount(); 
	int cx = m_MapInfo.GetCxBlockLength(); 
	int cz = m_MapInfo.GetCzBlockLength(); 
	for (int i = 0; i < z; ++i) 
		for (int j = 0; j < x; ++j) 
		{ 
			vTemp[i * x + j].x = j * (float)cx; 
			vTemp[i * x + j].y = (float)m_MapInfo.m_vecHeight[i * x + j]; 
			vTemp[i * x + j].z = i * (float)cz; 
			vTemp[i * x + j].tx = (float)j; 
			vTemp[i * x + j].ty = (float)i; 
		} 
	m_pTerrain->UnlockVertexBuffer(); 
 
	WORD *wTemp; 
	m_pTerrain->LockIndexBuffer(0, reinterpret_cast(&wTemp)); 
 
    for (int i = 0, n = 0; i < z - 1; ++i) 
		for (int j = 0; j < x - 1; ++j) 
		{ 
			wTemp[n++] = static_cast(i * x + j); 
			wTemp[n++] = static_cast((i + 1) * x + j); 
			wTemp[n++] = static_cast((i + 1) * x + (j + 1)); 
			wTemp[n++] = static_cast(i * x + j); 
			wTemp[n++] = static_cast((i + 1) * x + (j + 1)); 
			wTemp[n++] = static_cast(i * x + (j + 1)); 
		} 
	m_pTerrain->UnlockIndexBuffer();			 
 
	D3DXComputeNormals(m_pTerrain.Get(), 0); 
} 
 
BOOL CTerrain::SetTexture(LPCTSTR pSrcFileName) 
{ 
	IDirect3DTexture9	*texture = 0; 
	D3DXCreateTextureFromFile(m_pDevice.Get(), pSrcFileName, &texture); 
	m_pTexture.Reset(texture); 
 
	m_pDevice->SetTexture(0, m_pTexture.Get()); 
	return TRUE; 
} 
 
BOOL CTerrain::PreComputerLight (const D3DXVECTOR3	&vLightDir, 
								 const D3DXCOLOR	&vLightColor) 
{ 
	D3DXVECTOR3 vLight = -vLightDir; 
 
	TerrainVertex *vTemp; 
	m_pTerrain->LockVertexBuffer(0, reinterpret_cast(&vTemp)); 
	int nVertex = m_MapInfo.GetVertexCount(); 
	for (int n = 0; n < nVertex; ++n) 
		vTemp[n].color = vLightColor * ComputeShade(vTemp[n].normal, vLight); 
	m_pTerrain->UnlockVertexBuffer(); 
 
	return TRUE; 
} 
 
//C-------D 
//|     / | 
//|   /	  | 
//| /	  | 
//A-------B 
 
 
float CTerrain::GetHeight(float x, float z) 
{	return m_MapInfo.GetHeight(x, z);} 
 
VOID CTerrain::GetNormal(float x, float z, D3DXVECTOR3 *vNormal) 
{	m_MapInfo.GetNormal(x,z,vNormal);} 
 
BOOL CTerrain::IsInTerrain(float x, float z) 
{ 
	return m_MapInfo.IsInTerrain(x, z); 
} 
 
float CTerrain::ComputeShade(D3DXVECTOR3 normal, D3DXVECTOR3 reverseLight) 
{ 
	float cos = D3DXVec3Dot(&normal, &reverseLight); 
 
	if (cos < 0) 
		cos = 0; 
 
	return cos; 
} 
 
BOOL CTerrain::PrepareRenderState() 
{ 
	m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 
	m_pDevice->SetTexture(0, m_pTexture.Get()); 
	m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); 
	m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); 
	m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 
	m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 
	return TRUE; 
} 
 
BOOL CTerrain::ResetRenderState() 
{ 
    m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE); 
	m_pDevice->SetTexture(0, 0); 
	return TRUE; 
} 
 
BOOL CTerrain::Render() 
{ 
	PrepareRenderState(); 
	m_pTerrain->DrawSubset(0); 
	ResetRenderState(); 
	return TRUE; 
}