public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) {
        
        if (store!=null){
            if (store.remaining() < getWidth()*getHeight()*3)
                throw new BufferUnderflowException();
        }else{
            store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*3);
        }
        store.rewind();

        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();
//                            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
//                            adj = normalIndex + 1;
//                            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);
//                            adj = normalIndex - 1;
//                            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);
//                            adj = normalIndex + getWidth();
//                            opp = normalIndex + 1;
                    }
                }



                tempNorm.set(adjacentPoint).subtractLocal(rootPoint)
                        .crossLocal(oppositePoint.subtractLocal(rootPoint));
                tempNorm.multLocal(scale).normalizeLocal();
//                    store.put(tempNorm.x).put(tempNorm.y).put(tempNorm.z);
                BufferUtils.setInBuffer(tempNorm, store,
                        normalIndex);
                normalIndex++;
            }
        }

        return store;
    }
Creates a normal array from the normal data in this Geomap

@param store A preallocated FloatBuffer where to store the data (optional), size must be &gt;= getWidth()*getHeight()*3
@return store, or a new FloatBuffer if store is null

@throws NullPointerException If isLoaded() or hasNormalmap() is false
jme3-terrain/src/main/java/com/jme3/terrain/GeoMap.java