diff --git a/engine/src/terrain/com/jme3/terrain/Terrain.java b/engine/src/terrain/com/jme3/terrain/Terrain.java index 6f3872e8a..7386aebbd 100644 --- a/engine/src/terrain/com/jme3/terrain/Terrain.java +++ b/engine/src/terrain/com/jme3/terrain/Terrain.java @@ -125,17 +125,6 @@ public interface Terrain { */ public int getMaxLod(); - /** - * Called by an LodControl. - * Calculates the level of detail of the terrain and adjusts its geometry. - * This is where the Terrain's LOD algorithm will change the detail of - * the terrain based on how far away this position is from the particular - * terrain patch. - * @param location 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 location, LodCalculator lodCalculator); - /** * Lock or unlock the meshes of this terrain. * Locked meshes are un-editable but have better performance. diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java index 502702eff..50357d3f0 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java @@ -51,6 +51,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.logging.Level; import java.util.logging.Logger; @@ -111,9 +114,10 @@ public class TerrainGrid extends TerrainQuad { protected Set listeners = new HashSet(); protected Material material; protected LRUCache cache = new LRUCache(16); - private int cellsLoaded = 0; - private int[] gridOffset; - private boolean runOnce = false; + protected int cellsLoaded = 0; + protected int[] gridOffset; + protected boolean runOnce = false; + protected ExecutorService cacheExecutor; protected class UpdateQuadCache implements Runnable { @@ -266,44 +270,6 @@ public class TerrainGrid extends TerrainQuad { } - /** - * @deprecated not needed to be called any more, handled automatically - */ - public void initialize(Vector3f location) { - if (this.material == null) { - throw new RuntimeException("Material must be set prior to call of initialize"); - } - Vector3f camCell = this.getCamCell(location); - this.updateChildren(camCell); - for (TerrainGridListener l : this.listeners) { - l.gridMoved(camCell); - } - } - - @Override - public void update(List 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 - // 2: grids are associated with locations, and no incremental update is done, we load new grids for new locations, and unload those that are not needed anymore - Vector3f cam = locations.isEmpty() ? Vector3f.ZERO.clone() : locations.get(0); - Vector3f camCell = this.getCamCell(cam); // get the grid index value of where the camera is (ie. 2,1) - if (cellsLoaded > 1) { // Check if cells are updated before updating gridoffset. - gridOffset[0] = Math.round(camCell.x * (size / 2)); - gridOffset[1] = Math.round(camCell.z * (size / 2)); - cellsLoaded = 0; - } - if (camCell.x != this.currentCamCell.x || camCell.z != currentCamCell.z || !runOnce) { - // if the camera has moved into a new cell, load new terrain into the visible 4 center quads - this.updateChildren(camCell); - for (TerrainGridListener l : this.listeners) { - l.gridMoved(camCell); - } - } - runOnce = true; - super.update(locations, lodCalculator); - } - public Vector3f getCamCell(Vector3f location) { Vector3f tile = getTileCell(location); Vector3f offsetHalf = new Vector3f(-0.5f, 0, -0.5f); @@ -361,13 +327,6 @@ public class TerrainGrid extends TerrainQuad { } } - @Deprecated - /** - * @Deprecated, use updateChildren - */ - protected void updateChildrens(Vector3f camCell) { - updateChildren(camCell); - } /** * Called when the camera has moved into a new cell. We need to @@ -417,12 +376,12 @@ public class TerrainGrid extends TerrainQuad { // --------------------------------------------------- // --------------------------------------------------- - if (executor == null) { + if (cacheExecutor == null) { // use the same executor as the LODControl - executor = createExecutorService(); + cacheExecutor = createExecutorService(); } - executor.submit(new UpdateQuadCache(camCell)); + cacheExecutor.submit(new UpdateQuadCache(camCell)); this.currentCamCell = camCell; } @@ -480,6 +439,17 @@ public class TerrainGrid extends TerrainQuad { return terrain.getMaterial(worldLocation); } + protected ExecutorService createExecutorService() { + return Executors.newSingleThreadExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread th = new Thread(r); + th.setName("jME Terrain Thread"); + th.setDaemon(true); + return th; + } + }); + } + @Override public void read(JmeImporter im) throws IOException { super.read(im); diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java index aedd744fd..25b17d47b 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java @@ -48,7 +48,11 @@ import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator; import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; /** * Tells the terrain to update its Level of Detail. @@ -73,6 +77,15 @@ public class TerrainLodControl extends AbstractControl { private LodCalculator lodCalculator; private boolean hasResetLod = false; // used when enabled is set to false + private HashMap updatedPatches; + private final Object updatePatchesLock = new Object(); + + protected List lastCameraLocations; // used for LOD calc + private boolean lodCalcRunning = false; + private int lodOffCount = 0; + + protected ExecutorService executor; + public TerrainLodControl() { } @@ -98,10 +111,16 @@ public class TerrainLodControl extends AbstractControl { @Override protected void controlRender(RenderManager rm, ViewPort vp) { } - - @Override - public void update(float tpf) { - controlUpdate(tpf); + + protected ExecutorService createExecutorService() { + return Executors.newSingleThreadExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread th = new Thread(r); + th.setName("jME Terrain Thread"); + th.setDaemon(true); + return th; + } + }); } @Override @@ -126,10 +145,116 @@ public class TerrainLodControl extends AbstractControl { cameraLocations.add(c.getLocation()); } } - terrain.update(cameraLocations, lodCalculator); + updateLOD(cameraLocations, lodCalculator); + } + } + + // do all of the LOD calculations + protected void updateLOD(List locations, LodCalculator lodCalculator) { + // update any existing ones that need updating + updateQuadLODs(); + + if (lodCalculator.isLodOff()) { + // we want to calculate the base lod at least once + if (lodOffCount == 1) + return; + else + lodOffCount++; + } else + lodOffCount = 0; + + if (lastCameraLocations != null) { + if (lastCameraLocationsTheSame(locations) && !lodCalculator.isLodOff()) + return; // don't update if in same spot + else + lastCameraLocations = cloneVectorList(locations); + } + else { + lastCameraLocations = cloneVectorList(locations); + return; + } + + if (isLodCalcRunning()) { + return; + } + + //if (getParent() instanceof TerrainQuad) { + // return; // we just want the root quad to perform this. + //} + + if (executor == null) + executor = createExecutorService(); + + TerrainQuad terrain = (TerrainQuad)getSpatial(); + 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 updated) { + synchronized (updatePatchesLock) { + updatedPatches = updated; + } + } + + /** + * Back on the ogl thread: update the terrain patch geometries + * @param updatedPatches to be updated + */ + private void updateQuadLODs() { + synchronized (updatePatchesLock) { + + if (updatedPatches == null || updatedPatches.isEmpty()) + return; + + // do the actual geometry update here + for (UpdatedTerrainPatch utp : updatedPatches.values()) { + utp.updateAll(); + } + + updatedPatches.clear(); + } + } + + public boolean hasPatchesToUpdate() { + return updatedPatches != null && !updatedPatches.isEmpty(); + } + + private boolean lastCameraLocationsTheSame(List locations) { + boolean theSame = true; + for (Vector3f l : locations) { + for (Vector3f v : lastCameraLocations) { + if (!v.equals(l) ) { + theSame = false; + return false; + } + } } + return theSame; + } + + private synchronized boolean isLodCalcRunning() { + return lodCalcRunning; + } + + private synchronized void setLodCalcRunning(boolean running) { + lodCalcRunning = running; } + private List cloneVectorList(List locations) { + List cloned = new ArrayList(); + for(Vector3f l : locations) + cloned.add(l.clone()); + return cloned; + } + + + + + + + public Control cloneForSpatial(Spatial spatial) { if (spatial instanceof Terrain) { List cameraClone = new ArrayList(); @@ -190,6 +315,56 @@ public class TerrainLodControl extends AbstractControl { lodCalculator.turnOnLod(); } } + + + /** + * Calculates the LOD of all child terrain patches. + */ + private class UpdateLOD implements Runnable { + private List camLocations; + private LodCalculator lodCalculator; + + UpdateLOD(List camLocations, LodCalculator lodCalculator) { + this.camLocations = camLocations; + this.lodCalculator = lodCalculator; + } + + public void run() { + long start = System.currentTimeMillis(); + if (isLodCalcRunning()) { + //System.out.println("thread already running"); + return; + } + //System.out.println("spawned thread "+toString()); + setLodCalcRunning(true); + + TerrainQuad terrainQuad = (TerrainQuad)getSpatial(); + + // go through each patch and calculate its LOD based on camera distance + HashMap updated = new HashMap(); + boolean lodChanged = terrainQuad.calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here + + if (!lodChanged) { + // not worth updating anything else since no one's LOD changed + setLodCalcRunning(false); + return; + } + + + // then calculate its neighbour LOD values for seaming in the shader + terrainQuad.findNeighboursLod(updated); + + terrainQuad.fixEdges(updated); // 'updated' can get added to here + + terrainQuad.reIndexPages(updated, lodCalculator.usesVariableLod()); + + setUpdateQuadLODs(updated); // set back to main ogl thread + + setLodCalcRunning(false); + //double duration = (System.currentTimeMillis()-start); + //System.out.println("terminated in "+duration); + } + } @Override public void write(JmeExporter ex) throws IOException { diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java index cd9c29935..3d96f498e 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java @@ -106,6 +106,9 @@ public class TerrainPatch extends Geometry { protected TerrainPatch leftNeighbour, topNeighbour, rightNeighbour, bottomNeighbour; protected boolean searchedForNeighboursAlready = false; + // these two vectors are calculated on the GL thread, but used in the outside LOD thread + protected Vector3f worldTranslationCached; + protected Vector3f worldScaleCached; protected float[] lodEntropy; @@ -942,6 +945,22 @@ public class TerrainPatch extends Geometry { } } + /** + * Caches the transforms (except rotation) so the LOD calculator, + * which runs on a separate thread, can access them safely. + */ + protected void cacheTerrainTransforms() { + this.worldScaleCached = getWorldScale().clone(); + this.worldTranslationCached = getWorldTranslation().clone(); + } + + public Vector3f getWorldScaleCached() { + return worldScaleCached; + } + + public Vector3f getWorldTranslationCached() { + return worldTranslationCached; + } } diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java index dbcc57dc9..bfbcc79b5 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java @@ -61,9 +61,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; import java.util.logging.Level; import java.util.logging.Logger; @@ -104,34 +101,12 @@ public class TerrainQuad extends Node implements Terrain { protected float offsetAmount; protected int quadrant = 0; // 1=upper left, 2=lower left, 3=upper right, 4=lower right - - //protected LodCalculatorFactory lodCalculatorFactory; - //protected LodCalculator lodCalculator; - - protected List lastCameraLocations; // used for LOD calc - private boolean lodCalcRunning = false; - private int lodOffCount = 0; private int maxLod = -1; - private HashMap updatedPatches; - private final Object updatePatchesLock = new Object(); private BoundingBox affectedAreaBBox; // only set in the root quad private TerrainPicker picker; private Vector3f lastScale = Vector3f.UNIT_XYZ; - protected ExecutorService executor; - - protected ExecutorService createExecutorService() { - return Executors.newSingleThreadExecutor(new ThreadFactory() { - public Thread newThread(Runnable r) { - Thread th = new Thread(r); - th.setName("jME Terrain Thread"); - th.setDaemon(true); - return th; - } - }); - } - public TerrainQuad() { super("Terrain"); } @@ -220,24 +195,9 @@ public class TerrainQuad extends Node implements Terrain { this.size = quadSize; this.patchSize = patchSize; this.stepScale = scale; - //this.lodCalculatorFactory = lodCalculatorFactory; - //this.lodCalculator = lodCalculator; split(patchSize, heightMap); } - /*public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) { - if (children != null) { - for (int i = children.size(); --i >= 0;) { - Spatial child = children.get(i); - if (child instanceof TerrainQuad) { - ((TerrainQuad) child).setLodCalculatorFactory(lodCalculatorFactory); - } else if (child instanceof TerrainPatch) { - ((TerrainPatch) child).setLodCalculator(lodCalculatorFactory.createCalculator((TerrainPatch) child)); - } - } - } - }*/ - /** * Forces the recalculation of all normals on the terrain. */ @@ -253,16 +213,6 @@ public class TerrainQuad extends Node implements Terrain { return heightMap; } - /** - * Call from the update() method of a terrain controller to update - * the LOD values of each patch. - * This will perform the geometry calculation in a background thread and - * do the actual update on the opengl thread. - */ - public void update(List locations, LodCalculator lodCalculator) { - updateLOD(locations, lodCalculator); - } - /** * update the normals if there were any height changes recently. * Should only be called on the root quad @@ -277,73 +227,20 @@ public class TerrainQuad extends Node implements Terrain { setNormalRecalcNeeded(null); // set to false } } - - // do all of the LOD calculations - protected void updateLOD(List locations, LodCalculator lodCalculator) { - // update any existing ones that need updating - updateQuadLODs(); - - if (lodCalculator.isLodOff()) { - // we want to calculate the base lod at least once - if (lodOffCount == 1) - return; - else - lodOffCount++; - } else - lodOffCount = 0; - - if (lastCameraLocations != null) { - if (lastCameraLocationsTheSame(locations) && !lodCalculator.isLodOff()) - return; // don't update if in same spot - else - lastCameraLocations = cloneVectorList(locations); - } - else { - lastCameraLocations = cloneVectorList(locations); - return; - } - - if (isLodCalcRunning()) { - return; - } - - if (getParent() instanceof TerrainQuad) { - return; // we just want the root quad to perform this. - } - - if (executor == null) - executor = createExecutorService(); - - UpdateLOD updateLodThread = new UpdateLOD(locations, lodCalculator); - executor.execute(updateLodThread); - } - - private synchronized boolean isLodCalcRunning() { - return lodCalcRunning; - } - - private synchronized void setLodCalcRunning(boolean running) { - lodCalcRunning = running; - } - - private List cloneVectorList(List locations) { - List cloned = new ArrayList(); - for(Vector3f l : locations) - cloned.add(l.clone()); - return cloned; - } - - private boolean lastCameraLocationsTheSame(List locations) { - boolean theSame = true; - for (Vector3f l : locations) { - for (Vector3f v : lastCameraLocations) { - if (!v.equals(l) ) { - theSame = false; - return false; - } + + /** + * Caches the transforms (except rotation) so the LOD calculator, + * which runs on a separate thread, can access them safely. + */ + protected void cacheTerrainTransforms() { + for (int i = children.size(); --i >= 0;) { + Spatial child = children.get(i); + if (child instanceof TerrainQuad) { + ((TerrainQuad) child).cacheTerrainTransforms(); + } else if (child instanceof TerrainPatch) { + ((TerrainPatch) child).cacheTerrainTransforms(); } } - return theSame; } private int collideWithRay(Ray ray, CollisionResults results) { @@ -412,86 +309,10 @@ public class TerrainQuad extends Node implements Terrain { return null; } - //public float getTextureCoordinateScale() { - // return 1f/(float)totalSize; - //} public int getNumMajorSubdivisions() { return 1; } - - /** - * Calculates the LOD of all child terrain patches. - */ - private class UpdateLOD implements Runnable { - private List camLocations; - private LodCalculator lodCalculator; - - UpdateLOD(List camLocations, LodCalculator lodCalculator) { - this.camLocations = camLocations; - this.lodCalculator = lodCalculator; - } - - public void run() { - long start = System.currentTimeMillis(); - if (isLodCalcRunning()) { - //System.out.println("thread already running"); - return; - } - //System.out.println("spawned thread "+toString()); - setLodCalcRunning(true); - - // go through each patch and calculate its LOD based on camera distance - HashMap updated = new HashMap(); - boolean lodChanged = calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here - - if (!lodChanged) { - // not worth updating anything else since no one's LOD changed - setLodCalcRunning(false); - return; - } - // then calculate its neighbour LOD values for seaming in the shader - findNeighboursLod(updated); - - fixEdges(updated); // 'updated' can get added to here - - reIndexPages(updated, lodCalculator.usesVariableLod()); - - setUpdateQuadLODs(updated); // set back to main ogl thread - - setLodCalcRunning(false); - //double duration = (System.currentTimeMillis()-start); - //System.out.println("terminated in "+duration); - } - } - - private void setUpdateQuadLODs(HashMap updated) { - synchronized (updatePatchesLock) { - updatedPatches = updated; - } - } - - /** - * Back on the ogl thread: update the terrain patch geometries - * @param updatedPatches to be updated - */ - private void updateQuadLODs() { - synchronized (updatePatchesLock) { - - if (updatedPatches == null || updatedPatches.isEmpty()) - return; - - // do the actual geometry update here - for (UpdatedTerrainPatch utp : updatedPatches.values()) { - utp.updateAll(); - } - - updatedPatches.clear(); - } - } - public boolean hasPatchesToUpdate() { - return updatedPatches != null && !updatedPatches.isEmpty(); - } protected boolean calculateLod(List location, HashMap updates, LodCalculator lodCalculator) { diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/UpdatedTerrainPatch.java b/engine/src/terrain/com/jme3/terrain/geomipmap/UpdatedTerrainPatch.java index 7a335d0e6..f64ee1cc4 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/UpdatedTerrainPatch.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/UpdatedTerrainPatch.java @@ -44,140 +44,140 @@ import java.nio.IntBuffer; */ public class UpdatedTerrainPatch { - private TerrainPatch updatedPatch; - private int newLod; - private int previousLod; - private int rightLod,topLod,leftLod,bottomLod; - private IntBuffer newIndexBuffer; - private boolean reIndexNeeded = false; - private boolean fixEdges = false; + private TerrainPatch updatedPatch; + private int newLod; + private int previousLod; + private int rightLod,topLod,leftLod,bottomLod; + private IntBuffer newIndexBuffer; + private boolean reIndexNeeded = false; + private boolean fixEdges = false; - public UpdatedTerrainPatch(TerrainPatch updatedPatch, int newLod) { - this.updatedPatch = updatedPatch; - this.newLod = newLod; - } + public UpdatedTerrainPatch(TerrainPatch updatedPatch, int newLod) { + this.updatedPatch = updatedPatch; + 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 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() { - return updatedPatch.getName(); - } + public String getName() { + return updatedPatch.getName(); + } - protected boolean lodChanged() { - if (reIndexNeeded && previousLod != newLod) - return true; - else - return false; - } + protected boolean lodChanged() { + if (reIndexNeeded && previousLod != newLod) + return true; + else + return false; + } - protected TerrainPatch getUpdatedPatch() { - return updatedPatch; - } + protected TerrainPatch getUpdatedPatch() { + return updatedPatch; + } - protected void setUpdatedPatch(TerrainPatch updatedPatch) { - this.updatedPatch = updatedPatch; - } + protected void setUpdatedPatch(TerrainPatch updatedPatch) { + this.updatedPatch = updatedPatch; + } - protected int getNewLod() { - return newLod; - } + protected int getNewLod() { + return newLod; + } - public void setNewLod(int newLod) { - this.newLod = newLod; - if (this.newLod < 0) - throw new IllegalArgumentException(); - } + public void setNewLod(int newLod) { + this.newLod = newLod; + if (this.newLod < 0) + throw new IllegalArgumentException(); + } - protected IntBuffer getNewIndexBuffer() { - return newIndexBuffer; - } + protected IntBuffer getNewIndexBuffer() { + return newIndexBuffer; + } - protected void setNewIndexBuffer(IntBuffer newIndexBuffer) { - this.newIndexBuffer = newIndexBuffer; - } + protected void setNewIndexBuffer(IntBuffer newIndexBuffer) { + this.newIndexBuffer = newIndexBuffer; + } - protected int getRightLod() { - return rightLod; - } + protected int getRightLod() { + return rightLod; + } - protected void setRightLod(int rightLod) { - this.rightLod = rightLod; - } + protected void setRightLod(int rightLod) { + this.rightLod = rightLod; + } - protected int getTopLod() { - return topLod; - } + protected int getTopLod() { + return topLod; + } - protected void setTopLod(int topLod) { - this.topLod = topLod; - } + protected void setTopLod(int topLod) { + this.topLod = topLod; + } - protected int getLeftLod() { - return leftLod; - } + protected int getLeftLod() { + return leftLod; + } - protected void setLeftLod(int leftLod) { - this.leftLod = leftLod; - } + protected void setLeftLod(int leftLod) { + this.leftLod = leftLod; + } - protected int getBottomLod() { - return bottomLod; - } + protected int getBottomLod() { + return bottomLod; + } - protected void setBottomLod(int bottomLod) { - this.bottomLod = bottomLod; - } + protected void setBottomLod(int bottomLod) { + this.bottomLod = bottomLod; + } - public boolean isReIndexNeeded() { - return reIndexNeeded; - } + public boolean isReIndexNeeded() { + return reIndexNeeded; + } - public void setReIndexNeeded(boolean reIndexNeeded) { - this.reIndexNeeded = reIndexNeeded; - } + public void setReIndexNeeded(boolean reIndexNeeded) { + this.reIndexNeeded = reIndexNeeded; + } - public boolean isFixEdges() { - return fixEdges; - } + public boolean isFixEdges() { + return fixEdges; + } - public void setFixEdges(boolean fixEdges) { - this.fixEdges = fixEdges; - } + public void setFixEdges(boolean fixEdges) { + this.fixEdges = fixEdges; + } - public int getPreviousLod() { - return previousLod; - } + public int getPreviousLod() { + return previousLod; + } - public void setPreviousLod(int previousLod) { - this.previousLod = previousLod; - } + public void setPreviousLod(int previousLod) { + this.previousLod = previousLod; + } - public void updateAll() { - updatedPatch.setLod(newLod); - updatedPatch.setLodRight(rightLod); - updatedPatch.setLodTop(topLod); - updatedPatch.setLodLeft(leftLod); - updatedPatch.setLodBottom(bottomLod); - if (newIndexBuffer != null && (reIndexNeeded || fixEdges)) { - updatedPatch.setPreviousLod(previousLod); - updatedPatch.getMesh().clearBuffer(Type.Index); - updatedPatch.getMesh().setBuffer(Type.Index, 3, newIndexBuffer); - } - } + public void updateAll() { + updatedPatch.setLod(newLod); + updatedPatch.setLodRight(rightLod); + updatedPatch.setLodTop(topLod); + updatedPatch.setLodLeft(leftLod); + updatedPatch.setLodBottom(bottomLod); + if (newIndexBuffer != null && (reIndexNeeded || fixEdges)) { + updatedPatch.setPreviousLod(previousLod); + updatedPatch.getMesh().clearBuffer(Type.Index); + updatedPatch.getMesh().setBuffer(Type.Index, 3, newIndexBuffer); + } + } } diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java b/engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java index 3ab34c971..86bb38d91 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/lodcalc/DistanceLodCalculator.java @@ -82,7 +82,7 @@ public class DistanceLodCalculator implements LodCalculator { // go through each lod level to find the one we are in for (int i = 0; i <= terrainPatch.getMaxLod(); i++) { - if (distance < getLodDistanceThreshold() * (i + 1)*terrainPatch.getWorldScale().x || i == terrainPatch.getMaxLod()) { + if (distance < getLodDistanceThreshold() * (i + 1)*terrainPatch.getWorldScaleCached().x || i == terrainPatch.getMaxLod()) { boolean reIndexNeeded = false; if (i != terrainPatch.getLod()) { reIndexNeeded = true; @@ -107,9 +107,9 @@ public class DistanceLodCalculator implements LodCalculator { } 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; + Vector3f loc = terrainPatch.getWorldTranslationCached(); + loc.x += terrainPatch.getSize()*terrainPatch.getWorldScaleCached().x / 2; + loc.z += terrainPatch.getSize()*terrainPatch.getWorldScaleCached().z / 2; return loc; } diff --git a/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java b/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java index 499a8d60d..0ab647d62 100644 --- a/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java +++ b/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java @@ -7,6 +7,7 @@ import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.terrain.geomipmap.TerrainGrid; +import com.jme3.terrain.geomipmap.TerrainGridLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.grid.FractalTileLoader; import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator; @@ -128,7 +129,7 @@ public class TerrainFractalGridTest extends SimpleApplication { this.terrain.setLocalScale(2f, 1f, 2f); this.rootNode.attachChild(this.terrain); - TerrainLodControl control = new TerrainLodControl(this.terrain, this.getCamera()); + TerrainLodControl control = new TerrainGridLodControl(this.terrain, this.getCamera()); control.setLodCalculator(new DistanceLodCalculator(33, 2.7f)); // patch size, and a multiplier this.terrain.addControl(control); diff --git a/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java b/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java index 6c45e7272..27b7cf0a7 100644 --- a/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java +++ b/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java @@ -25,6 +25,7 @@ import com.jme3.scene.Spatial; import com.jme3.scene.debug.Arrow; import com.jme3.terrain.geomipmap.TerrainGrid; import com.jme3.terrain.geomipmap.TerrainGridListener; +import com.jme3.terrain.geomipmap.TerrainGridLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.geomipmap.grid.FractalTileLoader; @@ -158,9 +159,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication { this.terrain.setLocalScale(2f, 1f, 2f); this.rootNode.attachChild(this.terrain); - List cameras = new ArrayList(); - cameras.add(this.getCamera()); - TerrainLodControl control = new TerrainLodControl(this.terrain, cameras); + TerrainLodControl control = new TerrainGridLodControl(this.terrain, this.getCamera()); control.setLodCalculator( new DistanceLodCalculator(33, 2.7f) ); // patch size, and a multiplier this.terrain.addControl(control); diff --git a/engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java b/engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java index ec07e7afe..d25b92462 100644 --- a/engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java +++ b/engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java @@ -17,6 +17,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.terrain.geomipmap.TerrainGrid; import com.jme3.terrain.geomipmap.TerrainGridListener; +import com.jme3.terrain.geomipmap.TerrainGridLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator; @@ -50,7 +51,7 @@ public class TerrainGridSerializationTest extends SimpleApplication { this.rootNode.attachChild(this.terrain); - TerrainLodControl control = new TerrainLodControl(this.terrain, getCamera()); + TerrainLodControl control = new TerrainGridLodControl(this.terrain, getCamera()); control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier this.terrain.addControl(control); diff --git a/engine/src/test/jme3test/terrain/TerrainGridTest.java b/engine/src/test/jme3test/terrain/TerrainGridTest.java index 85f8ee424..4e1381c13 100644 --- a/engine/src/test/jme3test/terrain/TerrainGridTest.java +++ b/engine/src/test/jme3test/terrain/TerrainGridTest.java @@ -18,6 +18,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.terrain.geomipmap.TerrainGrid; import com.jme3.terrain.geomipmap.TerrainGridListener; +import com.jme3.terrain.geomipmap.TerrainGridLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.geomipmap.grid.ImageTileLoader; @@ -107,7 +108,7 @@ public class TerrainGridTest extends SimpleApplication { this.terrain.setLocalScale(1f, 1f, 1f); this.rootNode.attachChild(this.terrain); - TerrainLodControl control = new TerrainLodControl(this.terrain, getCamera()); + TerrainLodControl control = new TerrainGridLodControl(this.terrain, getCamera()); control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier this.terrain.addControl(control); diff --git a/engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java b/engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java index 86fbbf988..0af562b7e 100644 --- a/engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java +++ b/engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java @@ -17,6 +17,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.terrain.geomipmap.TerrainGrid; import com.jme3.terrain.geomipmap.TerrainGridListener; +import com.jme3.terrain.geomipmap.TerrainGridLodControl; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.geomipmap.grid.AssetTileLoader; @@ -108,7 +109,7 @@ public class TerrainGridTileLoaderTest extends SimpleApplication { this.rootNode.attachChild(this.terrain); - TerrainLodControl control = new TerrainLodControl(this.terrain, getCamera()); + TerrainLodControl control = new TerrainGridLodControl(this.terrain, getCamera()); control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier this.terrain.addControl(control);