OSDN Git Service

* Cleaned up and simplified the Terrain API.
authorbrentowens <brentowens@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Wed, 29 Jun 2011 21:56:20 +0000 (21:56 +0000)
committerbrentowens <brentowens@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Wed, 29 Jun 2011 21:56:20 +0000 (21:56 +0000)
* Removed dependence on TerrainQuad for TerrainLodControl
* Comments, general cleanup

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

engine/src/terrain/com/jme3/terrain/Terrain.java
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainLodControl.java
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java
engine/src/test/jme3test/terrain/TerrainTestReadWrite.java

index 85dd32e..9c6cd76 100644 (file)
@@ -34,7 +34,6 @@ package com.jme3.terrain;
 import com.jme3.material.Material;\r
 import com.jme3.math.Vector2f;\r
 import com.jme3.math.Vector3f;\r
-import com.jme3.scene.Spatial;\r
 import java.util.List;\r
 \r
 /**\r
@@ -107,20 +106,7 @@ public interface Terrain {
      * Infinite or "paged" terrains will not be able to support this, so use with caution.\r
      */\r
     public float[] getHeightMap();\r
-\r
-    /**\r
-     * Tell the terrain system to use/not use Level of Detail algorithms.\r
-     * This is allowed to be ignored if a particular implementation cannot support it.\r
-     */\r
-    public void useLOD(boolean useLod);\r
-\r
-    /**\r
-     * Check if the terrain is using LOD techniques.\r
-     * If a terrain system only supports enabled LOD, then this\r
-     * should always return true.\r
-     */\r
-    public boolean isUsingLOD();\r
-\r
+    \r
     /**\r
      * This is calculated by the specific LOD algorithm.\r
      * A value of one means that the terrain is showing full detail.\r
@@ -130,24 +116,19 @@ public interface Terrain {
     public int getMaxLod();\r
 \r
     /**\r
-     * Called in the update (pre or post, up to you) method of your game.\r
+     * Called by an LodControl.\r
      * Calculates the level of detail of the terrain and adjusts its geometry.\r
      * This is where the Terrain's LOD algorithm will change the detail of\r
      * the terrain based on how far away this position is from the particular\r
      * terrain patch.\r
-     * @param location often the Camera's location\r
+     * @param location: the Camera's location. A list of one camera location is normal \r
+     *  if you just have one camera in your scene.\r
      */\r
     public void update(List<Vector3f> location);\r
 \r
     /**\r
-     * Get the spatial instance of this Terrain. Right now just used in the \r
-     * terrain editor in JMP.\r
-     */\r
-    public Spatial getSpatial();\r
-\r
-    /**\r
      * Lock or unlock the meshes of this terrain.\r
-     * Locked meshes are uneditable but have better performance.\r
+     * Locked meshes are un-editable but have better performance.\r
      * This should call the underlying getMesh().setStatic()/setDynamic() methods.\r
      * @param locked or unlocked\r
      */\r
@@ -169,17 +150,15 @@ public interface Terrain {
     public Material getMaterial();\r
 \r
     /**\r
-     * Calculates the percentage along the terrain (in X-Z plane) that the\r
-     * supplied point (worldX,worldY) is, starting from the x=0, z=0 world\r
-     * position of the terrain.\r
-     * This method must take into account local translations and scale of the terrain.\r
-     * Used for painting onto an alpha image for texture splatting.\r
+     * Used for painting to get the number of vertices along the edge of the\r
+     * terrain.\r
+     * This is an un-scaled size, and should represent the vertex count (ie. the\r
+     * texture coord count) along an edge of a square terrain.\r
      * \r
-     * @param worldX world position on X axis\r
-     * @param worldY world position on Z axis\r
-     * @return a point (U,V in the range [0,1] )\r
+     * In the standard TerrainQuad default implementation, this will return\r
+     * the "totalSize" of the terrain (512 or so).\r
      */\r
-    public Vector2f getPointPercentagePosition(float worldX, float worldY);\r
+    public int getTerrainSize();\r
 \r
     /**\r
      * Get the scale of the texture coordinates. Normally if the texture is\r
index 9cd2c82..ab68ce0 100644 (file)
@@ -41,6 +41,7 @@ import java.util.List;
 import com.jme3.renderer.Camera;\r
 import com.jme3.renderer.RenderManager;\r
 import com.jme3.renderer.ViewPort;\r
+import com.jme3.scene.Node;\r
 import com.jme3.scene.Spatial;\r
 import com.jme3.scene.control.AbstractControl;\r
 import com.jme3.scene.control.Control;\r
@@ -61,22 +62,27 @@ import java.util.ArrayList;
  */\r
 public class TerrainLodControl extends AbstractControl {\r
 \r
-    private TerrainQuad terrain;\r
+    private Terrain terrain;\r
     private List<Camera> cameras;\r
     private List<Vector3f> cameraLocations = new ArrayList<Vector3f>();\r
 \r
     public TerrainLodControl() {\r
     }\r
 \r
+    public TerrainLodControl(Terrain terrain, Camera camera) {\r
+        List<Camera> cams = new ArrayList<Camera>();\r
+        cams.add(camera);\r
+        this.terrain = terrain;\r
+        this.cameras = cams;\r
+    }\r
+    \r
     /**\r
      * Only uses the first camera right now.\r
      * @param terrain to act upon (must be a Spatial)\r
      * @param cameras one or more cameras to reference for LOD calc\r
      */\r
     public TerrainLodControl(Terrain terrain, List<Camera> cameras) {\r
-        if (terrain instanceof TerrainQuad) {\r
-            this.terrain = (TerrainQuad) terrain;\r
-        }\r
+        this.terrain = terrain;\r
         this.cameras = cameras;\r
     }\r
 \r
@@ -107,11 +113,17 @@ public class TerrainLodControl extends AbstractControl {
                     cameraClone.add(c);\r
                 }\r
             }\r
-            return new TerrainLodControl((TerrainQuad) spatial, cameraClone);\r
+            return new TerrainLodControl((Terrain) spatial, cameraClone);\r
         }\r
         return null;\r
     }\r
 \r
