|
|
@ -922,44 +922,88 @@ 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) { |
|
|
|