Browse Source

Fix: extended TerrainGridListener with ozonegrif's extension
this allows physics to be handled by the user rather than manipulating in the grid
see tests for details

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7840 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

ant..om 14 years ago
parent
commit
dde0c0a885

+ 7 - 79
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java

@@ -32,7 +32,6 @@
 package com.jme3.terrain.geomipmap;
 package com.jme3.terrain.geomipmap;
 
 
 import com.jme3.scene.control.UpdateControl;
 import com.jme3.scene.control.UpdateControl;
-import com.jme3.app.Application;
 import com.jme3.bullet.PhysicsSpace;
 import com.jme3.bullet.PhysicsSpace;
 import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
 import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
 import com.jme3.bullet.control.RigidBodyControl;
 import com.jme3.bullet.control.RigidBodyControl;
@@ -40,7 +39,6 @@ import com.jme3.terrain.heightmap.HeightMap;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
-import java.util.concurrent.ExecutionException;
 import java.util.logging.Level;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
@@ -48,7 +46,6 @@ import com.jme3.material.Material;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
-import com.jme3.renderer.Camera;
 import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
 import com.jme3.terrain.geomipmap.lodcalc.LodCalculatorFactory;
 import com.jme3.terrain.geomipmap.lodcalc.LodDistanceCalculatorFactory;
 import com.jme3.terrain.geomipmap.lodcalc.LodDistanceCalculatorFactory;
 import com.jme3.terrain.heightmap.HeightMapGrid;
 import com.jme3.terrain.heightmap.HeightMapGrid;
@@ -153,11 +150,6 @@ public class TerrainGrid extends TerrainQuad {
         if (lodCalculatorFactory == null) {
         if (lodCalculatorFactory == null) {
             lodCalculatorFactory = new LodDistanceCalculatorFactory();
             lodCalculatorFactory = new LodDistanceCalculatorFactory();
         }
         }
-//        this.quadOrigins = new Vector3f[]{
-//            new Vector3f(-this.quarterSize, 0, -this.quarterSize).mult(this.stepScale),
-//            new Vector3f(-this.quarterSize, 0, this.quarterSize).mult(this.stepScale),
-//            new Vector3f(this.quarterSize, 0, -this.quarterSize).mult(this.stepScale),
-//            new Vector3f(this.quarterSize, 0, this.quarterSize).mult(this.stepScale)};
         this.quadIndex = new Vector3f[]{
         this.quadIndex = new Vector3f[]{
             new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2),
             new Vector3f(-1, 0, 2), new Vector3f(0, 0, 2), new Vector3f(1, 0, 2), new Vector3f(2, 0, 2),
             new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1),
             new Vector3f(-1, 0, 1), new Vector3f(0, 0, 1), new Vector3f(1, 0, 1), new Vector3f(2, 0, 1),
@@ -192,7 +184,6 @@ public class TerrainGrid extends TerrainQuad {
         for (TerrainGridListener l : this.listeners.values()) {
         for (TerrainGridListener l : this.listeners.values()) {
             l.gridMoved(camCell);
             l.gridMoved(camCell);
         }
         }
-        updatePhysics();
     }
     }
 
 
     @Override
     @Override
@@ -208,14 +199,13 @@ public class TerrainGrid extends TerrainQuad {
             for (TerrainGridListener l : this.listeners.values()) {
             for (TerrainGridListener l : this.listeners.values()) {
                 l.gridMoved(camCell);
                 l.gridMoved(camCell);
             }
             }
-            updatePhysics();
         }
         }
 
 
         super.update(locations);
         super.update(locations);
     }
     }
 
 
     public Vector3f getCell(Vector3f location) {
     public Vector3f getCell(Vector3f location) {
-        final Vector3f v = location.clone().divideLocal(this.getLocalScale().mult(this.quadSize-1)).add(0.5f, 0, 0.5f);
+        final Vector3f v = location.clone().divideLocal(this.getLocalScale().mult(this.quadSize - 1)).add(0.5f, 0, 0.5f);
         return new Vector3f(FastMath.floor(v.x), 0, FastMath.floor(v.z));
         return new Vector3f(FastMath.floor(v.x), 0, FastMath.floor(v.z));
     }
     }
 
 
