|
|
@ -860,8 +860,8 @@ public class TerrainQuad extends Node implements Terrain { |
|
|
|
|
|
|
|
|
|
|
|
public float getHeightmapHeight(Vector2f xz) { |
|
|
|
public float getHeightmapHeight(Vector2f xz) { |
|
|
|
// offset
|
|
|
|
// offset
|
|
|
|
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2); |
|
|
|
int x = Math.round((xz.x / getLocalScale().x) + (float)totalSize / 2f); |
|
|
|
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2); |
|
|
|
int z = Math.round((xz.y / getLocalScale().z) + (float)totalSize / 2f); |
|
|
|
|
|
|
|
|
|
|
|
return getHeightmapHeight(x, z); |
|
|
|
return getHeightmapHeight(x, z); |
|
|
|
} |
|
|
|
} |
|
|
@ -946,99 +946,84 @@ public class TerrainQuad extends Node implements Terrain { |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// the coord calculations should be the same as getHeight()
|
|
|
|
|
|
|
|
public void setHeight(Vector2f xz, float height) { |
|
|
|
public void setHeight(Vector2f xz, float height) { |
|
|
|
// offset
|
|
|
|
List<Vector2f> coord = new ArrayList<Vector2f>(); |
|
|
|
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2); |
|
|
|
coord.add(xz); |
|
|
|
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2); |
|
|
|
List<Float> h = new ArrayList<Float>(); |
|
|
|
|
|
|
|
h.add(height); |
|
|
|
|
|
|
|
|
|
|
|
setHeight(x, z, height); // adjust the actual mesh
|
|
|
|
setHeight(coord, h); |
|
|
|
|
|
|
|
|
|
|
|
setNormalRecalcNeeded(xz); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected void setHeight(int x, int z, float newVal) { |
|
|
|
public void adjustHeight(Vector2f xz, float delta) { |
|
|
|
int quad = findQuadrant(x, z); |
|
|
|
List<Vector2f> coord = new ArrayList<Vector2f>(); |
|
|
|
int split = (size + 1) >> 1; |
|
|
|
coord.add(xz); |
|
|
|
if (children != null) { |
|
|
|
List<Float> h = new ArrayList<Float>(); |
|
|
|
for (int i = children.size(); --i >= 0;) { |
|
|
|
h.add(delta); |
|
|
|
Spatial spat = children.get(i); |
|
|
|
|
|
|
|
int col = x; |
|
|
|
|
|
|
|
int row = z; |
|
|
|
|
|
|
|
boolean match = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get the childs quadrant
|
|
|
|
adjustHeight(coord, h); |
|
|
|
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) { |
|
|
|
public void setHeight(List<Vector2f> xz, List<Float> height) { |
|
|
|
match = true; |
|
|
|
setHeight(xz, height, 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) { |
|
|
|
public void adjustHeight(List<Vector2f> xz, List<Float> height) { |
|
|
|
if (spat instanceof TerrainQuad) { |
|
|
|
setHeight(xz, height, false); |
|
|
|
((TerrainQuad) spat).setHeight(col, row, newVal); |
|
|
|
|
|
|
|
} else if (spat instanceof TerrainPatch) { |
|
|
|
|
|
|
|
((TerrainPatch) spat).setHeight(col, row, newVal); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
protected void setHeight(List<Vector2f> xz, List<Float> height, boolean overrideHeight) { |
|
|
|
} |
|
|
|
if (xz.size() != height.size()) |
|
|
|
} |
|
|
|
throw new IllegalArgumentException("Both lists must be the same length!"); |
|
|
|
|
|
|
|
|
|
|
|
protected boolean isPointOnTerrain(int x, int z) { |
|
|
|
int halfSize = totalSize / 2; |
|
|
|
return (x >= 0 && x <= totalSize && z >= 0 && z <= totalSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Vector2f getPointPercentagePosition(float worldX, float worldY) { |
|
|
|
List<LocationHeight> locations = new ArrayList<LocationHeight>(); |
|
|
|
Vector2f uv = new Vector2f(worldX,worldY); |
|
|
|
|
|
|
|
uv.subtractLocal(getLocalTranslation().x, getLocalTranslation().z); // center it on 0,0
|
|
|
|
|
|
|
|
uv.addLocal(totalSize/2, totalSize/2); // shift the bottom left corner up to 0,0
|
|
|
|
|
|
|
|
uv.divideLocal(totalSize); // get the location as a percentage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return uv; |
|
|
|
// offset
|
|
|
|
|
|
|
|
for (int i=0; i<xz.size(); i++) { |
|
|
|
|
|
|
|
int x = Math.round((xz.get(i).x / getLocalScale().x) + halfSize); |
|
|
|
|
|
|
|
int z = Math.round((xz.get(i).y / getLocalScale().z) + halfSize); |
|
|
|
|
|
|
|
locations.add(new LocationHeight(x,z,height.get(i))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setHeight(locations, overrideHeight); // adjust height of the actual mesh
|
|
|
|
|
|
|
|
|
|
|
|
public void adjustHeight(Vector2f xz, float delta) { |
|
|
|
// signal that the normals need updating
|
|
|
|
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2); |
|
|
|
for (int i=0; i<xz.size(); i++) |
|
|
|
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2); |
|
|
|
setNormalRecalcNeeded(xz.get(i) ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!isPointOnTerrain(x,z)) |
|
|
|
protected class LocationHeight { |
|
|
|
return; |
|
|
|
int x; |
|
|
|
|
|
|
|
int z; |
|
|
|
|
|
|
|
float h; |
|
|
|
|
|
|
|
|
|
|
|
adjustHeight(x, z,delta); |
|
|
|
LocationHeight(){} |
|
|
|
|
|
|
|
|
|
|
|
setNormalRecalcNeeded(xz); |
|
|
|
LocationHeight(int x, int z, float h){ |
|
|
|
|
|
|
|
this.x = x; |
|
|
|
|
|
|
|
this.z = z; |
|
|
|
|
|
|
|
this.h = h; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected void adjustHeight(int x, int z, float delta) { |
|
|
|
protected void setHeight(List<LocationHeight> locations, boolean overrideHeight) { |
|
|
|
int quad = findQuadrant(x, z); |
|
|
|
if (children == null) |
|
|
|
int split = (size + 1) >> 1; |
|
|
|
return; |
|
|
|
if (children != null) { |
|
|
|
|
|
|
|
|
|
|
|
List<LocationHeight> quadLH1 = new ArrayList<LocationHeight>(); |
|
|
|
|
|
|
|
List<LocationHeight> quadLH2 = new ArrayList<LocationHeight>(); |
|
|
|
|
|
|
|
List<LocationHeight> quadLH3 = new ArrayList<LocationHeight>(); |
|
|
|
|
|
|
|
List<LocationHeight> quadLH4 = new ArrayList<LocationHeight>(); |
|
|
|
|
|
|
|
Spatial quad1 = null; |
|
|
|
|
|
|
|
Spatial quad2 = null; |
|
|
|
|
|
|
|
Spatial quad3 = null; |
|
|
|
|
|
|
|
Spatial quad4 = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get the child quadrants
|
|
|
|
for (int i = children.size(); --i >= 0;) { |
|
|
|
for (int i = children.size(); --i >= 0;) { |
|
|
|
Spatial spat = children.get(i); |
|
|
|
Spatial spat = children.get(i); |
|
|
|
int col = x; |
|
|
|
|
|
|
|
int row = z; |
|
|
|
|
|
|
|
boolean match = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get the childs quadrant
|
|
|
|
|
|
|
|
int childQuadrant = 0; |
|
|
|
int childQuadrant = 0; |
|
|
|
if (spat instanceof TerrainQuad) { |
|
|
|
if (spat instanceof TerrainQuad) { |
|
|
|
childQuadrant = ((TerrainQuad) spat).getQuadrant(); |
|
|
|
childQuadrant = ((TerrainQuad) spat).getQuadrant(); |
|
|
@ -1046,30 +1031,84 @@ public class TerrainQuad extends Node implements Terrain { |
|
|
|
childQuadrant = ((TerrainPatch) spat).getQuadrant(); |
|
|
|
childQuadrant = ((TerrainPatch) spat).getQuadrant(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (childQuadrant == 1 && (quad & 1) != 0) { |
|
|
|
if (childQuadrant == 1) |
|
|
|
match = true; |
|
|
|
quad1 = spat; |
|
|
|
} else if (childQuadrant == 2 && (quad & 2) != 0) { |
|
|
|
else if (childQuadrant == 2) |
|
|
|
row = z - split + 1; |
|
|
|
quad2 = spat; |
|
|
|
match = true; |
|
|
|
else if (childQuadrant == 3) |
|
|
|
} else if (childQuadrant == 3 && (quad & 4) != 0) { |
|
|
|
quad3 = spat; |
|
|
|
col = x - split + 1; |
|
|
|
else if (childQuadrant == 4) |
|
|
|
match = true; |
|
|
|
quad4 = spat; |
|
|
|
} else if (childQuadrant == 4 && (quad & 8) != 0) { |
|
|
|
|
|
|
|
col = x - split + 1; |
|
|
|
|
|
|
|
row = z - split + 1; |
|
|
|
|
|
|
|
match = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (match) { |
|
|
|
int split = (size + 1) >> 1; |
|
|
|
if (spat instanceof TerrainQuad) { |
|
|
|
|
|
|
|
((TerrainQuad) spat).adjustHeight(col, row, delta); |
|
|
|
// distribute each locationHeight into the quadrant it intersects
|
|
|
|
} else if (spat instanceof TerrainPatch) { |
|
|
|
for (LocationHeight lh : locations) { |
|
|
|
((TerrainPatch) spat).adjustHeight(col, row, delta); |
|
|
|
int quad = findQuadrant(lh.x, lh.z); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int col = lh.x; |
|
|
|
|
|
|
|
int row = lh.z; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((quad & 1) != 0) { |
|
|
|
|
|
|
|
quadLH1.add(lh); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ((quad & 2) != 0) { |
|
|
|
|
|
|
|
row = lh.z - split + 1; |
|
|
|
|
|
|
|
quadLH2.add(new LocationHeight(lh.x, row, lh.h)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ((quad & 4) != 0) { |
|
|
|
|
|
|
|
col = lh.x - split + 1; |
|
|
|
|
|
|
|
quadLH3.add(new LocationHeight(col, lh.z, lh.h)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ((quad & 8) != 0) { |
|
|
|
|
|
|
|
col = lh.x - split + 1; |
|
|
|
|
|
|
|
row = lh.z - split + 1; |
|
|
|
|
|
|
|
quadLH4.add(new LocationHeight(col, row, lh.h)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// send the locations to the children
|
|
|
|
|
|
|
|
if (!quadLH1.isEmpty()) { |
|
|
|
|
|
|
|
if (quad1 instanceof TerrainQuad) |
|
|
|
|
|
|
|
((TerrainQuad)quad1).setHeight(quadLH1, overrideHeight); |
|
|
|
|
|
|
|
else if(quad1 instanceof TerrainPatch) |
|
|
|
|
|
|
|
((TerrainPatch)quad1).setHeight(quadLH1, overrideHeight); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!quadLH2.isEmpty()) { |
|
|
|
|
|
|
|
if (quad2 instanceof TerrainQuad) |
|
|
|
|
|
|
|
((TerrainQuad)quad2).setHeight(quadLH2, overrideHeight); |
|
|
|
|
|
|
|
else if(quad2 instanceof TerrainPatch) |
|
|
|
|
|
|
|
((TerrainPatch)quad2).setHeight(quadLH2, overrideHeight); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!quadLH3.isEmpty()) { |
|
|
|
|
|
|
|
if (quad3 instanceof TerrainQuad) |
|
|
|
|
|
|
|
((TerrainQuad)quad3).setHeight(quadLH3, overrideHeight); |
|
|
|
|
|
|
|
else if(quad3 instanceof TerrainPatch) |
|
|
|
|
|
|
|
((TerrainPatch)quad3).setHeight(quadLH3, overrideHeight); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!quadLH4.isEmpty()) { |
|
|
|
|
|
|
|
if (quad4 instanceof TerrainQuad) |
|
|
|
|
|
|
|
((TerrainQuad)quad4).setHeight(quadLH4, overrideHeight); |
|
|
|
|
|
|
|
else if(quad4 instanceof TerrainPatch) |
|
|
|
|
|
|
|
((TerrainPatch)quad4).setHeight(quadLH4, overrideHeight); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected boolean isPointOnTerrain(int x, int z) { |
|
|
|
|
|
|
|
return (x >= 0 && x <= totalSize && z >= 0 && z <= totalSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Vector2f getPointPercentagePosition(float worldX, float worldY) { |
|
|
|
|
|
|
|
Vector2f uv = new Vector2f(worldX,worldY); |
|
|
|
|
|
|
|
uv.subtractLocal(getLocalTranslation().x, getLocalTranslation().z); // center it on 0,0
|
|
|
|
|
|
|
|
uv.addLocal(totalSize/2, totalSize/2); // shift the bottom left corner up to 0,0
|
|
|
|
|
|
|
|
uv.divideLocal(totalSize); // get the location as a percentage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return uv; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|