* 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
3.0
bre..ns 14 years ago
parent b8618eba26
commit 3383e2e086
  1. 3
      engine/src/terrain/com/jme3/terrain/Terrain.java
  2. 28
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java
  3. 17
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java
  4. 47
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java
  5. 120
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java
  6. 78
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java
  7. 5
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculator.java
  8. 1
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodCalculatorFactory.java
  9. 5
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodDistanceCalculatorFactory.java
  10. 2
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodPerspectiveCalculatorFactory.java
  11. 8
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/LodThreshold.java
  12. 28
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/PerspectiveLodCalculator.java
  13. 22
      engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/SimpleLodThreshold.java
  14. 2
      engine/src/test/jme3test/terrain/TerrainFractalGridTest.java
  15. 2
      engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java
  16. 2
      engine/src/test/jme3test/terrain/TerrainGridTest.java
  17. 5
      engine/src/test/jme3test/terrain/TerrainTest.java
  18. 29
      engine/src/test/jme3test/terrain/TerrainTestAdvanced.java
  19. 2
      engine/src/test/jme3test/terrain/TerrainTestCollision.java
  20. 2
      engine/src/test/jme3test/terrain/TerrainTestModifyHeight.java
  21. 2
      engine/src/test/jme3test/terrain/TerrainTestReadWrite.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.

@ -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) {

@ -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());
}
}

@ -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);

@ -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;

@ -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;
}
}

@ -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();
/**

@ -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 {

@ -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 {

@ -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;
}

@ -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();
}

@ -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;
}
}

@ -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);

@ -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();

@ -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();

@ -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();

@ -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);

@ -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() {

@ -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));

@ -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);

@ -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);

Loading…
Cancel
Save