Browse Source

* Make Geomap and LODGeomap use a float[] heightmap internally instead of FloatBuffer
* Remove normal map buffer from Geomap, not needed since its generated procedurally
* Optimized LODGeomap normal buffer generation to create less garbage

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

sha..rd 14 years ago
parent
commit
268a464191

+ 45 - 164
engine/src/terrain/com/jme3/terrain/GeoMap.java

@@ -53,38 +53,25 @@ import java.nio.IntBuffer;
  */
  */
 public class GeoMap implements Savable {
 public class GeoMap implements Savable {
     
     
-    protected FloatBuffer hdata;
-    protected ByteBuffer ndata;
+    protected float[] hdata;
     protected int width, height, maxval;
     protected int width, height, maxval;
     
     
     public GeoMap() {}
     public GeoMap() {}
     
     
-    public GeoMap(FloatBuffer heightData, ByteBuffer normalData, int width, int height, int maxval){
+    public GeoMap(float[] heightData, int width, int height, int maxval){
         this.hdata = heightData;
         this.hdata = heightData;
-        this.ndata = normalData;
         this.width = width;
         this.width = width;
         this.height = height;
         this.height = height;
         this.maxval = maxval;
         this.maxval = maxval;
     }
     }
 
 
-    public GeoMap(int width, int height, int maxval) {
-        this(BufferUtils.createFloatBuffer(width*height), null, width,height,maxval);
-    }
-
-    public FloatBuffer getHeightData(){
+    public float[] getHeightData(){
         if (!isLoaded())
         if (!isLoaded())
             return null;
             return null;
 
 
         return hdata;
         return hdata;
     }
     }
 
 
-    public ByteBuffer getNormalData(){
-        if (!isLoaded() || !hasNormalmap())
-            return null;
-
-        return ndata;
-    }
-
     /**
     /**
      * @return The maximum possible value that <code>getValue()</code> can 
      * @return The maximum possible value that <code>getValue()</code> can 
      * return. Mostly depends on the source data format (byte, short, int, etc).
      * return. Mostly depends on the source data format (byte, short, int, etc).
@@ -105,7 +92,7 @@ public class GeoMap implements Savable {
      * @throws NullPointerException If isLoaded() is false
      * @throws NullPointerException If isLoaded() is false
      */
      */
     public float getValue(int x, int y) {
     public float getValue(int x, int y) {
-        return hdata.get(y*width+x);
+        return hdata[y*width+x];
     }
     }
 
 
     /**
     /**
@@ -120,50 +107,9 @@ public class GeoMap implements Savable {
      * @throws NullPointerException If isLoaded() is false
      * @throws NullPointerException If isLoaded() is false
      */
      */
     public float getValue(int i) {
     public float getValue(int i) {
-        return hdata.get(i);
-    }
-
-    /**
-     * Returns the normal at a point
-     *
-     * If store is null, then a new vector is returned,
-     * otherwise, the result is stored in the provided vector
-     * and then returned from this method
-     *
-     * @param x the X coordinate
-     * @param y the Y coordinate
-     * @param store A preallocated vector for storing the normal data, optional
-     * @returns store, or a new vector with the normal data if store is null
-     *
-     * @throws NullPointerException If isLoaded() or hasNormalmap() is false
-     */
-    public Vector3f getNormal(int x, int y, Vector3f store) {
-        return getNormal(y*width+x,store);
+        return hdata[i];
     }
     }
 
 
-    /**
-     * Returns the normal at an index
-     *
-     * If store is null, then a new vector is returned,
-     * otherwise, the result is stored in the provided vector
-     * and then returned from this method
-     *
-     * See getHeight(int) for information about index lookup
-     *
-     * @param i the index
-     * @param store A preallocated vector for storing the normal data, optional
-     * @returns store, or a new vector with the normal data if store is null
-     *
-     * @throws NullPointerException If isLoaded() or hasNormalmap() is false
-     */
-    public Vector3f getNormal(int i, Vector3f store) {
-        ndata.position( i*3 );
-        if (store==null) store = new Vector3f();
-        store.setX( (((float)(ndata.get() & 0xFF)/255f)-0.5f)*2f );
-        store.setY( (((float)(ndata.get() & 0xFF)/255f)-0.5f)*2f );
-        store.setZ( (((float)(ndata.get() & 0xFF)/255f)-0.5f)*2f );
-        return store;
-    }
 
 
     /**
     /**
      * Returns the width of this Geomap
      * Returns the width of this Geomap
@@ -183,43 +129,6 @@ public class GeoMap implements Savable {
         return height;
         return height;
     }
     }
 
 
-    /**
-     * Copies a section of this geomap as a new geomap
-     */
-    public GeoMap copySubGeomap(int x, int y, int w, int h){
-        FloatBuffer nhdata = BufferUtils.createFloatBuffer(w * h);
-        hdata.position(y*width+x);
-        for (int cy = 0; cy < height; cy++){
-            hdata.limit(hdata.position()+w);
-            nhdata.put(hdata);
-            hdata.limit(hdata.capacity());
-            hdata.position(hdata.position()+width);
-        }
-        nhdata.flip();
-
-        ByteBuffer nndata = null;
-        if (ndata!=null){
-            nndata = BufferUtils.createByteBuffer(w*h*3);
-            ndata.position( (y*width+x)*3 );
-            for (int cy = 0; cy < height; cy++){
-                ndata.limit(ndata.position()+w*3);
-                nndata.put(ndata);
-                ndata.limit(ndata.capacity());
-                ndata.position(ndata.position()+width*3);
-            }
-            nndata.flip();
-        }
-
-        return new GeoMap(nhdata,nndata,w,h,maxval);
-    }
-
-    /**
-     * Returns true if this Geomap has a normalmap associated with it
-     */
-    public boolean hasNormalmap() {
-        return ndata != null;
-    }
-
     /**
     /**
      * Returns true if the Geomap data is loaded in memory
      * Returns true if the Geomap data is loaded in memory
      * If false, then the data is unavailable- must be loaded with load()
      * If false, then the data is unavailable- must be loaded with load()
@@ -250,65 +159,55 @@ public class GeoMap implements Savable {
             store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*3);
             store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*3);
         }
         }
         store.rewind();
         store.rewind();
-        
-        if (!hasNormalmap()){
-            Vector3f oppositePoint = new Vector3f();
-            Vector3f adjacentPoint = new Vector3f();
-            Vector3f rootPoint = new Vector3f();
-            Vector3f tempNorm = new Vector3f();
-            int normalIndex = 0;
-
-            for (int y = 0; y < getHeight(); y++) {
-                for (int x = 0; x < getWidth(); x++) {
-                    rootPoint.set(x, getValue(x,y), y);
-                    if (y == getHeight() - 1) {
-                        if (x == getWidth() - 1) {  // case #4 : last row, last col
-                            // left cross up
+
+        Vector3f oppositePoint = new Vector3f();
+        Vector3f adjacentPoint = new Vector3f();
+        Vector3f rootPoint = new Vector3f();
+        Vector3f tempNorm = new Vector3f();
+        int normalIndex = 0;
+
+        for (int y = 0; y < getHeight(); y++) {
+            for (int x = 0; x < getWidth(); x++) {
+                rootPoint.set(x, getValue(x,y), y);
+                if (y == getHeight() - 1) {
+                    if (x == getWidth() - 1) {  // case #4 : last row, last col
+                        // left cross up
 //                            adj = normalIndex - getWidth();
 //                            adj = normalIndex - getWidth();
 //                            opp = normalIndex - 1;
 //                            opp = normalIndex - 1;
-                            adjacentPoint.set(x, getValue(x,y-1), y-1);
-                            oppositePoint.set(x-1, getValue(x-1, y), y);
-                        } else {                    // case #3 : last row, except for last col
-                            // right cross up
+                        adjacentPoint.set(x, getValue(x,y-1), y-1);
+                        oppositePoint.set(x-1, getValue(x-1, y), y);
+                    } else {                    // case #3 : last row, except for last col
+                        // right cross up
 //                            adj = normalIndex + 1;
 //                            adj = normalIndex + 1;
 //                            opp = normalIndex - getWidth();
 //                            opp = normalIndex - getWidth();
-                            adjacentPoint.set(x+1, getValue(x+1,y), y);
-                            oppositePoint.set(x, getValue(x,y-1), y-1);
-                        }
-                    } else {
-                        if (x == getWidth() - 1) {  // case #2 : last column except for last row
-                            // left cross down
-                            adjacentPoint.set(x-1, getValue(x-1,y), y);
-                            oppositePoint.set(x, getValue(x,y+1), y+1);
+                        adjacentPoint.set(x+1, getValue(x+1,y), y);
+                        oppositePoint.set(x, getValue(x,y-1), y-1);
+                    }
+                } else {
+                    if (x == getWidth() - 1) {  // case #2 : last column except for last row
+                        // left cross down
+                        adjacentPoint.set(x-1, getValue(x-1,y), y);
+                        oppositePoint.set(x, getValue(x,y+1), y+1);
 //                            adj = normalIndex - 1;
 //                            adj = normalIndex - 1;
 //                            opp = normalIndex + getWidth();
 //                            opp = normalIndex + getWidth();
-                        } else {                    // case #1 : most cases
-                            // right cross down
-                            adjacentPoint.set(x, getValue(x,y+1), y+1);
-                            oppositePoint.set(x+1, getValue(x+1,y), y);
+                    } else {                    // case #1 : most cases
+                        // right cross down
+                        adjacentPoint.set(x, getValue(x,y+1), y+1);
+                        oppositePoint.set(x+1, getValue(x+1,y), y);
 //                            adj = normalIndex + getWidth();
 //                            adj = normalIndex + getWidth();
 //                            opp = normalIndex + 1;
 //                            opp = normalIndex + 1;
-                        }
                     }
                     }
+                }
 
 
 
 
 
 
-                    tempNorm.set(adjacentPoint).subtractLocal(rootPoint)
-                            .crossLocal(oppositePoint.subtractLocal(rootPoint));
-                    tempNorm.multLocal(scale).normalizeLocal();
+                tempNorm.set(adjacentPoint).subtractLocal(rootPoint)
+                        .crossLocal(oppositePoint.subtractLocal(rootPoint));
+                tempNorm.multLocal(scale).normalizeLocal();
 //                    store.put(tempNorm.x).put(tempNorm.y).put(tempNorm.z);
 //                    store.put(tempNorm.x).put(tempNorm.y).put(tempNorm.z);
-                    BufferUtils.setInBuffer(tempNorm, store,
-                            normalIndex);
-                    normalIndex++;
-                }
-            }
-        }else{
-            Vector3f temp = new Vector3f();
-            for (int z = 0; z < getHeight(); z++){
-                for (int x = 0; x < getWidth(); x++){
-                    getNormal(x,z,temp);
-                    store.put(temp.x).put(temp.y).put(temp.z);
-                }
+                BufferUtils.setInBuffer(tempNorm, store,
+                        normalIndex);
+                normalIndex++;
             }
             }
         }
         }
 
 
@@ -337,9 +236,8 @@ public class GeoMap implements Savable {
         }else{
         }else{
             store = BufferUtils.createFloatBuffer(width*height*3);
             store = BufferUtils.createFloatBuffer(width*height*3);
         }
         }
-        hdata.rewind();
 
 
-        assert hdata.limit() == height*width;
+        assert hdata.length == height*width;
 
 
         Vector3f offset = new Vector3f(-getWidth() * scale.x * 0.5f,
         Vector3f offset = new Vector3f(-getWidth() * scale.x * 0.5f,
                                        0,
                                        0,
@@ -347,10 +245,11 @@ public class GeoMap implements Savable {
         if (!center)
         if (!center)
             offset.zero();
             offset.zero();
 
 
+        int i = 0;
         for (int z = 0; z < height; z++){
         for (int z = 0; z < height; z++){
             for (int x = 0; x < width; x++){
             for (int x = 0; x < width; x++){
                 store.put( (float)x*scale.x + offset.x );
                 store.put( (float)x*scale.x + offset.x );
-                store.put( (float)hdata.get()*scale.y );
+                store.put( (float)hdata[i++]*scale.y );
                 store.put( (float)z*scale.z + offset.z );
                 store.put( (float)z*scale.z + offset.z );
             }
             }
         }
         }
@@ -433,24 +332,6 @@ public class GeoMap implements Savable {
         return m;
         return m;
     }
     }
     
     
-    /**
-     * Populate the height data from the supplied mesh.
-     * The mesh's dimensions should be the same as width and height
-     * of this geomap
-     */
-    public void populateHdataFromMesh(Mesh mesh) {
-        hdata = BufferUtils.createFloatBuffer(width*height);
-        hdata.rewind();
-        VertexBuffer pb = mesh.getBuffer(Type.Position);
-        FloatBuffer fb = (FloatBuffer) pb.getData();
-        for (int r=0; r<height; r++) {
-            for (int c=0; c<width; c++) {
-                float f = fb.get( (width*r) + c + 1);
-                hdata.put( f );
-            }
-        }
-    }
-
     public void write(JmeExporter ex) throws IOException {
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);
         OutputCapsule oc = ex.getCapsule(this);
         oc.write(hdata, "hdata", null);
         oc.write(hdata, "hdata", null);
@@ -461,7 +342,7 @@ public class GeoMap implements Savable {
 
 
     public void read(JmeImporter im) throws IOException {
     public void read(JmeImporter im) throws IOException {
         InputCapsule ic = im.getCapsule(this);
         InputCapsule ic = im.getCapsule(this);
-        hdata = ic.readFloatBuffer("hdata", null);
+        hdata = ic.readFloatArray("hdata", null);
         width = ic.readInt("width", 0);
         width = ic.readInt("width", 0);
         height = ic.readInt("height", 0);
         height = ic.readInt("height", 0);
         maxval = ic.readInt("maxval", 0);
         maxval = ic.readInt("maxval", 0);

+ 97 - 44
engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java

@@ -49,6 +49,7 @@ import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.util.BufferUtils;
 import com.jme3.util.BufferUtils;
 import com.jme3.util.TangentBinormalGenerator;
 import com.jme3.util.TangentBinormalGenerator;
+import com.jme3.util.TempVars;
 import java.io.IOException;
 import java.io.IOException;
 
 
 /**
 /**
@@ -69,8 +70,8 @@ public class LODGeomap extends GeoMap {
     public LODGeomap() {
     public LODGeomap() {
     }
     }
 
 
-    public LODGeomap(int size, FloatBuffer heightMap) {
-        super(heightMap, null, size, size, 1);
+    public LODGeomap(int size, float[] heightMap) {
+        super(heightMap, size, size, 1);
     }
     }
 
 
     public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center) {
     public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center) {
@@ -98,10 +99,6 @@ public class LODGeomap extends GeoMap {
         return m;
         return m;
     }
     }
 
 
-    protected void removeNormalBuffer() {
-        ndata = null;
-    }
-
     public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize) {
     public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize) {
         if (store != null) {
         if (store != null) {
             if (store.remaining() < getWidth() * getHeight() * 2) {
             if (store.remaining() < getWidth() * getHeight() * 2) {
@@ -762,94 +759,150 @@ public class LODGeomap extends GeoMap {
         }
         }
         store.rewind();
         store.rewind();
 
 
-        Vector3f rootPoint = new Vector3f();
-        Vector3f rightPoint = new Vector3f();
-        Vector3f leftPoint = new Vector3f();
-        Vector3f topPoint = new Vector3f();
-        Vector3f bottomPoint = new Vector3f();
+        TempVars vars = TempVars.get();
+        
+        Vector3f rootPoint = vars.vect1;
+        Vector3f rightPoint = vars.vect2;
+        Vector3f leftPoint = vars.vect3;
+        Vector3f topPoint = vars.vect4;
+        Vector3f bottomPoint = vars.vect5;
+        
+        Vector3f tmp1 = vars.vect6;
+        Vector3f tmp2 = vars.vect7;
 
 
         // calculate normals for each polygon
         // calculate normals for each polygon
         for (int r = 0; r < getHeight(); r++) {
         for (int r = 0; r < getHeight(); r++) {
             for (int c = 0; c < getWidth(); c++) {
             for (int c = 0; c < getWidth(); c++) {
 
 
                 rootPoint.set(c, getValue(c, r), r);
                 rootPoint.set(c, getValue(c, r), r);
-                Vector3f normal = new Vector3f();
+                Vector3f normal = vars.vect8;
 
 
                 if (r == 0) { // first row
                 if (r == 0) { // first row
                     if (c == 0) { // first column
                     if (c == 0) { // first column
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        normal.set(getNormal(bottomPoint, rootPoint, rightPoint, scale));
+                        getNormal(bottomPoint, rootPoint, rightPoint, scale, normal);
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else if (c == getWidth() - 1) { // last column
                     } else if (c == getWidth() - 1) { // last column
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        normal.set(getNormal(leftPoint, rootPoint, bottomPoint, scale));
+                        getNormal(leftPoint, rootPoint, bottomPoint, scale, normal);
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else { // all middle columns
                     } else { // all middle columns
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        Vector3f n1 = getNormal(leftPoint, rootPoint, bottomPoint, scale);
-                        Vector3f n2 = getNormal(bottomPoint, rootPoint, rightPoint, scale);
-                        normal.set(n1.add(n2).normalizeLocal());
+                        
+                        normal.set( getNormal(leftPoint, rootPoint, bottomPoint, scale, tmp1) );
+                        normal.add( getNormal(bottomPoint, rootPoint, rightPoint, scale, tmp1) );
+                        normal.normalizeLocal();
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     }
                     }
                 } else if (r == getHeight() - 1) { // last row
                 } else if (r == getHeight() - 1) { // last row
                     if (c == 0) { // first column
                     if (c == 0) { // first column
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
-                        normal.set(getNormal(rightPoint, rootPoint, topPoint, scale));
+                        getNormal(rightPoint, rootPoint, topPoint, scale, normal);
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else if (c == getWidth() - 1) { // last column
                     } else if (c == getWidth() - 1) { // last column
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
-                        normal.set(getNormal(topPoint, rootPoint, leftPoint, scale));
+                        getNormal(topPoint, rootPoint, leftPoint, scale, normal);
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else { // all middle columns
                     } else { // all middle columns
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
-                        Vector3f n1 = getNormal(topPoint, rootPoint, leftPoint, scale);
-                        Vector3f n2 = getNormal(rightPoint, rootPoint, topPoint, scale);
-                        normal.set(n1.add(n2).normalizeLocal());
+                        
+                        normal.set( getNormal(topPoint, rootPoint, leftPoint, scale, tmp1) );
+                        normal.add( getNormal(rightPoint, rootPoint, topPoint, scale, tmp1) );
+                        normal.normalizeLocal();
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     }
                     }
                 } else { // all middle rows
                 } else { // all middle rows
                     if (c == 0) { // first column
                     if (c == 0) { // first column
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        Vector3f n1 = getNormal(rightPoint, rootPoint, topPoint, scale);
-                        Vector3f n2 = getNormal(bottomPoint, rootPoint, rightPoint, scale);
-                        normal.set(n1.add(n2).normalizeLocal());
+                        
+                        normal.set( getNormal(rightPoint, rootPoint, topPoint, scale, tmp1) );
+                        normal.add( getNormal(bottomPoint, rootPoint, rightPoint, scale, tmp1) );
+                        normal.normalizeLocal();
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else if (c == getWidth() - 1) { // last column
                     } else if (c == getWidth() - 1) { // last column
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        Vector3f n1 = getNormal(topPoint, rootPoint, leftPoint, scale);
-                        Vector3f n2 = getNormal(leftPoint, rootPoint, bottomPoint, scale);
-                        normal.set(n1.add(n2).normalizeLocal());
+
+                        normal.set( getNormal(topPoint, rootPoint, leftPoint, scale, tmp1) );
+                        normal.add( getNormal(leftPoint, rootPoint, bottomPoint, scale, tmp1) );
+                        normal.normalizeLocal();
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     } else { // all middle columns
                     } else { // all middle columns
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         topPoint.set(c, getValue(c, r - 1), r - 1);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         leftPoint.set(c - 1, getValue(c - 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         rightPoint.set(c + 1, getValue(c + 1, r), r);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
                         bottomPoint.set(c, getValue(c, r + 1), r + 1);
-                        Vector3f n1 = getNormal(topPoint, rootPoint, leftPoint, scale);
-                        Vector3f n2 = getNormal(leftPoint, rootPoint, bottomPoint, scale);
-                        Vector3f n3 = getNormal(bottomPoint, rootPoint, rightPoint, scale);
-                        Vector3f n4 = getNormal(rightPoint, rootPoint, topPoint, scale);
-                        normal.set(n1.add(n2).add(n3).add(n4).normalizeLocal());
+                        
+                        normal.set( getNormal(topPoint,  rootPoint, leftPoint, scale, tmp1 ) );
+                        normal.add( getNormal(leftPoint, rootPoint, bottomPoint, scale, tmp1) );
+                        normal.add( getNormal(bottomPoint, rootPoint, rightPoint, scale, tmp1) );
+                        normal.add( getNormal(rightPoint, rootPoint, topPoint, scale, tmp1) );
+                        normal.normalizeLocal();
+                        
+                        normal.set(Vector3f.UNIT_Y);
                     }
                     }
                 }
                 }
-
+                
+                normal.set(Vector3f.UNIT_Y);
                 BufferUtils.setInBuffer(normal, store, (r * getWidth() + c)); // save the normal
                 BufferUtils.setInBuffer(normal, store, (r * getWidth() + c)); // save the normal
-
             }
             }
         }
         }
+        
+        vars.release();
 
 
         return store;
         return store;
     }
     }
 
 
-    private Vector3f getNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint, Vector3f scale) {
-        Vector3f normal = new Vector3f();
-        //scale = Vector3f.UNIT_XYZ;
-        normal.set(firstPoint.mult(scale)).subtractLocal(rootPoint.mult(scale)).crossLocal(secondPoint.mult(scale).subtract(rootPoint.mult(scale))).normalizeLocal();
-        return normal;
+    private Vector3f getNormal(Vector3f firstPoint, Vector3f rootPoint, Vector3f secondPoint, Vector3f scale, Vector3f store) {
+//        store.set(firstPoint).subtractLocal(rootPoint);
+//        tmp.set(secondPoint).subtractLocal(rootPoint);
+//        store.crossLocal(tmp).mult(scale).normalizeLocal();
+        
+       // store.set(
+       //         firstPoint.mult(scale)).subtractLocal(rootPoint.mult(scale))
+       //               .crossLocal(
+       //         secondPoint.mult(scale).subtract(rootPoint.mult(scale))).normalizeLocal();
+        
+        float x1 = firstPoint.x - rootPoint.x;
+        float y1 = firstPoint.y - rootPoint.y;
+        float z1 = firstPoint.z - rootPoint.z;
+        float x2 = secondPoint.x - rootPoint.x;
+        float y2 = secondPoint.y - rootPoint.y;
+        float z2 = secondPoint.z - rootPoint.z;
+        float x3 = (y1 * z2) - (z1 * y2);
+        float y3 = (z1 * x2) - (x1 * z2);
+        float z3 = (x1 * y2) - (y1 * x2);
+        
+        x3 *= scale.x;
+        y3 *= scale.y;
+        z3 *= scale.z;
+        
+        float inv = 1.0f / FastMath.sqrt(x3 * x3 + y3 * y3 + z3 * z3);
+        store.x = x3 * inv;
+        store.y = y3 * inv;
+        store.z = z3 * inv;
+        
+        return store;
+        
     }
     }
 
 
     /**
     /**
@@ -953,10 +1006,10 @@ public class LODGeomap extends GeoMap {
         Triangle t = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
         Triangle t = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
         Triangle t2 = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
         Triangle t2 = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
 
 
-        float h1 = hdata.get(index);                // top left
-        float h2 = hdata.get(index + 1);            // top right
-        float h3 = hdata.get(index + width);        // bottom left
-        float h4 = hdata.get(index + width + 1);    // bottom right
+        float h1 = hdata[index];                // top left
+        float h2 = hdata[index + 1];            // top right
+        float h3 = hdata[index + width];        // bottom left
+        float h4 = hdata[index + width + 1];    // bottom right
 
 
 
 
         if ((gridX == 0 && gridY == 0) || (gridX == width - 1 && gridY == width - 1)) {
         if ((gridX == 0 && gridY == 0) || (gridX == width - 1 && gridY == width - 1)) {

+ 4 - 7
engine/src/terrain/com/jme3/terrain/geomipmap/TerrainPatch.java

@@ -186,10 +186,7 @@ public class TerrainPatch extends Geometry {
 
 
         setLocalTranslation(origin);
         setLocalTranslation(origin);
 
 
-        FloatBuffer heightBuffer = BufferUtils.createFloatBuffer(size*size);
-        heightBuffer.put(heightMap);
-
-        geomap = new LODGeomap(size, heightBuffer);
+        geomap = new LODGeomap(size, heightMap);
         Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false);
         Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false);
         setMesh(m);
         setMesh(m);
 
 
@@ -216,7 +213,7 @@ public class TerrainPatch extends Geometry {
         return lodEntropy;
         return lodEntropy;
     }
     }
 
 
-    public FloatBuffer getHeightmap() {
+    public float[] getHeightmap() {
         return geomap.getHeightData();
         return geomap.getHeightData();
     }
     }
 
 
@@ -300,10 +297,10 @@ public class TerrainPatch extends Geometry {
                 continue;
                 continue;
             int idx = lh.z * size + lh.x;
             int idx = lh.z * size + lh.x;
             if (overrideHeight) {
             if (overrideHeight) {
-                geomap.getHeightData().put(idx, lh.h);
+                geomap.getHeightData()[idx] = lh.h;
             } else {
             } else {
                 float h = getMesh().getFloatBuffer(Type.Position).get(idx*3+1);
                 float h = getMesh().getFloatBuffer(Type.Position).get(idx*3+1);
-                geomap.getHeightData().put(idx, h+lh.h);
+                geomap.getHeightData()[idx] = h+lh.h;
             }
             }
             
             
         }
         }

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

@@ -1796,13 +1796,13 @@ public class TerrainQuad extends Node implements Terrain {
             if (getChild(0) instanceof TerrainPatch) {
             if (getChild(0) instanceof TerrainPatch) {
                 for (Spatial s : getChildren()) {
                 for (Spatial s : getChildren()) {
                     if ( ((TerrainPatch)s).getQuadrant() == 1)
                     if ( ((TerrainPatch)s).getQuadrant() == 1)
-                        ul = BufferUtils.getFloatArray(((TerrainPatch)s).getHeightmap());
+                        ul = ((TerrainPatch)s).getHeightmap();
                     else if(((TerrainPatch) s).getQuadrant() == 2)
                     else if(((TerrainPatch) s).getQuadrant() == 2)
-                        bl = BufferUtils.getFloatArray(((TerrainPatch)s).getHeightmap());
+                        bl = ((TerrainPatch)s).getHeightmap();
                     else if(((TerrainPatch) s).getQuadrant() == 3)
                     else if(((TerrainPatch) s).getQuadrant() == 3)
-                        ur = BufferUtils.getFloatArray(((TerrainPatch)s).getHeightmap());
+                        ur = ((TerrainPatch)s).getHeightmap();
                     else if(((TerrainPatch) s).getQuadrant() == 4)
                     else if(((TerrainPatch) s).getQuadrant() == 4)
-                        br = BufferUtils.getFloatArray(((TerrainPatch)s).getHeightmap());
+                        br = ((TerrainPatch)s).getHeightmap();
                 }
                 }
             }
             }
             else {
             else {