Game crashing when attempting to get terrain height

DannyZB

23-07-2008 12:23:40

#include "TerrainController.h"

using namespace Ogre;

TerrainController::TerrainController(){
mTerrainMgr = 0;
mSplatMgr = 0;
}

TerrainController::TerrainController(SceneManager * newSceneManager, unsigned int viewportHeight){
mSceneMgr = newSceneManager;
mTerrainMgr = new ET::TerrainManager(mSceneMgr);
mTerrainMgr->setLODErrorMargin(0, viewportHeight);
mTerrainMgr->setUseLODMorphing(true, 0.2, "morphFactor");

// create a fresh, mid-high terrain for editing
ET::TerrainInfo terrainInfo (129, 129, std::vector<float>(129*129, 0));
// set position and size of the terrain
terrainInfo.setExtents(AxisAlignedBox(-500, 0, -500, 500, 300, 500));
// now render it
mTerrainMgr->createTerrain(terrainInfo);

// create the splatting manager
mSplatMgr = new ET::SplattingManager("ETSplatting", "ET", 128, 128, 3);
// specify number of splatting textures we need to handle
mSplatMgr->setNumTextures(6);

// create a manual lightmap texture
TexturePtr lightmapTex = TextureManager::getSingleton().createManual(
"ETLightmap", "ET", TEX_TYPE_2D, 128, 128, 1, PF_BYTE_RGB);
Image lightmap;
ET::createTerrainLightmap(terrainInfo, lightmap, 128, 128, Vector3(1, -1, 1), ColourValue::White,
ColourValue(0.3, 0.3, 0.3));
lightmapTex->getBuffer(0, 0)->blitFromMemory(lightmap.getPixelBox(0, 0));

// load the terrain material and assign it
MaterialPtr material (MaterialManager::getSingleton().getByName("ETTerrainMaterial"));
mTerrainMgr->setMaterial(material);
}

TerrainController::~TerrainController(){
if (mTerrainMgr)
delete mTerrainMgr;
if (mSplatMgr)
delete mSplatMgr;
}

void TerrainController::createEditBrush()
{
// load the edit brush for terrain editing
Image image;
image.load("brush.png", "ET");
image.resize(16, 16);
mEditBrush = ET::loadBrushFromImage(image);
}

void TerrainController::loadTerrain()
{
// now we revert the process and load the data back from disk
// recreate terrain...
mTerrainMgr->destroyTerrain();
Image image;
image.load("ETterrain.png", "ET");
ET::TerrainInfo info;
ET::loadHeightmapFromImage(info, image);
info.setExtents(AxisAlignedBox(0, 0, 0, 1500, 300, 1500));
mTerrainMgr->createTerrain(info);
mTerrainInfo = & mTerrainMgr->getTerrainInfo();

// now load the splatting maps
for (uint i = 0; i < mSplatMgr->getNumMaps(); ++i)
{
image.load("ETcoverage."+StringConverter::toString(i)+".png", "ET");
mSplatMgr->loadMapFromImage(i, image);
}
// update the lightmap
updateLightmap();
}

void TerrainController::saveTerrain(std::string saveTarget = "default.zip")
{
// just for demonstration, we'll save anything we can
// start with the terrain
Image image;
ET::saveHeightmapToImage(*mTerrainInfo, image);
image.save(saveTarget + "heightmap.png");

// now save the splatting maps
for (uint i = 0; i < mSplatMgr->getNumMaps(); ++i)
{
mSplatMgr->saveMapToImage(i, image);
image.save(saveTarget + "splat" + StringConverter::toString(i)+ ".png");
}

// now the lightmap
Image lightmap;
ET::createTerrainLightmap(*mTerrainInfo, lightmap, 512, 512, Vector3(1, -1, 1), ColourValue(1,1,1),
ColourValue(0.3, 0.3, 0.3));
lightmap.save(saveTarget + "lightmap.png");

// generate a base texture for this terrain (could be used for older hardware instead of splatting)
// create an ImageList of our splatting textures.
ET::ImageList textures (6);
for (int i = 0; i < 6; ++i)
textures[i].load( "splatting" + StringConverter::toString(i)+ ".png", "ET");
// create the base texture
Image baseTexture;
mSplatMgr->createBaseTexture(baseTexture, 512, 512, textures, 20, 20);
baseTexture.save(saveTarget + "basetexture.png");

// finally create a minimap using the lightmap and the generated base texture
Image minimap = ET::createMinimap(baseTexture, lightmap);
minimap.save(saveTarget + "minimap.png");
}

