Undo in terrain modification

Problems building or running the engine, queries about how to use features etc.
User avatar
icaro56
Greenskin
Posts: 105
Joined: Sun Feb 15, 2009 2:03 am
Location: Belo Horizonte, MG, BRA
x 1

Undo in terrain modification

Post by icaro56 »

Hi,

I am with a lack of precision in my terrain modification in the version 64 bits. In 32 bits works.

When I modify the terrain, save the points in a vector and then I use the Undo function, the terrain stay with failures.

Modify Function

Code: Select all

typedef std::vector<Ogre::Vector3> MemList;
MemList mUndo;

void PolygonDisplacement::modify(bool show  )
    {
        if(mPoints.size() == 0)
            return;

        const int iMapWidth = (int)mHeightmap->getWidth(); // 8193

		const float fMapWidth = (float)(iMapWidth - 1); // 8193 - 1 = 8192

		const float fMapScale = fMapWidth / mfWidth; // 8192/32000 = 0.256

		const float fInvMapScale = 1.0f / fMapScale; // 1.0f/  0.256 = 3.90625

		const float fHalfWidth = mfWidth * 0.5; // 16000

		const float fMax = 65535.0f * mfScale; //65535.0 * 2248.0 = 147.322.680

		const float fInvScale = (1.0f / 65535.0f) * mfScale; // = 2248.0

        calculateMinMax();

		Ogre::Vector2 vMin = mMin;
		Ogre::Vector2 vMax = mMax;

		// [-half,+half] -> [0,width]
		vMin += fHalfWidth;
		vMax += fHalfWidth;

		// [0,width] -> [0,mapPixels]
		vMin *= fMapScale;
		vMax *= fMapScale;

		// Grab the pixel range inside the brush rect
		Vec2D<int> iMin(Math::ICeil(vMin.x),Math::ICeil(vMin.y));
		Vec2D<int> iMax(Math::IFloor(vMax.x),Math::IFloor(vMax.y));

		// Make sure it doesn't go out of bounds
		iMin.x = std::min(std::max(iMin.x,0),iMapWidth-1);
		iMin.y = std::min(std::max(iMin.y,0),iMapWidth-1);
		iMax.x = std::min(std::max(iMax.x,0),iMapWidth-1);
		iMax.y = std::min(std::max(iMax.y,0),iMapWidth-1);

        // Get the world position of pixels
		vMin = Ogre::Vector2(iMin.x,iMin.y) * fInvMapScale;
		vMax = Ogre::Vector2(iMax.x,iMax.y) * fInvMapScale;

		vMin -= fHalfWidth;
		vMax -= fHalfWidth;

		// Terrain position delta
		const float fDelta = mfWidth / float(iMapWidth-1);

		Ogre::Vector2 vTerrainPos = vMin;
		float fTerrainStartX = vMin.x;

        // Get pointer to the heightmap data
		HEIGHTMAPTYPE* pData = mHeightmap->getData();
		float height = 0.0f;

		mUndo.clear();
		mRedo.clear();

        Ogre::uchar* pImgData = imgMaskAlpha.getData();

        //Loop
		for (int y=iMin.y;y<=iMax.y;y++)
		{
			vTerrainPos.x = fTerrainStartX;
			for (int x=iMin.x;x<iMax.x;x++)
			{
				if ( inside(Ogre::Vector2(vTerrainPos.x,vTerrainPos.y)))
				{

					height = getHeight(Ogre::Vector2(vTerrainPos.x,vTerrainPos.y));

                    mUndo.push_back(Ogre::Vector3(x, pData[x + y * iMapWidth], y));

					pData[x + y * iMapWidth] = PACK_HEIGHT(std::min(std::max(height / fInvScale,0.0f),65535.0f));

                    if( show )
                    {
                        int _x = ((float)x / iMapWidth) * mImageWidth;
                        int _y = ((float)y / iMapWidth) * mImageWidth;
                        int iMaskPos = mImageWidth * _y * 4 + (_x * 4 - 1);
                        pImgData[ iMaskPos ] = 200; //A
                        pImgData[ iMaskPos - 1] = 50; //R
                        pImgData[ iMaskPos - 2] = 50; //G
                        pImgData[ iMaskPos - 3] = 200; //B
                    }
				}
				vTerrainPos.x += fDelta;
			}
            vTerrainPos.y += fDelta;
		}

        clearVertices();
        mPoints.clear();
        mHeight.clear();
        mManualObject->clear();
        if( show)
        {
            texMaskAlpha->unload();
            texMaskAlpha->loadImage(imgMaskAlpha);
        }
        mTerrain->getRootNode()->checkModifier(this);

    }

