Softened terrain API to allow for different tiling implementations. Added MultiTerrainLodControl
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9434 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
b5aa49bc16
commit
33a69d4536
@ -154,6 +154,9 @@ public class LODGeomap extends GeoMap {
|
|||||||
*/
|
*/
|
||||||
public IntBuffer writeIndexArrayLodDiff(IntBuffer store, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) {
|
public IntBuffer writeIndexArrayLodDiff(IntBuffer store, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) {
|
||||||
|
|
||||||
|
//if (true)
|
||||||
|
//return writeIndexArrayLodVariable(store, lod, height, lod, lod, lod);
|
||||||
|
|
||||||
IntBuffer buffer2 = store;
|
IntBuffer buffer2 = store;
|
||||||
int numIndexes = calculateNumIndexesLodDiff(lod);
|
int numIndexes = calculateNumIndexesLodDiff(lod);
|
||||||
if (store == null) {
|
if (store == null) {
|
||||||
@ -275,7 +278,7 @@ public class LODGeomap extends GeoMap {
|
|||||||
buffer.put(idx);
|
buffer.put(idx);
|
||||||
idx = (row + 2 * lod) * getWidth();
|
idx = (row + 2 * lod) * getWidth();
|
||||||
buffer.put(idx);
|
buffer.put(idx);
|
||||||
if (row < getWidth() - lod - 2 - 1) { //if not the last one
|
if (row < getWidth() - 1 - 2 * lod) { //if not the last one
|
||||||
idx = (row + 2 * lod) * getWidth() + lod;
|
idx = (row + 2 * lod) * getWidth() + lod;
|
||||||
buffer.put(idx);
|
buffer.put(idx);
|
||||||
idx = (row + 2 * lod) * getWidth();
|
idx = (row + 2 * lod) * getWidth();
|
||||||
@ -917,10 +920,12 @@ public class LODGeomap extends GeoMap {
|
|||||||
|
|
||||||
public void put(int value) {
|
public void put(int value) {
|
||||||
try {
|
try {
|
||||||
delegate.put(value);
|
|
||||||
count++;
|
count++;
|
||||||
|
if (count > delegate.limit())
|
||||||
|
throw new BufferOverflowException();
|
||||||
|
delegate.put(value);
|
||||||
} catch (BufferOverflowException e) {
|
} catch (BufferOverflowException e) {
|
||||||
//System.out.println("err buffer size: "+delegate.capacity());
|
System.out.println("err buffer size: "+delegate.capacity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package com.jme3.terrain.geomipmap;
|
||||||
|
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
|
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
||||||
|
import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An extension of the TerrainLodControl that handles
|
||||||
|
* multiple terrains at once. This is to be used if you
|
||||||
|
* have your own tiling/paging terrain system, such as
|
||||||
|
* TerrainGrid.
|
||||||
|
*
|
||||||
|
* @author Brent Owens
|
||||||
|
*/
|
||||||
|
public class MultiTerrainLodControl extends TerrainLodControl {
|
||||||
|
|
||||||
|
List<TerrainQuad> terrains = new ArrayList<TerrainQuad>();
|
||||||
|
private List<TerrainQuad> addedTerrains = new ArrayList<TerrainQuad>();
|
||||||
|
private List<TerrainQuad> removedTerrains = new ArrayList<TerrainQuad>();
|
||||||
|
|
||||||
|
public MultiTerrainLodControl(List<Camera> cameras) {
|
||||||
|
this.cameras = cameras;
|
||||||
|
lodCalculator = new DistanceLodCalculator(65, 2.7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiTerrainLodControl(Camera camera) {
|
||||||
|
List<Camera> cams = new ArrayList<Camera>();
|
||||||
|
cams.add(camera);
|
||||||
|
this.cameras = cams;
|
||||||
|
lodCalculator = new DistanceLodCalculator(65, 2.7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a terrain that will have its LOD handled by this control.
|
||||||
|
* It will be added next update run. You should only call this from
|
||||||
|
* the render thread.
|
||||||
|
*/
|
||||||
|
public void addTerrain(TerrainQuad tq) {
|
||||||
|
addedTerrains.add(tq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a terrain that will no longer have its LOD handled by this control.
|
||||||
|
* It will be removed next update run. You should only call this from
|
||||||
|
* the render thread.
|
||||||
|
*/
|
||||||
|
public void removeTerrain(TerrainQuad tq) {
|
||||||
|
removedTerrains.remove(tq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UpdateLOD getLodThread(List<Vector3f> locations, LodCalculator lodCalculator) {
|
||||||
|
return new UpdateMultiLOD(locations, lodCalculator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void prepareTerrain() {
|
||||||
|
if (!addedTerrains.isEmpty()) {
|
||||||
|
for (TerrainQuad t : addedTerrains) {
|
||||||
|
if (!terrains.contains(t))
|
||||||
|
terrains.add(t);
|
||||||
|
}
|
||||||
|
addedTerrains.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removedTerrains.isEmpty()) {
|
||||||
|
terrains.removeAll(removedTerrains);
|
||||||
|
removedTerrains.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TerrainQuad terrain : terrains)
|
||||||
|
terrain.cacheTerrainTransforms();// cache the terrain's world transforms so they can be accessed on the separate thread safely
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the parent UpdateLOD runnable to process
|
||||||
|
* multiple terrains.
|
||||||
|
*/
|
||||||
|
protected class UpdateMultiLOD extends UpdateLOD {
|
||||||
|
|
||||||
|
|
||||||
|
protected UpdateMultiLOD(List<Vector3f> camLocations, LodCalculator lodCalculator) {
|
||||||
|
super(camLocations, lodCalculator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, UpdatedTerrainPatch> call() throws Exception {
|
||||||
|
|
||||||
|
setLodCalcRunning(true);
|
||||||
|
|
||||||
|
HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();
|
||||||
|
|
||||||
|
for (TerrainQuad terrainQuad : terrains) {
|
||||||
|
// go through each patch and calculate its LOD based on camera distance
|
||||||
|
terrainQuad.calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TerrainQuad terrainQuad : terrains) {
|
||||||
|
// then calculate the neighbour LOD values for seaming
|
||||||
|
terrainQuad.findNeighboursLod(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TerrainQuad terrainQuad : terrains) {
|
||||||
|
// check neighbour quads that need their edges seamed
|
||||||
|
terrainQuad.fixEdges(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TerrainQuad terrainQuad : terrains) {
|
||||||
|
// perform the edge seaming, if it requires it
|
||||||
|
terrainQuad.reIndexPages(updated, lodCalculator.usesVariableLod());
|
||||||
|
}
|
||||||
|
|
||||||
|
//setUpdateQuadLODs(updated); // set back to main ogl thread
|
||||||
|
setLodCalcRunning(false);
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ package com.jme3.terrain.geomipmap;
|
|||||||
* With this you can have a parent, control or spatial, that manages a group of
|
* With this you can have a parent, control or spatial, that manages a group of
|
||||||
* TerrainQuads by linking them together through these four methods.
|
* TerrainQuads by linking them together through these four methods.
|
||||||
*
|
*
|
||||||
* The general orientation of TerrainQuads and their sun-quads is as such:
|
* The general orientation of TerrainQuads and their sub-quads is as such:
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* +-- x+ ---->
|
* +-- x+ ---->
|
||||||
@ -32,11 +32,23 @@ package com.jme3.terrain.geomipmap;
|
|||||||
*/
|
*/
|
||||||
public interface NeighbourFinder {
|
public interface NeighbourFinder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TerrainQuad to the right of the supplied 'center' quad.
|
||||||
|
*/
|
||||||
public TerrainQuad getRightQuad(TerrainQuad center);
|
public TerrainQuad getRightQuad(TerrainQuad center);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TerrainQuad to the left of the supplied 'center' quad.
|
||||||
|
*/
|
||||||
public TerrainQuad getLeftQuad(TerrainQuad center);
|
public TerrainQuad getLeftQuad(TerrainQuad center);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TerrainQuad above the supplied 'center' quad.
|
||||||
|
*/
|
||||||
public TerrainQuad getTopQuad(TerrainQuad center);
|
public TerrainQuad getTopQuad(TerrainQuad center);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TerrainQuad below the supplied 'center' quad.
|
||||||
|
*/
|
||||||
public TerrainQuad getDownQuad(TerrainQuad center);
|
public TerrainQuad getDownQuad(TerrainQuad center);
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,15 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the terrain to update its Level of Detail.
|
* Tells the terrain to update its Level of Detail.
|
||||||
@ -72,19 +78,20 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
public class TerrainLodControl extends AbstractControl {
|
public class TerrainLodControl extends AbstractControl {
|
||||||
|
|
||||||
private Terrain terrain;
|
private Terrain terrain;
|
||||||
private List<Camera> cameras;
|
protected List<Camera> cameras;
|
||||||
private List<Vector3f> cameraLocations = new ArrayList<Vector3f>();
|
private List<Vector3f> cameraLocations = new ArrayList<Vector3f>();
|
||||||
private LodCalculator lodCalculator;
|
protected LodCalculator lodCalculator;
|
||||||
private boolean hasResetLod = false; // used when enabled is set to false
|
private boolean hasResetLod = false; // used when enabled is set to false
|
||||||
|
|
||||||
private HashMap<String,UpdatedTerrainPatch> updatedPatches;
|
private HashMap<String,UpdatedTerrainPatch> updatedPatches;
|
||||||
private final Object updatePatchesLock = new Object();
|
private final Object updatePatchesLock = new Object();
|
||||||
|
|
||||||
protected List<Vector3f> lastCameraLocations; // used for LOD calc
|
protected List<Vector3f> lastCameraLocations; // used for LOD calc
|
||||||
private boolean lodCalcRunning = false;
|
private AtomicBoolean lodCalcRunning = new AtomicBoolean(false);
|
||||||
private int lodOffCount = 0;
|
private int lodOffCount = 0;
|
||||||
|
|
||||||
protected ExecutorService executor;
|
protected ExecutorService executor;
|
||||||
|
protected Future<HashMap<String, UpdatedTerrainPatch>> indexer;
|
||||||
|
|
||||||
public TerrainLodControl() {
|
public TerrainLodControl() {
|
||||||
}
|
}
|
||||||
@ -177,6 +184,7 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
if (isLodCalcRunning()) {
|
if (isLodCalcRunning()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setLodCalcRunning(true);
|
||||||
|
|
||||||
//if (getParent() instanceof TerrainQuad) {
|
//if (getParent() instanceof TerrainQuad) {
|
||||||
// return; // we just want the root quad to perform this.
|
// return; // we just want the root quad to perform this.
|
||||||
@ -185,25 +193,47 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
if (executor == null)
|
if (executor == null)
|
||||||
executor = createExecutorService();
|
executor = createExecutorService();
|
||||||
|
|
||||||
|
prepareTerrain();
|
||||||
|
|
||||||
|
UpdateLOD updateLodThread = getLodThread(locations, lodCalculator);
|
||||||
|
indexer = executor.submit(updateLodThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareTerrain() {
|
||||||
TerrainQuad terrain = (TerrainQuad)getSpatial();
|
TerrainQuad terrain = (TerrainQuad)getSpatial();
|
||||||
terrain.cacheTerrainTransforms();// cache the terrain's world transforms so they can be accessed on the separate thread safely
|
terrain.cacheTerrainTransforms();// cache the terrain's world transforms so they can be accessed on the separate thread safely
|
||||||
|
|
||||||
UpdateLOD updateLodThread = new UpdateLOD(locations, lodCalculator);
|
|
||||||
executor.execute(updateLodThread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpdateQuadLODs(HashMap<String,UpdatedTerrainPatch> updated) {
|
protected UpdateLOD getLodThread(List<Vector3f> locations, LodCalculator lodCalculator) {
|
||||||
synchronized (updatePatchesLock) {
|
return new UpdateLOD(locations, lodCalculator);
|
||||||
updatedPatches = updated;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Back on the ogl thread: update the terrain patch geometries
|
* Back on the ogl thread: update the terrain patch geometries
|
||||||
* @param updatedPatches to be updated
|
|
||||||
*/
|
*/
|
||||||
private void updateQuadLODs() {
|
private void updateQuadLODs() {
|
||||||
synchronized (updatePatchesLock) {
|
if (indexer != null) {
|
||||||
|
if (indexer.isDone()) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
HashMap<String, UpdatedTerrainPatch> updated = indexer.get();
|
||||||
|
if (updated != null) {
|
||||||
|
// do the actual geometry update here
|
||||||
|
for (UpdatedTerrainPatch utp : updated.values()) {
|
||||||
|
utp.updateAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Logger.getLogger(TerrainLodControl.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
Logger.getLogger(TerrainLodControl.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
indexer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*synchronized (updatePatchesLock) {
|
||||||
|
|
||||||
if (updatedPatches == null || updatedPatches.isEmpty())
|
if (updatedPatches == null || updatedPatches.isEmpty())
|
||||||
return;
|
return;
|
||||||
@ -213,13 +243,13 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
utp.updateAll();
|
utp.updateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedPatches.clear();
|
updatedPatches = null;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPatchesToUpdate() {
|
//public boolean hasPatchesToUpdate() {
|
||||||
return updatedPatches != null && !updatedPatches.isEmpty();
|
// return updatedPatches != null && !updatedPatches.isEmpty();
|
||||||
}
|
//}
|
||||||
|
|
||||||
private boolean lastCameraLocationsTheSame(List<Vector3f> locations) {
|
private boolean lastCameraLocationsTheSame(List<Vector3f> locations) {
|
||||||
boolean theSame = true;
|
boolean theSame = true;
|
||||||
@ -234,12 +264,12 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
return theSame;
|
return theSame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean isLodCalcRunning() {
|
protected synchronized boolean isLodCalcRunning() {
|
||||||
return lodCalcRunning;
|
return lodCalcRunning.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void setLodCalcRunning(boolean running) {
|
protected synchronized void setLodCalcRunning(boolean running) {
|
||||||
lodCalcRunning = running;
|
lodCalcRunning.set(running);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Vector3f> cloneVectorList(List<Vector3f> locations) {
|
private List<Vector3f> cloneVectorList(List<Vector3f> locations) {
|
||||||
@ -320,22 +350,20 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
/**
|
/**
|
||||||
* Calculates the LOD of all child terrain patches.
|
* Calculates the LOD of all child terrain patches.
|
||||||
*/
|
*/
|
||||||
private class UpdateLOD implements Runnable {
|
protected class UpdateLOD implements Callable<HashMap<String,UpdatedTerrainPatch>> {
|
||||||
private List<Vector3f> camLocations;
|
protected List<Vector3f> camLocations;
|
||||||
private LodCalculator lodCalculator;
|
protected LodCalculator lodCalculator;
|
||||||
|
|
||||||
UpdateLOD(List<Vector3f> camLocations, LodCalculator lodCalculator) {
|
protected UpdateLOD(List<Vector3f> camLocations, LodCalculator lodCalculator) {
|
||||||
this.camLocations = camLocations;
|
this.camLocations = camLocations;
|
||||||
this.lodCalculator = lodCalculator;
|
this.lodCalculator = lodCalculator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public HashMap<String, UpdatedTerrainPatch> call() throws Exception {
|
||||||
long start = System.currentTimeMillis();
|
//long start = System.currentTimeMillis();
|
||||||
if (isLodCalcRunning()) {
|
//if (isLodCalcRunning()) {
|
||||||
//System.out.println("thread already running");
|
// return null;
|
||||||
return;
|
//}
|
||||||
}
|
|
||||||
//System.out.println("spawned thread "+toString());
|
|
||||||
setLodCalcRunning(true);
|
setLodCalcRunning(true);
|
||||||
|
|
||||||
TerrainQuad terrainQuad = (TerrainQuad)getSpatial();
|
TerrainQuad terrainQuad = (TerrainQuad)getSpatial();
|
||||||
@ -347,7 +375,7 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
if (!lodChanged) {
|
if (!lodChanged) {
|
||||||
// not worth updating anything else since no one's LOD changed
|
// not worth updating anything else since no one's LOD changed
|
||||||
setLodCalcRunning(false);
|
setLodCalcRunning(false);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,11 +386,11 @@ public class TerrainLodControl extends AbstractControl {
|
|||||||
|
|
||||||
terrainQuad.reIndexPages(updated, lodCalculator.usesVariableLod());
|
terrainQuad.reIndexPages(updated, lodCalculator.usesVariableLod());
|
||||||
|
|
||||||
setUpdateQuadLODs(updated); // set back to main ogl thread
|
//setUpdateQuadLODs(updated); // set back to main ogl thread
|
||||||
|
|
||||||
setLodCalcRunning(false);
|
setLodCalcRunning(false);
|
||||||
//double duration = (System.currentTimeMillis()-start);
|
|
||||||
//System.out.println("terminated in "+duration);
|
return updated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ import java.util.List;
|
|||||||
public class TerrainPatch extends Geometry {
|
public class TerrainPatch extends Geometry {
|
||||||
|
|
||||||
protected LODGeomap geomap;
|
protected LODGeomap geomap;
|
||||||
protected int lod = -1; // this terrain patch's LOD
|
protected int lod = 0; // this terrain patch's LOD
|
||||||
private int maxLod = -1;
|
private int maxLod = -1;
|
||||||
protected int previousLod = -1;
|
protected int previousLod = -1;
|
||||||
protected int lodLeft, lodTop, lodRight, lodBottom; // it's neighbour's LODs
|
protected int lodLeft, lodTop, lodRight, lodBottom; // it's neighbour's LODs
|
||||||
@ -234,7 +234,7 @@ public class TerrainPatch extends Geometry {
|
|||||||
|
|
||||||
UpdatedTerrainPatch utp = updated.get(getName());
|
UpdatedTerrainPatch utp = updated.get(getName());
|
||||||
|
|
||||||
if (utp != null && (utp.isReIndexNeeded() || utp.isFixEdges()) ) {
|
if (utp != null && utp.isReIndexNeeded() ) {
|
||||||
int pow = (int) Math.pow(2, utp.getNewLod());
|
int pow = (int) Math.pow(2, utp.getNewLod());
|
||||||
boolean left = utp.getLeftLod() > utp.getNewLod();
|
boolean left = utp.getLeftLod() > utp.getNewLod();
|
||||||
boolean top = utp.getTopLod() > utp.getNewLod();
|
boolean top = utp.getTopLod() > utp.getNewLod();
|
||||||
|
@ -201,6 +201,7 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
|
|
||||||
public void setNeighbourFinder(NeighbourFinder neighbourFinder) {
|
public void setNeighbourFinder(NeighbourFinder neighbourFinder) {
|
||||||
this.neighbourFinder = neighbourFinder;
|
this.neighbourFinder = neighbourFinder;
|
||||||
|
resetCachedNeighbours();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,6 +361,8 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
}
|
}
|
||||||
TerrainPatch right = patch.rightNeighbour;
|
TerrainPatch right = patch.rightNeighbour;
|
||||||
TerrainPatch down = patch.bottomNeighbour;
|
TerrainPatch down = patch.bottomNeighbour;
|
||||||
|
TerrainPatch left = patch.leftNeighbour;
|
||||||
|
TerrainPatch top = patch.topNeighbour;
|
||||||
|
|
||||||
UpdatedTerrainPatch utp = updated.get(patch.getName());
|
UpdatedTerrainPatch utp = updated.get(patch.getName());
|
||||||
if (utp == null) {
|
if (utp == null) {
|
||||||
@ -370,34 +373,55 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
if (right != null) {
|
if (right != null) {
|
||||||
UpdatedTerrainPatch utpR = updated.get(right.getName());
|
UpdatedTerrainPatch utpR = updated.get(right.getName());
|
||||||
if (utpR == null) {
|
if (utpR == null) {
|
||||||
utpR = new UpdatedTerrainPatch(right, right.lod);
|
utpR = new UpdatedTerrainPatch(right);
|
||||||
updated.put(utpR.getName(), utpR);
|
updated.put(utpR.getName(), utpR);
|
||||||
|
utpR.setNewLod(right.lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
utp.setRightLod(utpR.getNewLod());
|
utp.setRightLod(utpR.getNewLod());
|
||||||
utpR.setLeftLod(utp.getNewLod());
|
utpR.setLeftLod(utp.getNewLod());
|
||||||
}
|
}
|
||||||
if (down != null) {
|
if (down != null) {
|
||||||
UpdatedTerrainPatch utpD = updated.get(down.getName());
|
UpdatedTerrainPatch utpD = updated.get(down.getName());
|
||||||
if (utpD == null) {
|
if (utpD == null) {
|
||||||
utpD = new UpdatedTerrainPatch(down, down.lod);
|
utpD = new UpdatedTerrainPatch(down);
|
||||||
updated.put(utpD.getName(), utpD);
|
updated.put(utpD.getName(), utpD);
|
||||||
|
utpD.setNewLod(down.lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
utp.setBottomLod(utpD.getNewLod());
|
utp.setBottomLod(utpD.getNewLod());
|
||||||
utpD.setTopLod(utp.getNewLod());
|
utpD.setTopLod(utp.getNewLod());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (left != null) {
|
||||||
|
UpdatedTerrainPatch utpL = updated.get(left.getName());
|
||||||
|
if (utpL == null) {
|
||||||
|
utpL = new UpdatedTerrainPatch(left);
|
||||||
|
updated.put(utpL.getName(), utpL);
|
||||||
|
utpL.setNewLod(left.lod);
|
||||||
|
}
|
||||||
|
utp.setLeftLod(utpL.getNewLod());
|
||||||
|
utpL.setRightLod(utp.getNewLod());
|
||||||
|
}
|
||||||
|
if (top != null) {
|
||||||
|
UpdatedTerrainPatch utpT = updated.get(top.getName());
|
||||||
|
if (utpT == null) {
|
||||||
|
utpT = new UpdatedTerrainPatch(top);
|
||||||
|
updated.put(utpT.getName(), utpT);
|
||||||
|
utpT.setNewLod(top.lod);
|
||||||
|
}
|
||||||
|
utp.setTopLod(utpT.getNewLod());
|
||||||
|
utpT.setBottomLod(utp.getNewLod());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Reset the cached references of neighbours.
|
||||||
* TerrainQuad caches neighbours for faster LOD checks.
|
* TerrainQuad caches neighbours for faster LOD checks.
|
||||||
* Sometimes you might want to reset this cache (for instance in TerrainGrid)
|
* Sometimes you might want to reset this cache (for instance in TerrainGrid)
|
||||||
*/
|
*/
|
||||||
protected void resetCachedNeighbours() {
|
public void resetCachedNeighbours() {
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
for (int x = children.size(); --x >= 0;) {
|
for (int x = children.size(); --x >= 0;) {
|
||||||
Spatial child = children.get(x);
|
Spatial child = children.get(x);
|
||||||
@ -441,33 +465,41 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
if (right != null) {
|
if (right != null) {
|
||||||
UpdatedTerrainPatch utpR = updated.get(right.getName());
|
UpdatedTerrainPatch utpR = updated.get(right.getName());
|
||||||
if (utpR == null) {
|
if (utpR == null) {
|
||||||
utpR = new UpdatedTerrainPatch(right, right.lod);
|
utpR = new UpdatedTerrainPatch(right);
|
||||||
updated.put(utpR.getName(), utpR);
|
updated.put(utpR.getName(), utpR);
|
||||||
|
utpR.setNewLod(right.lod);
|
||||||
}
|
}
|
||||||
|
utpR.setLeftLod(utp.getNewLod());
|
||||||
utpR.setFixEdges(true);
|
utpR.setFixEdges(true);
|
||||||
}
|
}
|
||||||
if (down != null) {
|
if (down != null) {
|
||||||
UpdatedTerrainPatch utpD = updated.get(down.getName());
|
UpdatedTerrainPatch utpD = updated.get(down.getName());
|
||||||
if (utpD == null) {
|
if (utpD == null) {
|
||||||
utpD = new UpdatedTerrainPatch(down, down.lod);
|
utpD = new UpdatedTerrainPatch(down);
|
||||||
updated.put(utpD.getName(), utpD);
|
updated.put(utpD.getName(), utpD);
|
||||||
|
utpD.setNewLod(down.lod);
|
||||||
}
|
}
|
||||||
|
utpD.setTopLod(utp.getNewLod());
|
||||||
utpD.setFixEdges(true);
|
utpD.setFixEdges(true);
|
||||||
}
|
}
|
||||||
if (top != null){
|
if (top != null){
|
||||||
UpdatedTerrainPatch utpT = updated.get(top.getName());
|
UpdatedTerrainPatch utpT = updated.get(top.getName());
|
||||||
if (utpT == null) {
|
if (utpT == null) {
|
||||||
utpT = new UpdatedTerrainPatch(top, top.lod);
|
utpT = new UpdatedTerrainPatch(top);
|
||||||
updated.put(utpT.getName(), utpT);
|
updated.put(utpT.getName(), utpT);
|
||||||
|
utpT.setNewLod(top.lod);
|
||||||
}
|
}
|
||||||
|
utpT.setBottomLod(utp.getNewLod());
|
||||||
utpT.setFixEdges(true);
|
utpT.setFixEdges(true);
|
||||||
}
|
}
|
||||||
if (left != null){
|
if (left != null){
|
||||||
UpdatedTerrainPatch utpL = updated.get(left.getName());
|
UpdatedTerrainPatch utpL = updated.get(left.getName());
|
||||||
if (utpL == null) {
|
if (utpL == null) {
|
||||||
utpL = new UpdatedTerrainPatch(left, left.lod);
|
utpL = new UpdatedTerrainPatch(left);
|
||||||
updated.put(utpL.getName(), utpL);
|
updated.put(utpL.getName(), utpL);
|
||||||
|
utpL.setNewLod(left.lod);
|
||||||
}
|
}
|
||||||
|
utpL.setRightLod(utp.getNewLod());
|
||||||
utpL.setFixEdges(true);
|
utpL.setFixEdges(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1278,6 +1310,8 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TerrainQuad getQuad(int quad) {
|
protected TerrainQuad getQuad(int quad) {
|
||||||
|
if (quad == 0)
|
||||||
|
return this;
|
||||||
if (children != null)
|
if (children != null)
|
||||||
for (int x = children.size(); --x >= 0;) {
|
for (int x = children.size(); --x >= 0;) {
|
||||||
Spatial child = children.get(x);
|
Spatial child = children.get(x);
|
||||||
@ -1355,7 +1389,7 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
else if (tp.getQuadrant() == 4)
|
else if (tp.getQuadrant() == 4)
|
||||||
return getPatch(2);
|
return getPatch(2);
|
||||||
else if (tp.getQuadrant() == 1) {
|
else if (tp.getQuadrant() == 1) {
|
||||||
// find the patch above and ask it for child 2.
|
// find the patch above and ask it for child 3.
|
||||||
TerrainQuad quad = findLeftQuad();
|
TerrainQuad quad = findLeftQuad();
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getPatch(3);
|
return quad.getPatch(3);
|
||||||
@ -1370,34 +1404,35 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
|
|
||||||
protected TerrainQuad findRightQuad() {
|
protected TerrainQuad findRightQuad() {
|
||||||
boolean useFinder = false;
|
boolean useFinder = false;
|
||||||
if (getParent() == null || !(getParent() instanceof TerrainQuad))
|
if (getParent() == null || !(getParent() instanceof TerrainQuad)) {
|
||||||
if (neighbourFinder == null)
|
if (neighbourFinder == null)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
useFinder = true;
|
useFinder = true;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainQuad pQuad = (TerrainQuad) getParent();
|
TerrainQuad pQuad = null;
|
||||||
|
if (!useFinder)
|
||||||
|
pQuad = (TerrainQuad) getParent();
|
||||||
|
|
||||||
if (quadrant == 1)
|
if (quadrant == 1)
|
||||||
return pQuad.getQuad(3);
|
return pQuad.getQuad(3);
|
||||||
else if (quadrant == 2)
|
else if (quadrant == 2)
|
||||||
return pQuad.getQuad(4);
|
return pQuad.getQuad(4);
|
||||||
else if (quadrant == 3) {
|
else if (quadrant == 3) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findRightQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getRightQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findRightQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(1);
|
return quad.getQuad(1);
|
||||||
} else if (quadrant == 4) {
|
} else if (quadrant == 4) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findRightQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getRightQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findRightQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(2);
|
return quad.getQuad(2);
|
||||||
|
} else if (quadrant == 0) {
|
||||||
|
// at the top quad
|
||||||
|
if (useFinder) {
|
||||||
|
TerrainQuad quad = neighbourFinder.getRightQuad(this);
|
||||||
|
return quad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -1405,34 +1440,35 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
|
|
||||||
protected TerrainQuad findDownQuad() {
|
protected TerrainQuad findDownQuad() {
|
||||||
boolean useFinder = false;
|
boolean useFinder = false;
|
||||||
if (getParent() == null || !(getParent() instanceof TerrainQuad))
|
if (getParent() == null || !(getParent() instanceof TerrainQuad)) {
|
||||||
if (neighbourFinder == null)
|
if (neighbourFinder == null)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
useFinder = true;
|
useFinder = true;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainQuad pQuad = (TerrainQuad) getParent();
|
TerrainQuad pQuad = null;
|
||||||
|
if (!useFinder)
|
||||||
|
pQuad = (TerrainQuad) getParent();
|
||||||
|
|
||||||
if (quadrant == 1)
|
if (quadrant == 1)
|
||||||
return pQuad.getQuad(2);
|
return pQuad.getQuad(2);
|
||||||
else if (quadrant == 3)
|
else if (quadrant == 3)
|
||||||
return pQuad.getQuad(4);
|
return pQuad.getQuad(4);
|
||||||
else if (quadrant == 2) {
|
else if (quadrant == 2) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findDownQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getDownQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findDownQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(1);
|
return quad.getQuad(1);
|
||||||
} else if (quadrant == 4) {
|
} else if (quadrant == 4) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findDownQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getDownQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findDownQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(3);
|
return quad.getQuad(3);
|
||||||
|
} else if (quadrant == 0) {
|
||||||
|
// at the top quad
|
||||||
|
if (useFinder) {
|
||||||
|
TerrainQuad quad = neighbourFinder.getDownQuad(this);
|
||||||
|
return quad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -1440,34 +1476,35 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
|
|
||||||
protected TerrainQuad findTopQuad() {
|
protected TerrainQuad findTopQuad() {
|
||||||
boolean useFinder = false;
|
boolean useFinder = false;
|
||||||
if (getParent() == null || !(getParent() instanceof TerrainQuad))
|
if (getParent() == null || !(getParent() instanceof TerrainQuad)) {
|
||||||
if (neighbourFinder == null)
|
if (neighbourFinder == null)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
useFinder = true;
|
useFinder = true;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainQuad pQuad = (TerrainQuad) getParent();
|
TerrainQuad pQuad = null;
|
||||||
|
if (!useFinder)
|
||||||
|
pQuad = (TerrainQuad) getParent();
|
||||||
|
|
||||||
if (quadrant == 2)
|
if (quadrant == 2)
|
||||||
return pQuad.getQuad(1);
|
return pQuad.getQuad(1);
|
||||||
else if (quadrant == 4)
|
else if (quadrant == 4)
|
||||||
return pQuad.getQuad(3);
|
return pQuad.getQuad(3);
|
||||||
else if (quadrant == 1) {
|
else if (quadrant == 1) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findTopQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getTopQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findTopQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(2);
|
return quad.getQuad(2);
|
||||||
} else if (quadrant == 3) {
|
} else if (quadrant == 3) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findTopQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getTopQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findTopQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(4);
|
return quad.getQuad(4);
|
||||||
|
} else if (quadrant == 0) {
|
||||||
|
// at the top quad
|
||||||
|
if (useFinder) {
|
||||||
|
TerrainQuad quad = neighbourFinder.getTopQuad(this);
|
||||||
|
return quad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -1475,34 +1512,35 @@ public class TerrainQuad extends Node implements Terrain {
|
|||||||
|
|
||||||
protected TerrainQuad findLeftQuad() {
|
protected TerrainQuad findLeftQuad() {
|
||||||
boolean useFinder = false;
|
boolean useFinder = false;
|
||||||
if (getParent() == null || !(getParent() instanceof TerrainQuad))
|
if (getParent() == null || !(getParent() instanceof TerrainQuad)) {
|
||||||
if (neighbourFinder == null)
|
if (neighbourFinder == null)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
useFinder = true;
|
useFinder = true;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainQuad pQuad = (TerrainQuad) getParent();
|
TerrainQuad pQuad = null;
|
||||||
|
if (!useFinder)
|
||||||
|
pQuad = (TerrainQuad) getParent();
|
||||||
|
|
||||||
if (quadrant == 3)
|
if (quadrant == 3)
|
||||||
return pQuad.getQuad(1);
|
return pQuad.getQuad(1);
|
||||||
else if (quadrant == 4)
|
else if (quadrant == 4)
|
||||||
return pQuad.getQuad(2);
|
return pQuad.getQuad(2);
|
||||||
else if (quadrant == 1) {
|
else if (quadrant == 1) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findLeftQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getLeftQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findLeftQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(3);
|
return quad.getQuad(3);
|
||||||
} else if (quadrant == 2) {
|
} else if (quadrant == 2) {
|
||||||
TerrainQuad quad = null;
|
TerrainQuad quad = pQuad.findLeftQuad();
|
||||||
if (useFinder)
|
|
||||||
quad = neighbourFinder.getLeftQuad(this);
|
|
||||||
else
|
|
||||||
quad = pQuad.findLeftQuad();
|
|
||||||
if (quad != null)
|
if (quad != null)
|
||||||
return quad.getQuad(4);
|
return quad.getQuad(4);
|
||||||
|
} else if (quadrant == 0) {
|
||||||
|
// at the top quad
|
||||||
|
if (useFinder) {
|
||||||
|
TerrainQuad quad = neighbourFinder.getLeftQuad(this);
|
||||||
|
return quad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -49,29 +49,24 @@ public class UpdatedTerrainPatch {
|
|||||||
private int previousLod;
|
private int previousLod;
|
||||||
private int rightLod,topLod,leftLod,bottomLod;
|
private int rightLod,topLod,leftLod,bottomLod;
|
||||||
private IntBuffer newIndexBuffer;
|
private IntBuffer newIndexBuffer;
|
||||||
private boolean reIndexNeeded = false;
|
//private boolean reIndexNeeded = false;
|
||||||
private boolean fixEdges = false;
|
private boolean fixEdges = false;
|
||||||
|
|
||||||
|
public UpdatedTerrainPatch(TerrainPatch updatedPatch) {
|
||||||
|
this.updatedPatch = updatedPatch;
|
||||||
|
}
|
||||||
|
|
||||||
public UpdatedTerrainPatch(TerrainPatch updatedPatch, int newLod) {
|
public UpdatedTerrainPatch(TerrainPatch updatedPatch, int newLod) {
|
||||||
this.updatedPatch = updatedPatch;
|
this.updatedPatch = updatedPatch;
|
||||||
this.newLod = newLod;
|
this.newLod = newLod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdatedTerrainPatch(TerrainPatch updatedPatch, int newLod, int prevLOD, boolean reIndexNeeded) {
|
|
||||||
this.updatedPatch = updatedPatch;
|
|
||||||
this.newLod = newLod;
|
|
||||||
this.previousLod = prevLOD;
|
|
||||||
this.reIndexNeeded = reIndexNeeded;
|
|
||||||
if (this.newLod <= 0)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return updatedPatch.getName();
|
return updatedPatch.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean lodChanged() {
|
protected boolean lodChanged() {
|
||||||
if (reIndexNeeded && previousLod != newLod)
|
if ( previousLod != newLod)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -92,12 +87,12 @@ public class UpdatedTerrainPatch {
|
|||||||
public void setNewLod(int newLod) {
|
public void setNewLod(int newLod) {
|
||||||
this.newLod = newLod;
|
this.newLod = newLod;
|
||||||
if (this.newLod < 0)
|
if (this.newLod < 0)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException("newLod cannot be less than zero, was: "+newLod);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IntBuffer getNewIndexBuffer() {
|
/*protected IntBuffer getNewIndexBuffer() {
|
||||||
return newIndexBuffer;
|
return newIndexBuffer;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
protected void setNewIndexBuffer(IntBuffer newIndexBuffer) {
|
protected void setNewIndexBuffer(IntBuffer newIndexBuffer) {
|
||||||
this.newIndexBuffer = newIndexBuffer;
|
this.newIndexBuffer = newIndexBuffer;
|
||||||
@ -144,12 +139,16 @@ public class UpdatedTerrainPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isReIndexNeeded() {
|
public boolean isReIndexNeeded() {
|
||||||
return reIndexNeeded;
|
if (lodChanged() || isFixEdges())
|
||||||
|
return true;
|
||||||
|
//if (leftLod != newLod || rightLod != newLod || bottomLod != newLod || topLod != newLod)
|
||||||
|
// return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReIndexNeeded(boolean reIndexNeeded) {
|
/*public void setReIndexNeeded(boolean reIndexNeeded) {
|
||||||
this.reIndexNeeded = reIndexNeeded;
|
this.reIndexNeeded = reIndexNeeded;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public boolean isFixEdges() {
|
public boolean isFixEdges() {
|
||||||
return fixEdges;
|
return fixEdges;
|
||||||
@ -159,9 +158,9 @@ public class UpdatedTerrainPatch {
|
|||||||
this.fixEdges = fixEdges;
|
this.fixEdges = fixEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPreviousLod() {
|
/*public int getPreviousLod() {
|
||||||
return previousLod;
|
return previousLod;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public void setPreviousLod(int previousLod) {
|
public void setPreviousLod(int previousLod) {
|
||||||
this.previousLod = previousLod;
|
this.previousLod = previousLod;
|
||||||
@ -173,7 +172,7 @@ public class UpdatedTerrainPatch {
|
|||||||
updatedPatch.setLodTop(topLod);
|
updatedPatch.setLodTop(topLod);
|
||||||
updatedPatch.setLodLeft(leftLod);
|
updatedPatch.setLodLeft(leftLod);
|
||||||
updatedPatch.setLodBottom(bottomLod);
|
updatedPatch.setLodBottom(bottomLod);
|
||||||
if (newIndexBuffer != null && (reIndexNeeded || fixEdges)) {
|
if (newIndexBuffer != null && isReIndexNeeded()) {
|
||||||
updatedPatch.setPreviousLod(previousLod);
|
updatedPatch.setPreviousLod(previousLod);
|
||||||
updatedPatch.getMesh().clearBuffer(Type.Index);
|
updatedPatch.getMesh().clearBuffer(Type.Index);
|
||||||
updatedPatch.getMesh().setBuffer(Type.Index, 3, newIndexBuffer);
|
updatedPatch.getMesh().setBuffer(Type.Index, 3, newIndexBuffer);
|
||||||
|
@ -71,12 +71,12 @@ public class DistanceLodCalculator implements LodCalculator {
|
|||||||
int prevLOD = terrainPatch.getLod();
|
int prevLOD = terrainPatch.getLod();
|
||||||
UpdatedTerrainPatch utp = updates.get(terrainPatch.getName());
|
UpdatedTerrainPatch utp = updates.get(terrainPatch.getName());
|
||||||
if (utp == null) {
|
if (utp == null) {
|
||||||
utp = new UpdatedTerrainPatch(terrainPatch, 0);
|
utp = new UpdatedTerrainPatch(terrainPatch);
|
||||||
updates.put(utp.getName(), utp);
|
updates.put(utp.getName(), utp);
|
||||||
}
|
}
|
||||||
utp.setNewLod(0);
|
utp.setNewLod(0);
|
||||||
utp.setPreviousLod(prevLOD);
|
utp.setPreviousLod(prevLOD);
|
||||||
utp.setReIndexNeeded(true);
|
//utp.setReIndexNeeded(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,15 +89,15 @@ public class DistanceLodCalculator implements LodCalculator {
|
|||||||
//System.out.println("lod change: "+lod+" > "+i+" dist: "+distance);
|
//System.out.println("lod change: "+lod+" > "+i+" dist: "+distance);
|
||||||
}
|
}
|
||||||
int prevLOD = terrainPatch.getLod();
|
int prevLOD = terrainPatch.getLod();
|
||||||
//previousLod = lod;
|
|
||||||
//lod = i;
|
|
||||||
UpdatedTerrainPatch utp = updates.get(terrainPatch.getName());
|
UpdatedTerrainPatch utp = updates.get(terrainPatch.getName());
|
||||||
if (utp == null) {
|
if (utp == null) {
|
||||||
utp = new UpdatedTerrainPatch(terrainPatch, i);//save in here, do not update actual variables
|
utp = new UpdatedTerrainPatch(terrainPatch);//save in here, do not update actual variables
|
||||||
updates.put(utp.getName(), utp);
|
updates.put(utp.getName(), utp);
|
||||||
}
|
}
|
||||||
|
utp.setNewLod(i);
|
||||||
utp.setPreviousLod(prevLOD);
|
utp.setPreviousLod(prevLOD);
|
||||||
utp.setReIndexNeeded(reIndexNeeded);
|
//utp.setReIndexNeeded(reIndexNeeded);
|
||||||
|
|
||||||
return reIndexNeeded;
|
return reIndexNeeded;
|
||||||
}
|
}
|
||||||
|
@ -106,15 +106,15 @@ public class PerspectiveLodCalculator implements LodCalculator {
|
|||||||
}
|
}
|
||||||
int prevLOD = patch.getLod();
|
int prevLOD = patch.getLod();
|
||||||
|
|
||||||
//previousLod = lod;
|
|
||||||
//lod = i;
|
|
||||||
UpdatedTerrainPatch utp = updates.get(patch.getName());
|
UpdatedTerrainPatch utp = updates.get(patch.getName());
|
||||||
if (utp == null) {
|
if (utp == null) {
|
||||||
utp = new UpdatedTerrainPatch(patch, i);//save in here, do not update actual variables
|
utp = new UpdatedTerrainPatch(patch);//save in here, do not update actual variables
|
||||||
updates.put(utp.getName(), utp);
|
updates.put(utp.getName(), utp);
|
||||||
}
|
}
|
||||||
|
utp.setNewLod(i);
|
||||||
utp.setPreviousLod(prevLOD);
|
utp.setPreviousLod(prevLOD);
|
||||||
utp.setReIndexNeeded(reIndexNeeded);
|
//utp.setReIndexNeeded(reIndexNeeded);
|
||||||
return reIndexNeeded;
|
return reIndexNeeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,13 @@ import com.jme3.material.Material;
|
|||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.shape.Sphere;
|
||||||
import com.jme3.terrain.ProgressMonitor;
|
import com.jme3.terrain.ProgressMonitor;
|
||||||
import com.jme3.terrain.Terrain;
|
import com.jme3.terrain.Terrain;
|
||||||
|
import com.jme3.terrain.geomipmap.MultiTerrainLodControl;
|
||||||
import com.jme3.terrain.geomipmap.NeighbourFinder;
|
import com.jme3.terrain.geomipmap.NeighbourFinder;
|
||||||
import com.jme3.terrain.geomipmap.TerrainLodControl;
|
|
||||||
import com.jme3.terrain.geomipmap.TerrainQuad;
|
import com.jme3.terrain.geomipmap.TerrainQuad;
|
||||||
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
@ -29,7 +31,8 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Demonstrates the NeighbourFinder interface for TerrainQuads,
|
* Demonstrates the NeighbourFinder interface for TerrainQuads,
|
||||||
* allowing you to tile terrains together without having to use
|
* allowing you to tile terrains together without having to use
|
||||||
* TerrainGrid.
|
* TerrainGrid. It also introduces the MultiTerrainLodControl that
|
||||||
|
* will seam the edges of all the terrains supplied.
|
||||||
*
|
*
|
||||||
* @author sploreg
|
* @author sploreg
|
||||||
*/
|
*/
|
||||||
@ -75,7 +78,31 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
rootNode.addLight(ambLight);
|
rootNode.addLight(ambLight);
|
||||||
|
|
||||||
cam.setLocation(new Vector3f(0, 256, 0));
|
cam.setLocation(new Vector3f(0, 256, 0));
|
||||||
cam.lookAtDirection(new Vector3f(0, -1f, 0).normalizeLocal(), Vector3f.UNIT_X);
|
cam.lookAtDirection(new Vector3f(0, -1, -1).normalizeLocal(), Vector3f.UNIT_Y);
|
||||||
|
|
||||||
|
|
||||||
|
Sphere s = new Sphere(12, 12, 3);
|
||||||
|
Geometry g = new Geometry("marker");
|
||||||
|
g.setMesh(s);
|
||||||
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
|
mat.setColor("Color", ColorRGBA.Red);
|
||||||
|
g.setMaterial(mat);
|
||||||
|
g.setLocalTranslation(0, -100, 0);
|
||||||
|
rootNode.attachChild(g);
|
||||||
|
|
||||||
|
Geometry g2 = new Geometry("marker");
|
||||||
|
g2.setMesh(s);
|
||||||
|
mat.setColor("Color", ColorRGBA.Red);
|
||||||
|
g2.setMaterial(mat);
|
||||||
|
g2.setLocalTranslation(10, -100, 0);
|
||||||
|
rootNode.attachChild(g2);
|
||||||
|
|
||||||
|
Geometry g3 = new Geometry("marker");
|
||||||
|
g3.setMesh(s);
|
||||||
|
mat.setColor("Color", ColorRGBA.Red);
|
||||||
|
g3.setMaterial(mat);
|
||||||
|
g3.setLocalTranslation(0, -100, 10);
|
||||||
|
rootNode.attachChild(g3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadHintText() {
|
public void loadHintText() {
|
||||||
@ -110,6 +137,8 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
* the use of NeighbourFinder.
|
* the use of NeighbourFinder.
|
||||||
* It just links up the left,right,top,bottom TerrainQuads
|
* It just links up the left,right,top,bottom TerrainQuads
|
||||||
* so LOD can work.
|
* so LOD can work.
|
||||||
|
* It does not implement many of the Terrain interface's methods,
|
||||||
|
* you will want to do that for your own implementations.
|
||||||
*/
|
*/
|
||||||
private class TiledTerrain extends Node implements Terrain, NeighbourFinder {
|
private class TiledTerrain extends Node implements Terrain, NeighbourFinder {
|
||||||
|
|
||||||
@ -132,41 +161,43 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
matTerrain.setFloat("DiffuseMap_0_scale", grassScale);
|
matTerrain.setFloat("DiffuseMap_0_scale", grassScale);
|
||||||
|
|
||||||
// CREATE THE TERRAIN
|
// CREATE THE TERRAIN
|
||||||
terrain1 = new TerrainQuad("terrain", 65, 513, null);
|
terrain1 = new TerrainQuad("terrain 1", 65, 513, null);
|
||||||
TerrainLodControl control1 = new TerrainLodControl(terrain1, getCamera());
|
|
||||||
control1.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
|
|
||||||
terrain1.addControl(control1);
|
|
||||||
terrain1.setMaterial(matTerrain);
|
terrain1.setMaterial(matTerrain);
|
||||||
terrain1.setLocalTranslation(-256, -100, -256);
|
terrain1.setLocalTranslation(-256, -100, -256);
|
||||||
terrain1.setLocalScale(1f, 1f, 1f);
|
terrain1.setLocalScale(1f, 1f, 1f);
|
||||||
this.attachChild(terrain1);
|
this.attachChild(terrain1);
|
||||||
|
|
||||||
terrain2 = new TerrainQuad("terrain", 65, 513, null);
|
terrain2 = new TerrainQuad("terrain 2", 65, 513, null);
|
||||||
TerrainLodControl control2 = new TerrainLodControl(terrain2, getCamera());
|
|
||||||
control2.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
|
|
||||||
terrain2.addControl(control2);
|
|
||||||
terrain2.setMaterial(matTerrain);
|
terrain2.setMaterial(matTerrain);
|
||||||
terrain2.setLocalTranslation(-256, -100, 256);
|
terrain2.setLocalTranslation(-256, -100, 256);
|
||||||
terrain2.setLocalScale(1f, 1f, 1f);
|
terrain2.setLocalScale(1f, 1f, 1f);
|
||||||
this.attachChild(terrain2);
|
this.attachChild(terrain2);
|
||||||
|
|
||||||
terrain3 = new TerrainQuad("terrain", 65, 513, null);
|
terrain3 = new TerrainQuad("terrain 3", 65, 513, null);
|
||||||
TerrainLodControl control3 = new TerrainLodControl(terrain3, getCamera());
|
|
||||||
control3.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
|
|
||||||
terrain3.addControl(control3);
|
|
||||||
terrain3.setMaterial(matTerrain);
|
terrain3.setMaterial(matTerrain);
|
||||||
terrain3.setLocalTranslation(256, -100, -256);
|
terrain3.setLocalTranslation(256, -100, -256);
|
||||||
terrain3.setLocalScale(1f, 1f, 1f);
|
terrain3.setLocalScale(1f, 1f, 1f);
|
||||||
this.attachChild(terrain3);
|
this.attachChild(terrain3);
|
||||||
|
|
||||||
terrain4 = new TerrainQuad("terrain", 65, 513, null);
|
terrain4 = new TerrainQuad("terrain 4", 65, 513, null);
|
||||||
TerrainLodControl control4 = new TerrainLodControl(terrain4, getCamera());
|
|
||||||
control4.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
|
|
||||||
terrain4.addControl(control4);
|
|
||||||
terrain4.setMaterial(matTerrain);
|
terrain4.setMaterial(matTerrain);
|
||||||
terrain4.setLocalTranslation(256, -100, 256);
|
terrain4.setLocalTranslation(256, -100, 256);
|
||||||
terrain4.setLocalScale(1f, 1f, 1f);
|
terrain4.setLocalScale(1f, 1f, 1f);
|
||||||
this.attachChild(terrain4);
|
this.attachChild(terrain4);
|
||||||
|
|
||||||
|
terrain1.setNeighbourFinder(this);
|
||||||
|
terrain2.setNeighbourFinder(this);
|
||||||
|
terrain3.setNeighbourFinder(this);
|
||||||
|
terrain4.setNeighbourFinder(this);
|
||||||
|
|
||||||
|
MultiTerrainLodControl lodControl = new MultiTerrainLodControl(getCamera());
|
||||||
|
lodControl.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
|
||||||
|
lodControl.addTerrain(terrain1);
|
||||||
|
lodControl.addTerrain(terrain2);
|
||||||
|
lodControl.addTerrain(terrain3);// order of these seems to matter
|
||||||
|
lodControl.addTerrain(terrain4);
|
||||||
|
this.addControl(lodControl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,6 +205,7 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
* 2 4
|
* 2 4
|
||||||
*/
|
*/
|
||||||
public TerrainQuad getRightQuad(TerrainQuad center) {
|
public TerrainQuad getRightQuad(TerrainQuad center) {
|
||||||
|
//System.out.println("lookup neighbour");
|
||||||
if (center == terrain1)
|
if (center == terrain1)
|
||||||
return terrain3;
|
return terrain3;
|
||||||
if (center == terrain2)
|
if (center == terrain2)
|
||||||
@ -187,6 +219,7 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
* 2 4
|
* 2 4
|
||||||
*/
|
*/
|
||||||
public TerrainQuad getLeftQuad(TerrainQuad center) {
|
public TerrainQuad getLeftQuad(TerrainQuad center) {
|
||||||
|
//System.out.println("lookup neighbour");
|
||||||
if (center == terrain3)
|
if (center == terrain3)
|
||||||
return terrain1;
|
return terrain1;
|
||||||
if (center == terrain4)
|
if (center == terrain4)
|
||||||
@ -200,6 +233,7 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
* 2 4
|
* 2 4
|
||||||
*/
|
*/
|
||||||
public TerrainQuad getTopQuad(TerrainQuad center) {
|
public TerrainQuad getTopQuad(TerrainQuad center) {
|
||||||
|
//System.out.println("lookup neighbour");
|
||||||
if (center == terrain2)
|
if (center == terrain2)
|
||||||
return terrain1;
|
return terrain1;
|
||||||
if (center == terrain4)
|
if (center == terrain4)
|
||||||
@ -213,6 +247,7 @@ public class TerrainTestTile extends SimpleApplication {
|
|||||||
* 2 4
|
* 2 4
|
||||||
*/
|
*/
|
||||||
public TerrainQuad getDownQuad(TerrainQuad center) {
|
public TerrainQuad getDownQuad(TerrainQuad center) {
|
||||||
|
//System.out.println("lookup neighbour");
|
||||||
if (center == terrain1)
|
if (center == terrain1)
|
||||||
return terrain2;
|
return terrain2;
|
||||||
if (center == terrain3)
|
if (center == terrain3)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user