Browse Source

* refactored TerrainLOD Control and removed some legacy classes for it, made it easier to use

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8233 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
bre..ns 14 years ago
parent
commit
3383e2e086
21 changed files with 228 additions and 182 deletions
  1. 2 1
      engine/src/terrain/com/jme3/terrain/Terrain.java
  2. 12 16
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java
  3. 16 1
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java
  4. 13 34
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java
  5. 63 57
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java
  6. 46 32
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java
  7. 2 3
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculator.java
  8. 1 0
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculatorFactory.java
  9. 2 3
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodDistanceCalculatorFactory.java
  10. 1 1
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodPerspectiveCalculatorFactory.java
  11. 4 4
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodThreshold.java
  12. 22 6
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/PerspectiveLodCalculator.java
  13. 14 8
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/SimpleLodThreshold.java
  14. 2 0
      engine/src/test/jme3test/terrain/TerrainFractalGridTest.java
  15. 2 0
      engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java
  16. 2 0
      engine/src/test/jme3test/terrain/TerrainGridTest.java
  17. 4 1
      engine/src/test/jme3test/terrain/TerrainTest.java
  18. 14 15
      engine/src/test/jme3test/terrain/TerrainTestAdvanced.java
  19. 2 0
      engine/src/test/jme3test/terrain/TerrainTestCollision.java
  20. 2 0
      engine/src/test/jme3test/terrain/TerrainTestModifyHeight.java
  21. 2 0
      engine/src/test/jme3test/terrain/TerrainTestReadWrite.java

+ 2 - 1
engine/src/terrain/com/jme3/terrain/Terrain.java

@@ -34,6 +34,7 @@ package com.jme3.terrain;
 import com.jme3.material.Material;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
 import java.util.List;
 
 /**
@@ -133,7 +134,7 @@ public interface Terrain {
      * @param location: the Camera's location. A list of one camera location is normal 
      *  if you just have one camera in your scene.
      */