@@ -224,8 +214,12 @@ public class TerrainGrid extends TerrainQuad {
             if (quadControls != null) {
             if (quadControls != null) {
                 this.getQuad(idx).removeControl(RigidBodyControl.class);
                 this.getQuad(idx).removeControl(RigidBodyControl.class);
             }
             }
+            for (TerrainGridListener l : listeners.values()) {
+                l.tileDetached(getCell(this.getQuad(idx).getWorldTranslation()), this.getQuad(idx));
+            }
             this.detachChild(this.getQuad(idx));
             this.detachChild(this.getQuad(idx));
         }
         }
+
     }
     }
 
 
     /**
     /**
@@ -241,50 +235,14 @@ public class TerrainGrid extends TerrainQuad {
         Vector3f loc = cam.mult(this.quadSize - 1).subtract(quarterSize, 0, quarterSize);// quadrant location handled TerrainQuad automatically now
         Vector3f loc = cam.mult(this.quadSize - 1).subtract(quarterSize, 0, quarterSize);// quadrant location handled TerrainQuad automatically now
         q.setLocalTranslation(loc);
         q.setLocalTranslation(loc);
 
 
-        if (quadControls != null) {
-            quadControls[quadrant - 1].setEnabled(false);
-            quadControls[quadrant - 1].setCollisionShape(new HeightfieldCollisionShape(q.getHeightMap(), getLocalScale()));
-            q.addControl(quadControls[quadrant - 1]);
-            space.addAll(q);
-            quadControls[quadrant - 1].setEnabled(true);
-            //quadControls[quadrant - 1].setPhysicsLocation(cam.add(this.quadOrigins[quadrant - 1]));
-        } else {
+        for (TerrainGridListener l : listeners.values()) {
+            l.tileAttached(cam, q);
         }
         }
 
 
         updateModelBound();
         updateModelBound();
     }
     }
 
 
-    public void updatePhysics() {
-        RigidBodyControl control = getControl(RigidBodyControl.class);
-        if (control != null) {
-            this.space = control.getPhysicsSpace();
-            space.remove(this);
-            this.removeControl(control);
-            this.quadControls = new RigidBodyControl[4];
-
-            for (int i = 0; i < 4; i++) {
-                int collisionGroupsCollideWith = control.getCollideWithGroups();
-                int collisionGroups = control.getCollisionGroup();
-                TerrainQuad q = getQuad(i + 1);
-                quadControls[i] = new RigidBodyControl(new HeightfieldCollisionShape(q == null ? new float[quadSize * quadSize] : q.getHeightMap(), getLocalScale()), 0);
-                quadControls[i].setCollideWithGroups(collisionGroupsCollideWith);
-                quadControls[i].setCollisionGroup(collisionGroups);
-                //quadControls[i].setPhysicsSpace(space);
-                //this.addControl(quadControls[i]);
-                if (q != null) {
-                    getQuad(i + 1).addControl(quadControls[i]);
-                    space.add(quadControls[i]);
-                }
-            }
-        }
-    }
-
     private void updateChildrens(Vector3f cam) {
     private void updateChildrens(Vector3f cam) {
-        //TerrainQuad q1 = cache.get(cam.add(quadIndex[9]));
-        //TerrainQuad q2 = cache.get(cam.add(quadIndex[5]));
-        //TerrainQuad q3 = cache.get(cam.add(quadIndex[10]));
-        //TerrainQuad q4 = cache.get(cam.add(quadIndex[6]));
-
         // ---------------------------------------------------
         // ---------------------------------------------------
         // LRU cache is used, so elements that need to remain
         // LRU cache is used, so elements that need to remain
         // should be touched.
         // should be touched.
@@ -326,37 +284,7 @@ public class TerrainGrid extends TerrainQuad {
 
 
         executor.submit(new UpdateQuadCache(cam));
         executor.submit(new UpdateQuadCache(cam));
 
 
-        /*        if (q1 == null || q2 == null || q3 == null || q4 == null) {
-        try {
-        executor.submit(new UpdateQuadCache(cam, true)).get(); // BLOCKING
-        q1 = cache.get(cam.add(quadIndex[9]));
-        q2 = cache.get(cam.add(quadIndex[5]));
-        q3 = cache.get(cam.add(quadIndex[10]));
-        q4 = cache.get(cam.add(quadIndex[6]));
-        } catch (InterruptedException ex) {
-        Logger.getLogger(TerrainGrid.class.getName()).log(Level.SEVERE, null, ex);
-        return;
-        } catch (ExecutionException ex) {
-        Logger.getLogger(TerrainGrid.class.getName()).log(Level.SEVERE, null, ex);
-        return;
-        }
-        }
-
-        executor.execute(new UpdateQuadCache(cam));
-
-
-        this.removeQuad(1);
-        this.removeQuad(2);
-        this.removeQuad(3);
-        this.removeQuad(4);
-
-        attachQuadAt(q1, 1, cam); // quadIndex[9]
-        attachQuadAt(q2, 2, cam); // quadIndex[5]
-        attachQuadAt(q3, 3, cam); // quadIndex[10]
-        attachQuadAt(q4, 4, cam); // quadIndex[6]
-         */
         this.currentCell = cam;
         this.currentCell = cam;
