2
0
Эх сурвалжийг харах

simplified terrain tangent generation, cleaned up code

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9200 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
bre..ns 13 жил өмнө
parent
commit
3420ec2881

+ 20 - 7
engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java

@@ -34,6 +34,7 @@ package com.jme3.terrain.geomipmap;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
+import com.jme3.math.Plane;
 import com.jme3.math.Triangle;
 import com.jme3.math.Triangle;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
@@ -87,7 +88,7 @@ public class LODGeomap extends GeoMap {
         IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod);
         IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod);
         FloatBuffer bb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
         FloatBuffer bb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
         FloatBuffer tanb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
         FloatBuffer tanb = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3);
-        writeTangentArray(tanb, bb, texb, scale);
+        writeTangentArray(nb, tanb, bb, texb, scale);
         Mesh m = new Mesh();
         Mesh m = new Mesh();
         m.setMode(Mode.TriangleStrip);
         m.setMode(Mode.TriangleStrip);
         m.setBuffer(Type.Position, 3, pb);
         m.setBuffer(Type.Position, 3, pb);
@@ -627,7 +628,7 @@ public class LODGeomap extends GeoMap {
         return num;
         return num;
     }
     }
 
 
-    public FloatBuffer[] writeTangentArray(FloatBuffer tangentStore, FloatBuffer binormalStore, FloatBuffer textureBuffer, Vector3f scale) {
+    public FloatBuffer[] writeTangentArray(FloatBuffer normalBuffer, FloatBuffer tangentStore, FloatBuffer binormalStore, FloatBuffer textureBuffer, Vector3f scale) {
         if (!isLoaded()) {
         if (!isLoaded()) {
             throw new NullPointerException();
             throw new NullPointerException();
         }
         }
@@ -650,18 +651,30 @@ public class LODGeomap extends GeoMap {
         }
         }
         binormalStore.rewind();
         binormalStore.rewind();
 
 
+        Vector3f normal = new Vector3f();
         Vector3f tangent = new Vector3f();
         Vector3f tangent = new Vector3f();
         Vector3f binormal = new Vector3f();
         Vector3f binormal = new Vector3f();
-        Vector3f v1 = new Vector3f();
+        /*Vector3f v1 = new Vector3f();
         Vector3f v2 = new Vector3f();
         Vector3f v2 = new Vector3f();
         Vector3f v3 = new Vector3f();
         Vector3f v3 = new Vector3f();
         Vector2f t1 = new Vector2f();
         Vector2f t1 = new Vector2f();
         Vector2f t2 = new Vector2f();
         Vector2f t2 = new Vector2f();
-        Vector2f t3 = new Vector2f();
-
-        //scale = Vector3f.UNIT_XYZ;
+        Vector2f t3 = new Vector2f();*/
 
 
         for (int r = 0; r < getHeight(); r++) {
         for (int r = 0; r < getHeight(); r++) {
+            for (int c = 0; c < getWidth(); c++) {
+                
+                int idx = (r * getWidth() + c) * 3;
+                normal.set(normalBuffer.get(idx), normalBuffer.get(idx+1), normalBuffer.get(idx+2));
+                tangent.set(normal.cross(new Vector3f(0,0,1)));
+                binormal.set(new Vector3f(1,0,0).cross(normal));
+                
+                BufferUtils.setInBuffer(tangent.normalizeLocal(), tangentStore, (r * getWidth() + c)); // save the tangent
+                BufferUtils.setInBuffer(binormal.normalizeLocal(), binormalStore, (r * getWidth() + c)); // save the binormal
+            }
+        }
+
+/*        for (int r = 0; r < getHeight(); r++) {
             for (int c = 0; c < getWidth(); c++) {
             for (int c = 0; c < getWidth(); c++) {
 
 
                 int texIdx = ((getHeight() - 1 - r) * getWidth() + c) * 2; // pull from the end
                 int texIdx = ((getHeight() - 1 - r) * getWidth() + c) * 2; // pull from the end
@@ -702,7 +715,7 @@ public class LODGeomap extends GeoMap {
                 BufferUtils.setInBuffer(binormal, binormalStore, (r * getWidth() + c)); // save the binormal
                 BufferUtils.setInBuffer(binormal, binormalStore, (r * getWidth() + c)); // save the binormal
             }
             }
         }
         }
-
+        */
         return new FloatBuffer[]{tangentStore, binormalStore};
         return new FloatBuffer[]{tangentStore, binormalStore};
     }
     }
 
 

+ 105 - 48
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java