Undo function

Code: Select all

void PolygonDisplacement::undo(bool show)
    {
        const int iMapWidth = (int)mHeightmap->getWidth();
        HEIGHTMAPTYPE* pData = mHeightmap->getData();

        Ogre::uchar* pImgData = imgMaskAlpha.getData();

        MemList::iterator itr = mUndo.begin();
        for (itr; itr != mUndo.end() ; ++itr)
        {
            mRedo.push_back(Ogre::Vector3((*itr).x, pData[int((*itr).x + (*itr).z * iMapWidth)], (*itr).z));
            pData[int((*itr).x + (*itr).z * iMapWidth)] = (*itr).y;

            int _x = ((*itr).x / iMapWidth) * mImageWidth;
            int _y = ((*itr).z / iMapWidth) * mImageWidth;
            int iMaskPos = mImageWidth * _y * 4 + (_x * 4 - 1);
            pImgData[ iMaskPos ] = 0; //A
            pImgData[ iMaskPos - 1] = 0; //R
            pImgData[ iMaskPos - 2] = 0; //G
            pImgData[ iMaskPos - 3] = 0; //B

        }

        if( show )
        {
            imgMaskAlpha.loadDynamicImage(pImgData, mImageWidth, mImageWidth, 1, Ogre::PF_A8R8G8B8 );
            texMaskAlpha->unload();
            texMaskAlpha->loadImage(imgMaskAlpha);
        }
        mUndo.clear();
    }
Could anyone help me?I am with a loss of data in 64 bits.
You do not have the required permissions to view the files attached to this post.
Ícaro Motta
User avatar
icaro56
Greenskin
Posts: 105
Joined: Sun Feb 15, 2009 2:03 am
Location: Belo Horizonte, MG, BRA
x 1

Re: Undo in terrain modification

Post by icaro56 »

No one ever had a similar error?
Ícaro Motta
User avatar
icaro56
Greenskin
Posts: 105
Joined: Sun Feb 15, 2009 2:03 am
Location: Belo Horizonte, MG, BRA
x 1

[SOLVED]Re: Undo in terrain modification

Post by icaro56 »

I change the data structure and works.

Code: Select all

struct TerrainModification
{
	int x;
	int y;
	HEIGHTMAPTYPE data;

	TerrainModification(int x1, int y1, HEIGHTMAPTYPE data1)
	{
		x = x1;
		y = y1;
		data = data1;
	}
};

typedef std::vector<TerrainModification> ModifyList;