-    public void update(List<Vector3f> location);
+    public void update(List<Vector3f> location, LodCalculator lodCalculator);
 
     /**
      * Lock or unlock the meshes of this terrain.

+ 12 - 16
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java

@@ -46,6 +46,7 @@ import com.jme3.material.Material;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
 import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
 import com.jme3.terrain.geomipmap.lodcalc.LodDistanceCalculatorFactory;
 import com.jme3.terrain.heightmap.HeightMapGrid;
@@ -88,7 +89,7 @@ public class TerrainGrid extends TerrainQuad {
                     if (q == null) {
                         // create the new Quad since it doesn't exist
                         HeightMap heightMapAt = heightMapGrid.getHeightMapAt(temp);
-                        q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, totalSize, heightMapAt == null ? null : heightMapAt.getHeightMap(), lodCalculatorFactory);
+                        q = new TerrainQuad(getName() + "Quad" + temp, patchSize, quadSize, totalSize, heightMapAt == null ? null : heightMapAt.getHeightMap());
                         q.setMaterial(material.clone());
                         log.log(Level.FINE, "Loaded TerrainQuad {0}", q.getName());
                     }
@@ -131,7 +132,7 @@ public class TerrainGrid extends TerrainQuad {
     }
 
     public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, HeightMapGrid heightMapGrid,
-            Vector2f offset, float offsetAmount, LodCalculatorFactory lodCalculatorFactory) {
+            Vector2f offset, float offsetAmount) {
         this.name = name;
         this.patchSize = patchSize;
         this.size = maxVisibleSize;
@@ -143,11 +144,11 @@ public class TerrainGrid extends TerrainQuad {
         this.totalSize = maxVisibleSize;
         this.offset = offset;
         this.offsetAmount = offsetAmount;
-        this.lodCalculatorFactory = lodCalculatorFactory;
+        //this.lodCalculatorFactory = lodCalculatorFactory;
         this.gridOffset = new int[]{0,0};
-        if (lodCalculatorFactory == null) {
-            lodCalculatorFactory = new LodDistanceCalculatorFactory();
-        }
+        //if (lodCalculatorFactory == null) {
+        //    lodCalculatorFactory = new LodDistanceCalculatorFactory();
+        //}
         this.quadIndex = new Vector3f[]{
         new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2),
         new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1),
@@ -157,17 +158,12 @@ public class TerrainGrid extends TerrainQuad {
         addControl(new UpdateControl());
     }
 
-    public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, HeightMapGrid heightMapGrid,
-            LodCalculatorFactory lodCalculatorFactory) {
-        this(name, patchSize, maxVisibleSize, scale, heightMapGrid, new Vector2f(), 0, lodCalculatorFactory);
-    }
-
-    public TerrainGrid(String name, int patchSize, int maxVisibleSize, HeightMapGrid heightMapGrid, LodCalculatorFactory lodCalculatorFactory) {
-        this(name, patchSize, maxVisibleSize, Vector3f.UNIT_XYZ, heightMapGrid, lodCalculatorFactory);
+    public TerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, HeightMapGrid heightMapGrid) {
+        this(name, patchSize, maxVisibleSize, scale, heightMapGrid, new Vector2f(), 0);
     }
 
     public TerrainGrid(String name, int patchSize, int maxVisibleSize, HeightMapGrid heightMapGrid) {
-        this(name, patchSize, maxVisibleSize, heightMapGrid, null);
+        this(name, patchSize, maxVisibleSize, Vector3f.UNIT_XYZ, heightMapGrid);
     }
 
     public TerrainGrid() {
@@ -185,7 +181,7 @@ public class TerrainGrid extends TerrainQuad {
     }
 
     @Override
-    public void update(List<Vector3f> locations) {
+    public void update(List<Vector3f> locations, LodCalculator lodCalculator) {
         // for now, only the first camera is handled.
         // to accept more, there are two ways:
         // 1: every camera has an associated grid, then the location is not enough to identify which camera location has changed
@@ -203,7 +199,7 @@ public class TerrainGrid extends TerrainQuad {
                 l.gridMoved(camCell);
             }
         }
-        super.update(locations);
+        super.update(locations, lodCalculator);
     }
 
     public Vector3f getCell(Vector3f location) {

+ 16 - 1
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java

@@ -46,6 +46,8 @@ import com.jme3.scene.Spatial;
 import com.jme3.scene.control.AbstractControl;
 import com.jme3.scene.control.Control;
 import com.jme3.terrain.Terrain;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
 import java.io.IOException;
 import java.util.ArrayList;
 
@@ -65,6 +67,7 @@ public class TerrainLodControl extends AbstractControl {
     private Terrain terrain;
     private List<Camera> cameras;
     private List<Vector3f> cameraLocations = new ArrayList<Vector3f>();
+    private LodCalculator lodCalculator;
 
     public TerrainLodControl() {
     }
@@ -74,6 +77,7 @@ public class TerrainLodControl extends AbstractControl {
         cams.add(camera);
         this.terrain = terrain;
         this.cameras = cams;
+        lodCalculator = new DistanceLodCalculator(); // a default calculator
     }
     
     /**
@@ -101,7 +105,7 @@ public class TerrainLodControl extends AbstractControl {
                     cameraLocations.add(c.getLocation());
                 }
             }
-            terrain.update(cameraLocations);
+            terrain.update(cameraLocations, lodCalculator);
         }
     }
 
@@ -144,11 +148,21 @@ public class TerrainLodControl extends AbstractControl {
         this.terrain = terrain;
     }
 
+    public LodCalculator getLodCalculator() {
+        return lodCalculator;
+    }
+
+    public void setLodCalculator(LodCalculator lodCalculator) {
+        this.lodCalculator = lodCalculator;
+    }
+    
+
     @Override
     public void write(JmeExporter ex) throws IOException {
         super.write(ex);
         OutputCapsule oc = ex.getCapsule(this);
         oc.write((Node)terrain, "terrain", null);
+        oc.write(lodCalculator, "lodCalculator", null);
     }
 
     @Override
@@ -156,5 +170,6 @@ public class TerrainLodControl extends AbstractControl {
         super.read(im);
         InputCapsule ic = im.getCapsule(this);
         terrain = (Terrain) ic.readSavable("terrain", null);
+        lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());
     }
 }

+ 13 - 34
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java

@@ -109,8 +109,8 @@ public class TerrainPatch extends Geometry {
     // amount the patch has been shifted.
     protected float offsetAmount;
 
-    protected LodCalculator lodCalculator;
-    protected LodCalculatorFactory lodCalculatorFactory;
+    //protected LodCalculator lodCalculator;
+    //protected LodCalculatorFactory lodCalculatorFactory;
 
     protected TerrainPatch leftNeighbour, topNeighbour, rightNeighbour, bottomNeighbour;
     protected boolean searchedForNeighboursAlready = false;
@@ -234,20 +234,7 @@ public class TerrainPatch extends Geometry {
         return maxLod;
     }
 
-    
-	
-
-    /**
-     * Delegates to the lodCalculator that was passed in.
-     * @param locations all possible camera locations
-     * @param updates update objects that may or may not contain this terrain patch
-     * @return true if the geometry needs re-indexing
-     */
-    protected boolean calculateLod(List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates) {
-        return lodCalculator.calculateLod(locations, updates);
-    }
-
-    protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated) {
+    protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated, boolean useVariableLod) {
 
         UpdatedTerrainPatch utp = updated.get(getName());
 
@@ -259,7 +246,7 @@ public class TerrainPatch extends Geometry {
             boolean bottom = utp.getBottomLod() > utp.getNewLod();
 
             IntBuffer ib = null;
-            if (lodCalculator.usesVariableLod())
+            if (useVariableLod)
                 ib = geomap.writeIndexArrayLodVariable(null, pow, (int) Math.pow(2, utp.getRightLod()), (int) Math.pow(2, utp.getTopLod()), (int) Math.pow(2, utp.getLeftLod()), (int) Math.pow(2, utp.getBottomLod()));
             else
                 ib = geomap.writeIndexArrayLodDiff(null, pow, right, top, left, bottom);
@@ -920,19 +907,11 @@ public class TerrainPatch extends Geometry {
     protected void setLodBottom(int lodBottom) {
         this.lodBottom = lodBottom;
     }
-
-    public LodCalculator getLodCalculator() {
-        return lodCalculator;
-    }
-
-    public void setLodCalculator(LodCalculator lodCalculator) {
-        this.lodCalculator = lodCalculator;
-    }
-
-    public void setLodCalculator(LodCalculatorFactory lodCalculatorFactory) {
+    
+    /*public void setLodCalculator(LodCalculatorFactory lodCalculatorFactory) {
         this.lodCalculatorFactory = lodCalculatorFactory;
         setLodCalculator(lodCalculatorFactory.createCalculator(this));
-    }
+    }*/
 
     @Override
     public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException {
@@ -1035,8 +1014,8 @@ public class TerrainPatch extends Geometry {
         oc.write(stepScale, "stepScale", Vector3f.UNIT_XYZ);
         oc.write(offset, "offset", Vector3f.UNIT_XYZ);
         oc.write(offsetAmount, "offsetAmount", 0);
-        oc.write(lodCalculator, "lodCalculator", null);
-        oc.write(lodCalculatorFactory, "lodCalculatorFactory", null);
+        //oc.write(lodCalculator, "lodCalculator", null);
+        //oc.write(lodCalculatorFactory, "lodCalculatorFactory", null);
         oc.write(lodEntropy, "lodEntropy", null);
         oc.write(geomap, "geomap", null);
         
@@ -1053,9 +1032,9 @@ public class TerrainPatch extends Geometry {
         stepScale = (Vector3f) ic.readSavable("stepScale", Vector3f.UNIT_XYZ);
         offset = (Vector2f) ic.readSavable("offset", Vector3f.UNIT_XYZ);
         offsetAmount = ic.readFloat("offsetAmount", 0);
-        lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());
-        lodCalculator.setTerrainPatch(this);
-        lodCalculatorFactory = (LodCalculatorFactory) ic.readSavable("lodCalculatorFactory", null);
+        //lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());
+        //lodCalculator.setTerrainPatch(this);
+        //lodCalculatorFactory = (LodCalculatorFactory) ic.readSavable("lodCalculatorFactory", null);
         lodEntropy = ic.readFloatArray("lodEntropy", null);
         geomap = (LODGeomap) ic.readSavable("geomap", null);
         
@@ -1077,7 +1056,7 @@ public class TerrainPatch extends Geometry {
         clone.offsetAmount = offsetAmount;
         //clone.lodCalculator = lodCalculator.clone();
         //clone.lodCalculator.setTerrainPatch(clone);
-        clone.setLodCalculator(lodCalculatorFactory.clone());
+        //clone.setLodCalculator(lodCalculatorFactory.clone());
         clone.geomap = new LODGeomap(size, geomap.getHeightData());
         clone.setLocalTranslation(getLocalTranslation().clone());
         Mesh m = clone.geomap.createMesh(clone.stepScale, Vector2f.UNIT_XY, clone.offset, clone.offsetAmount, clone.totalSize, false);

+ 63 - 57
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java

@@ -57,8 +57,9 @@ import com.jme3.scene.Spatial;
 import com.jme3.scene.debug.WireBox;
 import com.jme3.terrain.ProgressMonitor;
 import com.jme3.terrain.Terrain;
-import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
-import com.jme3.terrain.geomipmap.lodcalc.LodDistanceCalculatorFactory;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
+import com.jme3.terrain.geomipmap.lodcalc.SimpleLodThreshold;
 import com.jme3.terrain.geomipmap.picking.BresenhamTerrainPicker;
 import com.jme3.terrain.geomipmap.picking.TerrainPickData;
 import com.jme3.terrain.geomipmap.picking.TerrainPicker;
@@ -109,7 +110,8 @@ public class TerrainQuad extends Node implements Terrain {
 
     protected int quadrant = 1; // 1=upper left, 2=lower left, 3=upper right, 4=lower right
 
-    protected LodCalculatorFactory lodCalculatorFactory;
+    //protected LodCalculatorFactory lodCalculatorFactory;
+    //protected LodCalculator lodCalculator;
     
     protected List<Vector3f> lastCameraLocations; // used for LOD calc
     private boolean lodCalcRunning = false;
@@ -139,55 +141,55 @@ public class TerrainQuad extends Node implements Terrain {
     }
 
     public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap) {
-        this(name, patchSize, totalSize, heightMap, null);
-    }
-
-    public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {
-        this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap, lodCalculatorFactory);
+        this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap);
     }
     
-    public TerrainQuad(String name, int patchSize, int size, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {
-        this(name, patchSize, size, Vector3f.UNIT_XYZ, heightMap, totalSize, new Vector2f(), 0, lodCalculatorFactory);
+    public TerrainQuad(String name, int patchSize, int quadSize, int totalSize, float[] heightMap) {
+        this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap);
+    }
+
+    public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap) {
+        this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0);
         affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);
         fixNormalEdges(affectedAreaBBox);
         addControl(new NormalRecalcControl(this));
     }
-
-    public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {
-        this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory);
-        affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);
+    
+    public TerrainQuad(String name, int patchSize, int totalSize, int quadSize, Vector3f scale, float[] heightMap) {
+        this(name, patchSize, quadSize, scale, heightMap, totalSize, new Vector2f(), 0);
+        affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), totalSize*2, Float.MAX_VALUE, totalSize*2);
         fixNormalEdges(affectedAreaBBox);
         addControl(new NormalRecalcControl(this));
     }
 
