瀏覽代碼

fixed an issue with TerrainGrid not having a large enough cache of tiles. Properly hooked in the tileDetached event

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9772 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
bre..om 13 年之前
父節點
當前提交
c4574bff13

+ 35 - 17
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java

@@ -114,7 +114,8 @@ public class TerrainGrid extends TerrainQuad {
     protected Vector3f[] quadIndex;
     protected Set<TerrainGridListener> listeners = new HashSet<TerrainGridListener>();
     protected Material material;
-    protected LRUCache<Vector3f, TerrainQuad> cache = new LRUCache<Vector3f, TerrainQuad>(16);
+    //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 int cellsLoaded = 0;
     protected int[] gridOffset;
     protected boolean runOnce = false;
@@ -159,16 +160,28 @@ public class TerrainGrid extends TerrainQuad {
                     }
                     cache.put(quadCell, q);
 
+                    
+                    final int quadrant = getQuadrant(quadIdx);
+                    final TerrainQuad newQuad = q;
+                    
                     if (isCenter(quadIdx)) {
                         // if it should be attached as a child right now, attach it
-                        final int quadrant = getQuadrant(quadIdx);
-                        final TerrainQuad newQuad = q;
-                        // back on the OpenGL thread:
                         getControl(UpdateControl.class).enqueue(new Callable() {
-
+                            // back on the OpenGL thread:
+                            public Object call() throws Exception {
+                                if (newQuad.getParent() != null) {
+                                    attachQuadAt(newQuad, quadrant, quadCell, true);
+                                }
+                                else {
+                                    attachQuadAt(newQuad, quadrant, quadCell, false);
+                                }
+                                return null;
+                            }
+                        });
+                    } else {
+                        getControl(UpdateControl.class).enqueue(new Callable() {
                             public Object call() throws Exception {
-                                attachQuadAt(newQuad, quadrant, quadCell);
-                                //newQuad.resetCachedNeighbours();
+                                removeQuad(newQuad);
                                 return null;
                             }
                         });
@@ -292,30 +305,34 @@ public class TerrainGrid extends TerrainQuad {
         return gridTileLoader;
     }
     
-    protected void removeQuad(int idx) {
-        if (this.getQuad(idx) != null) {
+    protected void removeQuad(TerrainQuad q) {
+        if (q != null && ( (q.getQuadrant() > 0 && q.getQuadrant()<5) || q.getParent() != null) ) {
             for (TerrainGridListener l : listeners) {
-                l.tileDetached(getTileCell(this.getQuad(idx).getWorldTranslation()), this.getQuad(idx));
+                l.tileDetached(getTileCell(q.getWorldTranslation()), q);
             }
-            this.detachChild(this.getQuad(idx));
+            q.setQuadrant((short)0);
+            this.detachChild(q);
             cellsLoaded++; // For gridoffset calc., maybe the run() method is a better location for this.
         }
     }
 
     /**
      * Runs on the rendering thread
+     * @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) {
-        this.removeQuad(quadrant);
-
+    protected void attachQuadAt(TerrainQuad q, int quadrant, Vector3f quadCell, boolean shifted) {
+        
         q.setQuadrant((short) quadrant);
-        this.attachChild(q);
+        if (!shifted)
+            this.attachChild(q);
 
         Vector3f loc = quadCell.mult(this.quadSize - 1).subtract(quarterSize, 0, quarterSize);// quadrant location handled TerrainQuad automatically now
         q.setLocalTranslation(loc);
 
-        for (TerrainGridListener l : listeners) {
-            l.tileAttached(quadCell, q);
+        if (!shifted) {
+            for (TerrainGridListener l : listeners) {
+                l.tileAttached(quadCell, q);
+            }
         }
         updateModelBound();
         
@@ -374,6 +391,7 @@ public class TerrainGrid extends TerrainQuad {
                 cache.get(camCell.add(quadIndex[i * 4 + j]));
             }
         }
+        
         // ---------------------------------------------------
         // ---------------------------------------------------
 

+ 15 - 1
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java

@@ -34,14 +34,28 @@ package com.jme3.terrain.geomipmap;
 import com.jme3.math.Vector3f;
 
 /**
- *
+ * Notifies the user of grid change events, such as moving to new grid cells.
  * @author Anthyon
  */
 public interface TerrainGridListener {
 
+    /**
+     * Called whenever the camera has moved full grid cells. This triggers new tiles to load.
+     * @param newCenter 
+     */
     public void gridMoved(Vector3f newCenter);
 
+    /**
+     * Called when a TerrainQuad is attached to the scene and is visible (attached to the root TerrainGrid)
+     * @param cell the cell that is moved into
+     * @param quad the quad that was just attached
+     */
     public void tileAttached( Vector3f cell, TerrainQuad quad );
 
+    /**
+     * Called when a TerrainQuad is detached from its TerrainGrid parent: it is no longer on the scene graph.
+     * @param cell the cell that is moved into
+     * @param quad the quad that was just detached
+     */
     public void tileDetached( Vector3f cell, TerrainQuad quad );
 }

+ 0 - 4
engine/src/test/jme3test/terrain/TerrainGridSerializationTest.java

@@ -78,10 +78,6 @@ public class TerrainGridSerializationTest extends SimpleApplication {
                 public void gridMoved(Vector3f newCenter) {
                 }
 
-                public Material tileLoaded(Material material, Vector3f cell) {
-                    return material;
-                }
-
                 public void tileAttached(Vector3f cell, TerrainQuad quad) {
                     //workaround for bugged test j3o's
                     while(quad.getControl(RigidBodyControl.class)!=null){

+ 3 - 6
engine/src/test/jme3test/terrain/TerrainGridTest.java

@@ -115,8 +115,9 @@ public class TerrainGridTest extends SimpleApplication {
         final BulletAppState bulletAppState = new BulletAppState();
         stateManager.attach(bulletAppState);
 
-        this.getCamera().setLocation(new Vector3f(0, 200, 0));
-
+        this.getCamera().setLocation(new Vector3f(0, 400, 0));
+        this.getCamera().lookAt(new Vector3f(0,0,0), Vector3f.UNIT_Y);
+        
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
 
         DirectionalLight light = new DirectionalLight();
@@ -139,10 +140,6 @@ public class TerrainGridTest extends SimpleApplication {
                 public void gridMoved(Vector3f newCenter) {
                 }
 
-                public Material tileLoaded(Material material, Vector3f cell) {
-                    return material;
-                }
-
                 public void tileAttached(Vector3f cell, TerrainQuad quad) {
                     while(quad.getControl(RigidBodyControl.class)!=null){
                         quad.removeControl(RigidBodyControl.class);

+ 0 - 4
engine/src/test/jme3test/terrain/TerrainGridTileLoaderTest.java

@@ -136,10 +136,6 @@ public class TerrainGridTileLoaderTest extends SimpleApplication {
                 public void gridMoved(Vector3f newCenter) {
                 }
 
-                public Material tileLoaded(Material material, Vector3f cell) {
-                    return material;
-                }
-
                 public void tileAttached(Vector3f cell, TerrainQuad quad) {
                     while(quad.getControl(RigidBodyControl.class)!=null){
                         quad.removeControl(RigidBodyControl.class);