297 lines
9.8 KiB
C++
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;
|
|
}
|
|
};
|