在对话框注册函数里添加:
srand(GetTickCount());
img.Create(SIZE, SIZE, 32);
img_smooth.Create(SIZE, SIZE, 32);
img_colored.Create(SIZE, SIZE, 32);
OnBnClickedButton1();
在对话框绘制函数里添加:
CClientDC dc(this);
img.Draw(dc, 0, 0, SIZE - 1, SIZE - 1);
img_smooth.Draw(dc, SIZE + 2, 0, SIZE - 1, SIZE - 1);
img_colored.Draw(dc, SIZE + SIZE + 4, 0, SIZE - 1, SIZE - 1);
加在对话框cpp文件末尾:
void CHeightMapDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
//初始化高度值为-1
memset(HeightMap, -1, sizeof(HeightMap));
SetHeight(0, 0, RandBetween(0, 255));
SetHeight(SIZE - 1, 0, RandBetween(0, 255));
SetHeight(0, SIZE - 1, RandBetween(0, 255));
SetHeight(SIZE - 1, SIZE - 1, RandBetween(0, 255));
DiamondSquare(0, 0, SIZE - 1, SIZE - 1);
//原始
COLORREF *data = (COLORREF*)img.GetBits();
int bitCount = img.GetBPP() / 8;
int pitch = img.GetPitch() / bitCount;
for(int y = 0; y < SIZE; y++)
for(int x = 0; x < SIZE; x++)
data[pitch * y + x] = RGB(HeightMap[x][y], HeightMap[x][y], HeightMap[x][y]);
//平滑,取4点平均值作为左上点高度值
for(int y = 0; y < SIZE - 1; y++)
for(int x = 0; x < SIZE - 1; x++)
HeightMap[x][y] = (HeightMap[x][y] + HeightMap[x + 1][y] + HeightMap[x][y + 1] + HeightMap[x + 1][y + 1]) / 4;
data = (COLORREF*)img_smooth.GetBits();
bitCount = img_smooth.GetBPP() / 8;
pitch = img_smooth.GetPitch() / bitCount;
for(int y = 0; y < SIZE; y++)
for(int x = 0; x < SIZE; x++)
data[pitch * y + x] = RGB(HeightMap[x][y], HeightMap[x][y], HeightMap[x][y]);
//上色
data = (COLORREF*)img_colored.GetBits();
bitCount = img_colored.GetBPP() / 8;
pitch = img_colored.GetPitch() / bitCount;
for(int y = 0; y < SIZE; y++)
for(int x = 0; x < SIZE; x++)
{
double scale;
COLORREF color;
if(HeightMap[x][y] > 170)
{
scale = ((double)HeightMap[x][y] - 171.0f) / (255.0f - 170.0f);
color = RGB((int)(0xCC + (0xFF - 0xCC) * scale), (int)(0xCC + (0xFF - 0xCC) * scale), (int)(0xCC + (0xFF - 0xCC) * scale));
}
else if(HeightMap[x][y] > 85)
{
scale = ((double)HeightMap[x][y] - 86.0f) / (170.0f - 85.0f);
color = RGB((int)(0x52 + (0x5C - 0x52) * scale), (int)(0x97 + (0xB9 - 0x97) * scale), (int)(0xB7 + (0xE5 - 0xB7) * scale));
}
else
{
scale = (double)HeightMap[x][y] / 85.0f;
color = RGB((int)(0x39 + (0x4C - 0x39) * scale), (int)(0xC4 + (0xF1 - 0xC4) * scale), (int)(0x19 + (0x26 - 0x19) * scale));
}
data[pitch * y + x] = color;
}
RedrawWindow();
}
void CHeightMapDlg::DiamondSquare(int x1, int y1, int x2, int y2, int randomRange, double roughness)
{
//中心
int mx = (x1 + x2) / 2, my = (y1 + y2) / 2;
//TRACE("(%d, %d) (%d, %d) (%d, %d) %d %lf\n", x1, y1, x2, y2, mx, my, randomRange, roughness);
int m = (HeightMap[x1][y1] + HeightMap[x2][y1] + HeightMap[x1][y2] + HeightMap[x2][y2]) / 4 + RandBetween(-randomRange, randomRange);
SetHeight(mx, my, m);
int height, height2;
//上中点
height2 = GetHeight(mx, y1 + y1 - my);
//如果缺少1点数据则取3点平均值,可以改为BFS(迭代)保证要用的点已经计算
height = (HeightMap[x1][y1] + HeightMap[x2][y1] + m + (height2 != -1 ? height2 : 0)) / (height2 != -1 ? 4 : 3) + RandBetween(-randomRange, randomRange);
SetHeight(mx, y1, height);
//左中点
height2 = GetHeight(x1 + x1 - mx, my);
height = (HeightMap[x1][y1] + HeightMap[x1][y2] + m + (height2 != -1 ? height2 : 0)) / (height2 != -1 ? 4 : 3) + RandBetween(-randomRange, randomRange);
SetHeight(x1, my, height);
//下中点
height2 = GetHeight(mx, y2 + y2 - my);
height = (HeightMap[x1][y2] + HeightMap[x2][y2] + m + (height2 != -1 ? height2 : 0)) / (height2 != -1 ? 4 : 3) + RandBetween(-randomRange, randomRange);
SetHeight(mx, y2, height);
//右中点
height2 = GetHeight(x2 + x2 - mx, my);
height = (HeightMap[x2][y1] + HeightMap[x2][y2] + m + (height2 != -1 ? height2 : 0)) / (height2 != -1 ? 4 : 3) + RandBetween(-randomRange, randomRange);
SetHeight(x2, my, height);
//左上正方形
if(mx - x1 > 1 || my - y1 > 1)
DiamondSquare(x1, y1, mx, my, (int)(randomRange * roughness), roughness);
//右上正方形
if(x2 - mx > 1 || my - y1 > 1)
DiamondSquare(mx, y1, x2, my, (int)(randomRange * roughness), roughness);
//左下正方形
if(mx - x1 > 1 || y2 - my > 1)
DiamondSquare(x1, my, mx, y2, (int)(randomRange * roughness), roughness);
//右下正方形
if(x2 - mx > 1 || y2 - my > 1)
DiamondSquare(mx, my, x2, y2, (int)(randomRange * roughness), roughness);
}
//返回[min, max]均匀的随机整数
int CHeightMapDlg::RandBetween(int min, int max)
{
return (int)((double)rand()/(RAND_MAX + 1) * (max - min + 1)) + min;
}
魔装少女就是本大爷!——相川步