-//        this.updateModelBound();
     }
     }
 
 
     public void addListener(String id, TerrainGridListener listener) {
     public void addListener(String id, TerrainGridListener listener) {

+ 3 - 0
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGridListener.java

@@ -44,4 +44,7 @@ public interface TerrainGridListener {
 
 
     public Material tileLoaded(Material material, Vector3f cell);
     public Material tileLoaded(Material material, Vector3f cell);
 
 
+    public void tileAttached( Vector3f cell, TerrainQuad quad );
+
+    public void tileDetached( Vector3f cell, TerrainQuad quad );
 }
 }

+ 25 - 17
engine/src/test/jme3test/terrain/TerrainFractalGridTest.java

@@ -1,5 +1,6 @@
 package jme3test.terrain;
 package jme3test.terrain;
 
 
+import com.jme3.terrain.geomipmap.TerrainQuad;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 
 
@@ -77,13 +78,13 @@ public class TerrainFractalGridTest extends SimpleApplication {
         Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
         Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
         grass.setWrap(WrapMode.Repeat);
         grass.setWrap(WrapMode.Repeat);
         this.mat_terrain.setTexture("region1ColorMap", grass);
         this.mat_terrain.setTexture("region1ColorMap", grass);
-        this.mat_terrain.setVector3("region1", new Vector3f(88, 200, this.grassScale));
+        this.mat_terrain.setVector3("region1", new Vector3f(15, 200, this.grassScale));
 
 
         // DIRT texture
         // DIRT texture
         Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
         Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
         dirt.setWrap(WrapMode.Repeat);
         dirt.setWrap(WrapMode.Repeat);
         this.mat_terrain.setTexture("region2ColorMap", dirt);
         this.mat_terrain.setTexture("region2ColorMap", dirt);
-        this.mat_terrain.setVector3("region2", new Vector3f(0, 90, this.dirtScale));
+        this.mat_terrain.setVector3("region2", new Vector3f(0, 20, this.dirtScale));
 
 
         // ROCK texture
         // ROCK texture
         Texture rock = this.assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
         Texture rock = this.assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
@@ -156,28 +157,35 @@ public class TerrainFractalGridTest extends SimpleApplication {
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
 
 
         if (usePhysics) {
         if (usePhysics) {
+            CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
+            player3 = new CharacterControl(capsuleShape, 0.5f);
+            player3.setJumpSpeed(20);
+            player3.setFallSpeed(10);
+            player3.setGravity(10);
+
+            player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
+
+            bulletAppState.getPhysicsSpace().add(player3);
+
             terrain.addListener("physicsStartListener", new TerrainGridListener() {
             terrain.addListener("physicsStartListener", new TerrainGridListener() {
 
 
                 public void gridMoved(Vector3f newCenter) {
                 public void gridMoved(Vector3f newCenter) {
-                    terrain.removeListener("physicsStartListener");
-                    RigidBodyControl body = new RigidBodyControl(new HeightfieldCollisionShape(terrain.getHeightMap(), terrain.getLocalScale()), 0);
-                    terrain.addControl(body);
-                    bulletAppState.getPhysicsSpace().add(terrain);
-                    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
-                    player3 = new CharacterControl(capsuleShape, 0.5f);
-                    player3.setJumpSpeed(20);
-                    player3.setFallSpeed(10);
-                    player3.setGravity(10);
-
-                    player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
-
-                    bulletAppState.getPhysicsSpace().add(player3);
-                    physicsAdded = true;
                 }
                 }
 
 
                 public Material tileLoaded(Material material, Vector3f cell) {
                 public Material tileLoaded(Material material, Vector3f cell) {
                     return material;
                     return material;
                 }
                 }
+
+                public void tileAttached(Vector3f cell, TerrainQuad quad) {
+                    quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
+                    bulletAppState.getPhysicsSpace().add(quad);
+                }
+
+                public void tileDetached(Vector3f cell, TerrainQuad quad) {
+                    bulletAppState.getPhysicsSpace().remove(quad);
+                    quad.removeControl(RigidBodyControl.class);
+                }
+
             });
             });
         }
         }
         this.terrain.initialize(cam.getLocation());
         this.terrain.initialize(cam.getLocation());
@@ -254,7 +262,7 @@ public class TerrainFractalGridTest extends SimpleApplication {
                 this.walkDirection.addLocal(camDir.negate());
                 this.walkDirection.addLocal(camDir.negate());
             }
             }
 
 
-        if (usePhysics && physicsAdded) {
+        if (usePhysics) {
             this.player3.setWalkDirection(this.walkDirection);
             this.player3.setWalkDirection(this.walkDirection);
             this.cam.setLocation(this.player3.getPhysicsLocation());
             this.cam.setLocation(this.player3.getPhysicsLocation());
         }
         }

+ 31 - 25
engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java

@@ -22,6 +22,7 @@ import com.jme3.renderer.Camera;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
+import com.jme3.terrain.geomipmap.TerrainQuad;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.Namer;
 import com.jme3.terrain.heightmap.Namer;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture;
@@ -65,7 +66,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
         }else{
         }else{
             assetManager.registerLocator("mountains.zip", ZipLocator.class);
             assetManager.registerLocator("mountains.zip", ZipLocator.class);
         }
         }