-    protected TerrainQuad(String name, int patchSize, int size,
+    protected TerrainQuad(String name, int patchSize, int quadSize,
                             Vector3f scale, float[] heightMap, int totalSize,
-                            Vector2f offset, float offsetAmount,
-                            LodCalculatorFactory lodCalculatorFactory)
+                            Vector2f offset, float offsetAmount)
     {
         super(name);
         
         if (heightMap == null)
-            heightMap = generateDefaultHeightMap(size);
+            heightMap = generateDefaultHeightMap(quadSize);
         
-        if (!FastMath.isPowerOfTwo(size - 1)) {
-            throw new RuntimeException("size given: " + size + "  Terrain quad sizes may only be (2^N + 1)");
+        if (!FastMath.isPowerOfTwo(quadSize - 1)) {
+            throw new RuntimeException("size given: " + quadSize + "  Terrain quad sizes may only be (2^N + 1)");
         }
-        if (FastMath.sqrt(heightMap.length) > size) {
+        if (FastMath.sqrt(heightMap.length) > quadSize) {
             Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Heightmap size is larger than the terrain size. Make sure your heightmap image is the same size as the terrain!");
         }
         
         this.offset = offset;
         this.offsetAmount = offsetAmount;
         this.totalSize = totalSize;
-        this.size = size;
+        this.size = quadSize;
         this.patchSize = patchSize;
         this.stepScale = scale;
-        this.lodCalculatorFactory = lodCalculatorFactory;
+        //this.lodCalculatorFactory = lodCalculatorFactory;
+        //this.lodCalculator = lodCalculator;
         split(patchSize, heightMap);
     }
 
-    public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {
+    /*public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {
         if (children != null) {
             for (int i = children.size(); --i >= 0;) {
                 Spatial child = children.get(i);
@@ -198,7 +200,7 @@ public class TerrainQuad extends Node implements Terrain {
                 }
             }
         }
-    }
+    }*/
 
 
     /**
@@ -215,8 +217,8 @@ public class TerrainQuad extends Node implements Terrain {
       * This will perform the geometry calculation in a background thread and
       * do the actual update on the opengl thread.
       */
-    public void update(List<Vector3f> locations) {
-        updateLOD(locations);
+    public void update(List<Vector3f> locations, LodCalculator lodCalculator) {
+        updateLOD(locations, lodCalculator);
     }
 
     /**
@@ -235,7 +237,7 @@ public class TerrainQuad extends Node implements Terrain {
     }
 
     // do all of the LOD calculations
-    protected void updateLOD(List<Vector3f> locations) {
+    protected void updateLOD(List<Vector3f> locations, LodCalculator lodCalculator) {
         // update any existing ones that need updating
         updateQuadLODs();
 
@@ -261,7 +263,7 @@ public class TerrainQuad extends Node implements Terrain {
         if (executor == null)
             executor = createExecutorService();
         
-        UpdateLOD updateLodThread = new UpdateLOD(locations);
+        UpdateLOD updateLodThread = new UpdateLOD(locations, lodCalculator);
         executor.execute(updateLodThread);
     }
 
@@ -359,9 +361,11 @@ public class TerrainQuad extends Node implements Terrain {
      */
     private class UpdateLOD implements Runnable {
         private List<Vector3f> camLocations;
+        private LodCalculator lodCalculator;
 
-        UpdateLOD(List<Vector3f> location) {
-            camLocations = location;
+        UpdateLOD(List<Vector3f> camLocations, LodCalculator lodCalculator) {
+            this.camLocations = camLocations;
+            this.lodCalculator = lodCalculator;
         }
 
         public void run() {
@@ -375,7 +379,7 @@ public class TerrainQuad extends Node implements Terrain {
 
             // go through each patch and calculate its LOD based on camera distance
             HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();
-            boolean lodChanged = calculateLod(camLocations, updated); // 'updated' gets populated here
+            boolean lodChanged = calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here
 
             if (!lodChanged) {
                 // not worth updating anything else since no one's LOD changed
@@ -387,7 +391,7 @@ public class TerrainQuad extends Node implements Terrain {
 
             fixEdges(updated); // 'updated' can get added to here
 
-            reIndexPages(updated);
+            reIndexPages(updated, lodCalculator.usesVariableLod());
 
             setUpdateQuadLODs(updated); // set back to main ogl thread
 
@@ -422,7 +426,7 @@ public class TerrainQuad extends Node implements Terrain {
         }
     }
 
-    protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates) {
+    protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates, LodCalculator lodCalculator) {
 
         boolean lodChanged = false;
 
@@ -430,11 +434,11 @@ public class TerrainQuad extends Node implements Terrain {
             for (int i = children.size(); --i >= 0;) {
                 Spatial child = children.get(i);
                 if (child instanceof TerrainQuad) {
-                    boolean b = ((TerrainQuad) child).calculateLod(location, updates);
+                    boolean b = ((TerrainQuad) child).calculateLod(location, updates, lodCalculator);
                     if (b)
                         lodChanged = true;
                 } else if (child instanceof TerrainPatch) {
-                    boolean b = ((TerrainPatch) child).calculateLod(location, updates);
+                    boolean b = lodCalculator.calculateLod((TerrainPatch) child, location, updates);
                     if (b)
                         lodChanged = true;
                 }
@@ -561,14 +565,14 @@ public class TerrainQuad extends Node implements Terrain {
         }
     }
 
-    protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated) {
+    protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated, boolean usesVariableLod) {
         if (children != null) {
             for (int i = children.size(); --i >= 0;) {
                 Spatial child = children.get(i);
                 if (child instanceof TerrainQuad) {
-                    ((TerrainQuad) child).reIndexPages(updated);
+                    ((TerrainQuad) child).reIndexPages(updated, usesVariableLod);
                 } else if (child instanceof TerrainPatch) {
-                    ((TerrainPatch) child).reIndexGeometry(updated);
+                    ((TerrainPatch) child).reIndexGeometry(updated, usesVariableLod);
                 }
             }
         }
@@ -616,8 +620,8 @@ public class TerrainQuad extends Node implements Terrain {
         Vector2f tempOffset = new Vector2f();
         offsetAmount += quarterSize;
 
-        if (lodCalculatorFactory == null)
-            lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one
+        //if (lodCalculator == null)
+        //    lodCalculator = createDefaultLodCalculator(); // set a default one
 
         // 1 upper left of heightmap, lower left quad
         float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);
@@ -632,7 +636,7 @@ public class TerrainQuad extends Node implements Terrain {
 
         TerrainQuad quad1 = new TerrainQuad(getName() + "Quad1", blockSize,
                         split, stepScale, heightBlock1, totalSize, tempOffset,
-                        offsetAmount, lodCalculatorFactory);
+                        offsetAmount);
         quad1.setLocalTranslation(origin1);
         quad1.quadrant = 1;
         this.attachChild(quad1);
@@ -652,7 +656,7 @@ public class TerrainQuad extends Node implements Terrain {
 
         TerrainQuad quad2 = new TerrainQuad(getName() + "Quad2", blockSize,
                         split, stepScale, heightBlock2, totalSize, tempOffset,
-                        offsetAmount, lodCalculatorFactory);
+                        offsetAmount);
         quad2.setLocalTranslation(origin2);
         quad2.quadrant = 2;
         this.attachChild(quad2);
@@ -672,7 +676,7 @@ public class TerrainQuad extends Node implements Terrain {
 
         TerrainQuad quad3 = new TerrainQuad(getName() + "Quad3", blockSize,
                         split, stepScale, heightBlock3, totalSize, tempOffset,
-                        offsetAmount, lodCalculatorFactory);
+                        offsetAmount);
         quad3.setLocalTranslation(origin3);
         quad3.quadrant = 3;
         this.attachChild(quad3);
@@ -692,7 +696,7 @@ public class TerrainQuad extends Node implements Terrain {
 
         TerrainQuad quad4 = new TerrainQuad(getName() + "Quad4", blockSize,
                         split, stepScale, heightBlock4, totalSize, tempOffset,
-                        offsetAmount, lodCalculatorFactory);
+                        offsetAmount);
         quad4.setLocalTranslation(origin4);
         quad4.quadrant = 4;
         this.attachChild(quad4);
@@ -724,8 +728,8 @@ public class TerrainQuad extends Node implements Terrain {
         int halfSize = size >> 1;
         int split = (size + 1) >> 1;
 
-        if (lodCalculatorFactory == null)
-            lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one
+        //if (lodCalculator == null)
+        //    lodCalculator = createDefaultLodCalculator(); // set a default one
 
         offsetAmount += quarterSize;
 
@@ -748,7 +752,7 @@ public class TerrainQuad extends Node implements Terrain {
         this.attachChild(patch1);
         patch1.setModelBound(new BoundingBox());
         patch1.updateModelBound();
-        patch1.setLodCalculator(lodCalculatorFactory);
+        //patch1.setLodCalculator(lodCalculator);
         //TangentBinormalGenerator.generate(patch1);
 
         // 2 lower left
@@ -770,7 +774,7 @@ public class TerrainQuad extends Node implements Terrain {
         this.attachChild(patch2);
         patch2.setModelBound(new BoundingBox());
         patch2.updateModelBound();
-        patch2.setLodCalculator(lodCalculatorFactory);
+        //patch2.setLodCalculator(lodCalculator);
         //TangentBinormalGenerator.generate(patch2);
 
         // 3 upper right
@@ -792,7 +796,7 @@ public class TerrainQuad extends Node implements Terrain {
         this.attachChild(patch3);
         patch3.setModelBound(new BoundingBox());
         patch3.updateModelBound();
-        patch3.setLodCalculator(lodCalculatorFactory);
+        //patch3.setLodCalculator(lodCalculator);
         //TangentBinormalGenerator.generate(patch3);
 
         // 4 lower right
@@ -814,7 +818,7 @@ public class TerrainQuad extends Node implements Terrain {
         this.attachChild(patch4);
         patch4.setModelBound(new BoundingBox());
         patch4.updateModelBound();
-        patch4.setLodCalculator(lodCalculatorFactory);
+        //patch4.setLodCalculator(lodCalculator);
         //TangentBinormalGenerator.generate(patch4);
     }
 
@@ -1634,7 +1638,8 @@ public class TerrainQuad extends Node implements Terrain {
         offsetAmount = c.readFloat("offsetAmount", 0);
         quadrant = c.readInt("quadrant", 0);
         totalSize = c.readInt("totalSize", 0);
-        lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);
+        //lodCalculator = (LodCalculator) c.readSavable("lodCalculator", createDefaultLodCalculator());
+        //lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);
         
         if ( !(getParent() instanceof TerrainQuad) ) {
             BoundingBox all = new BoundingBox(getWorldTranslation(), totalSize, totalSize, totalSize);
@@ -1653,7 +1658,8 @@ public class TerrainQuad extends Node implements Terrain {
         c.write(offset, "offset", new Vector2f(0,0));
         c.write(offsetAmount, "offsetAmount", 0);
         c.write(quadrant, "quadrant", 0);
-        c.write(lodCalculatorFactory, "lodCalculatorFactory", null);
+        //c.write(lodCalculatorFactory, "lodCalculatorFactory", null);
+        //c.write(lodCalculator, "lodCalculator", null);
     }
 
     @Override
@@ -1671,7 +1677,9 @@ public class TerrainQuad extends Node implements Terrain {
         quadClone.offset = offset.clone();
         quadClone.offsetAmount = offsetAmount;
         quadClone.quadrant = quadrant;
-        quadClone.lodCalculatorFactory = lodCalculatorFactory.clone();
+        //quadClone.lodCalculatorFactory = lodCalculatorFactory.clone();
+        //quadClone.lodCalculator = lodCalculator.clone();
+        
         TerrainLodControl lodControl = quadClone.getControl(TerrainLodControl.class);
         if (lodControl != null && !(getParent() instanceof TerrainQuad)) {
             lodControl.setTerrain(quadClone); // set println in controller update to see if it is updating
@@ -1682,8 +1690,7 @@ public class TerrainQuad extends Node implements Terrain {
 
         return quadClone;
     }
-
-
+    
     public int getMaxLod() {
         if (maxLod < 0)
             maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide
@@ -1699,7 +1706,6 @@ public class TerrainQuad extends Node implements Terrain {
         return totalSize;
     }
 
-
     public float[] getHeightMap() {
 
         float[] hm = null;

+ 46 - 32
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java

@@ -50,27 +50,23 @@ import java.util.List;
  */
 public class DistanceLodCalculator implements LodCalculator {
 
-    private TerrainPatch terrainPatch;
-    private LodThreshold lodThresholdCalculator;
-
+    private int size; // size of a terrain patch
+    private float lodMultiplier = 2;
+    
     public DistanceLodCalculator() {
     }
-
-    public DistanceLodCalculator(LodThreshold lodThresholdCalculator) {
-        this.lodThresholdCalculator = lodThresholdCalculator;
+    
+    public DistanceLodCalculator(int patchSize, float multiplier) {
+        this.size = patchSize;
+        this.lodMultiplier = multiplier;
     }
-
-    public DistanceLodCalculator(TerrainPatch terrainPatch, LodThreshold lodThresholdCalculator) {
-        this.terrainPatch = terrainPatch;
-        this.lodThresholdCalculator = lodThresholdCalculator;
-    }
-
-    public boolean calculateLod(List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) {
-        float distance = getCenterLocation().distance(locations.get(0));
+    
+    public boolean calculateLod(TerrainPatch terrainPatch, List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) {
+        float distance = getCenterLocation(terrainPatch).distance(locations.get(0));
 
         // go through each lod level to find the one we are in
         for (int i = 0; i <= terrainPatch.getMaxLod(); i++) {
-            if (distance < lodThresholdCalculator.getLodDistanceThreshold() * (i + 1)*terrainPatch.getWorldScale().x || i == terrainPatch.getMaxLod()) {
+            if (distance < getLodDistanceThreshold() * (i + 1)*terrainPatch.getWorldScale().x || i == terrainPatch.getMaxLod()) {
                 boolean reIndexNeeded = false;
                 if (i != terrainPatch.getLod()) {
                     reIndexNeeded = true;
@@ -94,49 +90,67 @@ public class DistanceLodCalculator implements LodCalculator {
         return false;
     }
 
-    public Vector3f getCenterLocation() {
+    protected Vector3f getCenterLocation(TerrainPatch terrainPatch) {
         Vector3f loc = terrainPatch.getWorldTranslation().clone();
         loc.x += terrainPatch.getSize()*terrainPatch.getWorldScale().x / 2;
         loc.z += terrainPatch.getSize()*terrainPatch.getWorldScale().z / 2;
         return loc;
     }
 
-    public void setTerrainPatch(TerrainPatch terrainPatch) {
-        this.terrainPatch = terrainPatch;
-    }
-
-    protected LodThreshold getLodThreshold() {
-        return lodThresholdCalculator;
-    }
-
-    protected void setLodThreshold(LodThreshold lodThresholdCalculator) {
-        this.lodThresholdCalculator = lodThresholdCalculator;
-    }
-
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);
-        oc.write(lodThresholdCalculator, "lodThresholdCalculator", null);
+        oc.write(size, "patchSize", 32);
+        oc.write(lodMultiplier, "lodMultiplier", 32);
     }
 
     public void read(JmeImporter im) throws IOException {
         InputCapsule ic = im.getCapsule(this);
-        lodThresholdCalculator = (LodThreshold) ic.readSavable("lodThresholdCalculator", null);
+        size = ic.readInt("patchSize", 32);
+        lodMultiplier = ic.readFloat("lodMultiplier", 2.7f);
     }
 
     @Override
     public LodCalculator clone() {
         DistanceLodCalculator clone = new DistanceLodCalculator();
-        clone.lodThresholdCalculator = lodThresholdCalculator.clone();
 
         return clone;
     }
 
     @Override
     public String toString() {
-        return "DistanceLodCalculator " + lodThresholdCalculator.toString();
+        return "DistanceLodCalculator "+size+"*"+lodMultiplier;
     }
 
+    /**
+     * Gets the camera distance where the LOD level will change
+     */
+    protected float getLodDistanceThreshold() {
+        return size*lodMultiplier;
+    }
+    
+    /**
+     * Does this calculator require the terrain to have the difference of 
+     * LOD levels of neighbours to be more than 1.
+     */
     public boolean usesVariableLod() {
         return false;
     }
+
+    public float getLodMultiplier() {
+        return lodMultiplier;
+    }
+
+    public void setLodMultiplier(float lodMultiplier) {
+        this.lodMultiplier = lodMultiplier;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+    
+    
 }

+ 2 - 3
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculator.java

@@ -47,9 +47,8 @@ import java.util.List;
  */
 public interface LodCalculator extends Savable, Cloneable {
 
-    public void setTerrainPatch(TerrainPatch terrainPatch);
-    public boolean calculateLod(List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates);
-
+    public boolean calculateLod(TerrainPatch terrainPatch, List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates);
+    
     public LodCalculator clone();
 
     /**

+ 1 - 0
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculatorFactory.java

@@ -39,6 +39,7 @@ import com.jme3.terrain.geomipmap.TerrainPatch;
  * Creates LOD Calculator objects for the terrain patches.
  *
  * @author Brent Owens
+ * @deprecated phasing this out
  */
 public interface LodCalculatorFactory extends Savable, Cloneable {
 

+ 2 - 3
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodDistanceCalculatorFactory.java

@@ -42,6 +42,7 @@ import java.io.IOException;
 /**
  *
  * @author bowens
+ * @deprecated phasing out
  */
 public class LodDistanceCalculatorFactory implements LodCalculatorFactory {
 
@@ -61,9 +62,7 @@ public class LodDistanceCalculatorFactory implements LodCalculatorFactory {
     }
 
     public LodCalculator createCalculator(TerrainPatch terrainPatch) {
-        if (lodThreshold == null)
-            lodThreshold = new SimpleLodThreshold(terrainPatch.getSize(), lodThresholdSize);
-        return new DistanceLodCalculator(terrainPatch, lodThreshold);
+        return new DistanceLodCalculator();
     }
 
     public void write(JmeExporter ex) throws IOException {

+ 1 - 1
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodPerspectiveCalculatorFactory.java

@@ -42,6 +42,7 @@ import java.io.IOException;
  * TODO: Make it work with multiple cameras
  * TODO: Fix the cracks when the lod differences are greater than 1
  * for two adjacent blocks.
+ * @deprecated phasing out
  */
 public class LodPerspectiveCalculatorFactory implements LodCalculatorFactory {
 
@@ -59,7 +60,6 @@ public class LodPerspectiveCalculatorFactory implements LodCalculatorFactory {
 
     public LodCalculator createCalculator(TerrainPatch terrainPatch) {
         PerspectiveLodCalculator p = new PerspectiveLodCalculator(cam, pixelError);
-        p.setTerrainPatch(terrainPatch);
         return p;
     }
 

+ 4 - 4
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodThreshold.java

@@ -45,10 +45,10 @@ import com.jme3.export.Savable;
  */
 public interface LodThreshold extends Savable, Cloneable {
 
-	/**
-	 * A distance of how far between each LOD threshold.
-	 */
-	public float getLodDistanceThreshold();
+    /**
+     * A distance of how far between each LOD threshold.
+     */
+    public float getLodDistanceThreshold();
 
     public LodThreshold clone();
 }

+ 22 - 6
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/PerspectiveLodCalculator.java

@@ -50,6 +50,8 @@ public class PerspectiveLodCalculator implements LodCalculator {
     private float[] entropyDistances;
     private float pixelError;
 
+    public PerspectiveLodCalculator() {}
+    
     public PerspectiveLodCalculator(Camera cam, float pixelError){
         this.cam = cam;
         this.pixelError = pixelError;
@@ -71,12 +73,12 @@ public class PerspectiveLodCalculator implements LodCalculator {
         float T = (2f * pixelLimit) / v_res;
         return A / T;
     }
-
-    public void setTerrainPatch(TerrainPatch terrainPatch) {
-        patch = terrainPatch;
+    
+    public boolean calculateLod(List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) {
+        return calculateLod(patch, locations, updates);
     }
 
-    public boolean calculateLod(List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) {
+    public boolean calculateLod(TerrainPatch terrainPatch, List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) {
         if (entropyDistances == null){
             // compute entropy distances
             float[] lodEntropies = patch.getLodEntropies();
@@ -87,7 +89,7 @@ public class PerspectiveLodCalculator implements LodCalculator {
             }
         }
 
-        Vector3f patchPos = getCenterLocation();
+        Vector3f patchPos = getCenterLocation(patch);
 
         // vector from camera to patch
         //Vector3f toPatchDir = locations.get(0).subtract(patchPos).normalizeLocal();
@@ -120,7 +122,7 @@ public class PerspectiveLodCalculator implements LodCalculator {
         return false;
     }
 
-    public Vector3f getCenterLocation() {
+    public Vector3f getCenterLocation(TerrainPatch patch) {
         Vector3f loc = patch.getWorldTranslation().clone();
         loc.x += patch.getSize() / 2;
         loc.z += patch.getSize() / 2;
@@ -146,4 +148,18 @@ public class PerspectiveLodCalculator implements LodCalculator {
         return true;
     }
 
+    public float getPixelError() {
+        return pixelError;
+    }
+
+    public void setPixelError(float pixelError) {
+        this.pixelError = pixelError;
+    }
+
+    public void setCam(Camera cam) {
+        this.cam = cam;
+    }
+
+    
+    
 }

+ 14 - 8
engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/SimpleLodThreshold.java

@@ -36,6 +36,8 @@ import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
+import com.jme3.terrain.Terrain;
+import com.jme3.terrain.geomipmap.TerrainQuad;
 import java.io.IOException;
 
 
@@ -49,17 +51,21 @@ import java.io.IOException;
  */
 public class SimpleLodThreshold implements LodThreshold {
 	
-	private int size; // size of a terrain patch
+    private int size; // size of a terrain patch
     private float lodMultiplier = 2;
 
     
     public SimpleLodThreshold() {
-
+    }
+    
+    public SimpleLodThreshold(Terrain terrain) {
+        if (terrain instanceof TerrainQuad)
+            this.size = ((TerrainQuad)terrain).getPatchSize();
     }
 
-	public SimpleLodThreshold(int patchSize, float lodMultiplier) {
-		this.size = patchSize;
-	}
+    public SimpleLodThreshold(int patchSize, float lodMultiplier) {
+        this.size = patchSize;
+    }
 
     public float getLodMultiplier() {
         return lodMultiplier;
@@ -78,9 +84,9 @@ public class SimpleLodThreshold implements LodThreshold {
     }
 	
 
-	public float getLodDistanceThreshold() {
-		return size*lodMultiplier;
-	}
+    public float getLodDistanceThreshold() {
+        return size*lodMultiplier;
+    }
 
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainFractalGridTest.java

@@ -22,6 +22,7 @@ import com.jme3.renderer.Camera;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.terrain.heightmap.FractalHeightMapGrid;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
@@ -145,6 +146,7 @@ public class TerrainFractalGridTest extends SimpleApplication {
         List<Camera> cameras = new ArrayList<Camera>();
         cameras.add(this.getCamera());
         TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
+        control.setLodCalculator( new DistanceLodCalculator(33, 2.7f) ); // patch size, and a multiplier
         this.terrain.addControl(control);
 
         final BulletAppState bulletAppState = new BulletAppState();

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java

@@ -26,6 +26,7 @@ import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.terrain.heightmap.FractalHeightMapGrid;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.Namer;
@@ -158,6 +159,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
         List<Camera> cameras = new ArrayList<Camera>();
         cameras.add(this.getCamera());
         TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
+        control.setLodCalculator( new DistanceLodCalculator(33, 2.7f) ); // patch size, and a multiplier
         this.terrain.addControl(control);
 
         final BulletAppState bulletAppState = new BulletAppState();

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainGridTest.java

@@ -19,6 +19,7 @@ import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.Namer;
 import com.jme3.texture.Texture;
@@ -106,6 +107,7 @@ public class TerrainGridTest extends SimpleApplication {
         this.rootNode.attachChild(this.terrain);
 
         TerrainLodControl control = new TerrainLodControl(this.terrain, getCamera());
+        control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
         this.terrain.addControl(control);
 
         final BulletAppState bulletAppState = new BulletAppState();

+ 4 - 1
engine/src/test/jme3test/terrain/TerrainTest.java

@@ -47,6 +47,8 @@ import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
+import com.jme3.terrain.geomipmap.lodcalc.SimpleLodThreshold;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
 
@@ -155,8 +157,9 @@ public class TerrainTest extends SimpleApplication {
          * The total size is up to you. At 1025 it ran fine for me (200+FPS), however at
          * size=2049, it got really slow. But that is a jump from 2 million to 8 million triangles...
          */
-        terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
+        terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
         TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
+        control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
         terrain.addControl(control);
         terrain.setMaterial(matRock);
         terrain.setLocalTranslation(0, -100, 0);

+ 14 - 15
engine/src/test/jme3test/terrain/TerrainTestAdvanced.java

@@ -50,6 +50,7 @@ import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
 import com.jme3.util.SkyFactory;
@@ -96,7 +97,6 @@ public class TerrainTestAdvanced extends SimpleApplication {
         // TERRAIN TEXTURE material
         matTerrain = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
         matTerrain.setBoolean("useTriPlanarMapping", false);
-        matTerrain.setBoolean("WardIso", true);
 
         // ALPHA map (for splat textures)
         matTerrain.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/splat/alpha1.png"));
@@ -105,18 +105,17 @@ public class TerrainTestAdvanced extends SimpleApplication {
         // HEIGHTMAP image (for the terrain heightmap)
         Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
 
-
         // GRASS texture
         Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
         grass.setWrap(WrapMode.Repeat);
-        matTerrain.setTexture("DiffuseMap", grass);
-        matTerrain.setFloat("DiffuseMap_0_scale", grassScale);
+        matTerrain.setTexture("DiffuseMap_1", grass);
+        matTerrain.setFloat("DiffuseMap_1_scale", grassScale);
 
         // DIRT texture
         Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
         dirt.setWrap(WrapMode.Repeat);
-        matTerrain.setTexture("DiffuseMap_1", dirt);
-        matTerrain.setFloat("DiffuseMap_1_scale", dirtScale);
+        matTerrain.setTexture("DiffuseMap", dirt);
+        matTerrain.setFloat("DiffuseMap_0_scale", dirtScale);
 
         // ROCK texture
         Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
@@ -143,7 +142,7 @@ public class TerrainTestAdvanced extends SimpleApplication {
         normalMap1.setWrap(WrapMode.Repeat);
         Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
         normalMap2.setWrap(WrapMode.Repeat);
-        matTerrain.setTexture("NormalMap", normalMap0);
+        matTerrain.setTexture("NormalMap", normalMap2);
         matTerrain.setTexture("NormalMap_1", normalMap2);
         matTerrain.setTexture("NormalMap_2", normalMap2);
         matTerrain.setTexture("NormalMap_4", normalMap2);
@@ -158,10 +157,9 @@ public class TerrainTestAdvanced extends SimpleApplication {
         // CREATE HEIGHTMAP
         AbstractHeightMap heightmap = null;
         try {
-            //heightmap = new HillHeightMap(1025, 1000, 50, 100, (byte) 3);
-
-            heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
+            heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 0.5f);
             heightmap.load();
+            heightmap.smooth(0.9f, 1);
 
         } catch (Exception e) {
             e.printStackTrace();
@@ -178,6 +176,7 @@ public class TerrainTestAdvanced extends SimpleApplication {
          */
         terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
         TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
+        control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
         terrain.addControl(control);
         terrain.setMaterial(matTerrain);
         terrain.setModelBound(new BoundingBox());
@@ -185,17 +184,17 @@ public class TerrainTestAdvanced extends SimpleApplication {
         terrain.setLocalTranslation(0, -100, 0);
         terrain.setLocalScale(1f, 1f, 1f);
         rootNode.attachChild(terrain);
+        
+        Material debugMat = assetManager.loadMaterial("Common/Materials/VertexColor.j3m");
+        //terrain.generateDebugTangents(debugMat);
 
         DirectionalLight light = new DirectionalLight();
-        light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());
+        light.setDirection((new Vector3f(-0.25f, -1f, -0.25f)).normalize());
         rootNode.addLight(light);
 
-        AmbientLight ambLight = new AmbientLight();
-        ambLight.setColor(new ColorRGBA(1f, 1f, 0.8f, 0.2f));
-        rootNode.addLight(ambLight);
-
         cam.setLocation(new Vector3f(0, 10, -10));
         cam.lookAtDirection(new Vector3f(0, -1.5f, -1).normalizeLocal(), Vector3f.UNIT_Y);
+        flyCam.setMoveSpeed(400);
     }
 
     public void loadHintText() {

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainTestCollision.java

@@ -60,6 +60,7 @@ import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
 
@@ -134,6 +135,7 @@ public class TerrainTestCollision extends SimpleApplication {
 
         terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
         TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
+        control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
         terrain.addControl(control);
         terrain.setMaterial(matRock);
         terrain.setLocalScale(new Vector3f(2, 2, 2));

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainTestModifyHeight.java

@@ -54,6 +54,7 @@ import com.jme3.scene.shape.Sphere;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.FractalHeightMapGrid;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
@@ -317,6 +318,7 @@ public class TerrainTestModifyHeight extends SimpleApplication {
         // CREATE THE TERRAIN
         terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
         TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
+        control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
         terrain.addControl(control);
         terrain.setMaterial(matTerrain);
         terrain.setLocalTranslation(0, -100, 0);

+ 2 - 0
engine/src/test/jme3test/terrain/TerrainTestReadWrite.java

@@ -47,6 +47,7 @@ import com.jme3.scene.Node;
 import com.jme3.terrain.Terrain;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainQuad;
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
 import com.jme3.texture.Texture;
@@ -159,6 +160,7 @@ public class TerrainTestReadWrite extends SimpleApplication {
             // create the terrain as normal, and give it a control for LOD management
             TerrainQuad terrainQuad = new TerrainQuad("terrain", 65, 129, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
             TerrainLodControl control = new TerrainLodControl(terrainQuad, getCamera());
+            control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
             terrainQuad.addControl(control);
             terrainQuad.setMaterial(matTerrain);
             terrainQuad.setLocalTranslation(0, -100, 0);