void PolygonDisplacement::modify(bool show  )
    {
        if(mPoints.size() == 0)
            return;

        const int iMapWidth = (int)mHeightmap->getWidth(); // 8193

		const float fMapWidth = (float)(iMapWidth - 1); // 8193 - 1 = 8192

		const float fMapScale = fMapWidth / mfWidth; // 8192/32000 = 0.256

		const float fInvMapScale = 1.0f / fMapScale; // 1.0f/  0.256 = 3.90625

		const float fHalfWidth = mfWidth * 0.5f; // 16000

		const float fMax = MAX_INT * mfScale; //65535.0 * 2248.0 = 147.322.680

		const float fInvScale = (1.0f / MAX_INT) * mfScale; // = 2248.0

        calculateMinMax();

		Ogre::Vector2 vMin = mMin;
		Ogre::Vector2 vMax = mMax;

		// [-half,+half] -> [0,width]
		vMin += fHalfWidth;
		vMax += fHalfWidth;

		// [0,width] -> [0,mapPixels]
		vMin *= fMapScale;
		vMax *= fMapScale;

		// Grab the pixel range inside the brush rect
		Vec2D<int> iMin(Math::ICeil(vMin.x),Math::ICeil(vMin.y));
		Vec2D<int> iMax(Math::IFloor(vMax.x),Math::IFloor(vMax.y));

		// Make sure it doesn't go out of bounds
		iMin.x = std::min(std::max(iMin.x,0),iMapWidth-1);
		iMin.y = std::min(std::max(iMin.y,0),iMapWidth-1);
		iMax.x = std::min(std::max(iMax.x,0),iMapWidth-1);
		iMax.y = std::min(std::max(iMax.y,0),iMapWidth-1);

        // Get the world position of pixels
		vMin = Ogre::Vector2(iMin.x,iMin.y) * fInvMapScale;
		vMax = Ogre::Vector2(iMax.x,iMax.y) * fInvMapScale;

		vMin -= fHalfWidth;
		vMax -= fHalfWidth;

		// Terrain position delta
		const float fDelta = mfWidth / float(iMapWidth-1);

		Ogre::Vector2 vTerrainPos = vMin;
		float fTerrainStartX = vMin.x;

        // Get pointer to the heightmap data
		HEIGHTMAPTYPE* pData = mHeightmap->getData(); 
		float height = 0.0f;

		mUndo.clear();
		mRedo.clear();

        Ogre::uchar* pImgData = imgMaskAlpha.getData();

        //Loop
		for (int y=iMin.y;y<=iMax.y;y++)
		{
			vTerrainPos.x = fTerrainStartX;
			for (int x=iMin.x;x<iMax.x;x++)
			{
				if ( inside(Ogre::Vector2(vTerrainPos.x,vTerrainPos.y)))
				{

					height = getHeight(Ogre::Vector2(vTerrainPos.x,vTerrainPos.y));

                    //mUndo.push_back(Ogre::Vector3(x, UNPACK_HEIGHT(pData[x + y * iMapWidth]), y));
					mUndo.push_back(TerrainModification(x, y, pData[x + y * iMapWidth]));

					pData[x + y * iMapWidth] = PACK_HEIGHT(std::min(std::max(height / fInvScale,0.0f),MAX_INT));

                    if( show )
                    {
                        int _x = ((float)x / iMapWidth) * mImageWidth;
                        int _y = ((float)y / iMapWidth) * mImageWidth;
                        int iMaskPos = mImageWidth * _y * 4 + (_x * 4 - 1);
                        pImgData[ iMaskPos ] = 200; //A
                        pImgData[ iMaskPos - 1] = 50; //R
                        pImgData[ iMaskPos - 2] = 50; //G
                        pImgData[ iMaskPos - 3] = 200; //B
                    }
				}
				vTerrainPos.x += fDelta;
			}
            vTerrainPos.y += fDelta;
		}

        clearVertices();
        mPoints.clear();
        mHeight.clear();
        mManualObject->clear();
        if( show)
        {
            texMaskAlpha->unload();
            texMaskAlpha->loadImage(imgMaskAlpha);
        }
        mTerrain->getRootNode()->checkModifier(this);

    }

//////////////////////////////////////////////////////////////////////////////////////////////
    void PolygonDisplacement::undo(bool show)
    {
        const int iMapWidth = (int)mHeightmap->getWidth();
        HEIGHTMAPTYPE* pData = mHeightmap->getData();

        Ogre::uchar* pImgData = imgMaskAlpha.getData();

		ModifyList::iterator itr = mUndo.begin();
		for (itr; itr != mUndo.end() ; ++itr)
        {
            mRedo.push_back(TerrainModification((*itr).x, (*itr).y, pData[(*itr).x + (*itr).y * iMapWidth]));
            pData[(*itr).x + (*itr).y * iMapWidth] = (*itr).data;

            int _x = ((*itr).x / iMapWidth) * mImageWidth;
            int _y = ((*itr).y / iMapWidth) * mImageWidth;
            int iMaskPos = mImageWidth * _y * 4 + (_x * 4 - 1);
            pImgData[ iMaskPos ] = 0; //A
            pImgData[ iMaskPos - 1] = 0; //R
            pImgData[ iMaskPos - 2] = 0; //G
            pImgData[ iMaskPos - 3] = 0; //B

        }

        /*MemList::iterator itr = mUndo.begin();
        for (itr; itr != mUndo.end() ; ++itr)
        {
            mRedo.push_back(Ogre::Vector3((*itr).x, UNPACK_HEIGHT(pData[int((*itr).x + (*itr).z * iMapWidth)]), (*itr).z));
            pData[int((*itr).x + (*itr).z * iMapWidth)] = PACK_HEIGHT((*itr).y);

            int _x = ((*itr).x / iMapWidth) * mImageWidth;
            int _y = ((*itr).z / iMapWidth) * mImageWidth;
            int iMaskPos = mImageWidth * _y * 4 + (_x * 4 - 1);
            pImgData[ iMaskPos ] = 0; //A
            pImgData[ iMaskPos - 1] = 0; //R
            pImgData[ iMaskPos - 2] = 0; //G
            pImgData[ iMaskPos - 3] = 0; //B

        }*/

        if( show )
        {
            imgMaskAlpha.loadDynamicImage(pImgData, mImageWidth, mImageWidth, 1, Ogre::PF_A8R8G8B8 );
            texMaskAlpha->unload();
            texMaskAlpha->loadImage(imgMaskAlpha);
        }
        mUndo.clear();
		mTerrain->getRootNode()->checkModifier(this);
    } 

Ícaro Motta