@@ -314,13 +314,25 @@ public class TerrainPatch extends Geometry {
         getMesh().getBuffer(Type.Normal).updateData(newNormalBuffer);
         getMesh().getBuffer(Type.Normal).updateData(newNormalBuffer);
         FloatBuffer newTangentBuffer = null;
         FloatBuffer newTangentBuffer = null;
         FloatBuffer newBinormalBuffer = null;
         FloatBuffer newBinormalBuffer = null;
-        FloatBuffer[] tb = geomap.writeTangentArray(newTangentBuffer, newBinormalBuffer, (FloatBuffer)getMesh().getBuffer(Type.TexCoord).getData(), getWorldScale());
+        FloatBuffer[] tb = geomap.writeTangentArray(newNormalBuffer, newTangentBuffer, newBinormalBuffer, (FloatBuffer)getMesh().getBuffer(Type.TexCoord).getData(), getWorldScale());
         newTangentBuffer = tb[0];
         newTangentBuffer = tb[0];
         newBinormalBuffer = tb[1];
         newBinormalBuffer = tb[1];
         getMesh().getBuffer(Type.Tangent).updateData(newTangentBuffer);
         getMesh().getBuffer(Type.Tangent).updateData(newTangentBuffer);
         getMesh().getBuffer(Type.Binormal).updateData(newBinormalBuffer);
         getMesh().getBuffer(Type.Binormal).updateData(newBinormalBuffer);
     }
     }
 
 
+    private void setInBuffer(Mesh mesh, int index, Vector3f normal, Vector3f tangent, Vector3f binormal) {
+        VertexBuffer NB = mesh.getBuffer(Type.Normal);
+        VertexBuffer TB = mesh.getBuffer(Type.Tangent);
+        VertexBuffer BB = mesh.getBuffer(Type.Binormal);
+        BufferUtils.setInBuffer(normal, (FloatBuffer)NB.getData(), index);
+        BufferUtils.setInBuffer(tangent, (FloatBuffer)TB.getData(), index);
+        BufferUtils.setInBuffer(binormal, (FloatBuffer)BB.getData(), index);
+        NB.setUpdateNeeded();
+        TB.setUpdateNeeded();
+        BB.setUpdateNeeded();
+    }
+    
     /**
     /**
      * Matches the normals along the edge of the patch with the neighbours.
      * Matches the normals along the edge of the patch with the neighbours.
      * Computes the normals for the right, bottom, left, and top edges of the
      * Computes the normals for the right, bottom, left, and top edges of the
@@ -370,24 +382,41 @@ public class TerrainPatch extends Geometry {
                         bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                         bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                         
                         
                         averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), s, normal, tangent, binormal);
+                        setInBuffer(right.getMesh(), 0, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
+                        VertexBuffer tpBB = this.getMesh().getBuffer(Type.Binormal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
+                        VertexBuffer rightTB = right.getMesh().getBuffer(Type.Tangent);
+                        VertexBuffer rightBB = right.getMesh().getBuffer(Type.Binormal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), s);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), s);
+                        BufferUtils.setInBuffer(tangent, (FloatBuffer)tpTB.getData(), s);
+                        BufferUtils.setInBuffer(binormal, (FloatBuffer)tpBB.getData(), s);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), 0);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), 0);
+                        BufferUtils.setInBuffer(tangent, (FloatBuffer)rightTB.getData(), 0);
+                        BufferUtils.setInBuffer(binormal, (FloatBuffer)rightBB.getData(), 0);*/
                     } else {
                     } else {
                         topPoint.set(s, top.getHeightmapHeight(s,s-1), i-1);
                         topPoint.set(s, top.getHeightmapHeight(s,s-1), i-1);
                         bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                         bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                         
                         
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), s, normal, tangent, binormal);
+                        setInBuffer(right.getMesh(), 0, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        VertexBuffer tpTB = this.getMesh().getBuffer(Type.Tangent);
+                        VertexBuffer tpBB = this.getMesh().getBuffer(Type.Binormal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
+                        VertexBuffer rightTB = right.getMesh().getBuffer(Type.Tangent);
+                        VertexBuffer rightBB = right.getMesh().getBuffer(Type.Binormal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), s);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), s);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), 0);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), 0);*/
                         
                         
                         if (topRight != null) {
                         if (topRight != null) {
-                            VertexBuffer topRightNB = topRight.getMesh().getBuffer(Type.Normal);
+                            setInBuffer(topRight.getMesh(), (s+1)*s, normal, tangent, binormal);
+                            /*VertexBuffer topRightNB = topRight.getMesh().getBuffer(Type.Normal);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)topRightNB.getData(), (s+1)*s);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)topRightNB.getData(), (s+1)*s);
-                            topRightNB.setUpdateNeeded();
+                            topRightNB.setUpdateNeeded();*/
                         }
                         }
                     }
                     }
                 } else if (i == s) { // bottom point
                 } else if (i == s) { // bottom point
@@ -395,40 +424,48 @@ public class TerrainPatch extends Geometry {
                         topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                         topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                         
                         
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, null, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, null, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), (s+1)*(i+1)-1, normal, tangent, binormal);
+                        setInBuffer(right.getMesh(), (s+1)*(s), normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i+1)-1);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i+1)-1);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*(s));
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*(s));*/
                     } else {
                     } else {
                         topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                         topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                         bottomPoint.set(s, bottom.getHeightmapHeight(s,1), i+1);
                         bottomPoint.set(s, bottom.getHeightmapHeight(s,1), i+1);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), (s+1)*(s+1)-1, normal, tangent, binormal);
