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,
|
||||
* translated to world coordinates.
|
||||
@ -1010,7 +1065,7 @@ public class LODGeomap extends GeoMap {
|
||||
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
|
||||
t.get(0).x = (gridX);
|
||||
t.get(0).y = (h1);
|
||||
|
@ -590,6 +590,10 @@ public class TerrainPatch extends Geometry {
|
||||
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.
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// offset
|
||||
float x = (float)(((xz.x - getWorldTranslation().x) / getWorldScale().x) + (float)totalSize / 2f);
|
||||
float z = (float)(((xz.y - getWorldTranslation().z) / getWorldScale().z) + (float)totalSize / 2f);
|
||||
float height = getHeight(x, z);
|
||||
float x = (float)(((xz.x - getWorldTranslation().x) / getWorldScale().x) + (float)(totalSize-1) / 2f);
|
||||
float z = (float)(((xz.y - getWorldTranslation().z) / getWorldScale().z) + (float)(totalSize-1) / 2f);
|
||||
float height = getHeight((int)x, (int)z, (x%1f), (z%1f));
|
||||
height *= getWorldScale().y;
|
||||
return height;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
x-=0.5f;
|
||||
z-=0.5f;
|
||||
float col = FastMath.floor(x);
|
||||
float row = FastMath.floor(z);
|
||||
boolean onX = false;
|
||||
if(1 - (x - col)-(z - row) < 0) // what triangle to interpolate on
|
||||
onX = true;
|
||||
// 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;
|
||||
protected float getHeight(int x, int z, float xm, float zm) {
|
||||
|
||||
QuadrantChild match = findMatchingChild(x,z);
|
||||
if (match != null) {
|
||||
if (match.child instanceof TerrainQuad) {
|
||||
return ((TerrainQuad) match.child).getHeight(match.col, match.row, xm, zm);
|
||||
} else if (match.child instanceof TerrainPatch) {
|
||||
return ((TerrainPatch) match.child).getHeight(match.col, match.row, xm, zm);
|
||||
}
|
||||
}
|
||||
return Float.NaN;
|
||||
}
|
||||
|
||||
public Vector3f getNormal(Vector2f xz) {
|
||||
// offset
|
||||
|
Loading…
x
Reference in New Issue
Block a user