import com.jme3.material.Material;\r
import com.jme3.math.Vector2f;\r
import com.jme3.math.Vector3f;\r
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;\r
import java.util.List;\r
\r
/**\r
* @param location: the Camera's location. A list of one camera location is normal \r
* if you just have one camera in your scene.\r
*/\r
- public void update(List<Vector3f> location);\r
+ public void update(List<Vector3f> location, LodCalculator lodCalculator);\r
\r
/**\r
* Lock or unlock the meshes of this terrain.\r
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;
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());
}
}
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;
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),
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() {
}
@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
l.gridMoved(camCell);
}
}
- super.update(locations);
+ super.update(locations, lodCalculator);
}
public Vector3f getCell(Vector3f location) {
import com.jme3.scene.control.AbstractControl;\r
import com.jme3.scene.control.Control;\r
import com.jme3.terrain.Terrain;\r
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;\r
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;\r
import java.io.IOException;\r
import java.util.ArrayList;\r
\r
private Terrain terrain;\r
private List<Camera> cameras;\r
private List<Vector3f> cameraLocations = new ArrayList<Vector3f>();\r
+ private LodCalculator lodCalculator;\r
\r
public TerrainLodControl() {\r
}\r
cams.add(camera);\r
this.terrain = terrain;\r
this.cameras = cams;\r
+ lodCalculator = new DistanceLodCalculator(); // a default calculator\r
}\r
\r
/**\r
cameraLocations.add(c.getLocation());\r
}\r
}\r
- terrain.update(cameraLocations);\r
+ terrain.update(cameraLocations, lodCalculator);\r
}\r
}\r
\r
this.terrain = terrain;\r
}\r
\r
+ public LodCalculator getLodCalculator() {\r
+ return lodCalculator;\r
+ }\r
+\r
+ public void setLodCalculator(LodCalculator lodCalculator) {\r
+ this.lodCalculator = lodCalculator;\r
+ }\r
+ \r
+\r
@Override\r
public void write(JmeExporter ex) throws IOException {\r
super.write(ex);\r
OutputCapsule oc = ex.getCapsule(this);\r
oc.write((Node)terrain, "terrain", null);\r
+ oc.write(lodCalculator, "lodCalculator", null);\r
}\r
\r
@Override\r
super.read(im);\r
InputCapsule ic = im.getCapsule(this);\r
terrain = (Terrain) ic.readSavable("terrain", null);\r
+ lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());\r
}\r
}\r
// amount the patch has been shifted.\r
protected float offsetAmount;\r
\r
- protected LodCalculator lodCalculator;\r
- protected LodCalculatorFactory lodCalculatorFactory;\r
+ //protected LodCalculator lodCalculator;\r
+ //protected LodCalculatorFactory lodCalculatorFactory;\r
\r
protected TerrainPatch leftNeighbour, topNeighbour, rightNeighbour, bottomNeighbour;\r
protected boolean searchedForNeighboursAlready = false;\r
return maxLod;\r
}\r
\r
- \r
- \r
-\r
- /**\r
- * Delegates to the lodCalculator that was passed in.\r
- * @param locations all possible camera locations\r
- * @param updates update objects that may or may not contain this terrain patch\r
- * @return true if the geometry needs re-indexing\r
- */\r
- protected boolean calculateLod(List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates) {\r
- return lodCalculator.calculateLod(locations, updates);\r
- }\r
-\r
- protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated, boolean useVariableLod) {\r
\r
UpdatedTerrainPatch utp = updated.get(getName());\r
\r
boolean bottom = utp.getBottomLod() > utp.getNewLod();\r
\r
IntBuffer ib = null;\r
- if (lodCalculator.usesVariableLod())\r
+ if (useVariableLod)\r
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()));\r
else\r
ib = geomap.writeIndexArrayLodDiff(null, pow, right, top, left, bottom);\r
protected void setLodBottom(int lodBottom) {\r
this.lodBottom = lodBottom;\r
}\r
-\r
- public LodCalculator getLodCalculator() {\r
- return lodCalculator;\r
- }\r
-\r
- public void setLodCalculator(LodCalculator lodCalculator) {\r
- this.lodCalculator = lodCalculator;\r
- }\r
-\r
- public void setLodCalculator(LodCalculatorFactory lodCalculatorFactory) {\r
+ \r
+ /*public void setLodCalculator(LodCalculatorFactory lodCalculatorFactory) {\r
this.lodCalculatorFactory = lodCalculatorFactory;\r
setLodCalculator(lodCalculatorFactory.createCalculator(this));\r
- }\r
+ }*/\r
\r
@Override\r
public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException {\r
oc.write(stepScale, "stepScale", Vector3f.UNIT_XYZ);\r
oc.write(offset, "offset", Vector3f.UNIT_XYZ);\r
oc.write(offsetAmount, "offsetAmount", 0);\r
- oc.write(lodCalculator, "lodCalculator", null);\r
- oc.write(lodCalculatorFactory, "lodCalculatorFactory", null);\r
+ //oc.write(lodCalculator, "lodCalculator", null);\r
+ //oc.write(lodCalculatorFactory, "lodCalculatorFactory", null);\r
oc.write(lodEntropy, "lodEntropy", null);\r
oc.write(geomap, "geomap", null);\r
\r
stepScale = (Vector3f) ic.readSavable("stepScale", Vector3f.UNIT_XYZ);\r
offset = (Vector2f) ic.readSavable("offset", Vector3f.UNIT_XYZ);\r
offsetAmount = ic.readFloat("offsetAmount", 0);\r
- lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());\r
- lodCalculator.setTerrainPatch(this);\r
- lodCalculatorFactory = (LodCalculatorFactory) ic.readSavable("lodCalculatorFactory", null);\r
+ //lodCalculator = (LodCalculator) ic.readSavable("lodCalculator", new DistanceLodCalculator());\r
+ //lodCalculator.setTerrainPatch(this);\r
+ //lodCalculatorFactory = (LodCalculatorFactory) ic.readSavable("lodCalculatorFactory", null);\r
lodEntropy = ic.readFloatArray("lodEntropy", null);\r
geomap = (LODGeomap) ic.readSavable("geomap", null);\r
\r
clone.offsetAmount = offsetAmount;\r
//clone.lodCalculator = lodCalculator.clone();\r
//clone.lodCalculator.setTerrainPatch(clone);\r
- clone.setLodCalculator(lodCalculatorFactory.clone());\r
+ //clone.setLodCalculator(lodCalculatorFactory.clone());\r
clone.geomap = new LODGeomap(size, geomap.getHeightData());\r
clone.setLocalTranslation(getLocalTranslation().clone());\r
Mesh m = clone.geomap.createMesh(clone.stepScale, Vector2f.UNIT_XY, clone.offset, clone.offsetAmount, clone.totalSize, false);\r
import com.jme3.scene.debug.WireBox;\r
import com.jme3.terrain.ProgressMonitor;\r
import com.jme3.terrain.Terrain;\r
-import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;\r
-import com.jme3.terrain.geomipmap.lodcalc.LodDistanceCalculatorFactory;\r
+import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;\r
+import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;\r
+import com.jme3.terrain.geomipmap.lodcalc.SimpleLodThreshold;\r
import com.jme3.terrain.geomipmap.picking.BresenhamTerrainPicker;\r
import com.jme3.terrain.geomipmap.picking.TerrainPickData;\r
import com.jme3.terrain.geomipmap.picking.TerrainPicker;\r
\r
protected int quadrant = 1; // 1=upper left, 2=lower left, 3=upper right, 4=lower right\r
\r
- protected LodCalculatorFactory lodCalculatorFactory;\r
+ //protected LodCalculatorFactory lodCalculatorFactory;\r
+ //protected LodCalculator lodCalculator;\r
\r
protected List<Vector3f> lastCameraLocations; // used for LOD calc\r
private boolean lodCalcRunning = false;\r
}\r
\r
public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap) {\r
- this(name, patchSize, totalSize, heightMap, null);\r
- }\r
-\r
- public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
- this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap, lodCalculatorFactory);\r
+ this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap);\r
}\r
\r
- public TerrainQuad(String name, int patchSize, int size, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
- this(name, patchSize, size, Vector3f.UNIT_XYZ, heightMap, totalSize, new Vector2f(), 0, lodCalculatorFactory);\r
+ public TerrainQuad(String name, int patchSize, int quadSize, int totalSize, float[] heightMap) {\r
+ this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap);\r
+ }\r
+\r
+ public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap) {\r
+ this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0);\r
affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);\r
fixNormalEdges(affectedAreaBBox);\r
addControl(new NormalRecalcControl(this));\r
}\r
-\r
- public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
- this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory);\r
- affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size*2, Float.MAX_VALUE, size*2);\r
+ \r
+ public TerrainQuad(String name, int patchSize, int totalSize, int quadSize, Vector3f scale, float[] heightMap) {\r
+ this(name, patchSize, quadSize, scale, heightMap, totalSize, new Vector2f(), 0);\r
+ affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), totalSize*2, Float.MAX_VALUE, totalSize*2);\r
fixNormalEdges(affectedAreaBBox);\r
addControl(new NormalRecalcControl(this));\r
}\r
\r
- protected TerrainQuad(String name, int patchSize, int size,\r
+ protected TerrainQuad(String name, int patchSize, int quadSize,\r
Vector3f scale, float[] heightMap, int totalSize,\r
- Vector2f offset, float offsetAmount,\r
- LodCalculatorFactory lodCalculatorFactory)\r
+ Vector2f offset, float offsetAmount)\r
{\r
super(name);\r
\r
if (heightMap == null)\r
- heightMap = generateDefaultHeightMap(size);\r
+ heightMap = generateDefaultHeightMap(quadSize);\r
\r
- if (!FastMath.isPowerOfTwo(size - 1)) {\r
- throw new RuntimeException("size given: " + size + " Terrain quad sizes may only be (2^N + 1)");\r
+ if (!FastMath.isPowerOfTwo(quadSize - 1)) {\r
+ throw new RuntimeException("size given: " + quadSize + " Terrain quad sizes may only be (2^N + 1)");\r
}\r
- if (FastMath.sqrt(heightMap.length) > size) {\r
+ if (FastMath.sqrt(heightMap.length) > quadSize) {\r
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!");\r
}\r
\r
this.offset = offset;\r
this.offsetAmount = offsetAmount;\r
this.totalSize = totalSize;\r
- this.size = size;\r
+ this.size = quadSize;\r
this.patchSize = patchSize;\r
this.stepScale = scale;\r
- this.lodCalculatorFactory = lodCalculatorFactory;\r
+ //this.lodCalculatorFactory = lodCalculatorFactory;\r
+ //this.lodCalculator = lodCalculator;\r
split(patchSize, heightMap);\r
}\r
\r
- public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {\r
+ /*public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {\r
if (children != null) {\r
for (int i = children.size(); --i >= 0;) {\r
Spatial child = children.get(i);\r
}\r
}\r
}\r
- }\r
+ }*/\r
\r
\r
/**\r
* This will perform the geometry calculation in a background thread and\r
* do the actual update on the opengl thread.\r
*/\r
- public void update(List<Vector3f> locations) {\r
- updateLOD(locations);\r
+ public void update(List<Vector3f> locations, LodCalculator lodCalculator) {\r
+ updateLOD(locations, lodCalculator);\r
}\r
\r
/**\r
}\r
\r
// do all of the LOD calculations\r
- protected void updateLOD(List<Vector3f> locations) {\r
+ protected void updateLOD(List<Vector3f> locations, LodCalculator lodCalculator) {\r
// update any existing ones that need updating\r
updateQuadLODs();\r
\r
if (executor == null)\r
executor = createExecutorService();\r
\r
- UpdateLOD updateLodThread = new UpdateLOD(locations);\r
+ UpdateLOD updateLodThread = new UpdateLOD(locations, lodCalculator);\r
executor.execute(updateLodThread);\r
}\r
\r
*/\r
private class UpdateLOD implements Runnable {\r
private List<Vector3f> camLocations;\r
+ private LodCalculator lodCalculator;\r
\r
- UpdateLOD(List<Vector3f> location) {\r
- camLocations = location;\r
+ UpdateLOD(List<Vector3f> camLocations, LodCalculator lodCalculator) {\r
+ this.camLocations = camLocations;\r
+ this.lodCalculator = lodCalculator;\r
}\r
\r
public void run() {\r
\r
// go through each patch and calculate its LOD based on camera distance\r
HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();\r
- boolean lodChanged = calculateLod(camLocations, updated); // 'updated' gets populated here\r
+ boolean lodChanged = calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here\r
\r
if (!lodChanged) {\r
// not worth updating anything else since no one's LOD changed\r
\r
fixEdges(updated); // 'updated' can get added to here\r
\r
- reIndexPages(updated);\r
+ reIndexPages(updated, lodCalculator.usesVariableLod());\r
\r
setUpdateQuadLODs(updated); // set back to main ogl thread\r
\r
}\r
}\r
\r
- protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates) {\r
+ protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates, LodCalculator lodCalculator) {\r
\r
boolean lodChanged = false;\r
\r
for (int i = children.size(); --i >= 0;) {\r
Spatial child = children.get(i);\r
if (child instanceof TerrainQuad) {\r
- boolean b = ((TerrainQuad) child).calculateLod(location, updates);\r
+ boolean b = ((TerrainQuad) child).calculateLod(location, updates, lodCalculator);\r
if (b)\r
lodChanged = true;\r
} else if (child instanceof TerrainPatch) {\r
- boolean b = ((TerrainPatch) child).calculateLod(location, updates);\r
+ boolean b = lodCalculator.calculateLod((TerrainPatch) child, location, updates);\r
if (b)\r
lodChanged = true;\r
}\r
}\r
}\r
\r
- protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated, boolean usesVariableLod) {\r
if (children != null) {\r
for (int i = children.size(); --i >= 0;) {\r
Spatial child = children.get(i);\r
if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).reIndexPages(updated);\r
+ ((TerrainQuad) child).reIndexPages(updated, usesVariableLod);\r
} else if (child instanceof TerrainPatch) {\r
- ((TerrainPatch) child).reIndexGeometry(updated);\r
+ ((TerrainPatch) child).reIndexGeometry(updated, usesVariableLod);\r
}\r
}\r
}\r
Vector2f tempOffset = new Vector2f();\r
offsetAmount += quarterSize;\r
\r
- if (lodCalculatorFactory == null)\r
- lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+ //if (lodCalculator == null)\r
+ // lodCalculator = createDefaultLodCalculator(); // set a default one\r
\r
// 1 upper left of heightmap, lower left quad\r
float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
\r
TerrainQuad quad1 = new TerrainQuad(getName() + "Quad1", blockSize,\r
split, stepScale, heightBlock1, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
+ offsetAmount);\r
quad1.setLocalTranslation(origin1);\r
quad1.quadrant = 1;\r
this.attachChild(quad1);\r
\r
TerrainQuad quad2 = new TerrainQuad(getName() + "Quad2", blockSize,\r
split, stepScale, heightBlock2, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
+ offsetAmount);\r
quad2.setLocalTranslation(origin2);\r
quad2.quadrant = 2;\r
this.attachChild(quad2);\r
\r
TerrainQuad quad3 = new TerrainQuad(getName() + "Quad3", blockSize,\r
split, stepScale, heightBlock3, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
+ offsetAmount);\r
quad3.setLocalTranslation(origin3);\r
quad3.quadrant = 3;\r
this.attachChild(quad3);\r
\r
TerrainQuad quad4 = new TerrainQuad(getName() + "Quad4", blockSize,\r
split, stepScale, heightBlock4, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
+ offsetAmount);\r
quad4.setLocalTranslation(origin4);\r
quad4.quadrant = 4;\r
this.attachChild(quad4);\r
int halfSize = size >> 1;\r
int split = (size + 1) >> 1;\r
\r
- if (lodCalculatorFactory == null)\r
- lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+ //if (lodCalculator == null)\r
+ // lodCalculator = createDefaultLodCalculator(); // set a default one\r
\r
offsetAmount += quarterSize;\r
\r
this.attachChild(patch1);\r
patch1.setModelBound(new BoundingBox());\r
patch1.updateModelBound();\r
- patch1.setLodCalculator(lodCalculatorFactory);\r
+ //patch1.setLodCalculator(lodCalculator);\r
//TangentBinormalGenerator.generate(patch1);\r
\r
// 2 lower left\r
this.attachChild(patch2);\r
patch2.setModelBound(new BoundingBox());\r
patch2.updateModelBound();\r
- patch2.setLodCalculator(lodCalculatorFactory);\r
+ //patch2.setLodCalculator(lodCalculator);\r
//TangentBinormalGenerator.generate(patch2);\r
\r
// 3 upper right\r
this.attachChild(patch3);\r
patch3.setModelBound(new BoundingBox());\r
patch3.updateModelBound();\r
- patch3.setLodCalculator(lodCalculatorFactory);\r
+ //patch3.setLodCalculator(lodCalculator);\r
//TangentBinormalGenerator.generate(patch3);\r
\r
// 4 lower right\r
this.attachChild(patch4);\r
patch4.setModelBound(new BoundingBox());\r
patch4.updateModelBound();\r
- patch4.setLodCalculator(lodCalculatorFactory);\r
+ //patch4.setLodCalculator(lodCalculator);\r
//TangentBinormalGenerator.generate(patch4);\r
}\r
\r
offsetAmount = c.readFloat("offsetAmount", 0);\r
quadrant = c.readInt("quadrant", 0);\r
totalSize = c.readInt("totalSize", 0);\r
- lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);\r
+ //lodCalculator = (LodCalculator) c.readSavable("lodCalculator", createDefaultLodCalculator());\r
+ //lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);\r
\r
if ( !(getParent() instanceof TerrainQuad) ) {\r
BoundingBox all = new BoundingBox(getWorldTranslation(), totalSize, totalSize, totalSize);\r
c.write(offset, "offset", new Vector2f(0,0));\r
c.write(offsetAmount, "offsetAmount", 0);\r
c.write(quadrant, "quadrant", 0);\r
- c.write(lodCalculatorFactory, "lodCalculatorFactory", null);\r
+ //c.write(lodCalculatorFactory, "lodCalculatorFactory", null);\r
+ //c.write(lodCalculator, "lodCalculator", null);\r
}\r
\r
@Override\r
quadClone.offset = offset.clone();\r
quadClone.offsetAmount = offsetAmount;\r
quadClone.quadrant = quadrant;\r
- quadClone.lodCalculatorFactory = lodCalculatorFactory.clone();\r
+ //quadClone.lodCalculatorFactory = lodCalculatorFactory.clone();\r
+ //quadClone.lodCalculator = lodCalculator.clone();\r
+ \r
TerrainLodControl lodControl = quadClone.getControl(TerrainLodControl.class);\r
if (lodControl != null && !(getParent() instanceof TerrainQuad)) {\r
lodControl.setTerrain(quadClone); // set println in controller update to see if it is updating\r
\r
return quadClone;\r
}\r
-\r
-\r
+ \r
public int getMaxLod() {\r
if (maxLod < 0)\r
maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide\r
return totalSize;\r
}\r
\r
-\r
public float[] getHeightMap() {\r
\r
float[] hm = null;\r
*/
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;
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;
+ }
+
+
}
*/
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();
/**
* Creates LOD Calculator objects for the terrain patches.
*
* @author Brent Owens
+ * @deprecated phasing this out
*/
public interface LodCalculatorFactory extends Savable, Cloneable {
/**
*
* @author bowens
+ * @deprecated phasing out
*/
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 {
* 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 {
public LodCalculator createCalculator(TerrainPatch terrainPatch) {
PerspectiveLodCalculator p = new PerspectiveLodCalculator(cam, pixelError);
- p.setTerrainPatch(terrainPatch);
return p;
}
*/\r
public interface LodThreshold extends Savable, Cloneable {\r
\r
- /**\r
- * A distance of how far between each LOD threshold.\r
- */\r
- public float getLodDistanceThreshold();\r
+ /**\r
+ * A distance of how far between each LOD threshold.\r
+ */\r
+ public float getLodDistanceThreshold();\r
\r
public LodThreshold clone();\r
}\r
private float[] entropyDistances;
private float pixelError;
+ public PerspectiveLodCalculator() {}
+
public PerspectiveLodCalculator(Camera cam, float pixelError){
this.cam = cam;
this.pixelError = pixelError;
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();
}
}
- Vector3f patchPos = getCenterLocation();
+ Vector3f patchPos = getCenterLocation(patch);
// vector from camera to patch
//Vector3f toPatchDir = locations.get(0).subtract(patchPos).normalizeLocal();
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;
return true;
}
+ public float getPixelError() {
+ return pixelError;
+ }
+
+ public void setPixelError(float pixelError) {
+ this.pixelError = pixelError;
+ }
+
+ public void setCam(Camera cam) {
+ this.cam = cam;
+ }
+
+
+
}
import com.jme3.export.JmeExporter;\r
import com.jme3.export.JmeImporter;\r
import com.jme3.export.OutputCapsule;\r
+import com.jme3.terrain.Terrain;\r
+import com.jme3.terrain.geomipmap.TerrainQuad;\r
import java.io.IOException;\r
\r
\r
*/\r
public class SimpleLodThreshold implements LodThreshold {\r
\r
- private int size; // size of a terrain patch\r
+ private int size; // size of a terrain patch\r
private float lodMultiplier = 2;\r
\r
\r
public SimpleLodThreshold() {\r
-\r
+ }\r
+ \r
+ public SimpleLodThreshold(Terrain terrain) {\r
+ if (terrain instanceof TerrainQuad)\r
+ this.size = ((TerrainQuad)terrain).getPatchSize();\r
}\r
\r
- public SimpleLodThreshold(int patchSize, float lodMultiplier) {\r
- this.size = patchSize;\r
- }\r
+ public SimpleLodThreshold(int patchSize, float lodMultiplier) {\r
+ this.size = patchSize;\r
+ }\r
\r
public float getLodMultiplier() {\r
return lodMultiplier;\r
}\r
\r
\r
- public float getLodDistanceThreshold() {\r
- return size*lodMultiplier;\r
- }\r
+ public float getLodDistanceThreshold() {\r
+ return size*lodMultiplier;\r
+ }\r
\r
public void write(JmeExporter ex) throws IOException {\r
OutputCapsule oc = ex.getCapsule(this);\r
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;
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();
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;
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();
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;
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();
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;
* 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);
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;
// 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"));
// 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");
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);
// 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();
*/
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());
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() {
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;
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));
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;
// 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);
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;
// 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);