+                        setInBuffer(right.getMesh(), (s+1)*s, normal, tangent, binormal);
+                        setInBuffer(bottom.getMesh(), s, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                         VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
                         VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
 
 
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s+1)-1);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s+1)-1);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*s);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*s);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), s);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), s);*/
                         
                         
                         if (bottomRight != null) {
                         if (bottomRight != null) {
-                            VertexBuffer bottomRightNB = bottomRight.getMesh().getBuffer(Type.Normal);
+                            setInBuffer(bottomRight.getMesh(), 0, normal, tangent, binormal);
+                            /*VertexBuffer bottomRightNB = bottomRight.getMesh().getBuffer(Type.Normal);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)bottomRightNB.getData(), 0);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)bottomRightNB.getData(), 0);
-                            bottomRightNB.setUpdateNeeded();
+                            bottomRightNB.setUpdateNeeded();*/
                         }
                         }
-                        downNB.setUpdateNeeded();
+                        //downNB.setUpdateNeeded();
                     }
                     }
                 } else { // all in the middle
                 } else { // all in the middle
                     topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                     topPoint.set(s, this.getHeightmapHeight(s,i-1), i-1);
                     bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                     bottomPoint.set(s, this.getHeightmapHeight(s,i+1), i+1);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                    VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                    setInBuffer(this.getMesh(), (s+1)*(i+1)-1, normal, tangent, binormal);
+                    setInBuffer(right.getMesh(), (s+1)*(i), normal, tangent, binormal);
+                    /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                     VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                     VertexBuffer rightNB = right.getMesh().getBuffer(Type.Normal);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i+1)-1);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i+1)-1);
-                    BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*(i));
+                    BufferUtils.setInBuffer(normal, (FloatBuffer)rightNB.getData(), (s+1)*(i));*/
                 }
                 }
             }
             }
-            right.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
+            //right.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
         }
         }
 
 
         if (left != null) { // left side,    works its way down
         if (left != null) { // left side,    works its way down
@@ -441,24 +478,29 @@ public class TerrainPatch extends Geometry {
                     if (top == null) {
                     if (top == null) {
                         bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                         bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                         averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(null, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), 0, normal, tangent, binormal);
+                        setInBuffer(left.getMesh(), s, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), 0);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), 0);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), s);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), s);*/
                     } else {
                     } else {
                         topPoint.set(0, top.getHeightmapHeight(0,s-1), i-1);
                         topPoint.set(0, top.getHeightmapHeight(0,s-1), i-1);
                         bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                         bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                         
                         
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), 0, normal, tangent, binormal);
+                        setInBuffer(left.getMesh(), s, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), 0);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), 0);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), s);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), s);*/
                         
                         
                         if (topLeft != null) {
                         if (topLeft != null) {
-                            VertexBuffer topLeftNB = topLeft.getMesh().getBuffer(Type.Normal);
+                            setInBuffer(topLeft.getMesh(), (s+1)*(s+1)-1, normal, tangent, binormal);
+                            /*VertexBuffer topLeftNB = topLeft.getMesh().getBuffer(Type.Normal);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)topLeftNB.getData(), (s+1)*(s+1)-1);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)topLeftNB.getData(), (s+1)*(s+1)-1);
-                            topLeftNB.setUpdateNeeded();
+                            topLeftNB.setUpdateNeeded();*/
                         }
                         }
                     }
                     }
                 } else if (i == s) { // bottom point
                 } else if (i == s) { // bottom point
@@ -466,42 +508,50 @@ public class TerrainPatch extends Geometry {
                         topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                         topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                         
                         
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, null, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, null, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), (s+1)*(s), normal, tangent, binormal);
+                        setInBuffer(left.getMesh(), (s+1)*(i+1)-1, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s));
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s));
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);*/
                     } else {
                     } else {
                         topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                         topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                         bottomPoint.set(0, bottom.getHeightmapHeight(0,1), i+1);
                         bottomPoint.set(0, bottom.getHeightmapHeight(0,1), i+1);
                         
                         
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                         averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                        VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                        setInBuffer(this.getMesh(), (s+1)*(s), normal, tangent, binormal);
+                        setInBuffer(left.getMesh(), (s+1)*(i+1)-1, normal, tangent, binormal);
+                        setInBuffer(bottom.getMesh(), 0, normal, tangent, binormal);
+                        /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                         VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
                         VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
 
 
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s));
                         BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s));
                         BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);
                         BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);
