fix a bug in terrain getHeight for some edge cases
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9275 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
e3ed779fc9
commit
64b736f2e9
@ -929,6 +929,61 @@ public class LODGeomap extends GeoMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the two triangles that make up the grid section at the specified point.
|
||||||
|
*
|
||||||
|
* For every grid space there are two triangles oriented like this:
|
||||||
|
* *----*
|
||||||
|
* |a / |
|
||||||
|
* | / b|
|
||||||
|
* *----*
|
||||||
|
* The corners of the mesh have differently oriented triangles. The two
|
||||||
|
* corners that we have to special-case are the top left and bottom right
|
||||||
|
* corners. They are oriented inversely:
|
||||||
|
* *----*
|
||||||
|
* | \ b|
|
||||||
|
* |a \ |
|
||||||
|
* *----*
|
||||||
|
*/
|
||||||
|
protected float getHeight(int x, int z, float xm, float zm) {
|
||||||
|
|
||||||
|
int index = findClosestHeightIndex(x, z);
|
||||||
|
if (index < 0) {
|
||||||
|
return Float.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
float h1 = hdata[index]; // top left
|
||||||
|
float h2 = hdata[index + 1]; // top right
|
||||||
|
float h3 = hdata[index + width]; // bottom left
|
||||||
|
float h4 = hdata[index + width + 1]; // bottom right
|
||||||
|
|
||||||
|
//float dix = (x % 1f) ;
|
||||||
|
//float diz = (z % 1f) ;
|
||||||
|
|
||||||
|
if ((x == 0 && z == 0) || (x == width - 2 && z == width - 2)) {
|
||||||
|
// top left or bottom right grid point
|
||||||
|
/* 1----2
|
||||||
|
* | \ b|
|
||||||
|
* |a \ |
|
||||||
|
* 3----4 */
|
||||||
|
if (xm<zm)
|
||||||
|
return h1 + xm*(h4-h3) + zm*(h3-h1);
|
||||||
|
else
|
||||||
|
return h1 + xm*(h2-h1) + zm*(h4-h2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// all other grid points
|
||||||
|
/* 1----2
|
||||||
|
* |a / |
|
||||||
|
* | / b|
|
||||||
|
* 3----4 */
|
||||||
|
if (xm<(1-zm))
|
||||||
|
return h3 + (xm)*(h2-h1) + (1f-zm)*(h1-h3);
|
||||||
|
else
|
||||||
|
return h3 + (xm)*(h4-h3) + (1f-zm)*(h2-h4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a representation of the underlying triangle at the given point,
|
* Get a representation of the underlying triangle at the given point,
|
||||||
* translated to world coordinates.
|
* translated to world coordinates.
|
||||||
@ -1010,7 +1065,7 @@ public class LODGeomap extends GeoMap {
|
|||||||
float h4 = hdata[index + width + 1]; // bottom right
|
float h4 = hdata[index + width + 1]; // bottom right
|
||||||
|
|
||||||
|
|
||||||
if ((gridX == 0 && gridY == 0) || (gridX == width - 1 && gridY == width - 1)) {
|
if ((gridX == 0 && gridY == 0) || (gridX == width - 2 && gridY == width - 2)) {
|
||||||
// top left or bottom right grid point
|
// top left or bottom right grid point
|
||||||
t.get(0).x = (gridX);
|
t.get(0).x = (gridX);
|
||||||
t.get(0).y = (h1);
|
t.get(0).y = (h1);
|
||||||
|
@ -590,6 +590,10 @@ public class TerrainPatch extends Geometry {
|
|||||||
return normal;
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected float getHeight(int x, int z, float xm, float zm) {
|
||||||
|
return geomap.getHeight(x,z,xm,zm);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the mesh (sets it static) to improve performance.
|
* Locks the mesh (sets it static) to improve performance.
|
||||||
* But it it not editable then. Set unlock to make it editable.
|
* But it it not editable then. Set unlock to make it editable.
|
||||||
|
@ -922,45 +922,89 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for searching for a child and keeping
|
||||||
|
* track of its quadrant
|
||||||
|
*/
|
||||||
|
private class QuadrantChild {
|
||||||
|
int col;
|
||||||
|
int row;
|
||||||
|
Spatial child;
|
||||||
|
|
||||||
|
QuadrantChild(int col, int row, Spatial child) {
|
||||||
|
this.col = col;
|
||||||
|
this.row = row;
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuadrantChild findMatchingChild(int x, int z) {
|
||||||
|
int quad = findQuadrant(x, z);
|
||||||
|
int split = (size + 1) >> 1;
|
||||||
|
if (children != null) {
|
||||||
|
for (int i = children.size(); --i >= 0;) {
|
||||||
|
Spatial spat = children.get(i);
|
||||||
|
int col = x;
|
||||||
|
int row = z;
|
||||||
|
boolean match = false;
|
||||||
|
|
||||||
|
// get the childs quadrant
|
||||||
|
int childQuadrant = 0;
|
||||||
|
if (spat instanceof TerrainQuad) {
|
||||||
|
childQuadrant = ((TerrainQuad) spat).getQuadrant();
|
||||||
|
} else if (spat instanceof TerrainPatch) {
|
||||||
|
childQuadrant = ((TerrainPatch) spat).getQuadrant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childQuadrant == 1 && (quad & 1) != 0) {
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 2 && (quad & 2) != 0) {
|
||||||
|
row = z - split + 1;
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 3 && (quad & 4) != 0) {
|
||||||
|
col = x - split + 1;
|
||||||
|
match = true;
|
||||||
|
} else if (childQuadrant == 4 && (quad & 8) != 0) {
|
||||||
|
col = x - split + 1;
|
||||||
|
row = z - split + 1;
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
return new QuadrantChild(col, row, spat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the interpolated height of the terrain at the specified point.
|
||||||
|
* @param xz the location to get the height for
|
||||||
|
* @return Float.NAN if the value does not exist, or the coordinates are outside of the terrain
|
||||||
|
*/
|
||||||
public float getHeight(Vector2f xz) {
|
public float getHeight(Vector2f xz) {
|
||||||
// offset
|
// offset
|
||||||
float x = (float)(((xz.x - getWorldTranslation().x) / getWorldScale().x) + (float)totalSize / 2f);
|
float x = (float)(((xz.x - getWorldTranslation().x) / getWorldScale().x) + (float)(totalSize-1) / 2f);
|
||||||
float z = (float)(((xz.y - getWorldTranslation().z) / getWorldScale().z) + (float)totalSize / 2f);
|
float z = (float)(((xz.y - getWorldTranslation().z) / getWorldScale().z) + (float)(totalSize-1) / 2f);
|
||||||
float height = getHeight(x, z);
|
float height = getHeight((int)x, (int)z, (x%1f), (z%1f));
|
||||||
height *= getWorldScale().y;
|
height *= getWorldScale().y;
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gets an interpolated value at the specified point
|
* gets an interpolated value at the specified point
|
||||||
* @param x coordinate translated into actual (positive) terrain grid coordinates
|
|
||||||
* @param y coordinate translated into actual (positive) terrain grid coordinates
|
|
||||||
*/
|
*/
|
||||||
protected float getHeight(float x, float z) {
|
protected float getHeight(int x, int z, float xm, float zm) {
|
||||||
x-=0.5f;
|
|
||||||
z-=0.5f;
|
QuadrantChild match = findMatchingChild(x,z);
|
||||||
float col = FastMath.floor(x);
|
if (match != null) {
|
||||||
float row = FastMath.floor(z);
|
if (match.child instanceof TerrainQuad) {
|
||||||
boolean onX = false;
|
return ((TerrainQuad) match.child).getHeight(match.col, match.row, xm, zm);
|
||||||
if(1 - (x - col)-(z - row) < 0) // what triangle to interpolate on
|
} else if (match.child instanceof TerrainPatch) {
|
||||||
onX = true;
|
return ((TerrainPatch) match.child).getHeight(match.col, match.row, xm, zm);
|
||||||
// v1--v2 ^
|
|
||||||
// | / | |
|
|
||||||
// | / | |
|
|
||||||
// v3--v4 | Z
|
|
||||||
// |
|
|
||||||
// <-------Y
|
|
||||||
// X
|
|
||||||
float v1 = getHeightmapHeight((int) FastMath.ceil(x), (int) FastMath.ceil(z));
|
|
||||||
float v2 = getHeightmapHeight((int) FastMath.floor(x), (int) FastMath.ceil(z));
|
|
||||||
float v3 = getHeightmapHeight((int) FastMath.ceil(x), (int) FastMath.floor(z));
|
|
||||||
float v4 = getHeightmapHeight((int) FastMath.floor(x), (int) FastMath.floor(z));
|
|
||||||
if (onX) {
|
|
||||||
return ((x - col) + (z - row) - 1f)*v1 + (1f - (x - col))*v2 + (1f - (z - row))*v3;
|
|
||||||
} else {
|
|
||||||
return (1f - (x - col) - (z - row))*v4 + (z - row)*v2 + (x - col)*v3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return Float.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector3f getNormal(Vector2f xz) {
|
public Vector3f getNormal(Vector2f xz) {
|
||||||
// offset
|
// offset
|
||||||
|
Loading…
x
Reference in New Issue
Block a user