+    public void setCamera(Camera camera) {\r
+        List<Camera> cams = new ArrayList<Camera>();\r
+        cams.add(camera);\r
+        setCameras(cams);\r
+    }\r
+    \r
     public void setCameras(List<Camera> cameras) {\r
         this.cameras = cameras;\r
         cameraLocations.clear();\r
@@ -123,12 +135,12 @@ public class TerrainLodControl extends AbstractControl {
     @Override\r
     public void setSpatial(Spatial spatial) {\r
         super.setSpatial(spatial);\r
-        if (spatial instanceof TerrainQuad) {\r
-            this.terrain = (TerrainQuad) spatial;\r
+        if (spatial instanceof Terrain) {\r
+            this.terrain = (Terrain) spatial;\r
         }\r
     }\r
 \r
-    public void setTerrain(TerrainQuad terrain) {\r
+    public void setTerrain(Terrain terrain) {\r
         this.terrain = terrain;\r
     }\r
 \r
@@ -136,13 +148,13 @@ public class TerrainLodControl extends AbstractControl {
     public void write(JmeExporter ex) throws IOException {\r
         super.write(ex);\r
         OutputCapsule oc = ex.getCapsule(this);\r
-        oc.write(terrain, "terrain", null);\r
+        oc.write((Node)terrain, "terrain", null);\r
     }\r
 \r
     @Override\r
     public void read(JmeImporter im) throws IOException {\r
         super.read(im);\r
         InputCapsule ic = im.getCapsule(this);\r
-        terrain = (TerrainQuad) ic.readSavable("terrain", null);\r
+        terrain = (Terrain) ic.readSavable("terrain", null);\r
     }\r
 }\r
index dc0b5d7..bb0643b 100644 (file)
@@ -67,7 +67,6 @@ import com.jme3.util.TangentBinormalGenerator;
 import java.util.ArrayList;\r
 import java.util.List;\r
 import java.util.Map;\r
-import java.util.logging.Logger;\r
 \r
 /**\r
  * A terrain quad is a node in the quad tree of the terrain system.\r
@@ -99,7 +98,6 @@ public class TerrainQuad extends Node implements Terrain {
 \r
     protected List<Vector3f> lastCameraLocations; // used for LOD calc\r
     private boolean lodCalcRunning = false;\r
-    private boolean usingLOD = true;\r
     private int maxLod = -1;\r
     private HashMap<String,UpdatedTerrainPatch> updatedPatches;\r
     private final Object updatePatchesLock = new Object();\r
@@ -274,10 +272,6 @@ public class TerrainQuad extends Node implements Terrain {
             return 0;\r
     }\r
 \r
-    public Spatial getSpatial() {\r
-        return this;\r
-    }\r
-\r
     public void generateEntropy(ProgressMonitor progressMonitor) {\r
         // only check this on the root quad\r
         if (isRootQuad())\r
@@ -312,11 +306,11 @@ public class TerrainQuad extends Node implements Terrain {
     public Material getMaterial() {\r
         // get the material from one of the children. They all share the same material\r
         if (children != null) {\r
-                       for (int i = children.size(); --i >= 0;) {\r
-                               Spatial child = children.get(i);\r
-                               if (child instanceof TerrainQuad) {\r
-                                       return ((TerrainQuad)child).getMaterial();\r
-                               } else if (child instanceof TerrainPatch) {\r
+            for (int i = children.size(); --i >= 0;) {\r
+                Spatial child = children.get(i);\r
+                if (child instanceof TerrainQuad) {\r
+                    return ((TerrainQuad)child).getMaterial();\r
+                } else if (child instanceof TerrainPatch) {\r
                     return ((TerrainPatch)child).getMaterial();\r
                 }\r
             }\r
@@ -383,12 +377,11 @@ public class TerrainQuad extends Node implements Terrain {
      */\r
     private void updateQuadLODs() {\r
         synchronized (updatePatchesLock) {\r
-            //if (true)\r
-            // return;\r
+            \r
             if (updatedPatches == null || updatedPatches.isEmpty())\r
                 return;\r
 \r
-            //TODO do the actual geometry update here\r
+            // do the actual geometry update here\r
             for (UpdatedTerrainPatch utp : updatedPatches.values()) {\r
                 utp.updateAll();\r
             }\r
@@ -582,7 +575,7 @@ public class TerrainQuad extends Node implements Terrain {
         offsetAmount += quarterSize;\r
 \r
         if (lodCalculatorFactory == null)\r
-                lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+            lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
 \r
         // 1 upper left\r
         float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
@@ -690,7 +683,7 @@ public class TerrainQuad extends Node implements Terrain {
         int split = (size + 1) >> 1;\r
 \r
         if (lodCalculatorFactory == null)\r
-                lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+            lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
 \r
         offsetAmount += quarterSize;\r
 \r
@@ -1104,13 +1097,9 @@ public class TerrainQuad extends Node implements Terrain {
         return (x >= 0 && x <= totalSize && z >= 0 && z <= totalSize);\r
     }\r
 \r
-    public Vector2f getPointPercentagePosition(float worldX, float worldY) {\r
-        Vector2f uv = new Vector2f(worldX,worldY);\r
-        uv.subtractLocal(getLocalTranslation().x, getLocalTranslation().z); // center it on 0,0\r
-        uv.addLocal(totalSize/2, totalSize/2); // shift the bottom left corner up to 0,0\r
-        uv.divideLocal(totalSize); // get the location as a percentage\r
-\r
-        return uv;\r
+    \r
+    public int getTerrainSize() {\r
+        return totalSize;\r
     }\r
 \r
 \r
@@ -1510,10 +1499,6 @@ public class TerrainQuad extends Node implements Terrain {
         quadrant = c.readInt("quadrant", 0);\r
         totalSize = c.readInt("totalSize", 0);\r
         lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);\r
-\r
-        // the terrain is re-built on load, so we need to run this once\r
-        //affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size);\r
-        //updateNormals();\r
     }\r
 \r
     @Override\r
@@ -1564,14 +1549,6 @@ public class TerrainQuad extends Node implements Terrain {
         return maxLod;\r
     }\r
 \r
-    public void useLOD(boolean useLod) {\r
-        usingLOD = useLod;\r
-    }\r
-\r
-    public boolean isUsingLOD() {\r
-        return usingLOD;\r
-}\r
-\r
     public int getPatchSize() {\r
         return patchSize;\r
     }\r
@@ -1583,9 +1560,6 @@ public class TerrainQuad extends Node implements Terrain {
 \r
     public float[] getHeightMap() {\r
 \r
-        //if (true)\r
-        //    return heightMap;\r
-\r
         float[] hm = null;\r
         int length = ((size-1)/2)+1;\r
         int area = size*size;\r
index 6bd5ff8..0b0a376 100644 (file)
@@ -33,6 +33,7 @@ package jme3test.terrain;
 
 import com.jme3.app.SimpleApplication;
 import com.jme3.bounding.BoundingBox;
+import com.jme3.export.Savable;
 import com.jme3.export.binary.BinaryExporter;
 import com.jme3.export.binary.BinaryImporter;
 import com.jme3.font.BitmapText;
@@ -44,6 +45,8 @@ import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
+import com.jme3.scene.Node;
+import com.jme3.terrain.Terrain;
 import com.jme3.terrain.geomipmap.TerrainLodControl;
 import com.jme3.terrain.geomipmap.TerrainQuad;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
@@ -69,7 +72,7 @@ import jme3tools.converters.ImageToAwt;
  */
 public class TerrainTestReadWrite extends SimpleApplication {
 
-    private TerrainQuad terrain;
+    private Terrain terrain;
     protected BitmapText hintText;
     private float grassScale = 64;
     private float dirtScale = 16;
@@ -147,8 +150,6 @@ public class TerrainTestReadWrite extends SimpleApplication {
         // CREATE HEIGHTMAP
         AbstractHeightMap heightmap = null;
         try {
-            //heightmap = new HillHeightMap(1025, 1000, 50, 100, (byte) 3);
-
             heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
             heightmap.load();
 
@@ -160,15 +161,17 @@ public class TerrainTestReadWrite extends SimpleApplication {
             loadTerrain();
         } else {
             // create the terrain as normal, and give it a control for LOD management
-            terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
+            TerrainQuad terrainQuad = new TerrainQuad("terrain", 65, 129, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
             List<Camera> cameras = new ArrayList<Camera>();
             cameras.add(getCamera());
-            TerrainLodControl control = new TerrainLodControl(terrain, cameras);
-            terrain.addControl(control);
-            terrain.setMaterial(matTerrain);
-            terrain.setLocalTranslation(0, -100, 0);
-            terrain.setLocalScale(2f, 1f, 2f);
-            rootNode.attachChild(terrain);
+            TerrainLodControl control = new TerrainLodControl(terrainQuad, cameras);
+            terrainQuad.addControl(control);
+            terrainQuad.setMaterial(matTerrain);
+            terrainQuad.setLocalTranslation(0, -100, 0);
+            terrainQuad.setLocalScale(4f, 0.25f, 4f);
+            rootNode.attachChild(terrainQuad);
+            
+            this.terrain = terrainQuad;
         }
 
         DirectionalLight light = new DirectionalLight();
@@ -211,7 +214,7 @@ public class TerrainTestReadWrite extends SimpleApplication {
                     fos = new FileOutputStream(new File("terrainsave.jme"));
 
                     // we just use the exporter and pass in the terrain
-                    BinaryExporter.getInstance().save(terrain, new BufferedOutputStream(fos));
+                    BinaryExporter.getInstance().save((Savable)terrain, new BufferedOutputStream(fos));
 
                     fos.flush();
                     float duration = (System.currentTimeMillis() - start) / 1000.0f;
@@ -237,29 +240,28 @@ public class TerrainTestReadWrite extends SimpleApplication {
             long start = System.currentTimeMillis();
             // remove the existing terrain and detach it from the root node.
             if (terrain != null) {
-                terrain.removeFromParent();
-                terrain.removeControl(TerrainLodControl.class);
-                terrain.detachAllChildren();
+                Node existingTerrain = (Node)terrain;
+                existingTerrain.removeFromParent();
+                existingTerrain.removeControl(TerrainLodControl.class);
+                existingTerrain.detachAllChildren();
                 terrain = null;
             }
 
             // import the saved terrain, and attach it back to the root node
-            fis = new FileInputStream(new File("terrainsave.jme"));
+            File f = new File("terrainsave.jme");
+            fis = new FileInputStream(f);
             BinaryImporter imp = BinaryImporter.getInstance();
             imp.setAssetManager(assetManager);
             terrain = (TerrainQuad) imp.load(new BufferedInputStream(fis));
-            rootNode.attachChild(terrain);
+            rootNode.attachChild((Node)terrain);
 
             float duration = (System.currentTimeMillis() - start) / 1000.0f;
             System.out.println("Load took " + duration + " seconds");
 
-            // now we have to add back the cameras to the LOD control, since we didn't want to duplicate them on save
-            List<Camera> cameras = new ArrayList<Camera>();
-            cameras.add(getCamera());
-            TerrainLodControl lodControl = terrain.getControl(TerrainLodControl.class);
-            if (lodControl != null) {
-                lodControl.setCameras(cameras);
-            }
+            // now we have to add back the camera to the LOD control
+            TerrainLodControl lodControl = ((Node)terrain).getControl(TerrainLodControl.class);
+            if (lodControl != null)
+                lodControl.setCamera(getCamera());
 
         } catch (IOException ex) {
             Logger.getLogger(TerrainTestReadWrite.class.getName()).log(Level.SEVERE, null, ex);
@@ -286,10 +288,10 @@ public class TerrainTestReadWrite extends SimpleApplication {
         public void onAction(String name, boolean pressed, float tpf) {
             if (name.equals("clone") && !pressed) {
 
-                TerrainQuad clone = terrain.clone();
-                terrain.removeFromParent();
+                Terrain clone = (Terrain) ((Node)terrain).clone();
+                ((Node)terrain).removeFromParent();
                 terrain = clone;
-                getRootNode().attachChild(terrain);
+                getRootNode().attachChild((Node)terrain);
             }
         }
     };