Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Codechange] Implemented 'getHeightAt' using Ogre::Terrain source code #880

Merged
merged 1 commit into from May 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
145 changes: 141 additions & 4 deletions source/main/terrain/TerrainGeometryManager.cpp
Expand Up @@ -31,9 +31,11 @@ using namespace Ogre;
#define XZSTR(X,Z) String("[") + TOSTRING(X) + String(",") + TOSTRING(Z) + String("]")

TerrainGeometryManager::TerrainGeometryManager(TerrainManager *terrainManager) :
terrainManager(terrainManager)
, disableCaching(false)
disableCaching(false)
, mHeightData(nullptr)
, mTerrainsImported(false)
, m_is_flat(true)
, terrainManager(terrainManager)
{
}

Expand All @@ -42,6 +44,133 @@ TerrainGeometryManager::~TerrainGeometryManager()
mTerrainGroup->removeAllTerrains();
}

/// @author Ported from OGRE engine, www.ogre3d.org, file OgreTerrain.cpp
void TerrainGeometryManager::getTerrainPositionAlign(Real x, Real y, Real z, Terrain::Alignment align, Vector3* outTSpos)
{
switch(align)
{
case Terrain::ALIGN_X_Z:
outTSpos->x = (x - mBase - mPos.x) / ((mSize - 1) * mScale);
outTSpos->y = (z + mBase - mPos.z) / ((mSize - 1) * -mScale);
outTSpos->z = y;
break;
case Terrain::ALIGN_Y_Z:
outTSpos->x = (z - mBase - mPos.z) / ((mSize - 1) * -mScale);
outTSpos->y = (y + mBase - mPos.y) / ((mSize - 1) * mScale);
outTSpos->z = x;
break;
case Terrain::ALIGN_X_Y:
outTSpos->x = (x - mBase - mPos.x) / ((mSize - 1) * mScale);
outTSpos->y = (y - mBase - mPos.y) / ((mSize - 1) * mScale);
outTSpos->z = z;
break;
};
}

/// @author Ported from OGRE engine, www.ogre3d.org, file OgreTerrain.cpp
float TerrainGeometryManager::getHeightAtPoint(long x, long y)
{
// clamp
x = std::min(x, (long)mSize - 1L);
x = std::max(x, 0L);
y = std::min(y, (long)mSize - 1L);
y = std::max(y, 0L);

return mHeightData[y * mSize + x];
}

/// @author Ported from OGRE engine, www.ogre3d.org, file OgreTerrain.cpp
float TerrainGeometryManager::getHeightAtTerrainPosition(Real x, Real y)
{
// get left / bottom points (rounded down)
Real factor = (Real)mSize - 1.0f;
Real invFactor = 1.0f / factor;

long startX = static_cast<long>(x * factor);
long startY = static_cast<long>(y * factor);
long endX = startX + 1;
long endY = startY + 1;

// now get points in terrain space (effectively rounding them to boundaries)
// note that we do not clamp! We need a valid plane
Real startXTS = startX * invFactor;
Real startYTS = startY * invFactor;
Real endXTS = endX * invFactor;
Real endYTS = endY * invFactor;

// now clamp
endX = std::min(endX, (long)mSize-1);
endY = std::min(endY, (long)mSize-1);

// get parametric from start coord to next point
Real xParam = (x - startXTS) / invFactor;
Real yParam = (y - startYTS) / invFactor;


/* For even / odd tri strip rows, triangles are this shape:
even odd
3---2 3---2
| / | | \ |
0---1 0---1
*/

// Build all 4 positions in terrain space, using point-sampled height
Vector3 v0 (startXTS, startYTS, getHeightAtPoint(startX, startY));
Vector3 v1 (endXTS, startYTS, getHeightAtPoint(endX, startY));
Vector3 v2 (endXTS, endYTS, getHeightAtPoint(endX, endY));
Vector3 v3 (startXTS, endYTS, getHeightAtPoint(startX, endY));
// define this plane in terrain space
Plane plane;
if (startY % 2)
{
// odd row
bool secondTri = ((1.0 - yParam) > xParam);
if (secondTri)
plane.redefine(v0, v1, v3);
else
plane.redefine(v1, v2, v3);
}
else
{
// even row
bool secondTri = (yParam > xParam);
if (secondTri)
plane.redefine(v0, v2, v3);
else
plane.redefine(v0, v1, v2);
}

// Solve plane equation for z
return (-plane.normal.x * x
-plane.normal.y * y
- plane.d) / plane.normal.z;
}