-        
+
         this.flyCam.setMoveSpeed(100f);
         this.flyCam.setMoveSpeed(100f);
         ScreenshotAppState state = new ScreenshotAppState();
         ScreenshotAppState state = new ScreenshotAppState();
         this.stateManager.attach(state);
         this.stateManager.attach(state);
@@ -140,22 +141,8 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
         }));
         }));
         this.terrain.setMaterial(this.matRock);
         this.terrain.setMaterial(this.matRock);
 
 
-        this.terrain.addListener("alphaListener", new TerrainGridListener() {
-
-            public void gridMoved(Vector3f newCenter) {
-            }
-
-            public Material tileLoaded(Material material, Vector3f cell) {
-                int x = (int)Math.abs(512 * (cell.x % 2));
-                int z = (int)Math.abs(512 * (cell.z % 2));
-                material.setTexture("Alpha", assetManager.loadTexture("Scenes/TerrainAlphaTest/alphamap_" + x + "_" + z + ".png"));
-                return material;
-            }
-        });
-
         this.terrain.setLocalTranslation(0, 0, 0);
         this.terrain.setLocalTranslation(0, 0, 0);
         this.terrain.setLocalScale(2f, 1f, 2f);
         this.terrain.setLocalScale(2f, 1f, 2f);
-        this.terrain.initialize(Vector3f.ZERO);
         this.rootNode.attachChild(this.terrain);
         this.rootNode.attachChild(this.terrain);
 
 
         List<Camera> cameras = new ArrayList<Camera>();
         List<Camera> cameras = new ArrayList<Camera>();
@@ -163,7 +150,7 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
         TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
         TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
         this.terrain.addControl(control);
         this.terrain.addControl(control);
 
 
-        BulletAppState bulletAppState = new BulletAppState();
+        final BulletAppState bulletAppState = new BulletAppState();
         stateManager.attach(bulletAppState);
         stateManager.attach(bulletAppState);
 
 
 
 
