* performance improvements to terrain height modification
* api change to let you pass in many points to be adjusted in the terrain git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7643 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
026b7f2211
commit
993b220922
@ -50,12 +50,12 @@ import java.util.List;
|
||||
*/
|
||||
public interface Terrain {
|
||||
|
||||
/**
|
||||
* Get the real-world height of the terrain at the specified X-Z coorindate.
|
||||
* @param xz the X-Z world coordinate
|
||||
* @return the height at the given point
|
||||
*/
|
||||
public float getHeight(Vector2f xz);
|
||||
/**
|
||||
* Get the real-world height of the terrain at the specified X-Z coorindate.
|
||||
* @param xz the X-Z world coordinate
|
||||
* @return the height at the given point
|
||||
*/
|
||||
public float getHeight(Vector2f xz);
|
||||
|
||||
/**
|
||||
* Get the heightmap height at the specified X-Z coordinate. This does not
|
||||
@ -65,15 +65,25 @@ public interface Terrain {
|
||||
*/
|
||||
public float getHeightmapHeight(Vector2f xz);
|
||||
|
||||
/**
|
||||
* Set the height at the specified X-Z coordinate.
|
||||
/**
|
||||
* Set the height at the specified X-Z coordinate.
|
||||
* To set the height of the terrain and see it, you will have
|
||||
* to unlock the terrain meshes by calling terrain.setLocked(false) before
|
||||
* you call setHeight().
|
||||
* @param xzCoordinate coordinate to set the height
|
||||
* @param height that will be set at the coordinate
|
||||
*/
|
||||
public void setHeight(Vector2f xzCoordinate, float height);
|
||||
* @param xzCoordinate coordinate to set the height
|
||||
* @param height that will be set at the coordinate
|
||||
*/
|
||||
public void setHeight(Vector2f xzCoordinate, float height);
|
||||
|
||||
/**
|
||||
* Set the height at many points. The two lists must be the same size.
|
||||
* Each xz coordinate entry matches to a height entry, 1 for 1. So the
|
||||
* first coordinate matches to the first height value, the last to the
|
||||
* last etc.
|
||||
* @param xz a list of coordinates where the hight will be set
|
||||
* @param height the heights that match the xz coordinates
|
||||
*/
|
||||
public void setHeight(List<Vector2f> xz, List<Float> height);
|
||||
|
||||
/**
|
||||
* Raise/lower the height in one call (instead of getHeight then setHeight).
|
||||
@ -81,44 +91,54 @@ public interface Terrain {
|
||||
* @param delta +- value to adjust the height by
|
||||
*/
|
||||
public void adjustHeight(Vector2f xzCoordinate, float delta);
|
||||
|
||||
/**
|
||||
* Get the heightmap of the entire terrain.
|
||||
* This can return null if that terrain object does not store the height data.
|
||||
* Infinite or "paged" terrains will not be able to support this, so use with caution.
|
||||
*/
|
||||
public float[] getHeightMap();
|
||||
|
||||
/**
|
||||
* Tell the terrain system to use/not use Level of Detail algorithms.
|
||||
/**
|
||||
* Raise/lower the height at many points. The two lists must be the same size.
|
||||
* Each xz coordinate entry matches to a height entry, 1 for 1. So the
|
||||
* first coordinate matches to the first height value, the last to the
|
||||
* last etc.
|
||||
* @param xz a list of coordinates where the hight will be adjusted
|
||||
* @param height +- value to adjust the height by, that matches the xz coordinates
|
||||
*/
|
||||
public void adjustHeight(List<Vector2f> xz, List<Float> height);
|
||||
|
||||
/**
|
||||
* Get the heightmap of the entire terrain.
|
||||
* This can return null if that terrain object does not store the height data.
|
||||
* Infinite or "paged" terrains will not be able to support this, so use with caution.
|
||||
*/
|
||||
public float[] getHeightMap();
|
||||
|
||||
/**
|
||||
* Tell the terrain system to use/not use Level of Detail algorithms.
|
||||
* This is allowed to be ignored if a particular implementation cannot support it.
|
||||
*/
|
||||
public void useLOD(boolean useLod);
|
||||
*/
|
||||
public void useLOD(boolean useLod);
|
||||
|
||||
/**
|
||||
* Check if the terrain is using LOD techniques.
|
||||
* If a terrain system only supports enabled LOD, then this
|
||||
* should always return true.
|
||||
*/
|
||||
public boolean isUsingLOD();
|
||||
public boolean isUsingLOD();
|
||||
|
||||
/**
|
||||
* This is calculated by the specific LOD algorithm.
|
||||
* A value of one means that the terrain is showing full detail.
|
||||
* The higher the value, the more the terrain has been generalized
|
||||
* and the less detailed it will be.
|
||||
*/
|
||||
public int getMaxLod();
|
||||
|
||||
/**
|
||||
* This is calculated by the specific LOD algorithm.
|
||||
* A value of one means that the terrain is showing full detail.
|
||||
* The higher the value, the more the terrain has been generalized
|
||||
* and the less detailed it will be.
|
||||
*/
|
||||
public int getMaxLod();
|
||||
|
||||
/**
|
||||
* Called in the update (pre or post, up to you) method of your game.
|
||||
* Calculates the level of detail of the terrain and adjusts its geometry.
|
||||
* This is where the Terrain's LOD algorithm will change the detail of
|
||||
* the terrain based on how far away this position is from the particular
|
||||
* terrain patch.
|
||||
* @param location often the Camera's location
|
||||
*/
|
||||
public void update(List<Vector3f> location);
|
||||
/**
|
||||
* Called in the update (pre or post, up to you) method of your game.
|
||||
* Calculates the level of detail of the terrain and adjusts its geometry.
|
||||
* This is where the Terrain's LOD algorithm will change the detail of
|
||||
* the terrain based on how far away this position is from the particular
|
||||
* terrain patch.
|
||||
* @param location often the Camera's location
|
||||
*/
|
||||
public void update(List<Vector3f> location);
|
||||
|
||||
/**
|
||||
* Get the spatial instance of this Terrain. Right now just used in the
|
||||
|
@ -55,6 +55,7 @@ import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.VertexBuffer.Type;
|
||||
import com.jme3.terrain.geomipmap.TerrainQuad.LocationHeight;
|
||||
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
||||
import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
|
||||
import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
|
||||
@ -306,16 +307,24 @@ public class TerrainPatch extends Geometry {
|
||||
return geomap.getGridTrianglesAtPoint(x, z, getWorldScale() , getWorldTranslation());
|
||||
}
|
||||
|
||||
public void setHeight(float x, float z, float height) {
|
||||
if (x < 0 || z < 0 || x >= size || z >= size)
|
||||
return;
|
||||
int idx = (int) (z * size + x);
|
||||
geomap.getHeightData().put(idx, height);
|
||||
protected void setHeight(List<LocationHeight> locationHeights, boolean overrideHeight) {
|
||||
|
||||
for (LocationHeight lh : locationHeights) {
|
||||
if (lh.x < 0 || lh.z < 0 || lh.x >= size || lh.z >= size)
|
||||
continue;
|
||||
int idx = lh.z * size + lh.x;
|
||||
if (overrideHeight) {
|
||||
geomap.getHeightData().put(idx, lh.h);
|
||||
} else {
|
||||
float h = getMesh().getFloatBuffer(Type.Position).get(idx*3+1);
|
||||
geomap.getHeightData().put(idx, h+lh.h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false);
|
||||
getMesh().clearBuffer(Type.Position);
|
||||
getMesh().setBuffer(Type.Position, 3, newVertexBuffer);
|
||||
// normals are updated from the terrain controller on update()
|
||||
getMesh().setBuffer(Type.Position, 3, newVertexBuffer);
|
||||
}
|
||||
|
||||
public void adjustHeight(float x, float z, float delta) {
|
||||
@ -328,7 +337,7 @@ public class TerrainPatch extends Geometry {
|
||||
|
||||
FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false);
|
||||
getMesh().clearBuffer(Type.Position);
|
||||
getMesh().setBuffer(Type.Position, 3, newVertexBuffer);
|
||||
getMesh().setBuffer(Type.Position, 3, newVertexBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -806,15 +806,15 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
*/
|
||||
public void attachBoundChildren(Node parent) {
|
||||
for (int i = 0; i < this.getQuantity(); i++) {
|
||||
if (this.getChild(i) instanceof TerrainQuad) {
|
||||
((TerrainQuad) getChild(i)).attachBoundChildren(parent);
|
||||
} else if (this.getChild(i) instanceof TerrainPatch) {
|
||||
BoundingVolume bv = getChild(i).getWorldBound();
|
||||
if (this.getChild(i) instanceof TerrainQuad) {
|
||||
((TerrainQuad) getChild(i)).attachBoundChildren(parent);
|
||||
} else if (this.getChild(i) instanceof TerrainPatch) {
|
||||
BoundingVolume bv = getChild(i).getWorldBound();
|
||||
if (bv instanceof BoundingBox) {
|
||||
attachBoundingBox((BoundingBox)bv, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BoundingVolume bv = getWorldBound();
|
||||
if (bv instanceof BoundingBox) {
|
||||
attachBoundingBox((BoundingBox)bv, parent);
|
||||
@ -858,13 +858,13 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
return affectedAreaBBox != null;
|
||||
}
|
||||
|
||||
public float getHeightmapHeight(Vector2f xz) {
|
||||
public float getHeightmapHeight(Vector2f xz) {
|
||||
// offset
|
||||
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2);
|
||||
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2);
|
||||
int x = Math.round((xz.x / getLocalScale().x) + (float)totalSize / 2f);
|
||||
int z = Math.round((xz.y / getLocalScale().z) + (float)totalSize / 2f);
|
||||
|
||||
return getHeightmapHeight(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will just get the heightmap value at the supplied point,
|
||||
@ -946,59 +946,155 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// the coord calculations should be the same as getHeight()
|
||||
public void setHeight(Vector2f xz, float height) {
|
||||
List<Vector2f> coord = new ArrayList<Vector2f>();
|
||||
coord.add(xz);
|
||||
List<Float> h = new ArrayList<Float>();
|
||||
h.add(height);
|
||||
|
||||
setHeight(coord, h);
|
||||
}
|
||||
|
||||
public void adjustHeight(Vector2f xz, float delta) {
|
||||
List<Vector2f> coord = new ArrayList<Vector2f>();
|
||||
coord.add(xz);
|
||||
List<Float> h = new ArrayList<Float>();
|
||||
h.add(delta);
|
||||
|
||||
adjustHeight(coord, h);
|
||||
}
|
||||
|
||||
public void setHeight(List<Vector2f> xz, List<Float> height) {
|
||||
setHeight(xz, height, true);
|
||||
}
|
||||
|
||||
public void adjustHeight(List<Vector2f> xz, List<Float> height) {
|
||||
setHeight(xz, height, false);
|
||||
}
|
||||
|
||||
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!");
|
||||
|
||||
int halfSize = totalSize / 2;
|
||||
|
||||
List<LocationHeight> locations = new ArrayList<LocationHeight>();
|
||||
|
||||
// offset
|
||||
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2);
|
||||
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2);
|
||||
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(x, z, height); // adjust the actual mesh
|
||||
setHeight(locations, overrideHeight); // adjust height of the actual mesh
|
||||
|
||||
setNormalRecalcNeeded(xz);
|
||||
}
|
||||
// signal that the normals need updating
|
||||
for (int i=0; i<xz.size(); i++)
|
||||
setNormalRecalcNeeded(xz.get(i) );
|
||||
}
|
||||
|
||||
protected void setHeight(int x, int z, float newVal) {
|
||||
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;
|
||||
protected class LocationHeight {
|
||||
int x;
|
||||
int z;
|
||||
float h;
|
||||
|
||||
// get the childs quadrant
|
||||
int childQuadrant = 0;
|
||||
if (spat instanceof TerrainQuad) {
|
||||
childQuadrant = ((TerrainQuad) spat).getQuadrant();
|
||||
} else if (spat instanceof TerrainPatch) {
|
||||
childQuadrant = ((TerrainPatch) spat).getQuadrant();
|
||||
}
|
||||
LocationHeight(){}
|
||||
|
||||
LocationHeight(int x, int z, float h){
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.h = h;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
protected void setHeight(List<LocationHeight> locations, boolean overrideHeight) {
|
||||
if (children == null)
|
||||
return;
|
||||
|
||||
if (match) {
|
||||
if (spat instanceof TerrainQuad) {
|
||||
((TerrainQuad) spat).setHeight(col, row, newVal);
|
||||
} else if (spat instanceof TerrainPatch) {
|
||||
((TerrainPatch) spat).setHeight(col, row, newVal);
|
||||
}
|
||||
}
|
||||
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;) {
|
||||
Spatial spat = children.get(i);
|
||||
int childQuadrant = 0;
|
||||
if (spat instanceof TerrainQuad) {
|
||||
childQuadrant = ((TerrainQuad) spat).getQuadrant();
|
||||
} else if (spat instanceof TerrainPatch) {
|
||||
childQuadrant = ((TerrainPatch) spat).getQuadrant();
|
||||
}
|
||||
|
||||
if (childQuadrant == 1)
|
||||
quad1 = spat;
|
||||
else if (childQuadrant == 2)
|
||||
quad2 = spat;
|
||||
else if (childQuadrant == 3)
|
||||
quad3 = spat;
|
||||
else if (childQuadrant == 4)
|
||||
quad4 = spat;
|
||||
}
|
||||
|
||||
int split = (size + 1) >> 1;
|
||||
|
||||
// distribute each locationHeight into the quadrant it intersects
|
||||
for (LocationHeight lh : locations) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1016,63 +1112,6 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
}
|
||||
|
||||
|
||||
public void adjustHeight(Vector2f xz, float delta) {
|
||||
int x = Math.round((xz.x / getLocalScale().x) + totalSize / 2);
|
||||
int z = Math.round((xz.y / getLocalScale().z) + totalSize / 2);
|
||||
|
||||
if (!isPointOnTerrain(x,z))
|
||||
return;
|
||||
|
||||
adjustHeight(x, z,delta);
|
||||
|
||||
setNormalRecalcNeeded(xz);
|
||||
}
|
||||
|
||||
protected void adjustHeight(int x, int z, float delta) {
|
||||
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) {
|
||||
if (spat instanceof TerrainQuad) {
|
||||
((TerrainQuad) spat).adjustHeight(col, row, delta);
|
||||
} else if (spat instanceof TerrainPatch) {
|
||||
((TerrainPatch) spat).adjustHeight(col, row, delta);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// a position can be in multiple quadrants, so use a bit anded value.
|
||||
private int findQuadrant(int x, int y) {
|
||||
int split = (size + 1) >> 1;
|
||||
|
@ -66,7 +66,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
private TerrainQuad terrain;
|
||||
Material matTerrain;
|
||||
Material matWire;
|
||||
boolean wireframe = false;
|
||||
boolean wireframe = true;
|
||||
boolean triPlanar = false;
|
||||
boolean wardiso = false;
|
||||
boolean minnaert = false;
|
||||
@ -206,14 +206,14 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
if (pressed) {
|
||||
Vector3f intersection = getWorldIntersection();
|
||||
if (intersection != null) {
|
||||
adjustHeight(intersection, 16, 1);
|
||||
adjustHeight(intersection, 64, 1);
|
||||
}
|
||||
}
|
||||
} else if (name.equals("Lower")) {
|
||||
if (pressed) {
|
||||
Vector3f intersection = getWorldIntersection();
|
||||
if (intersection != null) {
|
||||
adjustHeight(intersection, 16, -1);
|
||||
adjustHeight(intersection, 32, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,8 +230,11 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
float xStepAmount = terrain.getLocalScale().x;
|
||||
float zStepAmount = terrain.getLocalScale().z;
|
||||
long start = System.currentTimeMillis();
|
||||
List<Vector2f> locs = new ArrayList<Vector2f>();
|
||||
List<Float> heights = new ArrayList<Float>();
|
||||
|
||||
for (int z = -radiusStepsZ; z < radiusStepsZ; z++) {
|
||||
for (int x = -radiusStepsZ; x < radiusStepsX; x++) {
|
||||
for (int x = -radiusStepsX; x < radiusStepsX; x++) {
|
||||
|
||||
float locX = loc.x + (x * xStepAmount);
|
||||
float locZ = loc.z + (z * zStepAmount);
|
||||
@ -239,13 +242,14 @@ public class TerrainTestModifyHeight extends SimpleApplication {
|
||||
if (isInRadius(locX - loc.x, locZ - loc.z, radius)) {
|
||||
// see if it is in the radius of the tool
|
||||
float h = calculateHeight(radius, height, locX - loc.x, locZ - loc.z);
|
||||
|
||||
// increase the height
|
||||
terrain.adjustHeight(new Vector2f(locX, locZ), h);
|
||||
locs.add(new Vector2f(locX, locZ));
|
||||
heights.add(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("took: " + (System.currentTimeMillis() - start));
|
||||
|
||||
terrain.adjustHeight(locs, heights);
|
||||
//System.out.println("Modified "+locs.size()+" points, took: " + (System.currentTimeMillis() - start)+" ms");
|
||||
terrain.updateModelBound();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user