mirror of
				https://github.com/Dejvino/roadtrip
				synced 2025-10-31 07:45:22 +00:00 
			
		
		
		
	Map: Fine-grained terrain grid implemented. Now there is smoother loading and unloading of terrain tiles.
This commit is contained in:
		
							parent
							
								
									c9a5429193
								
							
						
					
					
						commit
						bdadc3c739
					
				| @ -41,6 +41,7 @@ import com.jme3.math.FastMath; | ||||
| import com.jme3.math.Vector2f; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.scene.Spatial; | ||||
| import com.jme3.scene.control.LodControl; | ||||
| import com.jme3.scene.control.UpdateControl; | ||||
| import com.jme3.terrain.Terrain; | ||||
| import com.jme3.terrain.geomipmap.LRUCache; | ||||
| @ -122,10 +123,11 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|     protected HeightMapGrid heightMapGrid; | ||||
|     private TerrainGridTileLoader gridTileLoader; | ||||
|     protected Vector3f[] quadIndex; | ||||
|     protected Set<TerrainGridListener> listeners = new HashSet<TerrainGridListener>(); | ||||
|     protected Set<TerrainGridListener> listeners = new HashSet<>(); | ||||
|     protected Material material; | ||||
|     //cache  needs to be 1 row (4 cells) larger than what we care is cached | ||||
|     protected LRUCache<Vector3f, TerrainQuad> cache = new LRUCache<Vector3f, TerrainQuad>(20); | ||||
|     protected LRUCache<Vector3f, TerrainQuad> cache = new LRUCache<>( | ||||
|             getSubdivisionsPerSide() * getSubdivisionsPerSide() + getSubdivisionsPerSide()); | ||||
|     protected int cellsLoaded = 0; | ||||
|     protected int[] gridOffset; | ||||
|     protected boolean runOnce = false; | ||||
| @ -134,6 +136,11 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|     public int getSize() { | ||||
|         return size; | ||||
|     } | ||||
|      | ||||
|     public int getSubdivisionsPerSide() | ||||
|     { | ||||
|         return 8; | ||||
|     } | ||||
| 
 | ||||