@@ -172,19 +159,38 @@ public class TerrainGridAlphaMapTest extends SimpleApplication {
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
 
 
         if (usePhysics) {
         if (usePhysics) {
-            RigidBodyControl body = new RigidBodyControl(new HeightfieldCollisionShape(terrain.getHeightMap(), terrain.getLocalScale()), 0);
-            terrain.addControl(body);
-            bulletAppState.getPhysicsSpace().add(terrain);
             CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
             CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
-            this.player3 = new CharacterControl(capsuleShape, 0.5f);
-            this.player3.setJumpSpeed(20);
-            this.player3.setFallSpeed(30);
-            this.player3.setGravity(30);
+            player3 = new CharacterControl(capsuleShape, 0.5f);
+            player3.setJumpSpeed(20);
+            player3.setFallSpeed(10);
+            player3.setGravity(10);
+
+            player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
+
+            bulletAppState.getPhysicsSpace().add(player3);
 
 
-            this.player3.setPhysicsLocation(new Vector3f(0, 256, 0));
+            terrain.addListener("physicsStartListener", new TerrainGridListener() {
+
+                public void gridMoved(Vector3f newCenter) {
+                }
+
+                public Material tileLoaded(Material material, Vector3f cell) {
+                    return material;
+                }
+
+                public void tileAttached(Vector3f cell, TerrainQuad quad) {
+                    quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
+                    bulletAppState.getPhysicsSpace().add(quad);
+                }
+
+                public void tileDetached(Vector3f cell, TerrainQuad quad) {
+                    bulletAppState.getPhysicsSpace().remove(quad);
+                    quad.removeControl(RigidBodyControl.class);
+                }
 
 
-            bulletAppState.getPhysicsSpace().add(this.player3);
+            });
         }
         }
+        this.terrain.initialize(cam.getLocation());
         this.initKeys();
         this.initKeys();
     }
     }
 
 

+ 23 - 15
engine/src/test/jme3test/terrain/TerrainGridTest.java

@@ -18,6 +18,7 @@ import com.jme3.math.Vector3f;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGrid;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainGridListener;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
+import com.jme3.terrain.geomipmap.TerrainQuad;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.ImageBasedHeightMapGrid;
 import com.jme3.terrain.heightmap.Namer;
 import com.jme3.terrain.heightmap.Namer;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture;
@@ -115,28 +116,35 @@ public class TerrainGridTest extends SimpleApplication {
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
 
 
         if (usePhysics) {
         if (usePhysics) {
+            CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
+            player3 = new CharacterControl(capsuleShape, 0.5f);
+            player3.setJumpSpeed(20);
+            player3.setFallSpeed(10);
+            player3.setGravity(10);
+
+            player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
+
+            bulletAppState.getPhysicsSpace().add(player3);
+
             terrain.addListener("physicsStartListener", new TerrainGridListener() {
             terrain.addListener("physicsStartListener", new TerrainGridListener() {
 
 
                 public void gridMoved(Vector3f newCenter) {
                 public void gridMoved(Vector3f newCenter) {
-                    terrain.removeListener("physicsStartListener");
-                    RigidBodyControl body = new RigidBodyControl(new HeightfieldCollisionShape(terrain.getHeightMap(), terrain.getLocalScale()), 0);
-                    terrain.addControl(body);
-                    bulletAppState.getPhysicsSpace().add(terrain);
-                    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
-                    player3 = new CharacterControl(capsuleShape, 0.5f);
-                    player3.setJumpSpeed(20);
-                    player3.setFallSpeed(30);
-                    player3.setGravity(30);
-
-                    player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
-
-                    bulletAppState.getPhysicsSpace().add(player3);
-                    physicsAdded = true;
                 }
                 }
 
 
                 public Material tileLoaded(Material material, Vector3f cell) {
                 public Material tileLoaded(Material material, Vector3f cell) {
                     return material;
                     return material;
                 }
                 }
+
+                public void tileAttached(Vector3f cell, TerrainQuad quad) {
+                    quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
+                    bulletAppState.getPhysicsSpace().add(quad);
+                }
+
+                public void tileDetached(Vector3f cell, TerrainQuad quad) {
+                    bulletAppState.getPhysicsSpace().remove(quad);
+                    quad.removeControl(RigidBodyControl.class);
+                }
+
             });
             });
         }
         }
         this.terrain.initialize(cam.getLocation());
         this.terrain.initialize(cam.getLocation());
@@ -213,7 +221,7 @@ public class TerrainGridTest extends SimpleApplication {
             this.walkDirection.addLocal(camDir.negate());
             this.walkDirection.addLocal(camDir.negate());
         }
         }
 
 
-        if (usePhysics && physicsAdded) {
+        if (usePhysics) {
             this.player3.setWalkDirection(this.walkDirection);
             this.player3.setWalkDirection(this.walkDirection);
             this.cam.setLocation(this.player3.getPhysicsLocation());
             this.cam.setLocation(this.player3.getPhysicsLocation());
         }
         }