⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 field.cpp

📁 QuadTree.rar
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                                                     + 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 + -