#pragma once #include "TerrainPrimitive.h" class CTerrainPrimitiveForSingleTile : public CTerrainPrimitive { public: CTerrainPrimitiveForSingleTile( float fTileLength, int nVertexCount, const K3DIndexBuffer* pCommonIndexBuffer, WORD wTile, CTerrainTextureInfo* pTextureInfo, const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev, bool& rResult ) : CTerrainPrimitive( nVertexCount, pCommonIndexBuffer, pTerrainInfo ) , m_fTileLength( fTileLength ) { if( !pTextureInfo->IsValidTexture( wTile ) ) { rResult = false; return; } float fTexDetail = pTextureInfo->GetTextureDetailRatio( wTile ); m_spTexture = pTextureInfo->GetTexture( wTile ); K3DMatrixScaling( &m_matScale, 1.f / ( m_fTileLength * fTexDetail ), 1.f / ( m_fTileLength * fTexDetail ), 0.f ); // 버텍스 버퍼 생성 int nTotalVertexCount = (m_nVertexCount * m_nVertexCount); m_spVB = pDev->CreateVertexBuffer( K3DFVF_TERRAIN, nTotalVertexCount ); if( m_spVB == NULL || !m_spVB->IsValidVtx() ) { rResult = false; return; } // transform 이동 좌표 m_vtWorldTransform = pTerrainInfo->GetVertex( 0, 0 ); m_vtWorldTransform.z = 0.f; // 버텍스 버퍼 Lock K3DTERRAINVERTEX* pVertices; int nSize; m_spVB->Lock( (void**)&pVertices, nSize ); if( !pVertices ) { rResult = false; return; } for( int nY = 0; nY < m_nVertexCount; ++nY ) { for( int nX = 0; nX < m_nVertexCount; ++nX ) { pVertices->pos = K3DVertex( float(nX) * m_fTileLength, float(nY) * m_fTileLength, pTerrainInfo->GetHeight( nX, nY ) ); pVertices->normal = pTerrainInfo->GetVertexNormalVector( nX, nY ); pVertices->diffuse = KColor( pTerrainInfo->GetColor( nX, nY ) ); pVertices++; } } m_spVB->Unlock(); rResult = true; } virtual ~CTerrainPrimitiveForSingleTile() { } void Render( KViewportObject* viewport, K3DRenderDevice* dev ) { if( NULL != m_spVB ) { K3DMatrix matWorldTransform; K3DMatrixIdentity( matWorldTransform ); K3DVector vtPos = m_vtWorldTransform; if( NULL != m_pOriginCorrection ) vtPos -= *m_pOriginCorrection; K3DMatrixSetPosVector( matWorldTransform, vtPos ); // render state 설정 dev->SetRenderState( K3DRenderDevice::RS_TERRAIN_SINGLETILE ); dev->SetTransform( K3DRenderDevice::TS_WORLD, matWorldTransform ); K3DMatrix matTexture; K3DMatrixMultiply( &matTexture, viewport->GetInverseViewMatrix(), &m_matScale ); // 텍스쳐 몇 텍스쳐 변환 행렬 설정 dev->SetTransform( K3DRenderDevice::TS_TEXTURE0, matTexture ); dev->SetTexture( 0, m_spTexture ); // 그리기 dev->DrawIndexedTriangleVB( m_spVB, m_spCommonIndexBuffer ); // 텍스쳐 및 텍스쳐 변환 행렬 환원 dev->SetTexture( 0, NULL ); dev->SetTransformIdentity( K3DRenderDevice::TS_TEXTURE0 ); } } bool RefreshHeight( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) { // 버텍스 버퍼 Lock K3DTERRAINVERTEX* pVertices; int nSize; m_spVB->Lock( (void**)&pVertices, nSize ); if( !pVertices ) return false; for( int nY = 0; nY < m_nVertexCount; ++nY ) { for( int nX = 0; nX < m_nVertexCount; ++nX ) { // 높이값과 normal vector값 변경 pVertices->pos = K3DVertex( float(nX) * m_fTileLength, float(nY) * m_fTileLength, pTerrainInfo->GetHeight( nX, nY ) ); pVertices->normal = pTerrainInfo->GetVertexNormalVector( nX, nY ); pVertices++; } } m_spVB->Unlock(); return true; } bool RefreshTile( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) { return true; } // 이 프리미티브는 타일 설정이 불가. bool RefreshColor( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) { // 버텍스 버퍼 Lock K3DTERRAINVERTEX* pVertices; int nSize; m_spVB->Lock( (void**)&pVertices, nSize ); if( !pVertices ) return false; for( int nY = 0; nY < m_nVertexCount; ++nY ) { for( int nX = 0; nX < m_nVertexCount; ++nX ) { // diffuse값 변경 pVertices->diffuse = KColor( pTerrainInfo->GetColor( nX, nY ) ); pVertices++; } } m_spVB->Unlock(); return true; } protected: float m_fTileLength; K3DTextureSPtr m_spTexture; K3DMatrix m_matScale; };