쿼드트리의 정의
129*129크기인 지형일 경우 노드에 저장되는 인덱스 값의 예를 든 것이다.
지형관리 클래스
전에 했던 예제와는 다르게 이제부터 지형을 다루기 위한 전문 클래스를 만들었다
지금까지 우리는 정점버퍼와 인덱스버퍼, 그리고 지형의 높이 맵 정보들을 직접 메인함수에서 가지고 있었지만, 이제부터는 쿼드트리와의 결합의 편리성을 고려해 따로 ZTerrain이라는 클래스로 분리해야만 한다.
class ZTerrain
{
private:
int m_cxDIB; /// DIB의 가로픽셀수
int m_czDIB; /// DIB의 세로픽셀수
int m_cyDIB; /// DIB의 최대높이값(즉 0 ~ 255사이의 값)
D3DXVECTOR3 m_vfScale; /// x scale, y scale, z scale
TERRAINVERTEX* m_pvHeightMap; /// 높이맵의 정점배열
LPDIRECT3DDEVICE9 m_pd3dDevice; /// 출력용 D3D디바이스
LPDIRECT3DTEXTURE9 m_pTex[MAX_TERRAIN_TEX]; /// 텍스처
LPDIRECT3DVERTEXBUFFER9 m_pVB; /// 지형출력용 정점버퍼
LPDIRECT3DINDEXBUFFER9 m_pIB; /// 지형출력용 인덱스버퍼
int m_nTriangles; /// 출력할 삼각형의 개수
ZQuadTree* m_pQuadTree; /// 쿼드트리 객체의 포인터
public:
// 생성과 관련된 함수들
ZTerrain();
~ZTerrain();
/**
* @brief 지형객체를 초기화한다.
* @param pDev : 출력용 D3D디바이스
* @param pvfScale : 높이맵의 x,y,z값에 곱할 척도값(scale vector)
* @param lpBMPFilename : 높이맵용 BMP파일명
* @param lpTexFilename : 출력용 D3D디바이스
*/
HRESULT Create( LPDIRECT3DDEVICE9 pDev, D3DXVECTOR3* pvfScale, LPSTR lpBMPFilename, LPSTR lpTexFilename[MAX_TERRAIN_TEX] );
// ZTerrain내부에서 사용되는 함수들
private:
/// 지형객체를 메모리에서 소거한다.
HRESULT _Destroy();
/// 지형객체에서 사용할 텍스처를 읽어들인다.
HRESULT _LoadTextures( LPSTR lpTexFilename[MAX_TERRAIN_TEX] );
/// BMP파일을 열어서 높이맵을 생성한다.
HRESULT _BuildHeightMap( LPSTR lpFilename );
/// BMP파일의 크기에 맞춰서 쿼드트리를 생성한다.
HRESULT _BuildQuadTree();
/// 정점, 인덱스 버퍼를 생성한다.
HRESULT _CreateVIB();
/// 화면에 지형을 출력한다.
HRESULT _Render();
public:
/// x, z위치의 정점값을 얻어낸다.
TERRAINVERTEX* GetVertex( int x, int z ) { return (m_pvHeightMap+x+z*m_cxDIB); }
/// x, z위치의 높이(y)값만 얻어내다.
float GetHeight( int x, int z ) { return (GetVertex( x, z ))->p.y; }
/// 높이맵 BMP파일의 가로픽셀수
int GetCXDIB() { return m_cxDIB; }
/// 높이맵 BMP파일의 가로픽셀수
int GetCZDIB() { return m_czDIB; }
/// 높이맵의 실제 x축 폭(column)값
float GetCXTerrain() { return m_cxDIB * m_vfScale.x; }
/// 높이맵의 실제 y축 높이(height)값
float GetCYTerrain() { return m_cyDIB * m_vfScale.y; }
/// 높이맵의 실제 z축 길이(row)값
float GetCZTerrain() { return m_czDIB * m_vfScale.z; }
/// 화면에 지형을 출력한다.
HRESULT Draw();
};
최초로 객체를 생성한 다음 Create()함수에서 높이 맵으로 사용될 BMP 파일과 텍스쳐 정보를 입력받아 지형정보를 생성하게 된다.
_BuildHeightMap() 함수에서 높이맵을 생성하는 소스를 살펴보면 알겠지만, 높이맵의 가로와 세로 크기가 2^n+1이 아닌 경우에는 E_FAIL을 리턴하도록 구성하면 좋을것이다,
현재 ZTerrain 클래스는 Draw()함수를 호출해서 지형을 그리는데, Draw()함수는 아래와같다.
/// 화면에 지형을 출력한다.
HRESULT ZTerrain::Draw()
{
LPDWORD pI;
if( FAILED( m_pIB->Lock( 0, (m_cxDIB-1)*(m_czDIB-1)*2 * sizeof(TRIINDEX), (void**)&pI, 0 ) ) )
return E_FAIL;
m_nTriangles = m_pQuadTree->GenerateIndex( pI );
m_pIB->Unlock();
// g_pLog->Log( "Triangles=%d", m_nTriangles );
_Render();
return S_OK;
}
Lock()함수로 인덱스 버퍼의 포인터를 얻어 낸 후 쿼드트리로부터 출력할 삼각형의 인덱스 버퍼를 얻어낸다, 그리고 다시 인덱스 버퍼의 Unlock()을 호출 한 뒤, 쿼드트리에서 생성한 인덱스 버퍼의 내용으로 DrawIndexedPrimitive() 함수를 사용하여 지형정보 삼각형을 그려준다. ZTerrain 클래스는 높이 맵을 읽어서 정점버퍼와 인덱스버퍼를 만들고, 쿼드트리를 내부에 갖고있다. 앞으로는 쿼드트리 클래스를 향상시켜 좀 더 다양하면서도 효율적인 지형처리 기법을 사용해보자
Dib.h, Dib.cpp에 대해
이번에는 BMP파일을 사용하기 위해 BMP를 전문으로 다루는 소스를 사용하였다.
BMP파일은 특성상 가장 간단한 구조를 갖고 있음에도 불구하고 몇가지 제한사항 때문에 다루기가 까다로운 것 또한 사실이다. 실제 개발시에는 DevIL처럼 공개되어있는 그래픽 라이브러리, 혹은 LeadTool같은 상용툴을 사용해도 무방하지만, BMP파일을 직접 다루어보는 것도 좋은 경험이 될것이라 생각되어 소개한 소스다.
구현화면은 전과 동일하다
단지 속도향상이 있다는건데
전 소스나 쿼드트리나 어차피 내 컴에서는 뭐로가도 무리없는 소스이기때문에
특별한 속도향상은 느끼질 못하겠다.
- 그래도 성능향상을 위해 필요하다는 거
'Graphics > DirectX' 카테고리의 다른 글
Direct X - LOD (Level Of Detail) (2) | 2014.08.21 |
---|---|
Direct X - 쿼드트리 컬링 (0) | 2014.08.16 |
Direct X - 절두체 컬링 (0) | 2014.08.11 |
Direct X - 카메라 (2) | 2014.08.04 |
Direct X - 지형 처리 기법 (0) | 2014.07.31 |