فهرست منبع

* fixed bug with terrain collision and flat terrain having a zero-volume bounding box
* corrected terrain.getHeight()

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

bre..ns 14 سال پیش
والد
کامیت
6940694e14
1فایلهای تغییر یافته به همراه48 افزوده شده و 19 حذف شده
  1. 48 19
      engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java

+ 48 - 19
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java

@@ -77,6 +77,20 @@ import java.util.logging.Logger;
  *
  * The leaves of the terrain quad tree are Terrain Patches. These have the real geometry mesh.
  *
+ * 
+ * Heightmap coordinates start from the bottom left of the world and work towards the
+ * top right. This will seem upside down, but the texture coordinates compensate; and
+ * it allows you to easily get the heightmap values at real world X,Z coordinates.
+ * 
+ *  +x
+ *  ^
+ *  | ......N = length of heightmap
+ *  | :     :
+ *  | :     :
+ *  | 0.....:
+ *  +---------> +z
+ * (world coordinates)
+ * 
  * @author Brent Owens
  */
 public class TerrainQuad extends Node implements Terrain {
@@ -152,16 +166,17 @@ public class TerrainQuad extends Node implements Terrain {
                             LodCalculatorFactory lodCalculatorFactory)
     {
         super(name);
+        
+        if (heightMap == null)
+            heightMap = generateDefaultHeightMap(size);
+        
         if (!FastMath.isPowerOfTwo(size - 1)) {
             throw new RuntimeException("size given: " + size + "  Terrain quad sizes may only be (2^N + 1)");
         }
         if (FastMath.sqrt(heightMap.length) > size) {
             Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Heightmap size is larger than the terrain size. Make sure your heightmap image is the same size as the terrain!");
         }
-
-        if (heightMap == null)
-            heightMap = generateDefaultHeightMap(size);
-
+        
         this.offset = offset;
         this.offsetAmount = offsetAmount;
         this.totalSize = totalSize;
@@ -958,21 +973,29 @@ public class TerrainQuad extends Node implements Terrain {
      * @param y coordinate translated into actual (positive) terrain grid coordinates
      */
     protected float getHeight(float x, float z, Vector2f xz) {
-        float topLeft = getHeightmapHeight((int)FastMath.floor(x), (int)FastMath.ceil(z));
-        float topRight = getHeightmapHeight((int)FastMath.ceil(x), (int)FastMath.ceil(z));
-        float bottomLeft = getHeightmapHeight((int)FastMath.floor(x), (int)FastMath.floor(z));
-        float bottomRight = getHeightmapHeight((int)FastMath.ceil(x), (int)FastMath.floor(z));
-
-        // create a vertical, down-facing, ray and get the height from that
-        float max = Math.max(Math.max(Math.max(topLeft, topRight), bottomRight),bottomLeft);
-        max = max*getWorldScale().y;
-        Ray ray = new Ray(new Vector3f(xz.x,max+10f,xz.y), new Vector3f(0,-1,0).normalizeLocal());
-        CollisionResults cr = new CollisionResults();
-        int num = this.collideWith(ray, cr);
-        if (num > 0)
-            return cr.getClosestCollision().getContactPoint().y;
-        else
-            return 0;
+        x-=0.5f;
+        z-=0.5f;
+        float col = FastMath.floor(x);
+        float row = FastMath.floor(z);
+        boolean onX = false;
+        if(1 - (x - col)-(z - row) < 0) // what triangle to interpolate on
+            onX = true;
+        // v1--v2  ^
+        // |  / |  |
+        // | /  |  |
+        // v3--v4  | Z
+        //         |
+        // <-------Y
+        //     X 
+        float v1 = getHeightmapHeight((int) FastMath.ceil(x), (int) FastMath.ceil(z));
+        float v2 = getHeightmapHeight((int) FastMath.floor(x), (int) FastMath.ceil(z));
+        float v3 = getHeightmapHeight((int) FastMath.ceil(x), (int) FastMath.floor(z));
+        float v4 = getHeightmapHeight((int) FastMath.floor(x), (int) FastMath.floor(z));
+        if (onX) {
+            return ((x - col) + (z - row) - 1f)*v1 + (1f - (x - col))*v2 + (1f - (z - row))*v3;
+        } else {
+            return (1f - (x - col) - (z - row))*v4 + (z - row)*v2 + (x - col)*v3;
+        }
     }
 
     public void setHeight(Vector2f xz, float height) {
@@ -1473,6 +1496,12 @@ public class TerrainQuad extends Node implements Terrain {
                 for (int i = 0; i < getQuantity(); i++) {
                     if (children.get(i) instanceof TerrainPatch) {
                         TerrainPatch tp = (TerrainPatch) children.get(i);
+                        if (tp.getModelBound() instanceof BoundingBox) {
+                            if (((BoundingBox)tp.getModelBound()).getYExtent() == 0) {
+                                // a correction so the box always has a volume
+                                ((BoundingBox)tp.getModelBound()).setYExtent(0.00001f);
+                            }
+                        }
                         if (tp.getWorldBound().intersects(toTest)) {
                             CollisionResults cr = new CollisionResults();
                             toTest.collideWith(tp.getWorldBound(), cr);