Files
2026-06-01 12:46:52 +02:00

297 lines
9.8 KiB
C++

#pragma once
#include <list>
#include "KPrimitive.h"
#include "TerrainDefine.h"
#include "TerrainCustomTexturePrimitive.h"
#include "TerrainTextureInfo.h"
#include "KViewport.h"
#include "k3dpccp.h"
#ifdef _RAC
#include "TerrainPropForGame.h"
#endif
const float VIEW_DELTA = 500.f;
class CTerrainPrimitive : public K3DPrimitive
{
public:
CTerrainPrimitive( int nVertexCount, K3DIndexBuffer* pCommonIndexBuffer, const CTerrainInfo* pTerrainInfo )
: m_nVertexCount( nVertexCount )
, m_spCommonIndexBuffer(pCommonIndexBuffer)
, m_pOriginCorrection( NULL )
, m_vtWorldTransform( K3DVertex( 0.f, 0.f, 0.f ) )
, m_nTerrainLoadLevel( TERRAIN_LOD_LEVEL_1 )
{
m_type = KPRIMITIVE_TERRAIN;
m_pVB = NULL;
m_nIndexVB = -1;
m_vertexMin = pTerrainInfo->GetVertex( 0, 0 );
m_vertexMax = pTerrainInfo->GetVertex( m_nVertexCount - 1, m_nVertexCount - 1 );
m_vtCenterWorldTransform = pTerrainInfo->GetVertex( (m_nVertexCount - 1)/2, (m_nVertexCount - 1)/2 );
for( int nY = 0; nY < m_nVertexCount; ++nY )
{
for( int nX = 0; nX < m_nVertexCount; ++nX )
{
float fZ = pTerrainInfo->GetHeight( nX, nY );
if( fZ < m_vertexMin.z ) m_vertexMin.z = fZ;
if( fZ > m_vertexMax.z ) m_vertexMax.z = fZ;
}
}
m_vMinProp = m_vertexMin;
m_vMaxProp = m_vertexMax;
CreateTerrainCube();
CreateVisibleCube();
m_bUpdateLength = false;
m_nTerrainLoadLevel = TERRAIN_LOD_LEVEL_1;
for( int i = 0; i < TERRAIN_LOD_CRACK_MAX; ++i )
m_nNeighborsTerrainLoadLevel[i] = TERRAIN_LOD_LEVEL_1;
}
virtual ~CTerrainPrimitive() { }
void SetOriginCorrection( const K3DVertex* pOriginCorrection = NULL )
{ m_pOriginCorrection = pOriginCorrection; }
const K3DVertex* GetVisibleCube() const { return m_VisibleCube; }
const K3DVertex* GetTerrainCube() const { return m_TerrainCube; }
void SetPropBound( const K3DVector &vMinProp, const K3DVector &vMaxProp )
{
bool bIsCheck = false;
if( m_vMinProp.x > vMinProp.x ) { m_vMinProp.x = vMinProp.x; bIsCheck = true; }
if( m_vMinProp.y > vMinProp.y ) { m_vMinProp.y = vMinProp.y; bIsCheck = true; }
if( m_vMinProp.z > vMinProp.z ) { m_vMinProp.z = vMinProp.z; bIsCheck = true; }
if( m_vMaxProp.x < vMaxProp.x ) { m_vMaxProp.x = vMaxProp.x; bIsCheck = true; }
if( m_vMaxProp.y < vMaxProp.y ) { m_vMaxProp.y = vMaxProp.y; bIsCheck = true; }
if( m_vMaxProp.z < vMaxProp.z ) { m_vMaxProp.z = vMaxProp.z; bIsCheck = true; }
if( bIsCheck )
CreateVisibleCube();
}
CTerrainCustomTexturePrimitive* CreateCustomTexturePrimitive()
#ifdef _RAC
{ return new CTerrainCustomTexturePrimitive( m_pVB, m_spCommonIndexBuffer, m_vtWorldTransform ); }
#else
{ return new CTerrainCustomTexturePrimitive( m_spVB, m_spCommonIndexBuffer, m_vtWorldTransform ); }
#endif
#ifdef _RAC
virtual void ReloadProp(TERRAINPROP_VECTOR &listPropVector) {}
#endif
virtual void TestRenderObject() {}
virtual void Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum = true ) = 0;
inline bool CheckFogFar( KViewportObject* viewport )
{
float fNear, fFar, fTop, fBottom;
float fLen = ( m_vtWorldTransform - K3DVector(viewport->GetCameraTargetPos().x, viewport->GetCameraTargetPos().y,0) ).Magnitude();
viewport->GetFogFactor( fNear, fFar, fTop, fBottom );
if( fLen >= (fFar-VIEW_DELTA) ) //포그 Far 보다 멀면, 텍스쳐 설정 NULL
return true;
return false;
}
const K3DVertex& GetWorldTransform() { return m_vtWorldTransform; }
const K3DVertex& GetCenterWorldTransform() { return m_vtCenterWorldTransform; }
/// terrain list를 rendering 하기 전에 불리움
virtual void PreRenderPrimitiveGroup(K3DRenderDevice* pDev, KViewportObject* pViewport) {}
/// terrain list를 전부 rendering 하고 나서 불리움 ( viewport에서 call해줌)
virtual void PostRenderPrimitiveGroup(K3DRenderDevice* pDev, KViewportObject* pViewport) {}
virtual void SetLightMapTex(K3DTexture* pLightmapTex) {}
void GetVisibleMinMaxValue( float& minX, float& minY, float& minZ, float& maxX, float& maxY, float& maxZ )
{
minX = min(m_vertexMin.x, m_vMinProp.x);
maxX = max(m_vertexMax.x, m_vMaxProp.x);
minY = min(m_vertexMin.y, m_vMinProp.y);
maxY = max(m_vertexMax.y, m_vMaxProp.y);
minZ = min(m_vertexMin.z, m_vMinProp.z);
maxZ = max(m_vertexMax.z, m_vMaxProp.z);
}
void GetSegmentMinMaxValue( float& minX, float& minY, float& minZ, float& maxX, float& maxY, float& maxZ )
{
//지형만 큐브
minX = m_vertexMin.x;
maxX = m_vertexMax.x;
minY = m_vertexMin.y;
maxY = m_vertexMax.y;
minZ = m_vertexMin.z;
maxZ = m_vertexMax.z;
}
static void SetCheckOcclusionCulling( bool bCheck ) { s_CheckOcclusionCulling = bCheck; }
virtual void CalcLength( const K3DVector& rCameraPos ) {}
void SetTerrainLodLevel( TERRAIN_LOD_LEVEL nLevel ) { m_nTerrainLoadLevel = nLevel; }
void SetNeighborsTerrainLoadLevel( TERRAIN_LOD_LEVEL nLevel, TERRAIN_LOD_CRACK nLodCrack )
{
m_nNeighborsTerrainLoadLevel[nLodCrack] = nLevel;
}
public: // for Editor
virtual bool RefreshHeight( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) = 0;
virtual bool RefreshTile( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) = 0;
virtual bool RefreshColor( const CTerrainInfo* pTerrainInfo, K3DRenderDevice* pDev ) = 0;
public: // For vertex manipulation (color reading)
K3DVertexBufferSPtr *GetVertexBuffer() { return &m_spVB; }
int GetVertexCount() { return m_nVertexCount; } ///< actually (m_nVertexCount*m_nVertexCount) vertexes in vertex-buffer
TERRAIN_LOD_LEVEL GetTerrainLodLevel() { return m_nTerrainLoadLevel; }
TERRAIN_LOD_LEVEL GetNeighborsTerrainLoadLevel( TERRAIN_LOD_CRACK nLodCrack ) { return m_nNeighborsTerrainLoadLevel[nLodCrack]; }
protected:
K3DVertexBufferSPtr m_spVB;
K3DVertexBuffer* m_pVB;
int m_nIndexVB;
K3DIndexBufferSPtr m_spCommonIndexBuffer;
const K3DVertex* m_pOriginCorrection;
K3DVertex m_vtWorldTransform;
K3DVertex m_vtCenterWorldTransform;
int m_nVertexCount;
K3DVertex m_VisibleCube[8];
K3DVertex m_TerrainCube[8];
K3DVertex m_vMinProp, m_vMaxProp;
K3DVertex m_vertexMin, m_vertexMax;
static bool s_CheckOcclusionCulling;
TERRAIN_LOD_LEVEL m_nTerrainLoadLevel;
TERRAIN_LOD_LEVEL m_nNeighborsTerrainLoadLevel[TERRAIN_LOD_CRACK_MAX];
bool m_bUpdateLength;
void CreateVisibleCube()
{
float minx = min(m_vertexMin.x, m_vMinProp.x);
float maxx = max(m_vertexMax.x, m_vMaxProp.x);
float miny = min(m_vertexMin.y, m_vMinProp.y);
float maxy = max(m_vertexMax.y, m_vMaxProp.y);
float minz = min(m_vertexMin.z, m_vMinProp.z);
float maxz = max(m_vertexMax.z, m_vMaxProp.z);
//프랍과 합쳐진 큐브
m_VisibleCube[0] = KPCCP::get_cube_vertex(0, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[1] = KPCCP::get_cube_vertex(1, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[2] = KPCCP::get_cube_vertex(2, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[3] = KPCCP::get_cube_vertex(3, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[4] = KPCCP::get_cube_vertex(4, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[5] = KPCCP::get_cube_vertex(5, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[6] = KPCCP::get_cube_vertex(6, minx, maxx, miny, maxy, minz, maxz);
m_VisibleCube[7] = KPCCP::get_cube_vertex(7, minx, maxx, miny, maxy, minz, maxz);
}
void CreateTerrainCube()
{
//지형만 큐브
float minx = m_vertexMin.x;
float maxx = m_vertexMax.x;
float miny = m_vertexMin.y;
float maxy = m_vertexMax.y;
float minz = m_vertexMin.z;
float maxz = m_vertexMax.z;
m_TerrainCube[0] = KPCCP::get_cube_vertex(0, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[1] = KPCCP::get_cube_vertex(1, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[2] = KPCCP::get_cube_vertex(2, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[3] = KPCCP::get_cube_vertex(3, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[4] = KPCCP::get_cube_vertex(4, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[5] = KPCCP::get_cube_vertex(5, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[6] = KPCCP::get_cube_vertex(6, minx, maxx, miny, maxy, minz, maxz);
m_TerrainCube[7] = KPCCP::get_cube_vertex(7, minx, maxx, miny, maxy, minz, maxz);
}
public:
static K3DIndexBuffer* CreateCommonIndexBuffer( int nTileCount, K3DRenderDevice* pDev )
{
assert( pDev && "Device Lost???" );
if( pDev == NULL ) return NULL;
int nVertexCount = (nTileCount + 1);
K3DIndexBuffer* pCommonIndexBuffer = pDev->CreateIndexBuffer( (nTileCount * nTileCount) * 3 * 2 ); // 1타일 당 삼각형 2개
if( !pCommonIndexBuffer )
return NULL;
int nSize;
WORD* pIndices;
// 인덱스 버퍼 Lock
pCommonIndexBuffer->Lock( (void**)&pIndices, nSize );
if( !pIndices )
{
pCommonIndexBuffer->Discard();
return NULL;
}
WORD* debug = pIndices;
for( int nY = 0; nY < nTileCount; ++nY )
{
for( int nX = 0; nX < nTileCount; ++nX )
{
WORD wIndex = static_cast<WORD>((nY * nVertexCount) + nX);
*pIndices++ = wIndex;
*pIndices++ = wIndex + (WORD)nVertexCount;
*pIndices++ = wIndex + 1;
*pIndices++ = wIndex + 1;
*pIndices++ = wIndex + (WORD)nVertexCount;
*pIndices++ = wIndex + (WORD)nVertexCount + 1;
}
}
pCommonIndexBuffer->Unlock();
return pCommonIndexBuffer;
}
static K3DIndexBuffer* CreateCommonCrackIndexBuffer( K3DRenderDevice* pDev )
{
assert( pDev && "Device Lost???" );
if( pDev == NULL ) return NULL;
K3DIndexBuffer* pCommonIndexBuffer = pDev->CreateIndexBuffer( 8 );
if( !pCommonIndexBuffer )
return NULL;
int nSize;
WORD* pIndices;
// 인덱스 버퍼 Lock
pCommonIndexBuffer->Lock( (void**)&pIndices, nSize );
if( !pIndices )
{
pCommonIndexBuffer->Discard();
return NULL;
}
*pIndices++ = 0;
*pIndices++ = 7;
*pIndices++ = 8;
*pIndices++ = 9;
*pIndices++ = 10;
*pIndices++ = 11;
*pIndices++ = 12;
*pIndices++ = 13;
pCommonIndexBuffer->Unlock();
return pCommonIndexBuffer;
}
};