-                        BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), 0);
+                        BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), 0);*/
                         
                         
                         if (bottomLeft != null) {
                         if (bottomLeft != null) {
-                            VertexBuffer bottomLeftNB = bottomLeft.getMesh().getBuffer(Type.Normal);
+                            setInBuffer(bottomLeft.getMesh(), s, normal, tangent, binormal);
+                            /*VertexBuffer bottomLeftNB = bottomLeft.getMesh().getBuffer(Type.Normal);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)bottomLeftNB.getData(), s);
                             BufferUtils.setInBuffer(normal, (FloatBuffer)bottomLeftNB.getData(), s);
-                            bottomLeftNB.setUpdateNeeded();
+                            bottomLeftNB.setUpdateNeeded();*/
                         }
                         }
-                        downNB.setUpdateNeeded();
+                        //downNB.setUpdateNeeded();
                     }
                     }
                 } else { // all in the middle
                 } else { // all in the middle
                     topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                     topPoint.set(0, this.getHeightmapHeight(0,i-1), i-1);
                     bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                     bottomPoint.set(0, this.getHeightmapHeight(0,i+1), i+1);
                     
                     
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                    VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                    setInBuffer(this.getMesh(), (s+1)*(i), normal, tangent, binormal);
+                    setInBuffer(left.getMesh(), (s+1)*(i+1)-1, normal, tangent, binormal);
+                    /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                     VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                     VertexBuffer leftNB = left.getMesh().getBuffer(Type.Normal);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i));
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(i));
-                    BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);
+                    BufferUtils.setInBuffer(normal, (FloatBuffer)leftNB.getData(), (s+1)*(i+1)-1);*/
                 }
                 }
             }
             }
-            left.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
+            //left.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
         }
         }
         
         
         if (top != null) { // top side,    works its way right
         if (top != null) { // top side,    works its way right
@@ -521,13 +571,15 @@ public class TerrainPatch extends Geometry {
                     leftPoint.set(i-1, this.getHeightmapHeight(i-1,0), 0);
                     leftPoint.set(i-1, this.getHeightmapHeight(i-1,0), 0);
                     rightPoint.set(i+1, this.getHeightmapHeight(i+1,0), 0);
                     rightPoint.set(i+1, this.getHeightmapHeight(i+1,0), 0);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                    VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                    setInBuffer(this.getMesh(), i, normal, tangent, binormal);
+                    setInBuffer(top.getMesh(), (s+1)*(s)+i, normal, tangent, binormal);
+                    /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), i);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), i);
                     VertexBuffer topNB = top.getMesh().getBuffer(Type.Normal);
                     VertexBuffer topNB = top.getMesh().getBuffer(Type.Normal);
-                    BufferUtils.setInBuffer(normal, (FloatBuffer)topNB.getData(), (s+1)*(s)+i);
+                    BufferUtils.setInBuffer(normal, (FloatBuffer)topNB.getData(), (s+1)*(s)+i);*/
                 }
                 }
             }
             }
-            top.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
+            //top.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
             
             
         }
         }
         
         
@@ -548,19 +600,21 @@ public class TerrainPatch extends Geometry {
                     leftPoint.set(i-1, this.getHeightmapHeight(i-1,s), s);
                     leftPoint.set(i-1, this.getHeightmapHeight(i-1,s), s);
                     rightPoint.set(i+1, this.getHeightmapHeight(i+1,s), s);
                     rightPoint.set(i+1, this.getHeightmapHeight(i+1,s), s);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
                     averageNormalsTangents(topPoint, rootPoint, leftPoint, bottomPoint, rightPoint, null, null, null, null, null, normal, tangent, binormal);
-                    VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
+                    setInBuffer(this.getMesh(), (s+1)*(s)+i, normal, tangent, binormal);
+                    setInBuffer(bottom.getMesh(), i, normal, tangent, binormal);
+                    /*VertexBuffer tpNB = this.getMesh().getBuffer(Type.Normal);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s)+i);
                     BufferUtils.setInBuffer(normal, (FloatBuffer)tpNB.getData(), (s+1)*(s)+i);
                     VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
                     VertexBuffer downNB = bottom.getMesh().getBuffer(Type.Normal);
-                    BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), i);
+                    BufferUtils.setInBuffer(normal, (FloatBuffer)downNB.getData(), i);*/
                 }
                 }
             }
             }
