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);
}
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();
}