Ko biết post lên có thừa hay không nhưng mà cứ đưa lên 1 cách tạo heightmap mà tui biết:
Bước 1: Chuẩn bị 1 file BITMAP (trắng đen) thể hiện địa hình dạng 2D
Nhỏ thôi, không cần lớn để không làm chậm quá trình đọc file. Ví dụ (128x128) -> (128 km x 128 km hay m,...).
Tại sao phải là trắng đen, Vì 1 pixel của hình trắng đen có giá trị R = G = B = height;
Màu đen (height = 0) là nơi có địa hình thấp nhất.
Màu trắng (height = 255) là nơi có địa hình cao nhất.
Bước 2: Xây dựng MAP dưới dạng MESH
Code:
typedef struct TagVERTEX {
float x,y,z;
float nx,ny,nz;
D3DCOLOR color;
}VERTEX;
Xây dựng cấu trúc mảng VERTEX aMap[widthBMP][heightBMP].(Cấu trúc này tui cài đặt theo kiểu DX, với OpenGL thì đơn giản hơn nhiều).
- Giải mã format file BMP trên (lưu dạng *.TGA cho dễ giải mã) và duyệt từng PIXEL để lấy giá trị màu -> Height.
Code:
// Xây dựng HEIGHT
for (int i = 0;i<widthBMP;i++){
for (int j = 0;j<heightBMP;i++){
aMap[i][j].x = i * DONVI;
aMap[i][j].y = GetHeight(i,j) * DONVI; // <- GetHeight tự viết
aMap[i][j].z = j * DONVI;
}
}
// Make IndexBuff
int aIndexBuffer[];
int nIndex=0;
/*
(0)---(1)(4)--(5) .........
| / | / | .........
| / | / | .........
| / | / | .........
(2)--(3) (6)--(7) .........
.........
.........
*/
for (i = 0;i<widthBMP-1;i++){
for (j = 0;j<heightBMP-1;j++){
aIndexBuffer[nIndex] = j*widthBMP+ i;
nIndex++;
aIndexBuffer[nIndex] = j*widthBMP+ i + 1;
nIndex++;
aIndexBuffer[nIndex] = (j+1)*widthBMP+ i;
nIndex++;
aIndexBuffer[nIndex] = (j+1)*widthBMP+ i + 1;
nIndex++;
}
}
Như vậy ta đã có 1 mảng aHeightMap. Tuy nhiên, nếu vẽ nó lên thì vẫn chưa hoàn chỉnh vì nó vẫn còn bị bậc thang do GetHeight. Do đó chưa cần phải vội vàng vẽ.
Bước 3: Xử lý SMOOTH
- Có rất nhiều thuật toán xử lý SMOOTH nhưng với dạng HEIGHTMAP này thì có lẽ chỉ nên xử dụng kỹ thuật tính trung bình các height trong MAP.
Ví dụ:
Code:
......
......[1] [2] [3] ......
|
......[4]<-[5]->[6] ......
|
......[7] [8] [9] ......
......
Height[5] = Height[1]
+ Height[2]
+ Height[3]
+ Height[4]
+ Height[5]
+ Height[6]
+ Height[7]
+ Height[8]
+ Height[9]
Height[5] = Height[5] / 9
Code:
void SmoothMap(VERTEX aMap[][heightBMP])
for (int i = 1;i<widthBMP-1;i++){
for (int j = 1;j<heightBMP-1;i++){
aMap[i][j].y += aMap[i-1][j-1].y + aMap[i][j].y + aMap[i][j+1].y +
aMap[i][j-1].y + + aMap[i][j+1].y +
aMap[i+1][j-1].y + aMap[i+1][j].y + aMap[i+1][j+1].y;
aMap[i][j].y = aMap[i][j].y / 9;
// Tính VECTOR PHÁP TUYẾN.....
}
}
}
Gọi chừng 3 -> 5 (Load càng nhiều thì nó càng mượt)lần hàm SmoothMap thì chúng ta sẽ có 1 MAP mượt mà.
Lúc này có lẽ ta nên load lại MAP để tính VECTOR PHÁP TUYẾN... Tuơng đối dễ
Bước cuối cùng:
Có lẽ cũng là bước khó nhất. Là dùng TEXTURE và MULTI_TEXURE (BUMP MAPPING) để trang điểm cho cái MAP dễ thương của mình.
Bookmarks