2004년 7월 18일 쯤
- 현재 하이트 맵의 가장 간단한건 구현... 와이어프레임으로 랜더링하고 있다.
raw 파일에서 64*64 크기의 높이 정보를 읽어와서 버텍스들을 생성하고 인덱스버퍼를 만들어 랜더링한다. 랜더링 상태를
SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME) 으로 설정해서 와이어프레임이 꽉꽉차서 보인다.(과거 이 옵션을 몰라서 랜더링 옵션을 D3DPT_LINESTRIP 으로 하고 랜더링된 와이어프래임을 보고 "어째서 나의 와이어 프레임은 부실하게 나올까" 하고 고민한적이있다....)
음 하이트맵의 데이타를 생성하는 코드를 써보면
unsigned char TmpHeight;
// 버텍스버퍼와 인덱스버퍼를 위한 중간 버퍼들
FVF_HEIGHTMAP* pVertexData = new FVF_HEIGHTMAP[m_dwVertices];
WORD* pIndexData = new WORD[m_dwPrimitives*3];
//파일에서 높이 정보를 읽어오고 버텍스정보를 삽입한다.
FILE* pFile;
UINT nIndex = 0;
pFile = fopen(szFilename, "rb");
for(unsigned y = 0;y < (HEIMAP_Y + 1); y++)
{
for(unsigned x = 0;x < (HEIMAP_X + 1); x++)
{
TmpHeight = fgetc(pFile);
// 버텍스 데이타 구성
pVertexData[x + y * (HEIMAP_X+1)].fX = (float)x;
pVertexData[x + y * (HEIMAP_X+1)].fY = (float)TmpHeight / 15.0f - 40;
pVertexData[x + y * (HEIMAP_X+1)].fZ = (float)y;
pVertexData[x + y * (HEIMAP_X+1)].dwColor = 0xffffffff;
if( (y < HEIMAP_Y) && (x < HEIMAP_X) )
{
// 인덱스 데이타 구성
pIndexData[(x+y*(HEIMAP_X))*6 +0] = x + y * (HEIMAP_X+1);
pIndexData[(x+y*(HEIMAP_X))*6 +1] = x+1 + y * (HEIMAP_X+1);
pIndexData[(x+y*(HEIMAP_X))*6 +2] = x + (y+1) * (HEIMAP_X+1);
pIndexData[(x+y*(HEIMAP_X))*6 +3] = x + y * (HEIMAP_X+1);
pIndexData[(x+y*(HEIMAP_X))*6 +4] = x+1 + (y+1) * (HEIMAP_X+1);
pIndexData[(x+y*(HEIMAP_X))*6 +5] = x + (y+1) * (HEIMAP_X+1);
}
}
}
fclose(pFile);
// 버텍스버퍼를 구성한다.
m_pVB->Create(m_pGraphics, m_dwVertices, sizeof(FVF_HEIGHTMAP), D3DFVF_HEIGHTMAP);
m_pVB->Set(0, m_dwVertices, pVertexData);
//인덱스데이타를 구성한다.
m_pIB->Create(m_pGraphics, m_dwPrimitives*3);
m_pIB->Set(0, m_dwPrimitives*3, pIndexData);
// 버덱스데이타, 인덱스데이타 메모리를 해재한다.
delete [] pVertexData;
delete [] pIndexData;
이정도... 간단하다. 밑은 스크린샷 이제는 텍스쳐 매트릭스를 적용하여 한 중류의 텍스쳐로 덥어보자
음 위의 내용을 이해하면 텍스쳐매트릭스를 사용하는데는 지장이 없을듯 하다. 문제는 다이렉트X SDK인데... 나만 그러는지 모르겠지만
D3DXMatrixDeterminant 를 사용했을때 런타임에러가 발생한다. 그래서 2003 Summer Update로 업데이트를 했는데 일단 위의 문제는 해결됐다. 다만 인테페이스가 바뀐게 좀 있어서 짜증이 난다. -_-;;; 쓰던 코드를 좀 손봐야 할듯하다.
2004년 7월 22일
위의 화면처럼 나오는데... 여러종류의 텍스쳐를 입히는것도 아주 쉬울듯하다. 그냥 텍스쳐별로 따로따로 인덱스버퍼를 구성하면 되니... 그런데 그렇게 할려면 맵의 파일 포멧이 좀 바껴야 할태고 그럴려면 이왕에 전용 에디터를 만드는쪽이 좆타... 라는 결론이 나와서 -_-;;; 좀 귀찮다. 일단 위의 하이트맵을 랜더링하는 코드를 보면
void CHeightMap::Rendering(HEIGHTMAP_DRAW_OPTION hdOption)
{
D3DXMATRIX matrixView;
m_pGraphics->GetDeviceCOM()->GetTransform(D3DTS_VIEW, &matrixView);
FLOAT fDeterminantMatView = D3DXMatrixDeterminant(&matrixView);
D3DXMATRIX matViewInv;
D3DXMatrixInverse(&matViewInv, &fDeterminantMatView, &matrixView);
D3DXMATRIX matScale;
ZeroMemory(&matScale, sizeof(D3DXMATRIX));
matScale._11=1.0f/1.0f;
matScale._32=1.0f/1.0f;
D3DXMATRIX matTex;
D3DXMatrixMultiply(&matTex, &matViewInv, &matScale);
// 텍스쳐 좌표 자동생성을 위한 세팅
m_pGraphics->GetDeviceCOM()->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
m_pGraphics->GetDeviceCOM()->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
m_pGraphics->GetDeviceCOM()->SetTransform(D3DTS_TEXTURE0, &matTex);
// 랜더링 옵션이 WIRE이면 랜더링 상태를 설정
if(hdOption == RENDER_WIRE)
m_pGraphics->GetDeviceCOM()->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
m_pIB->Render( D3DPT_TRIANGLELIST, 0, 0, m_pVB->GetNumVertices(), 0, m_dwPrimitives, m_pVB, m_pTextureDefault );
// 랜더링 옵션이 WIRE이면 랜더링 상태를 해제
if(hdOption == RENDER_WIRE)
m_pGraphics->GetDeviceCOM()->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
// 텍스쳐 좌표 자동생성을 위한 세팅 해제
m_pGraphics->GetDeviceCOM()->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
m_pGraphics->GetDeviceCOM()->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
이정도... 자세한 내용은 빗자루님의 글을 참고하는게 좋다. 간단히 설명하면 카메라의 위치와 버텍스의 위치값으로 UV값을 자동 생성해서 텍스쳐를 입히는 것이다.
자 그럼 다음은 맵에디터다