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,...).
![](http://i77.photobucket.com/albums/j72/thanhduongnt/TextureMap.jpg)
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ẽ.
![](http://i77.photobucket.com/albums/j72/thanhduongnt/HeightMap_NoSmooth.png)
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ễ
![](http://i77.photobucket.com/albums/j72/thanhduongnt/HeightMap1_LINE.jpg)
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