|     protected class UpdateQuadCache implements Runnable { | ||||
| 
 | ||||
| @ -153,9 +160,9 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|          * neighbours). | ||||
|          */ | ||||
|         public void run() { | ||||
|             for (int i = 0; i < 4; i++) { | ||||
|                 for (int j = 0; j < 4; j++) { | ||||
|                     int quadIdx = i * 4 + j; | ||||
|             for (int i = 0; i < getSubdivisionsPerSide(); i++) { | ||||
|                 for (int j = 0; j < getSubdivisionsPerSide(); j++) { | ||||
|                     int quadIdx = i * getSubdivisionsPerSide() + j; | ||||
|                     final Vector3f quadCell = location.add(quadIndex[quadIdx]); | ||||
|                     TerrainQuad q = cache.get(quadCell); | ||||
|                     if (q == null) { | ||||
| @ -221,20 +228,18 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|     } | ||||
| 
 | ||||
|     protected boolean isCenter(int quadIndex) { | ||||
|         return quadIndex == 9 || quadIndex == 5 || quadIndex == 10 || quadIndex == 6; | ||||
|         // The only thing that is not a center for us here are the edges of the grid. | ||||
|         int w = getSubdivisionsPerSide(); | ||||
|         // left / right edge | ||||
|         if (quadIndex % w == 0 || (quadIndex + 1) % w == 0) return false; | ||||
|         // top / down edge | ||||
|         if (quadIndex < w || quadIndex >= (w*w - w)) return false; | ||||
|         // center | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     protected int getQuadrant(int quadIndex) { | ||||
|         if (quadIndex == 5) { | ||||
|             return 1; | ||||
|         } else if (quadIndex == 9) { | ||||
|             return 2; | ||||
|         } else if (quadIndex == 6) { | ||||
|             return 3; | ||||
|         } else if (quadIndex == 10) { | ||||
|             return 4; | ||||
|         } | ||||
|         return 0; // error | ||||
|         return quadIndex + 1; // whatever, just not 0 | ||||
|     } | ||||
| 
 | ||||
|     public FineTerrainGrid(String name, int patchSize, int maxVisibleSize, Vector3f scale, TerrainGridTileLoader terrainQuadGrid, | ||||
| @ -268,8 +273,8 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
| 
 | ||||
|     private void initData() { | ||||
|         int maxVisibleSize = size; | ||||
|         this.quarterSize = maxVisibleSize >> 2; | ||||
|         this.quadSize = (maxVisibleSize + 1) >> 1; | ||||
|         this.quarterSize = maxVisibleSize / getSubdivisionsPerSide(); | ||||
|         this.quadSize = (maxVisibleSize / getSubdivisionsPerSide()) + 1; | ||||
|         this.totalSize = maxVisibleSize; | ||||
|         this.gridOffset = new int[]{0, 0}; | ||||
| 
 | ||||
| @ -282,11 +287,14 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|          *         | | ||||
|          *         z | ||||
|          */ | ||||
|         this.quadIndex = new Vector3f[]{ | ||||
|             new Vector3f(-1, 0, -1), new Vector3f(0, 0, -1), new Vector3f(1, 0, -1), new Vector3f(2, 0, -1), | ||||
|             new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(2, 0, 0), | ||||
|             new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1), | ||||
|             new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2)}; | ||||
|         // generate a grid of quad positions | ||||
|         this.quadIndex = new Vector3f[getSubdivisionsPerSide() * getSubdivisionsPerSide()]; | ||||
|         int i = 0; | ||||
|         for (int z = -getSubdivisionsPerSide() / 2 + 1; z <= getSubdivisionsPerSide() / 2; z++) { | ||||
|             for (int x = -getSubdivisionsPerSide() / 2 + 1; x <= getSubdivisionsPerSide() / 2; x++) { | ||||
|                 quadIndex[i++] = new Vector3f(x, 0, z); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @ -357,7 +365,7 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|     } | ||||
|      | ||||
|     protected void removeQuad(TerrainQuad q) { | ||||
|         if (q != null && ( (q.getQuadrant() > 0 && q.getQuadrant()<5) || q.getParent() != null) ) { | ||||
|         if (q != null && ( q.getParent() != null) ) { | ||||
|             for (TerrainGridListener l : listeners) { | ||||
|                 l.tileDetached(getTileCell(q.getWorldTranslation()), q); | ||||
|             } | ||||
| @ -372,7 +380,6 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|      * @param shifted quads are still attached to the parent and don't need to re-load | ||||
|      */ | ||||
|     protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f quadCell, boolean shifted) { | ||||
|          | ||||
|         q.setQuadrant((short) quadrant); | ||||
|         if (!shifted) | ||||
|             this.attachChild(q); | ||||
| @ -386,7 +393,6 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|             } | ||||
|         } | ||||
|         updateModelBound(); | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|      | ||||
| @ -412,17 +418,17 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|         } | ||||
| 
 | ||||
|         int xMin = 0; | ||||
|         int xMax = 4; | ||||
|         int xMax = getSubdivisionsPerSide(); | ||||
|         int yMin = 0; | ||||
|         int yMax = 4; | ||||
|         int yMax = getSubdivisionsPerSide(); | ||||
|         if (dx == -1) { // camera moved to -X direction | ||||
|             xMax = 3; | ||||
|             xMax = getSubdivisionsPerSide() - 1; | ||||
|         } else if (dx == 1) { // camera moved to +X direction | ||||
|             xMin = 1; | ||||
|         } | ||||
| 
 | ||||
|         if (dy == -1) { // camera moved to -Y direction | ||||
|             yMax = 3; | ||||
|             yMax = getSubdivisionsPerSide() - 1; | ||||
|         } else if (dy == 1) { // camera moved to +Y direction | ||||
|             yMin = 1; | ||||
|         } | ||||
| @ -432,7 +438,7 @@ public class FineTerrainGrid extends TerrainQuad { | ||||
|         // either way in one of the axes (say X or Y axis) then they are all touched. | ||||
|         for (int i = yMin; i < yMax; i++) { | ||||
|             for (int j = xMin; j < xMax; j++) { | ||||
|                 cache.get(camCell.add(quadIndex[i * 4 + j])); | ||||
|                 cache.get(camCell.add(quadIndex[i * getSubdivisionsPerSide() + j])); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|  | ||||
| @ -16,6 +16,7 @@ import com.jme3.scene.Spatial; | ||||
| import com.jme3.terrain.geomipmap.*; | ||||
| import com.jme3.terrain.geomipmap.grid.FractalTileLoader; | ||||
| import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator; | ||||
| import com.jme3.terrain.geomipmap.lodcalc.LodCalculator; | ||||
| import com.jme3.terrain.noise.ShaderUtils; | ||||
| import com.jme3.terrain.noise.basis.FilteredBasis; | ||||
| import com.jme3.terrain.noise.filter.IterativeFilter; | ||||
| @ -35,7 +36,7 @@ import roadtrip.view.model.GameWorldState; | ||||
|  */ | ||||
| public class GameWorldView { | ||||
| 
 | ||||
|     public static boolean DEBUG = false;//true; | ||||
|     public static boolean DEBUG = true; | ||||
|      | ||||
|     private final GameWorldState state; | ||||
| 
 | ||||
| @ -157,10 +158,12 @@ public class GameWorldView { | ||||
|         //terrain.terrainGrid.setLocalScale(2f, 1f, 2f); | ||||
|         this.rootNode.attachChild(terrain.terrainGrid); | ||||
| 
 | ||||
|         TerrainLodControl control = new FineTerrainGridLodControl(terrain.terrainGrid, camera); | ||||
|         control.setLodCalculator(new DistanceLodCalculator(patchSize + 1, 3.7f)); // patch size, and a multiplier | ||||
|         terrain.terrainGrid.addControl(control); | ||||
| 
 | ||||
|         final TerrainLodControl lodControl = new FineTerrainGridLodControl(terrain.terrainGrid, camera); | ||||
|         lodControl.setLodCalculator(new DistanceLodCalculator(patchSize + 1, 3.7f)); // patch size, and a multiplier | ||||
|         terrain.terrainGrid.addControl(lodControl); | ||||
|          | ||||
|         final Spatial treeModel = assetManager.loadModel("Models/tree.j3o"); | ||||
|          | ||||
|         final FineTerrainGrid terrainGrid = terrain.terrainGrid; | ||||
|         terrainGrid.addListener(new TerrainGridListener() { | ||||
| 
 | ||||
| @ -170,6 +173,7 @@ public class GameWorldView { | ||||
| 
 | ||||
|             @Override | ||||
|             public void tileAttached(Vector3f cell, TerrainQuad quad) { | ||||
|                 lodControl.forceUpdate(); | ||||
|                 while(quad.getControl(RigidBodyControl.class)!=null){ | ||||
|                     quad.removeControl(RigidBodyControl.class); | ||||
|                 } | ||||
| @ -180,7 +184,8 @@ public class GameWorldView { | ||||
| 
 | ||||
|                 String quadObjectsNodeKey = getQuadObjectsNodeKey(quad); | ||||
|                 Node objects = new Node(quadObjectsNodeKey); | ||||
|                 populateQuadObjectsNode(quad, objects); | ||||
|                 // TODO: fix | ||||
|                 //populateQuadObjectsNode(quad, objects); | ||||
|                 rootNode.attachChild(objects); | ||||
|             } | ||||
| 
 | ||||
| @ -189,7 +194,6 @@ public class GameWorldView { | ||||
|                 ProceduralMapQuadBlock mapQuadBlock = state.proceduralMap.getMapQuadBlock(quad); | ||||
| 
 | ||||
|                 // Add map objects (for now - trees) | ||||
|                 Spatial treeModel = assetManager.loadModel("Models/tree.j3o"); | ||||
|                 //System.out.println("Grid @ " + terrainGrid.getLocalTranslation() + " s " + terrainGrid.getLocalScale()); | ||||
|                 //System.out.println("Quad " + quad.getName() + " @ " + quad.getLocalTranslation()); | ||||
|                 for (MapObjectInstance mapObject : mapQuadBlock.getMapObjects()) { | ||||
| @ -202,7 +206,7 @@ public class GameWorldView { | ||||
|                     if (control != null) { | ||||
|                         modelInstance.addControl(control); | ||||
|                         control.setPhysicsLocation(pos); | ||||
|                         physicsSpace.add(control); | ||||
|                         //physicsSpace.add(control); | ||||
|                     } | ||||
|                     objects.attachChild(modelInstance); | ||||
|                 } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user