#pragma once #include "TerrainDefine.h" class CTerrainFaceNormalInfo { public: struct FACENORMAL_STRUCT { K3DVector vtFaceNormalLower; K3DVector vtFaceNormalUpper; }; CTerrainFaceNormalInfo() : m_rcTerrainArea( KRect( 0, 0, 0, 0 ) ) , m_pFaceNormals( NULL ) { m_DefaultFaceNormal.vtFaceNormalLower = c_DefaultNormal; m_DefaultFaceNormal.vtFaceNormalUpper = c_DefaultNormal; } CTerrainFaceNormalInfo( const KRect& rTerrainArea, const CTerrainInfo* pTerrainInfo = NULL ) : m_pFaceNormals( NULL ) { m_DefaultFaceNormal.vtFaceNormalLower = c_DefaultNormal; m_DefaultFaceNormal.vtFaceNormalUpper = c_DefaultNormal; Initialize( rTerrainArea, pTerrainInfo ); } virtual ~CTerrainFaceNormalInfo() { Release(); } void Initialize( const KRect& rTerrainArea, const CTerrainInfo* pTerrainInfo = NULL ) { Release(); m_rcTerrainArea = rTerrainArea; int nTotalFaceNormalCount = (m_rcTerrainArea.GetWidth() * m_rcTerrainArea.GetHeight()); m_pFaceNormals = new FACENORMAL_STRUCT[ nTotalFaceNormalCount ]; Refresh( m_rcTerrainArea, pTerrainInfo ); } void Release() { m_rcTerrainArea = KRect( 0, 0, 0, 0 ); SAFE_DELETE_ARRAY( m_pFaceNormals ); } const FACENORMAL_STRUCT* GetFaceNormalData( int nX, int nY ) const { nX -= m_rcTerrainArea.left; nY -= m_rcTerrainArea.top; return ( 0 <= nX && nX < m_rcTerrainArea.GetWidth() && 0 <= nY && nY < m_rcTerrainArea.GetHeight() ) ? (m_pFaceNormals + (nY * m_rcTerrainArea.GetWidth()) + nX) : &m_DefaultFaceNormal; } void Refresh( const KRect& rRefreshArea, const CTerrainInfo* pTerrainInfo = NULL ) { int nSX = (rRefreshArea.left < m_rcTerrainArea.left ) ? m_rcTerrainArea.left : rRefreshArea.left ; int nSY = (rRefreshArea.top < m_rcTerrainArea.top ) ? m_rcTerrainArea.top : rRefreshArea.top ; int nEX = (rRefreshArea.right > m_rcTerrainArea.right ) ? m_rcTerrainArea.right : rRefreshArea.right ; int nEY = (rRefreshArea.bottom > m_rcTerrainArea.bottom ) ? m_rcTerrainArea.bottom : rRefreshArea.bottom; FACENORMAL_STRUCT* pStruct = m_pFaceNormals + ( (nSY - m_rcTerrainArea.left) * m_rcTerrainArea.GetWidth() ) + (nSX - m_rcTerrainArea.top); if( NULL != pTerrainInfo ) { for( int nY( nSY ); nY < nEY; ++nY ) { for( int nX( nSX ); nX < nEX; ++nX ) { K3DVertex v0 = pTerrainInfo->GetVertex( nX, nY ); K3DVertex v1 = pTerrainInfo->GetVertex( nX + 1, nY ); K3DVertex v2 = pTerrainInfo->GetVertex( nX, nY + 1 ); K3DVertex v3 = pTerrainInfo->GetVertex( nX + 1, nY + 1 ); pStruct->vtFaceNormalLower = CTerrainInfo::BuildNormalVector( v1, v0, v2 ); pStruct->vtFaceNormalUpper = CTerrainInfo::BuildNormalVector( v1, v2, v3 ); pStruct++; } pStruct += (m_rcTerrainArea.GetWidth() - (nEX - nSX)); } } else { for( int nY( nSY ); nY < nEY; ++nY ) { for( int nX( nSX ); nX < nEX; ++nX ) *pStruct++ = m_DefaultFaceNormal; pStruct += (m_rcTerrainArea.GetWidth() - (nEX - nSX)); } } } private: KRect m_rcTerrainArea; FACENORMAL_STRUCT* m_pFaceNormals; FACENORMAL_STRUCT m_DefaultFaceNormal; };