void TerrainController::deformTerrain(float brushIntensity, Vector3 deformPosition )
{
// translate our cursor position to vertex indexes
int x = mTerrainInfo->posToVertexX(deformPosition.x);
int z = mTerrainInfo->posToVertexZ(deformPosition.z);
// now tell the ETM to deform the terrain
mTerrainMgr->deform(x, z, mEditBrush, brushIntensity);
}

void TerrainController::paintTerrain(float brushIntensity , Vector3 paintPosition, int splattingTextureIndex)
{
int x = mTerrainInfo->posToVertexX(paintPosition.x);
int z = mTerrainInfo->posToVertexZ(paintPosition.z);
// now use the splatting manager to update the coverage maps
mSplatMgr->paint(splattingTextureIndex, x, z, mEditBrush, brushIntensity);
}

void TerrainController::updateLightmap()
{
Image lightmap;
ET::createTerrainLightmap(*mTerrainInfo, lightmap, 128, 128, Vector3(1, -1, 1), ColourValue(1,1,1),
ColourValue(0.3, 0.3, 0.3));

// get our dynamic texture and update its contents
TexturePtr tex = TextureManager::getSingleton().getByName("terrainLightmap");
tex->getBuffer(0, 0)->blitFromMemory(lightmap.getPixelBox(0, 0));
}

int TerrainController::getHeightAt(int x, int z)
{
return mTerrainInfo->getHeightAt(x,z);
}

void TerrainController::bridgePoints(int x1, int z1, int x2, int z2, int width)
{
ET::Brush EB = mEditBrush; // Save old brush
////////////////////////////////////////////
std::vector<float> BridgeBrush((x2-x1)*(z2-z1));

float y1 = getHeightAt(x1,z1);
float y2 = 1;//getHeightAt(x2,z2);

float ytozx = (float)(y2-y1) / sqrt( (float)(z1-z2)*(z1-z2) + (x2-x1)*(x2-x1) ); // calculate upwards inclination using pythagoras
float ztox = (float)(z2-z1) / (x2-x1);

for (int ix=0; ix<=x2-x1; ++ix){
for(int iz=0; iz<=z2-z1; ++iz){
if( ( (float)iz/ix <= (ztox+0.3) ) && ( (float)iz/ix >= (ztox-0.3) ))
BridgeBrush[ix + ix*iz] = (y2>y1)? y1 + ytozx*(float)(y2-y1) / sqrt( float(z1-z2)*(z1-z2) + (x2-x1)*(x2-x1) )
:y2 + ytozx*(float)(y1-y2) / sqrt( float(z1-z2)*(z1-z2) + (x2-x1)*(x2-x1) );
}
}

////////////////////////////////////////////
mEditBrush = EB; // Restore original brush
}

void TerrainController::drawGradient(std::vector<float>& image , int x1, int z1, int x2, int z2)
{/*
int pix = color.getRGB();
int dy = y1 - y0;
int dx = x1 - x0;
int stepx, stepy;

if (dy < 0) { dy = -dy; stepy = -raster.width; } else { stepy = raster.width; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1;
dx <<= 1;

y0 *= raster.width;
y1 *= raster.width;
raster.pixel[x0+y0] = pix;
if (dx > dy) {
int fraction = dy - (dx >> 1);
while (x0 != x1) {
if (fraction >= 0) {
y0 += stepy;
fraction -= dx;
}
x0 += stepx;
fraction += dy;
raster.pixel[x0+y0] = pix;
}
} else {
int fraction = dx - (dy >> 1);
while (y0 != y1) {
if (fraction >= 0) {
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
raster.pixel[x0+y0] = pix;
}
}
*/

}


I created this code to seperate the terrain implementation from the rest of the editor..

In this class , the moment I call mTerrainInfo->getHeightAt(x,z);
The Editor control stalls ..

CABAListic

23-07-2008 13:03:10

Just a quick glance, but you do not assign mTerrainInfo in the constructor. Therefore, if you do not call loadTerrain before accessing mTerrainInfo, that variable would be undefined. I would expect a crash in that case, but you never know.

If that's not the problem, might be that the position you give to getHeightAt are out of range. I think ETM catches that, but my memory is failing me here.

Either way, getHeightAt does not include any loops, so there's really no way it could enter an infinite loop...