示例#1
0
void ManipulatorTerrain::OnEdit( float dt )
{
	assert(m_curEditMode != eTerrainEditMode_None);

	//第0层不能编辑BlendMap,应该从第1层开始
	if(m_curEditMode == eTerrainEditMode_Splat && m_curEditLayer == 0)
		return;

	Ogre::Terrain* pTerrain = ManipulatorSystem.GetScene()->GetTerrain();

	const Vector3 brushPos = m_brush[m_curBrushIndex]->GetPosition();
	Vector3 tsPos;
	pTerrain->getTerrainPosition(brushPos, &tsPos);

	float brushSizeW, brushSizeH;
	m_brush[m_curBrushIndex]->GetDimension(brushSizeW, brushSizeH);
	float worldSize = GetWorldSize();
	brushSizeW /= worldSize;
	brushSizeH /= worldSize;

	int multiplier;
	Ogre::TerrainLayerBlendMap* layer = nullptr;
	if(m_curEditMode == eTerrainEditMode_Deform)
	{
		multiplier = pTerrain->getSize() - 1;
	}
	else
	{
		multiplier = pTerrain->getLayerBlendMapSize();
		layer = pTerrain->getLayerBlendMap(m_curEditLayer);
	}

	long startx = (long)((tsPos.x - brushSizeW / 2) * multiplier);
	long starty = (long)((tsPos.y - brushSizeH / 2) * multiplier);
	long endx = (long)((tsPos.x + brushSizeW / 2) * multiplier);
	long endy= (long)((tsPos.y + brushSizeH / 2) * multiplier);
	startx = max(startx, 0L);
	starty = max(starty, 0L);
	endx = min(endx, (long)multiplier);
	endy = min(endy, (long)multiplier);
	
	for (long y = starty; y <= endy; ++y)
	{
		for (long x = startx; x <= endx; ++x)
		{
			float tsXdist = (x / multiplier) - tsPos.x;
			float tsYdist = (y / multiplier)  - tsPos.y;

			if(m_curEditMode == eTerrainEditMode_Deform)
			{
				float* pData = pTerrain->getHeightData();
				pData[y*GetMapSize()+x] += 100.0f * dt;

			}
			else
			{
				float* pData = layer->getBlendPointer();
				size_t imgY = multiplier - y;
				float newValue = pData[imgY*multiplier+x] + dt;
				newValue = Ogre::Math::Clamp(newValue, 0.0f, 1.0f);
				pData[imgY*multiplier+x] = newValue;
			}
		}
	}
	
	
	if(m_curEditMode == eTerrainEditMode_Deform)
	{
		Ogre::Rect rect(startx, starty, endx, endy);
		pTerrain->dirtyRect(rect);
		pTerrain->update();
	}
	else
	{
		size_t imgStartY = multiplier - starty;
		size_t imgEndY = multiplier - endy;
		Ogre::Rect rect(startx, min(imgStartY,imgEndY), endx, max(imgStartY,imgEndY));

		layer->dirtyRect(rect);
		layer->update();
	}
}
//-----------------------------------------------------------------------------------------
void CTerrainGroupEditor::_splat(CTerrainPageEditor *handle, Ogre::Vector3 &editpos, float timePassed)
{
    Ogre::Rect brushrect, maprect;

    Ogre::Terrain *terrain = static_cast<Ogre::Terrain*>(handle->getHandle());

    int mBlendMapSize = terrain->getLayerBlendMapSize();
    editpos.x *= (float)mBlendMapSize;
    editpos.y = (1.0f - editpos.y) * (float)mBlendMapSize;
    if(!_getEditRect(editpos, brushrect, maprect, mBlendMapSize))
        return;

    int mLayer = 0;

    mLayer = handle->_getLayerID(mTextureDiffuse, mTextureNormal, mEditDirection);

    if(mLayer == -1)
    {
        Ogre::String msg = handle->getName() + " already has the maximum number of supported texture layers.";
        mSystem->DisplayMessageDialog(OTR(msg), DLGTYPE_OK);
        return;
    }
    else if(mLayer == 0)
    {
        Ogre::TerrainLayerBlendMap *mBlendMaps[128];
        float *mBlendDatas[128];
        int mLayerMax = terrain->getLayerCount();

        for(int l = 1;l < mLayerMax;l++)
        {
            mBlendMaps[l] = terrain->getLayerBlendMap(l);
            mBlendDatas[l] = mBlendMaps[l]->getBlendPointer();
        }

        float maxVal;
        int u;
        int num;

        for(u = mLayerMax-1;u > 0;u--)
        {
            mLayer = u;
            maxVal = 0.0f;

            for(int j = maprect.top;j < maprect.bottom;j++)
            {
                int mapPos = (j * mBlendMapSize) + maprect.left;

                for(int i = maprect.left;i < maprect.right;i++)
                {
                    maxVal += mBlendDatas[u][mapPos];
                }
            }

            num = (maprect.top*mBlendMapSize);
            num = (num+maprect.right)-(num+maprect.left);
            if (maxVal > num)
                break;
        }

        if (mLayer == 0)
            return;

        mEditDirection = true;
    }

    handle->_notifyModification(mLayer, maprect);

    int mLayerMax = terrain->getLayerCount();
    Ogre::TerrainLayerBlendMap *mBlendMaps[128];
    float *mBlendDatas[128];

    Ogre::TerrainLayerBlendMap *mCurrentBlendMap = terrain->getLayerBlendMap(mLayer);
    float *mCurrentBlendData = mCurrentBlendMap->getBlendPointer();

    for(int l = mLayer;l < mLayerMax;l++)
    {
        mBlendMaps[l] = terrain->getLayerBlendMap(l);
        mBlendDatas[l] = mBlendMaps[l]->getBlendPointer();
    }

    float mRatio = (float)BRUSH_DATA_SIZE / (float)mBrushSize;
    float brushPos;
    int mapPos;

    int right = brushrect.right;
    brushrect.right = BRUSH_DATA_SIZE - brushrect.left;
    brushrect.left = BRUSH_DATA_SIZE - right;

    float factor = mBrushIntensity * timePassed * 0.2f;
    if(!mEditDirection)
    {
        int u;
        float sum;

        for(int j = maprect.top;j < maprect.bottom;j++)
        {
            brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE;
            brushPos += brushrect.right;

            mapPos = (j * mBlendMapSize) + maprect.left;

            for(int i = maprect.left;i < maprect.right;i++)
            {
                brushPos -= mRatio;

                assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0);
                assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0);

                sum = 0.0f;

                for(u = mLayer + 1;u < mLayerMax;u++)
                    sum += mBlendDatas[u][mapPos];

                float val = mCurrentBlendData[mapPos] + (mBrushData[(int)brushPos] * factor);
                sum += val;

                if(sum > 1.0f)
                {
                    float normfactor = 1.0f / (float)sum;
                    mCurrentBlendData[mapPos] = val * normfactor;
                    for(u = mLayer + 1;u < mLayerMax;u++)
                        mBlendDatas[u][mapPos] *= normfactor;
                }
                else
                    mCurrentBlendData[mapPos] = val;

                ++mapPos;
            }
        }
        for(u = mLayer;u < mLayerMax;u++)
        {
            mBlendMaps[u]->dirtyRect(maprect);
            mBlendMaps[u]->update();
        }
    }
    else
    {
        for(int j = maprect.top;j < maprect.bottom;j++)
        {
            brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE;
            brushPos += brushrect.right;

            mapPos = (j * mBlendMapSize) + maprect.left;

            for(int i = maprect.left;i < maprect.right;i++)
            {
                brushPos -= mRatio;

                assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0);
                assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0);

                float val = mCurrentBlendData[mapPos] - (mBrushData[(int)brushPos] * factor);

                if(val < 0.0f)
                    val = 0.0f;

                mCurrentBlendData[mapPos] = val;
                ++mapPos;
            }
        }
        mCurrentBlendMap->dirtyRect(maprect);
        mCurrentBlendMap->update();
    }
}
示例#3
0
//-----------------------------------------------------------------------------------------
void CTerrainGroupEditor::_splat(CTerrainPageEditor *handle, Ogre::Vector3 &editpos, float timePassed)
{
    Ogre::Rect brushrect, maprect;

    Ogre::Terrain *terrain = static_cast<Ogre::Terrain*>(handle->getHandle());

    int mBlendMapSize = terrain->getLayerBlendMapSize();
    editpos.x *= (float)mBlendMapSize;
    editpos.y = (1.0f - editpos.y) * (float)mBlendMapSize;
    if(!_getEditRect(editpos, brushrect, maprect, mBlendMapSize))
        return;

    int mLayer = 0;

    mLayer = handle->_getLayerID(mTextureDiffuse, mTextureNormal, mEditDirection);

    if(mLayer < 1)
        return;

    handle->_notifyModification(mLayer, maprect);

    int mLayerMax = terrain->getLayerCount();
    Ogre::TerrainLayerBlendMap *mBlendMaps[128];
    float *mBlendDatas[128];

    Ogre::TerrainLayerBlendMap *mCurrentBlendMap = terrain->getLayerBlendMap(mLayer);
    float *mCurrentBlendData = mCurrentBlendMap->getBlendPointer();

    for(int l = mLayer;l < mLayerMax;l++)
    {
        mBlendMaps[l] = terrain->getLayerBlendMap(l);
        mBlendDatas[l] = mBlendMaps[l]->getBlendPointer();
    }

    float mRatio = (float)BRUSH_DATA_SIZE / (float)mBrushSize;
    float brushPos;
    int mapPos;

    int right = brushrect.right;
    brushrect.right = BRUSH_DATA_SIZE - brushrect.left;
    brushrect.left = BRUSH_DATA_SIZE - right;

    float factor = mBrushIntensity * timePassed * 0.2f;
    if(!mEditDirection)
    {
        int u;
        float sum;

        for(int j = maprect.top;j < maprect.bottom;j++)
        {
            brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE;
            brushPos += brushrect.right;

            mapPos = (j * mBlendMapSize) + maprect.left;

            for(int i = maprect.left;i < maprect.right;i++)
            {
                brushPos -= mRatio;

                assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0);
                assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0);

                sum = 0.0f;

                for(u = mLayer + 1;u < mLayerMax;u++)
                    sum += mBlendDatas[u][mapPos];

                float val = mCurrentBlendData[mapPos] + (mBrushData[(int)brushPos] * factor);
                sum += val;

                if(sum > 1.0f)
                {
                    float normfactor = 1.0f / (float)sum;
                    mCurrentBlendData[mapPos] = val * normfactor;
                    for(u = mLayer + 1;u < mLayerMax;u++)
                        mBlendDatas[u][mapPos] *= normfactor;
                }
                else
                    mCurrentBlendData[mapPos] = val;

                ++mapPos;
            }
        }
        for(u = mLayer;u < mLayerMax;u++)
        {
            mBlendMaps[u]->dirtyRect(maprect);
            mBlendMaps[u]->update();
        }
    }
    else
    {
        for(int j = maprect.top;j < maprect.bottom;j++)
        {
            brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE;
            brushPos += brushrect.right;

            mapPos = (j * mBlendMapSize) + maprect.left;

            for(int i = maprect.left;i < maprect.right;i++)
            {
                brushPos -= mRatio;

                assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0);
                assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0);

                float val = mCurrentBlendData[mapPos] - (mBrushData[(int)brushPos] * factor);

                if(val < 0.0f)
                    val = 0.0f;

                mCurrentBlendData[mapPos] = val;
                ++mapPos;
            }
        }
        mCurrentBlendMap->dirtyRect(maprect);
        mCurrentBlendMap->update();
    }
}