/// @author Ported from OGRE engine, www.ogre3d.org, file OgreTerrain.cpp
float TerrainGeometryManager::getHeightAtWorldPosition(float x, float z)
{
Vector3 terrPos;
getTerrainPositionAlign(x, 0.0f, z, mAlign, &terrPos);
return getHeightAtTerrainPosition(terrPos.x, terrPos.y);
}

float TerrainGeometryManager::getHeightAt(float x, float z)
{
if (m_is_flat)
return 0.0f;
else
return getHeightAtWorldPosition(x, z);
}

Ogre::Vector3 TerrainGeometryManager::getNormalAt(float x, float y, float z, float precision)
{
Ogre::Vector3 left(-precision, getHeightAt(x - precision, z) - y, 0.0f);
Ogre::Vector3 down(0.0f, getHeightAt(x, z + precision) - y, precision);
down = left.crossProduct(down);
down.normalise();
return down;
}

void TerrainGeometryManager::loadOgreTerrainConfig(String filename)
{
String ext;
Expand Down Expand Up @@ -136,7 +265,7 @@ void TerrainGeometryManager::initTerrain()

pageConfigFormat = m_terrain_config.GetString("PageFileFormat", baseName + "-page-{X}-{Z}.otc");

bool is_flat = m_terrain_config.GetBool("Flat", false);
m_is_flat = m_terrain_config.GetBool("Flat", false);

terrainPos = Vector3(mapsizex / 2.0f, 0.0f, mapsizez / 2.0f);

Expand All @@ -154,7 +283,7 @@ void TerrainGeometryManager::initTerrain()
for (long z = pageMinZ; z <= pageMaxZ; ++z)
{
LoadingWindow::getSingleton().setProgress(23, _L("preparing terrain page ") + XZSTR(x,z));
defineTerrain(x, z, is_flat);
defineTerrain(x, z, m_is_flat);
LoadingWindow::getSingleton().setProgress(23, _L("loading terrain page ") + XZSTR(x,z));

/*
Expand All @@ -169,6 +298,14 @@ void TerrainGeometryManager::initTerrain()
LoadingWindow::getSingleton().setProgress(23, _L("loading terrain pages"));
mTerrainGroup->loadAllTerrains(true);

Terrain* terrain = mTerrainGroup->getTerrain(0, 0);
mHeightData = terrain->getHeightData();
mAlign = terrain->getAlignment();
mSize = terrain->getSize();
mWorldSize = terrain->getWorldSize();
mBase = -mWorldSize * 0.5f;
mScale = mWorldSize / (Real)(mSize - 1);
mPos = terrain->getPosition();

// update the blend maps
if (mTerrainsImported)
Expand Down
32 changes: 18 additions & 14 deletions source/main/terrain/TerrainGeometryManager.h
Expand Up @@ -42,22 +42,15 @@ class TerrainGeometryManager : public IManager, public IHeightFinder

void loadOgreTerrainConfig(Ogre::String filename);

inline Ogre::TerrainGroup *getTerrainGroup() { return mTerrainGroup; };
Ogre::TerrainGroup *getTerrainGroup() { return mTerrainGroup; };

float getHeightAt(float x, float z);
float getHeightAtPoint(long x, long z);
float getHeightAtTerrainPosition(float x, float z);
float getHeightAtWorldPosition(float x, float z);
void getTerrainPositionAlign(Ogre::Real x, Ogre::Real y, Ogre::Real z, Ogre::Terrain::Alignment align, Ogre::Vector3* outWSpos);

inline float getHeightAt(float x, float z)
{
return mTerrainGroup->getHeightAtWorldPosition(x, 1000, z);
}

inline Ogre::Vector3 getNormalAt(float x, float y, float z, float precision = 0.1f)
{
Ogre::Vector3 left(-precision, getHeightAt(x - precision, z) - y, 0.0f);
Ogre::Vector3 down(0.0f, getHeightAt(x, z + precision) - y, precision);
down = left.crossProduct(down);
down.normalise();
return down;
}
Ogre::Vector3 getNormalAt(float x, float y, float z, float precision = 0.1f);

Ogre::String getCompositeMaterialName();

Expand Down Expand Up @@ -87,6 +80,17 @@ class TerrainGeometryManager : public IManager, public IHeightFinder

Ogre::Vector3 terrainPos;

bool m_is_flat;
Ogre::Terrain* mTerrain;

Ogre::Terrain::Alignment mAlign;
Ogre::Vector3 mPos;
Ogre::Real mBase;
Ogre::Real mScale;
Ogre::uint16 mSize;
Ogre::Real mWorldSize;
float* mHeightData;

// terrain engine specific
Ogre::TerrainGroup *mTerrainGroup;
Ogre::TerrainPaging* mTerrainPaging;
Expand Down