-            bottom.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
+            //bottom.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
             
             
         }
         }
 
 
-        this.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
-        this.getMesh().getBuffer(Type.Tangent).setUpdateNeeded();
-        this.getMesh().getBuffer(Type.Binormal).setUpdateNeeded();
+        //this.getMesh().getBuffer(Type.Normal).setUpdateNeeded();
+        //this.getMesh().getBuffer(Type.Tangent).setUpdateNeeded();
+        //this.getMesh().getBuffer(Type.Binormal).setUpdateNeeded();
     }
     }
 
 
     protected void averageNormalsTangents(
     protected void averageNormalsTangents(
@@ -582,25 +636,28 @@ public class TerrainPatch extends Geometry {
         
         
         Vector3f n1 = Vector3f.ZERO;
         Vector3f n1 = Vector3f.ZERO;
         if (topPoint != null && leftPoint != null) {
         if (topPoint != null && leftPoint != null) {
-            n1 = calculateNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale));
+            n1.set(calculateNormal(topPoint.mult(scale), rootPoint.mult(scale), leftPoint.mult(scale)));
         }
         }
         Vector3f n2 = Vector3f.ZERO;
         Vector3f n2 = Vector3f.ZERO;
         if (leftPoint != null && bottomPoint != null) {
         if (leftPoint != null && bottomPoint != null) {
-            n2 = calculateNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale));
+            n2.set(calculateNormal(leftPoint.mult(scale), rootPoint.mult(scale), bottomPoint.mult(scale)));
         }
         }
         Vector3f n3 = Vector3f.ZERO;
         Vector3f n3 = Vector3f.ZERO;
         if (rightPoint != null && bottomPoint != null) {
         if (rightPoint != null && bottomPoint != null) {
-            n3 = calculateNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale));
+            n3.set(calculateNormal(bottomPoint.mult(scale), rootPoint.mult(scale), rightPoint.mult(scale)));
         }
         }
         Vector3f n4 = Vector3f.ZERO;
         Vector3f n4 = Vector3f.ZERO;
         if (rightPoint != null && topPoint != null) {
         if (rightPoint != null && topPoint != null) {
-            n4 = calculateNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale));
+            n4.set(calculateNormal(rightPoint.mult(scale), rootPoint.mult(scale), topPoint.mult(scale)));
         }
         }
         
         
-        if (bottomPoint != null && rightPoint != null && rootTex != null && rightTex != null && bottomTex != null)
-            LODGeomap.calculateTangent(new Vector3f[]{rootPoint.mult(scale),rightPoint.mult(scale),bottomPoint.mult(scale)}, new Vector2f[]{rootTex,rightTex,bottomTex}, tangent, binormal);
+        //if (bottomPoint != null && rightPoint != null && rootTex != null && rightTex != null && bottomTex != null)
+        //    LODGeomap.calculateTangent(new Vector3f[]{rootPoint.mult(scale),rightPoint.mult(scale),bottomPoint.mult(scale)}, new Vector2f[]{rootTex,rightTex,bottomTex}, tangent, binormal);
 
 
-        normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal());
+        normal.set(n1.add(n2).add(n3).add(n4).normalize());
+        
+        tangent.set(normal.cross(new Vector3f(0,0,1)).normalize());
+        binormal.set(new Vector3f(1,0,0).cross(normal).normalize());
     }
     }
 
 
     private Vector3f calculateNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) {
     private Vector3f calculateNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint) {

+ 2 - 1
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java

@@ -1675,8 +1675,9 @@ public class TerrainQuad extends Node implements Terrain {
                             }
                             }
                         }
                         }
                     }
                     }
-                    else
+                    else if (children.get(i) instanceof TerrainQuad) {
                         ((TerrainQuad) children.get(i)).findPick(toTest, results);
                         ((TerrainQuad) children.get(i)).findPick(toTest, results);
+                    }
                 }
                 }
             }
             }
         }
         }