* 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 { | public interface Terrain { | ||||||
| 
 | 
 | ||||||
| 	/** |     /** | ||||||
| 	 * Get the real-world height of the terrain at the specified X-Z coorindate. |      * Get the real-world height of the terrain at the specified X-Z coorindate. | ||||||
| 	 * @param xz the X-Z world coordinate |      * @param xz the X-Z world coordinate | ||||||
| 	 * @return the height at the given point |      * @return the height at the given point | ||||||
| 	 */ |      */ | ||||||
| 	public float getHeight(Vector2f xz); |     public float getHeight(Vector2f xz); | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Get the heightmap height at the specified X-Z coordinate. This does not |      * 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); |     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 set the height of the terrain and see it, you will have | ||||||
|      * to unlock the terrain meshes by calling terrain.setLocked(false) before |      * to unlock the terrain meshes by calling terrain.setLocked(false) before | ||||||
|      * you call setHeight(). |      * you call setHeight(). | ||||||
| 	 * @param xzCoordinate coordinate to set the height |      * @param xzCoordinate coordinate to set the height | ||||||
| 	 * @param height that will be set at the coordinate |      * @param height that will be set at the coordinate | ||||||
| 	 */ |      */ | ||||||
| 	public void setHeight(Vector2f xzCoordinate, float height); |     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). |      * 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 |      * @param delta +- value to adjust the height by | ||||||
|      */ |      */ | ||||||
|     public void adjustHeight(Vector2f xzCoordinate, float delta); |     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. |      * 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. |      * Check if the terrain is using LOD techniques. | ||||||
|      * If a terrain system only supports enabled LOD, then this |      * If a terrain system only supports enabled LOD, then this | ||||||
|      * should always return true. |      * 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. |      * Called in the update (pre or post, up to you) method of your game. | ||||||
| 	 * A value of one means that the terrain is showing full detail. |      * Calculates the level of detail of the terrain and adjusts its geometry. | ||||||
| 	 * The higher the value, the more the terrain has been generalized  |      * This is where the Terrain's LOD algorithm will change the detail of | ||||||
| 	 * and the less detailed it will be. |      * the terrain based on how far away this position is from the particular | ||||||
| 	 */ |      * terrain patch. | ||||||
| 	public int getMaxLod(); |      * @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  |      * 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.Mesh; | ||||||
| import com.jme3.scene.VertexBuffer; | import com.jme3.scene.VertexBuffer; | ||||||
| import com.jme3.scene.VertexBuffer.Type; | 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.DistanceLodCalculator; | ||||||
| import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; | import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; | ||||||
| import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory; | import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory; | ||||||
| @ -306,16 +307,24 @@ public class TerrainPatch extends Geometry { | |||||||
|         return geomap.getGridTrianglesAtPoint(x, z, getWorldScale() , getWorldTranslation()); |         return geomap.getGridTrianglesAtPoint(x, z, getWorldScale() , getWorldTranslation()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void setHeight(float x, float z, float height) { |     protected void setHeight(List<LocationHeight> locationHeights, boolean overrideHeight) { | ||||||
|         if (x < 0 || z < 0 || x >= size || z >= size) |  | ||||||
|             return; |  | ||||||
|         int idx = (int) (z * size + x); |  | ||||||
|         geomap.getHeightData().put(idx, height); |  | ||||||
|          |          | ||||||
|  |         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); |         FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false); | ||||||
|         getMesh().clearBuffer(Type.Position); |         getMesh().clearBuffer(Type.Position); | ||||||
| 		getMesh().setBuffer(Type.Position, 3, newVertexBuffer); |         getMesh().setBuffer(Type.Position, 3, newVertexBuffer); | ||||||
|         // normals are updated from the terrain controller on update() |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void adjustHeight(float x, float z, float delta) { |     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); |         FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false); | ||||||
|         getMesh().clearBuffer(Type.Position); |         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) { |     public void attachBoundChildren(Node parent) { | ||||||
|         for (int i = 0; i < this.getQuantity(); i++) { |         for (int i = 0; i < this.getQuantity(); i++) { | ||||||
| 			if (this.getChild(i) instanceof TerrainQuad) { |             if (this.getChild(i) instanceof TerrainQuad) { | ||||||
| 				((TerrainQuad) getChild(i)).attachBoundChildren(parent); |                 ((TerrainQuad) getChild(i)).attachBoundChildren(parent); | ||||||
| 			} else if (this.getChild(i) instanceof TerrainPatch) { |             } else if (this.getChild(i) instanceof TerrainPatch) { | ||||||
| 				BoundingVolume bv = getChild(i).getWorldBound(); |                 BoundingVolume bv = getChild(i).getWorldBound(); | ||||||
|                 if (bv instanceof BoundingBox) { |                 if (bv instanceof BoundingBox) { | ||||||
|                     attachBoundingBox((BoundingBox)bv, parent); |                     attachBoundingBox((BoundingBox)bv, parent); | ||||||
|                 } |                 } | ||||||
| 			} |             } | ||||||
| 		} |         } | ||||||
|         BoundingVolume bv = getWorldBound(); |         BoundingVolume bv = getWorldBound(); | ||||||
|         if (bv instanceof BoundingBox) { |         if (bv instanceof BoundingBox) { | ||||||
|             attachBoundingBox((BoundingBox)bv, parent); |             attachBoundingBox((BoundingBox)bv, parent); | ||||||
| @ -858,13 +858,13 @@ public class TerrainQuad extends Node implements Terrain { | |||||||
|         return affectedAreaBBox != null; |         return affectedAreaBBox != null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 	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); | ||||||
| 	} |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * This will just get the heightmap value at the supplied point, |      * This will just get the heightmap value at the supplied point, | ||||||
| @ -946,59 +946,155 @@ 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) { | ||||||
|  |         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 |         // offset | ||||||
|         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); |             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) { |     protected class LocationHeight { | ||||||
|         int quad = findQuadrant(x, z); |         int x; | ||||||
|         int split = (size + 1) >> 1; |         int z; | ||||||
|         if (children != null) { |         float h; | ||||||
|             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 |         LocationHeight(){} | ||||||
|                 int childQuadrant = 0; |          | ||||||
|                 if (spat instanceof TerrainQuad) { |         LocationHeight(int x, int z, float h){ | ||||||
|                     childQuadrant = ((TerrainQuad) spat).getQuadrant(); |             this.x = x; | ||||||
|                 } else if (spat instanceof TerrainPatch) { |             this.z = z; | ||||||
|                     childQuadrant = ((TerrainPatch) spat).getQuadrant(); |             this.h = h; | ||||||
|                 } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|                 if (childQuadrant == 1 && (quad & 1) != 0) { |     protected void setHeight(List<LocationHeight> locations, boolean overrideHeight) { | ||||||
|                     match = true; |         if (children == null) | ||||||
|                 } else if (childQuadrant == 2 && (quad & 2) != 0) { |             return; | ||||||
|                     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) { |         List<LocationHeight> quadLH1 = new ArrayList<LocationHeight>(); | ||||||
|                     if (spat instanceof TerrainQuad) { |         List<LocationHeight> quadLH2 = new ArrayList<LocationHeight>(); | ||||||
|                         ((TerrainQuad) spat).setHeight(col, row, newVal); |         List<LocationHeight> quadLH3 = new ArrayList<LocationHeight>(); | ||||||
|                     } else if (spat instanceof TerrainPatch) { |         List<LocationHeight> quadLH4 = new ArrayList<LocationHeight>(); | ||||||
|                         ((TerrainPatch) spat).setHeight(col, row, newVal); |         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. |     // a position can be in multiple quadrants, so use a bit anded value. | ||||||
|     private int findQuadrant(int x, int y) { |     private int findQuadrant(int x, int y) { | ||||||
|         int split = (size + 1) >> 1; |         int split = (size + 1) >> 1; | ||||||
|  | |||||||
| @ -66,7 +66,7 @@ public class TerrainTestModifyHeight extends SimpleApplication { | |||||||
|     private TerrainQuad terrain; |     private TerrainQuad terrain; | ||||||
|     Material matTerrain; |     Material matTerrain; | ||||||
|     Material matWire; |     Material matWire; | ||||||
|     boolean wireframe = false; |     boolean wireframe = true; | ||||||
|     boolean triPlanar = false; |     boolean triPlanar = false; | ||||||
|     boolean wardiso = false; |     boolean wardiso = false; | ||||||
|     boolean minnaert = false; |     boolean minnaert = false; | ||||||
| @ -206,14 +206,14 @@ public class TerrainTestModifyHeight extends SimpleApplication { | |||||||
|                 if (pressed) { |                 if (pressed) { | ||||||
|                     Vector3f intersection = getWorldIntersection(); |                     Vector3f intersection = getWorldIntersection(); | ||||||
|                     if (intersection != null) { |                     if (intersection != null) { | ||||||
|                         adjustHeight(intersection, 16, 1); |                         adjustHeight(intersection, 64, 1); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } else if (name.equals("Lower")) { |             } else if (name.equals("Lower")) { | ||||||
|                 if (pressed) { |                 if (pressed) { | ||||||
|                     Vector3f intersection = getWorldIntersection(); |                     Vector3f intersection = getWorldIntersection(); | ||||||
|                     if (intersection != null) { |                     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 xStepAmount = terrain.getLocalScale().x; | ||||||
|         float zStepAmount = terrain.getLocalScale().z; |         float zStepAmount = terrain.getLocalScale().z; | ||||||
|         long start = System.currentTimeMillis(); |         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 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 locX = loc.x + (x * xStepAmount); | ||||||
|                 float locZ = loc.z + (z * zStepAmount); |                 float locZ = loc.z + (z * zStepAmount); | ||||||
| @ -239,13 +242,14 @@ public class TerrainTestModifyHeight extends SimpleApplication { | |||||||
|                 if (isInRadius(locX - loc.x, locZ - loc.z, radius)) { |                 if (isInRadius(locX - loc.x, locZ - loc.z, radius)) { | ||||||
|                     // see if it is in the radius of the tool |                     // see if it is in the radius of the tool | ||||||
|                     float h = calculateHeight(radius, height, locX - loc.x, locZ - loc.z); |                     float h = calculateHeight(radius, height, locX - loc.x, locZ - loc.z); | ||||||
| 
 |                     locs.add(new Vector2f(locX, locZ)); | ||||||
|                     // increase the height |                     heights.add(h); | ||||||
|                     terrain.adjustHeight(new Vector2f(locX, locZ), 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(); |         terrain.updateModelBound(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user