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 ..