'2008/07/08'에 해당되는 글 3건
- 2008/07/08 [D3DX] 높이맵 완성! (3)
- 2008/07/08 [D3DX] 맵 타일 완성!
- 2008/07/08 [D3DX] ID3DXBuffer
:: 높이맵정보를 가지고 있는 이미지 파일(웹에올리기 위해 jpg로 확장자 변환하였다.)
먼저 33 * 33 타일을 만들었다
버텍스수는 33 * 33 = 1089가 되므로 픽셀수도 1089개 되어야함..
33 * 33 짜리 이미지는 포토샵에서 필터 - 렌더 - Difference Clouds 을 적용하여 만들었다.
이미지 - 적용 에서 그레이스케일로한후 save as 에서 .raw 확장자로 저장하게되면
한 픽셀당 8 비트가 할당된 이미지가 만들어지게된다(총 1089바이트)
색상이 흰색에 가까울수록 255에 가깝고 검은색에 가까울수록 0에 가깝다
이제, 이 픽셀들을 버텍스들과 매핑시킬때 버텍스의 y 좌표값에 이 바이트값을 넣어주면 높이가 표현된다.
맵이미지 파일을 읽어올때는 fopen() 과 fscanf() 를 사용해서 읽었다.
읽은후에는 버텍스버퍼 락을걸고 1089 번 루프를 돌면서 각 버텍스의 y성분만 건드려주면된다.
제법 간지나게 나온듯해서 뿌듯하다 -_-흐흐..
.. 그리고 몇가지 이슈사항..
1. D3DXCreateVertexBuffer9 로 버텍스 버퍼를 생성할때 D3DUSAGE 인자를 넣어야하는데..
높이맵처럼 버텍스의 특정 성분(y좌표)만 수정이 빈번하게 이루어진다면 어떤 플래그를 넣어야할까..
D3DUSAGE_WRITEONLY, D3DUSAGE_DYNAMIC(이걸로 해봤더니 버텍스버퍼에 쓰기할때 에러난다), 등등등..
플래그가 여러개가 있는데.. 뭘쓰는게 가장 최적화에좋을지..
2. 1바이트는 0 부터 255까지 나타낼수있는데 이 값을 그대로 버텍스의 Y성분에 적용해버리면 안되고
0.03 정도를 곱해서 전체적인 수치를 좀 낮춰줘야한다.. 왜냐하면.. 버텍스 간의 간격이 1로되어있는데
높이가 255면 아예 화면에 보이지도 않을정도로 커져버리기때문..
3D 세계의 맵을 구성하는 가장 기본적인 단위인 "타일" 이다.
아무리 거대한 맵이라도 이 타일이 합쳐져서 큰 맵하나가 되는것이다.
이제 여기에 Y (높이맵) 값만 적용해주면 그럴싸한 지형이 완성될것이다.!!
이 타일의 버텍스버퍼와 인덱스버퍼를 만드는 코드는 다음과 같이작성했다.
void Cdx3dView::initPlane()
{
int width = 15; // 가로 버텍스수 15개
int height = 15; //세로 버텍스수 15개
int total = width*height; // 총 버텍스수
float gap = 1.0f; //버텍스 간의 거리
PVertex arrTemp[225];
for(int i=0;i<width;i++) // 행
{
for(int j=0;j<width;j++) // 열
{
arrTemp[ j + i*width ].position = D3DXVECTOR3(gap*(float)j, 0.0f, gap*(float)i);
}
}
void *pTemp;
m_pd3dDevice->CreateVertexBuffer(sizeof(PVertex)*total, 0, PVertex::FVF, D3DPOOL_MANAGED, &planeVB, 0);
planeVB->Lock(0, sizeof(PVertex)*total, (void**)&pTemp, 0);
memcpy(pTemp, arrTemp, sizeof(arrTemp));
planeVB->Unlock();
int numPolygon = (width -1) * (width -1) * 2;
PIndex arrTemp2[392]; // 폴리곤 갯수만큼 인덱스 생성.
int cntPolygon = 0;
for(int i=0;i<width-1;i++)
{
if(cntPolygon >= numPolygon){ break; }
for(int j=0;j<width-1;j++)
{
//하단 폴리곤
arrTemp2[cntPolygon].a = i*width + j;
arrTemp2[cntPolygon].b = i*width + (j+1);
arrTemp2[cntPolygon].c = (i+1)*width + (j+1);
cntPolygon++;
//상단 폴리곤
arrTemp2[cntPolygon].a = i*width + j;
arrTemp2[cntPolygon].b = (i+1) * width + j;
arrTemp2[cntPolygon].c = (i+1) * width + (j+1);
cntPolygon++;
}
}
m_pd3dDevice->CreateIndexBuffer(sizeof(PIndex)*numPolygon, 0, D3DFMT_INDEX32, D3DPOOL_MANAGED, &planeIB, 0);
void *pIB;
planeIB->Lock(0, sizeof(arrTemp2), (void **)&pIB, 0);
memcpy(pIB, arrTemp2, sizeof(arrTemp2));
planeIB->Unlock();
}
지금 이걸보면 타일의 중심이 3d 좌표계의 중심과 일치하지않는데.. 이건 좋은방법이 아닌것같다
타일의 중심과 3d 좌표계의 중심(원점)이 일치하게 하는게 좋을것같다
어차피 이 타일이라는것은 월드에서 반복적으로 그려져야 하므로.. 원점을 중심으로 하는 타일을 만들어서
이것을 재활용 하는 방식이 될것이다.. 즉 이 원점을 중심으로 하는 타일이 맵의 "템플릿"(틀) 이 될것이다.
D3DXLoadMeshFromX(....)를 호출하면 여러가지 정보를 프로그래머에게 넘겨주는데
이때 사용하는것이 ID3DXBuffer 이다
x파일로부터 메쉬를 읽어들일때, 그 메쉬의 메터리얼정보나 인접삼각형 정보까지 넘어오는데 이
정보들이 ID3DXBuffer 로 넘어온다.
ID3DXBuffer에 속한 버퍼의 타입이 결정되어있지 않으므로 명시적으로 타입을 정해야한다
받아올때 다음과같이 받아오면된다
매터리얼 정보를 받아온다고할때
ID3DXBuffer *buffer;
D3DXLoadMeshFromX( , , , ,&buffer , ) //다른 인수에대한 설명은 생략.
D3DXMATERIAL *mtrls = (D3DXMATERIAL *)(buffer -> GetBufferPointer());
mtrls[0].MatD3D // D3DMATERIAL9 구조체에 접근
mtrsl[0].pTextureFileName // 텍스쳐파일명(문자열)에 접근
이렇게 하면된다.
ID3DXBuffer 의 GetBufferPointer() 메서드는 ID3DXBuffer 가 관리하고있는 버퍼의 첫번째 메모리 블록주소를 리턴한다. 이것을 D3DXMATERIAL * 로 형변환을 하게되면 버퍼(배열)에 접근할때 오프셋이 달라지는효과가 나는것이다 D3DXMATERIAL 의 크기를 72바이트라고 가정할때, mtrls[0], mtrls[1] 둘의 메모리 블락수 차이는 72 가 되는 것이다. 즉 mtrls[1] 은 mtrls[0] 이 존재하는 메모리보다 72 블락 뒤에 있다는것이다.

이올린에 북마크하기
이올린에 추천하기
Prev
Rss Feed