180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright (c) 2009-2010 jMonkeyEngine
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * All rights reserved.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Redistribution and use in source and binary forms, with or without
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * modification, are permitted provided that the following conditions are
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * met:
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * * Redistributions of source code must retain the above copyright
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *   notice, this list of conditions and the following disclaimer.
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * * Redistributions in binary form must reproduce the above copyright
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger *   notice, this list of conditions and the following disclaimer in the
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *   documentation and/or other materials provided with the distribution.
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *   may be used to endorse or promote products derived from this software
18096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *   without specific prior written permission.
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
20e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupackage com.jme3.terrain;
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.export.*;
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.math.Vector2f;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.math.Vector3f;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.scene.Mesh;
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.scene.VertexBuffer.Type;
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport com.jme3.util.BufferUtils;
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport java.io.IOException;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport java.nio.BufferUnderflowException;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport java.nio.FloatBuffer;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport java.nio.IntBuffer;
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Constructs heightfields to be used in Terrain.
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic class GeoMap implements Savable {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    protected float[] hdata;
51d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    protected int width, height, maxval;
52d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
53d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    public GeoMap() {}
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    @Deprecated
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public GeoMap(FloatBuffer heightData, int width, int height, int maxval){
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        hdata = new float[heightData.limit()];
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        heightData.get(hdata);
59d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this.width = width;
60d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this.height = height;
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this.maxval = maxval;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public GeoMap(float[] heightData, int width, int height, int maxval){
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this.hdata = heightData;
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this.width = width;
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this.height = height;
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this.maxval = maxval;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    @Deprecated
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public FloatBuffer getHeightData(){
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!isLoaded())
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return null;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return BufferUtils.createFloatBuffer(hdata);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public float[] getHeightArray(){
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!isLoaded())
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return null;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return hdata;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
84e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    /**
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @return The maximum possible value that <code>getValue()</code> can
86096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * return. Mostly depends on the source data format (byte, short, int, etc).
87096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     */
88096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    public int getMaximumValue(){
89096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return maxval;
90096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
91096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
92096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    /**
93096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * Returns the height value for a given point.
94096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
95096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * MUST return the same value as getHeight(y*getWidth()+x)
96096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
97096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @param x the X coordinate
98096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @param y the Y coordinate
99096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @returns an arbitrary height looked up from the heightmap
100096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
101096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @throws NullPointerException If isLoaded() is false
102096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     */
103096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    public float getValue(int x, int y) {
104096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return hdata[y*width+x];
105096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
106096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
107096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    /**
108096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * Returns the height value at the given index.
109096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
110096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * zero index is top left of map,
111096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * getWidth()*getHeight() index is lower right
112096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
113096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @param i The index
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * @returns an arbitrary height looked up from the heightmap
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * @throws NullPointerException If isLoaded() is false
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public float getValue(int i) {
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return hdata[i];
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
123096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    /**
124096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * Returns the width of this Geomap
125096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
126096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     * @returns the width of this Geomap
127096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     */
128096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    public int getWidth() {
129096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return width;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Returns the height of this Geomap
134096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger     *
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @returns the height of this Geomap
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    public int getHeight() {
138096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return height;
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Returns true if the Geomap data is loaded in memory
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * If false, then the data is unavailable- must be loaded with load()
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * before the methods getHeight/getNormal can be used
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @returns wether the geomap data is loaded in system memory
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public boolean isLoaded() {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Creates a normal array from the normal data in this Geomap
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @param store A preallocated FloatBuffer where to store the data (optional), size must be >= getWidth()*getHeight()*3
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @returns store, or a new FloatBuffer if store is null
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @throws NullPointerException If isLoaded() or hasNormalmap() is false
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) {
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (store!=null){
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (store.remaining() < getWidth()*getHeight()*3)
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                throw new BufferUnderflowException();
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }else{
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*3);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        store.rewind();
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Vector3f oppositePoint = new Vector3f();
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Vector3f adjacentPoint = new Vector3f();
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Vector3f rootPoint = new Vector3f();
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Vector3f tempNorm = new Vector3f();
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int normalIndex = 0;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int y = 0; y < getHeight(); y++) {
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int x = 0; x < getWidth(); x++) {
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rootPoint.set(x, getValue(x,y), y);
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (y == getHeight() - 1) {
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (x == getWidth() - 1) {  // case #4 : last row, last col
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        // left cross up
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//                            adj = normalIndex - getWidth();
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//                            opp = normalIndex - 1;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        adjacentPoint.set(x, getValue(x,y-1), y-1);
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        oppositePoint.set(x-1, getValue(x-1, y), y);
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    } else {                    // case #3 : last row, except for last col
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        // right cross up
188096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger//                            adj = normalIndex + 1;
189096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger//                            opp = normalIndex - getWidth();
190096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                        adjacentPoint.set(x+1, getValue(x+1,y), y);
191096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                        oppositePoint.set(x, getValue(x,y-1), y-1);
192096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                    }
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (x == getWidth() - 1) {  // case #2 : last column except for last row
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        // left cross down
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        adjacentPoint.set(x-1, getValue(x-1,y), y);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        oppositePoint.set(x, getValue(x,y+1), y+1);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//                            adj = normalIndex - 1;
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//                            opp = normalIndex + getWidth();
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    } else {                    // case #1 : most cases
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        // right cross down
202363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        adjacentPoint.set(x, getValue(x,y+1), y+1);
203363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        oppositePoint.set(x+1, getValue(x+1,y), y);
204363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//                            adj = normalIndex + getWidth();
205363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//                            opp = normalIndex + 1;
206363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    }
207363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                }
208363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
209e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
210e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
211e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                tempNorm.set(adjacentPoint).subtractLocal(rootPoint)
212e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                        .crossLocal(oppositePoint.subtractLocal(rootPoint));
213e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                tempNorm.multLocal(scale).normalizeLocal();
214e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger//                    store.put(tempNorm.x).put(tempNorm.y).put(tempNorm.z);
215e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                BufferUtils.setInBuffer(tempNorm, store,
216e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                        normalIndex);
217e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                normalIndex++;
218e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            }
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
220d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
221d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return store;
222d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
225d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * Creates a vertex array from the height data in this Geomap
226d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *
227d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * The scale argument specifies the scale to use for the vertex buffer.
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * For example, if scale is 10,1,10, then the greatest X value is getWidth()*10
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *
230d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * @param store A preallocated FloatBuffer where to store the data (optional), size must be >= getWidth()*getHeight()*3
231d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * @param scale Created vertexes are scaled by this vector
232d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *
233d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * @returns store, or a new FloatBuffer if store is null
234d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *
235d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * @throws NullPointerException If isLoaded() is false
236d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     */
237d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    public FloatBuffer writeVertexArray(FloatBuffer store, Vector3f scale, boolean center) {
238363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
239096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (store!=null){
240096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (store.remaining() < width*height*3)
241096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                throw new BufferUnderflowException();
242096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }else{
243096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            store = BufferUtils.createFloatBuffer(width*height*3);
244096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
245096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
246096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        assert hdata.length == height*width;
247096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
248096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        Vector3f offset = new Vector3f(-getWidth() * scale.x * 0.5f,
249096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                       0,
250096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                       -getWidth() * scale.z * 0.5f);
251096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (!center)
252d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            offset.zero();
253d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int i = 0;
255096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        for (int z = 0; z < height; z++){
256096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            for (int x = 0; x < width; x++){
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                store.put( (float)x*scale.x + offset.x );
258096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                store.put( (float)hdata[i++]*scale.y );
259096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                store.put( (float)z*scale.z + offset.z );
260096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return store;
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public Vector2f getUV(int x, int y, Vector2f store){
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        store.set( (float)x / (float)getWidth(),
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   (float)y / (float)getHeight() );
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return store;
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public Vector2f getUV(int i, Vector2f store){
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return store;
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale){
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (store!=null){
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (store.remaining() < getWidth()*getHeight()*2)
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                throw new BufferUnderflowException();
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }else{
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*2);
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (offset == null)
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            offset = new Vector2f();
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
287096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        Vector2f tcStore = new Vector2f();
288363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int y = 0; y < getHeight(); y++){
289363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            for (int x = 0; x < getWidth(); x++){
290363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                getUV(x,y,tcStore);
291363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                store.put( offset.x + tcStore.x * scale.x );
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                store.put( offset.y + tcStore.y * scale.y );
293096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
295096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
297363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return store;
298363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
300096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    public IntBuffer writeIndexArray(IntBuffer store){
301096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        int faceN = (getWidth()-1)*(getHeight()-1)*2;
302363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
303e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (store!=null){
304e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            if (store.remaining() < faceN*3)
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                throw new BufferUnderflowException();
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }else{
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            store = BufferUtils.createIntBuffer(faceN*3);
308        }
309
310        int i = 0;
311        for (int z = 0; z < getHeight()-1; z++){
312            for (int x = 0; x < getWidth()-1; x++){
313                store.put(i).put(i+getWidth()).put(i+getWidth()+1);
314                store.put(i+getWidth()+1).put(i+1).put(i);
315                i++;
316
317                // TODO: There's probably a better way to do this..
318                if (x==getWidth()-2) i++;
319            }
320        }
321        store.flip();
322
323        return store;
324    }
325
326    public Mesh createMesh(Vector3f scale, Vector2f tcScale, boolean center){
327        FloatBuffer pb = writeVertexArray(null, scale, center);
328        FloatBuffer tb = writeTexCoordArray(null, Vector2f.ZERO, tcScale);
329        FloatBuffer nb = writeNormalArray(null, scale);
330        IntBuffer ib = writeIndexArray(null);
331        Mesh m = new Mesh();
332        m.setBuffer(Type.Position, 3, pb);
333        m.setBuffer(Type.Normal, 3, nb);
334        m.setBuffer(Type.TexCoord, 2, tb);
335        m.setBuffer(Type.Index, 3, ib);
336        m.setStatic();
337        m.updateBound();
338        return m;
339    }
340
341    public void write(JmeExporter ex) throws IOException {
342        OutputCapsule oc = ex.getCapsule(this);
343        oc.write(hdata, "hdataarray", null);
344        oc.write(width, "width", 0);
345        oc.write(height, "height", 0);
346        oc.write(maxval, "maxval", 0);
347    }
348
349    public void read(JmeImporter im) throws IOException {
350        InputCapsule ic = im.getCapsule(this);
351        hdata = ic.readFloatArray("hdataarray", null);
352        if (hdata == null) {
353            FloatBuffer buf = ic.readFloatBuffer("hdata", null);
354            if (buf != null) {
355                hdata = new float[buf.limit()];
356                buf.get(hdata);
357            }
358        }
359        width = ic.readInt("width", 0);
360        height = ic.readInt("height", 0);
361        maxval = ic.readInt("maxval", 0);
362    }
363
364
365}
366