📄 field.cpp
字号:
+ RandFloat(-fRandRange, fRandRange);
*fMinHeight = min(*fMinHeight, fHeights[imy * m_nBorderSize + imx]);
*fMaxHeight = max(*fMaxHeight, fHeights[imy * m_nBorderSize + imx]);
}
}
// 确定各边中点高度(*方形步骤*)
// 上个步骤已经确定菱形中心点高度,而各边中心点都有菱形中心点高度确定
// 仅设置左、上两个边就可以了,右、下两个边会被下个循环设定,避免重复。
for(int iy = 0; iy < m_nFieldSize; iy += nRectSize)
{
for(int ix = 0; ix < m_nFieldSize; ix += nRectSize)
{
// 右下角
int iex = ix + nRectSize;
int iey = iy + nRectSize;
// 中心
int imx = ix + iHalfRect;
int imy = iy + iHalfRect;
int il = ix - iHalfRect;
int it = iy - iHalfRect;
if(il < 0)il += nRectSize;
if(it < 0)it += nRectSize;
// 确定左边中心高度
fHeights[imy * m_nBorderSize + ix] = (fHeights[imy * m_nBorderSize + il ]
+ fHeights[iy * m_nBorderSize + ix ]
+ fHeights[imy * m_nBorderSize + imx]
+ fHeights[iey * m_nBorderSize + ix ]) / 4
+ RandFloat(-fRandRange, fRandRange);
// 确定上边中心高度
fHeights[iy * m_nBorderSize + imx] = (fHeights[iy * m_nBorderSize + ix ]
+ fHeights[it * m_nBorderSize + imx]
+ fHeights[iy * m_nBorderSize + iex]
+ fHeights[imy * m_nBorderSize + imx]) / 4
+ RandFloat(-fRandRange, fRandRange);
*fMinHeight = min(min(*fMinHeight, fHeights[imy * m_nBorderSize + ix]), fHeights[iy * m_nBorderSize + imx]);
*fMaxHeight = max(max(*fMaxHeight, fHeights[imy * m_nBorderSize + ix]), fHeights[iy * m_nBorderSize + imx]);
// 确定右边中心高度
if(iex == m_nFieldSize)
{
int ir = iex + iHalfRect;
if(ir > m_nFieldSize)ir -= nRectSize;
// 确定右边中心高度
fHeights[imy * m_nBorderSize + iex] = (fHeights[imy * m_nBorderSize + imx]
+ fHeights[iy * m_nBorderSize + iex]
+ fHeights[imy * m_nBorderSize + ir ]
+ fHeights[iey * m_nBorderSize + iex]) / 4
+ RandFloat(-fRandRange, fRandRange);
*fMinHeight = min(*fMinHeight, fHeights[imy * m_nBorderSize + iex]);
*fMaxHeight = max(*fMaxHeight, fHeights[imy * m_nBorderSize + iex]);
}
// 确定下边中心高度
if(iey == m_nFieldSize)
{
int ib = iey + iHalfRect;
if(ib > m_nFieldSize)ib -= nRectSize;
// 确定下边中心高度
fHeights[iey * m_nBorderSize + imx] = (fHeights[iey * m_nBorderSize + ix ]
+ fHeights[imy * m_nBorderSize + imx]
+ fHeights[iey * m_nBorderSize + iex]
+ fHeights[ib * m_nBorderSize + imx]) / 4
+ RandFloat(-fRandRange, fRandRange);
*fMinHeight = min(*fMinHeight, fHeights[iey * m_nBorderSize + imx]);
*fMaxHeight = max(*fMaxHeight, fHeights[iey * m_nBorderSize + imx]);
}
}
}
// 更新迭代
nRectSize /= 2;
fRandRange *= std::pow(2.0f, - fRoughness);
}
}
void CField::SlabHeights(float* fHeights, float* fMinHeight, float* fMaxHeight, float fDegree)
{
for(int i = 0; i < m_nHeightsNum; ++i)
{
if(fHeights[i] <= 0.000001f && fHeights[i] >= -0.000001f)
continue;
if(fHeights[i] > 0.0f)
fHeights[i] *= 1 + fDegree * (*fMaxHeight - fHeights[i]) / fHeights[i];
else
fHeights[i] *= 1 + fDegree * (*fMinHeight - fHeights[i]) / fHeights[i];
}
}
void CField::BlurHeights(float* fHeights, float* fMinHeight, float* fMaxHeight, int nTimes)
{
assert(fHeights);
float* fTempHeights = new float[m_nHeightsNum];
if(!fTempHeights)return;
*fMinHeight = 0.0f;
*fMaxHeight = 0.0f;
for(int i = 0; i < nTimes; ++i)
{
for(int iy = 0; iy < m_nBorderSize; ++iy)
{
for(int ix = 0; ix < m_nBorderSize; ++ix)
{
int il = ix - 1;
if(il < 0)il = ix + 1;
int it = iy - 1;
if(it < 0)it = iy + 1;
int ir = ix + 1;
if(ir == m_nBorderSize)ir = ix - 1;
int ib = iy + 1;
if(ib == m_nBorderSize)ib = iy - 1;
float fAverage = (fHeights[iy * m_nBorderSize + ix]
+fHeights[iy * m_nBorderSize + il]
+fHeights[it * m_nBorderSize + ix]
+fHeights[iy * m_nBorderSize + ir]
+fHeights[ib * m_nBorderSize + ix]) / 5;
fTempHeights[iy * m_nBorderSize + ix] = fAverage;
*fMinHeight = min(*fMinHeight, fAverage);
*fMaxHeight = max(*fMaxHeight, fAverage);
}
}
memcpy(fHeights, fTempHeights, sizeof(float) * m_nHeightsNum);
}
}
void CField::NormalizeHeights(float* fHeights, float fMinHeight, float fMaxHeight)
{
float fRange = fMaxHeight - fMinHeight;
for(int i = 0; i < m_nHeightsNum; ++i)
m_byHeights[i] = unsigned char(255 * (fMaxHeight - fHeights[i]) / fRange);
m_byMinHeight = 0;
m_byMaxHeight = 255;
}
void CField::RandomHeight(float fRoughness /*= 0.5f*/, float fSlab /*= 0.5f*/, int nBlur /*= 2*/)
{
// 分配内存
float* fTempHeights = new float[m_nHeightsNum];
if(!fTempHeights)return;
for(int i = 0; i < m_nHeightsNum; ++i)
fTempHeights[i] = 0.0f;
// 最大、最小高度
float fMinHeight = 0.0f;
float fMaxHeight = 0.0f;
// 开始生成
MakeHeightsPlasma(fTempHeights, &fMinHeight, &fMaxHeight, fRoughness);
SlabHeights(fTempHeights, &fMinHeight, &fMaxHeight, fSlab);
BlurHeights(fTempHeights, &fMinHeight, &fMaxHeight, nBlur);
NormalizeHeights(fTempHeights, fMinHeight, fMaxHeight);
delete[] fTempHeights;
}
void CField::Paint(HDC hdc)
{
if(!m_bValid)
return;
int nImgWidth = m_nBorderSize * 2 + 1;
int nImgHeight = m_nBorderSize;
LPCOLORREF pImgData = new COLORREF[nImgWidth * nImgHeight];
HDC dcMem = CreateCompatibleDC(hdc);
HBITMAP bmpMem = CreateCompatibleBitmap(hdc, nImgWidth, nImgHeight);
SelectObject(dcMem, bmpMem);
// --绘制高度图--
int nRow = 0;
for(int nRow = 0; nRow < m_nBorderSize; ++nRow)
{
for(int i = 0; i < m_nBorderSize; ++i)
{
unsigned char color = GetHeight(i, nRow);
pImgData[nRow * nImgWidth + i] = RGB(255 - color, color, color);
pImgData[nRow * nImgWidth + i + m_nBorderSize + 1] = RGB(255 - color, color, color);
}
}
SetBitmapBits(bmpMem, sizeof(COLORREF) * nImgWidth * nImgHeight, pImgData);
// --绘制"块"--
HPEN penNew = CreatePen(PS_SOLID, 1, 0x00000000);
HPEN penOld = (HPEN)SelectObject(dcMem, penNew);
LOGBRUSH lb;
lb.lbStyle = BS_HOLLOW;
lb.lbColor = 0x00ff0000;
lb.lbHatch = 0;
HBRUSH brsNew = CreateBrushIndirect(&lb);
HBRUSH brsOld = (HBRUSH)SelectObject(dcMem, brsNew);
// 加入第一个"块"
int nCurTileNum = 0;
STile tileNew(m_nFieldSize >> 1, m_nFieldSize >> 1, m_nFieldSize);
m_Tiles[nCurTileNum++] = tileNew;
// 开始分块
int nIndex = 0;
while(nIndex < nCurTileNum)
{
STile* pTile = &m_Tiles[nIndex];
int sx = pTile->m_cx - (pTile->m_size >> 1);
int sz = pTile->m_cz - (pTile->m_size >> 1);
int ex = sx + pTile->m_size;
int ez = sz + pTile->m_size;
// 绘制方块
Rectangle(dcMem, sx + m_nBorderSize + 1, sz, ex + m_nBorderSize + 2, ez + 1);
STile tileChild;
for(int i = 0; i < 4; ++i)
{
// 加入子节点
m_Tiles[nIndex].GetChild(i, &tileChild);
if(!IsTileValid(&tileChild))
continue;
if(m_byQuarters[tileChild.m_cz * m_nBorderSize + tileChild.m_cx])
m_Tiles[nCurTileNum++] = tileChild;
}
++nIndex;
}
// 画到屏幕上
BitBlt(hdc, 0, 0, nImgWidth, nImgHeight, dcMem, 0, 0, SRCCOPY);
SelectObject(dcMem, penOld);
DeleteObject(penNew);
SelectObject(dcMem, brsOld);
DeleteObject(brsNew);
DeleteDC(dcMem);
DeleteObject(bmpMem);
delete[] pImgData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -