RAW RAW std vectorint heightmap bool Terrain read
RAW 파일 로딩하기 • RAW파일은 일련의 연속된 바이트 블록으로 다음의 메서드를 이 용해 손쉽게 블록을 읽기 가능 std: : vector<int> _heightmap; bool Terrain: : read. Raw. File(std: : string file. Name) { // 각 벡터를 위한 높이 std: : vector<BYTE> in( _num. Vertices); std: : ifstream in. File(file. Name. c_str(), std: : ios_base: : binary); if(in. File == 0) return false; 2009 -1학기 컴퓨터게임(Direct. X) 8
in. File. read( (char*) &in[0]; // 버퍼 in. size()); // 버퍼로 읽어들일 바이트 수 in. File. close(); // byte 벡터를 int 벡터로 복사 _heightmap. resize( _num. Vertices); for(int i = 0; i < in. size(); i++) _heightmap[i] = in[i]; return true; } 2009 -1학기 컴퓨터게임(Direct. X) 9
• Terrain 클래스는 높이맵 내의 항목에 접근하고 수정하기 위한 다음의 두 메서드를 제공 int Terrain: : get. Heightmp. Entry(int row, int col) { return _heightmap[raw*_num. Verts. Per. Row+col]; } void Terrain: : set. Heightmap. Entry(int row, int col, int value) { _heightmap[row*_num. Verts. Per. Row+col] = value; } 2009 -1학기 컴퓨터게임(Direct. X) 11
class Terrain { public: Terrain( IDirect 3 DDevice 9* device, std: : string heightmap. File. Name, int num. Verts. Per. Row, int num. Verts. Per. Col, int cell. Spacing, // 셀 간의 간격 float height. Scale); // 높이 배율을 조정하는 값 …. . // 메서드 생략 private: … //장치/버텍스 버퍼 생략 2009 -1학기 컴퓨터게임(Direct. X) 14
int _num. Verts. Per. Row; int _num. Verts. Per. Col; int _cell. Spacing; int _num. Cells. Per. Row; int _num. Cells. Per. Col; int _width; int _depth; int _num. Vertices; int _num. Triangles; float _height. Scale; }; 전체 코드는 예제 참고 2009 -1학기 컴퓨터게임(Direct. X) 15
• 생성자에 전달된 값들을 이용해 다음과 같은 방법으로 다른 변수 들의 값을 계산함. _num. Cells. Per. Row = _num. Verts. Per. Row – 1; _num. Cells. Per. Col = _num. Verts. Per. Col – 1; _width = _num. Cells. Per. Col * _cell. Spacing; _depth = _num. Cells. Per. Col * _cell. Spacing; _num. Vertices = _numverts. Per. Row * _numverts. Per. Col; _num. Triangles = _num. Cells. Per. Row * _num. Cells. Per. Col * 2; 2009 -1학기 컴퓨터게임(Direct. X) 16
• 우리가 이용할 지형의 버텍스 구조체 struct Terrain. Vertex{ Terrain. Vertex(){} Terrain. Vertex(float x, float y, float z, float u, float v){ _x = x; _y = y; _z = z; _u = u; _v = v; } float _x, _y, _z; float _u, _v; static const DWORD FVF; }; const DWORD Terrain: : Terrain. Vertex: : FVF = D 3 DFVF_XYZ | D 3 DFVF_TEX 1; 2009 -1학기 컴퓨터게임(Direct. X) 17
n u = j · u. Coord. Increament. Size n v = i · v. Coord. Increament. Size 여기에서 1 n n u. Coord. Increament. Size = num. Cell. Cols 1 v. Coord. Increament. Size = num. Cell. Rows 2009 -1학기 컴퓨터게임(Direct. X) 21
n 최종적으로 버텍스를 생성하는 코드 bool Terrain: : compute. Vertices(){ HRESULT hr = 0; hr = _device->Create. Vertex. Buffer( _num. Vertices * sizeof(Terrain. Vertex), D 3 DUSAGE_WRITEONLY, Terrain. Vertex: : FVF, D 3 DPOOL_MANAGED, &_vb, 0); if(FAILED(hr)) return false; int start. X = -_width / 2; // 버텍스 생성을 시작할 좌표 int start. Z = _depth / 2; 2009 -1학기 컴퓨터게임(Direct. X) 22
int end. X = _width / 2; int end. Z = -_depth / 2; // 버텍스 생성을 마칠 좌표 // 하나의 버텍스에서 다음 버텍스로 증가할 // 텍스처 좌표의 크기를 계산 float u. Coord. Increment. Size = 1. 0 f / (float)_num. Cells. Per. Row; float v. Coord. Increment. Size = 1. 0 f / (float)_num. Cells. Per. Col; Terrain. Vertex* v = 0; _vb->Lock(0, 0, (void**)&v, 0); int i = 0; 2009 -1학기 컴퓨터게임(Direct. X) 23
v[index] = Terrain. Vertex( (float)x, (float)_heightmap[index], (float)z, (float)j * u. Coord. Increment. Size, (float)i * v. Coord. Increment. Size); j++; // next column } i++; // next row } _vb->Unlock(); return true; } 2009 -1학기 컴퓨터게임(Direct. X) 25
• 사각형(i, j)를 찾기 위한 범용 공식 ∆ ABC = {i·num. Verts. Per. Row+j+1 (i+1) ·num. Verts. Per. Row+J} ∆ CBD = {(i+1)·num. Verts. Per. Row+j i·num. Verts. Per. Row+j+1 (i+1) ·num. Verts. Per. Row+j+1} 2009 -1학기 컴퓨터게임(Direct. X) 27
인덱스를 계산하는 코드 Bool Terrain: : compute. Indices() { HRESULT hr = 0; hr = _device->Create. Index. Buffer( _num. Triangles * 3 * sizeof(WORD), //삼각형당 3개의 인덱스 D 3 DUSAGE_WRITEONLY, D 3 DFMT_INDEX 16, D 3 DPOOLMANAGED, &_ib, 0); 2009 -1학기 컴퓨터게임(Direct. X) 28
for(int j = 0; j < _num. Cells. Per. Row; j++) { indices[base. Index] = i * _num. Verts. Per. Row + j; indices[base. Index + 1] = i * _num. Verts. Per. Row + j + 1; indices[base. Index + 2] = (i+1) * _num. Verts. Per. Row + j; indices[base. Index + 3] = (i+1) * _num. Verts. Per. Row + j; indices[base. Index + 4] = i * _num. Verts. Per. Row + j + 1; indices[base. Index + 5] = (i+1) * _num. Verts. Per. Row + j + 1; base. Index += 6; } } _ib->Unlock(); return true; } 2009 -1학기 컴퓨터게임(Direct. X) 30
bool load. Texture(std: : string file. Name); bool Terrain: : load. Texture(std: : string file. Name) { HRESULT hr = 0; hr = D 3 DXCreate. Texture. From. File( _device, file. Name. c_str(), &_tex); if(FAILED(hr)) return false; return true; } 2009 -1학기 컴퓨터게임(Direct. X) 32
텍스처를 만들어내는 코드 bool Terrain: : gen. Texture(D 3 DXVECTOR 3* direction. To. Light) { HRESULT hr = 0; // 각각의 사각형 셀을 위한 텍셀 int tex. Width = _num. Cells. Per. Row; int tex. Height = _num. Cells. Per. Col; // 빈 텍스처를 만든다. hr = D 3 DXCreate. Texture( _device, tex. Width, tex. Height, 0, // create a complete mipmap chain 0, // usage D 3 DFMT_X 8 R 8 G 8 B 8, // 32 bit XRGB format D 3 DPOOL_MANAGED, &_tex); 2009 -1학기 컴퓨터게임(Direct. X) 35
if(FAILED(hr)) return false; D 3 DSURFACE_DESC texture. Desc; _tex->Get. Level. Desc(0 /*level*/, &texture. Desc); //직접 32비트 픽셀을 이용해 텍스처를 채우므로 //올바른 포맷인지를 먼저 확인 if( texture. Desc. Format != D 3 DFMT_X 8 R 8 G 8 B 8 ) return false; D 3 DLOCKED_RECT locked. Rect; _tex->Lock. Rect(0/*lock top surface*/, &locked. Rect, 0 /* lock entire tex*/, 0/*flags*/); // 텍스처를 채운다. DWORD* image. Data = (DWORD*)locked. Rect. p. Bits; 2009 -1학기 컴퓨터게임(Direct. X) 36
for(int i = 0; i < tex. Height; i++) { for(int j = 0; j < tex. Width; j++) { D 3 DXCOLOR c; // 사각형의 우측 상단 높이를 구한다. float height = (float)get. Heightmap. Entry(i, j) / _height. Scale; // 대응되는 사각형 높이에 따라 텍셀의 컬러를 지정한다. if( (height) < 42. 5 f ) c = d 3 d: : BEACH_SAND; else if( (height) < 85. 0 f ) c = d 3 d: : LIGHT_YELLOW_GREEN; else if( (height) < 127. 5 f ) c = d 3 d: : PUREGREEN; else if( (height) < 170. 0 f ) c = d 3 d: : DARK_YELLOW_GREEN; else if( (height) < 212. 5 f ) c = d 3 d: : DARKBROWN; else c = d 3 d: : WHITE; 2009 -1학기 컴퓨터게임(Direct. X) 37
image. Data[i * locked. Rect. Pitch / 4 + j] = (D 3 DCOLOR)c; } } _tex->Unlock. Rect(0); // 지형을 밝힌다. if(!light. Terrain(direction. To. Light)) { : : Message. Box(0, "light. Terrain() - FAILED", 0, 0); return false; } hr = D 3 DXFilter. Texture( _tex, // 밉맵 레벨을 채울 텍스처 0, // 디폴트 팔레트 0, // 하위 레벨의 원본으로 최상위 레벨을 이용 D 3 DX_DEFAULT); // 디폴트 필터 2009 -1학기 컴퓨터게임(Direct. X) 38
if(FAILED(hr)) { : : Message. Box(0, "D 3 DXFilter. Texture() - FAILED", 0, 0); return false; } return true; } 2009 -1학기 컴퓨터게임(Direct. X) 39
float Terrain: : compute. Shade(int cell. Row, int cell. Col, D 3 DXVECTOR 3* direction. To. Light) { // 사각형의 새 버텍스 높이를 얻는다. float height. A = get. Heightmap. Entry(cell. Row, cell. Col); float height. B = get. Heightmap. Entry(cell. Row, cell. Col+1); float height. C = get. Heightmap. Entry(cell. Row+1, cell. Col); // 사각형의 두 벡터 외적을 이용해 // 법선을 찾아낸다. D 3 DXVECTOR 3 u(_cell. Spacing, height. B - height. A, 0. 0 f); D 3 DXVECTOR 3 v(0. 0 f, height. C - height. A, _cell. Spacing); 2009 -1학기 컴퓨터게임(Direct. X) 49
D 3 DXVECTOR 3 n; D 3 DXVec 3 Cross(&n, &u, &v); D 3 DXVec 3 Normalize(&n, &n); float cosine = D 3 DXVec 3 Dot(&n, direction. To. Light); if(cosine < 0. 0 f) cosine = 0. 0 f; return cosine; } 2009 -1학기 컴퓨터게임(Direct. X) 50
n Terrain: : light. Terrain 메서드의 가장 중요한 부분 DWORD* image. Data = (DWORD*)locked. Rect. p. Bits; for(int i = 0; i < texture. Desc. Height; i++){ for(int j = 0; j < texture. Desc. Width; j++){ int index = i * locked. Rect. Pitch / 4 + j; // 셀의 현재 컬러를 얻는다. D 3 DXCOLOR c( image. Data[index] ); // 셀에 음영을 적용한다. c *= compute. Shade(i, j, direction. To. Light); ; // 음영을 입힌 컬러를 저장한다. image. Data[index] = (D 3 DCOLOR)c; } } 2009 -1학기 컴퓨터게임(Direct. X) 52
Y v 1 y v 2 Z (x, z) v 0 v 3 X 2009 -1학기 컴퓨터게임(Direct. X) 59
Terrain: : get. Height를 완결하는 코드 if(dz < 1. 0 f - dx) // 위쪽 삼각형 ABC { float uy = B - A; // A->B float vy = C - A; // A->C height = A + d 3 d: : Lerp(0. 0 f, uy, dx) + d 3 d: : Lerp(0. 0 f, vy, dz); } else // 아래쪽 삼각형 DCB { float uy = C - D; // D->C float vy = B - D; // D->B height = D + d 3 d: : Lerp(0. 0 f, uy, 1. 0 f - dx) + d 3 d: : Lerp(0. 0 f, vy, 1. 0 f - dz); } return height; } 2009 -1학기 컴퓨터게임(Direct. X) 66
bool Setup() { D 3 DXVECTOR 3 light. Direction(0. 0 f, 1. 0 f, 0. 0 f); The. Terrain = new Terrain(Device, "coast. Mountain 64. raw", 64, 10, 0. 5 f); The. Terrain->gen. Texture(&light. Direction); FPS = new FPSCounter(Device); Device->Set. Sampler. State(0, D 3 DSAMP_MAGFILTER, D 3 DTEXF_LINEAR); Device->Set. Sampler. State(0, D 3 DSAMP_MINFILTER, D 3 DTEXF_LINEAR); Device->Set. Sampler. State(0, D 3 DSAMP_MIPFILTER, D 3 DTEXF_LINEAR); 2009 -1학기 컴퓨터게임(Direct. X) 70
D 3 DXMATRIX proj; D 3 DXMatrix. Perspective. Fov. LH( &proj, D 3 DX_PI * 0. 25 f, // 45 - degree (float)Width / (float)Height, 1. 0 f, 1000. 0 f); Device->Set. Transform(D 3 DTS_PROJECTION, &proj); return true; } void Cleanup() { d 3 d: : Delete<Terrain*>(The. Terrain); d 3 d: : Delete<FPSCounter*>(FPS); } 2009 -1학기 컴퓨터게임(Direct. X) 71
bool Display(float time. Delta) { if( Device ) { if( : : Get. Async. Key. State(VK_UP) & 0 x 8000 f ) The. Camera. walk(100. 0 f * time. Delta); if( : : Get. Async. Key. State(VK_DOWN) & 0 x 8000 f ) The. Camera. walk(-100. 0 f * time. Delta); if( : : Get. Async. Key. State(VK_LEFT) & 0 x 8000 f ) The. Camera. yaw(-1. 0 f * time. Delta); if( : : Get. Async. Key. State(VK_RIGHT) & 0 x 8000 f ) The. Camera. yaw(1. 0 f * time. Delta); 2009 -1학기 컴퓨터게임(Direct. X) 72
if( : : Get. Async. Key. State('N') & 0 x 8000 f ) The. Camera. strafe(-100. 0 f * time. Delta); if( : : Get. Async. Key. State('M') & 0 x 8000 f ) The. Camera. strafe(100. 0 f * time. Delta); if( : : Get. Async. Key. State('W') & 0 x 8000 f ) The. Camera. pitch(1. 0 f * time. Delta); if( : : Get. Async. Key. State('S') & 0 x 8000 f ) The. Camera. pitch(-1. 0 f * time. Delta); 2009 -1학기 컴퓨터게임(Direct. X) 73
D 3 DXVECTOR 3 pos; The. Camera. get. Position(&pos); float height = The. Terrain->get. Height( pos. x, pos. z ); pos. y = height + 5. 0 f; The. Camera. set. Position(&pos); D 3 DXMATRIX V; The. Camera. get. View. Matrix(&V); Device->Set. Transform(D 3 DTS_VIEW, &V); Device->Clear(0, 0, D 3 DCLEAR_TARGET | D 3 DCLEAR_ZBUFFER, 0 xff 000000, 1. 0 f, 0); Device->Begin. Scene(); 2009 -1학기 컴퓨터게임(Direct. X) 74
D 3 DXMATRIX I; D 3 DXMatrix. Identity(&I); if( The. Terrain ) The. Terrain->draw(&I, false); if( FPS ) FPS->render(0 xffff, time. Delta); Device->End. Scene(); Device->Present(0, 0, 0, 0); } return true; } 2009 -1학기 컴퓨터게임(Direct. X) 75
- Slides: 75