diff --git a/engine/src/core/com/jme3/scene/CameraNode.java b/engine/src/core/com/jme3/scene/CameraNode.java index c78f6c35c..c6bb48b94 100644 --- a/engine/src/core/com/jme3/scene/CameraNode.java +++ b/engine/src/core/com/jme3/scene/CameraNode.java @@ -36,7 +36,8 @@ import com.jme3.scene.control.CameraControl; import com.jme3.scene.control.CameraControl.ControlDirection; /** - * This Node is a shorthand for using a CameraControl. + * CameraNode simply uses {@link CameraControl} to implement + * linking of camera and node data. * * @author Tim8Dev */ @@ -45,7 +46,7 @@ public class CameraNode extends Node { private CameraControl camControl; /** - * for IO purpose + * Serialization only. Do not use. */ public CameraNode() { } diff --git a/engine/src/core/com/jme3/scene/control/package.html b/engine/src/core/com/jme3/scene/control/package.html new file mode 100644 index 000000000..a387840d8 --- /dev/null +++ b/engine/src/core/com/jme3/scene/control/package.html @@ -0,0 +1,17 @@ + + + + + + + + + +The com.jme3.control package provides +{@link com.jme3.scene.control.Control controls}. +Controls represent the "logical" programming of scene graph elements, containing +callbacks for when a {@link com.jme3.scene.Spatial} is rendered or updated +by the engine. + + + diff --git a/engine/src/core/com/jme3/scene/debug/Arrow.java b/engine/src/core/com/jme3/scene/debug/Arrow.java index fcd76fcac..0b26839a6 100644 --- a/engine/src/core/com/jme3/scene/debug/Arrow.java +++ b/engine/src/core/com/jme3/scene/debug/Arrow.java @@ -37,9 +37,17 @@ import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer.Type; import java.nio.FloatBuffer; +/** + * The Arrow debug shape represents an arrow. + * An arrow is simply a line going from the original toward an extent + * and at the tip there will be triangle-like shape. + * + * @author Kirill Vainer + */ public class Arrow extends Mesh { - Quaternion tempQuat = new Quaternion(); - Vector3f tempVec = new Vector3f(); + + private Quaternion tempQuat = new Quaternion(); + private Vector3f tempVec = new Vector3f(); private static final float[] positions = new float[]{ 0, 0, 0, @@ -50,15 +58,25 @@ public class Arrow extends Mesh { 0, -0.05f, 0.9f, // tip buttom }; + /** + * Serialization only. Do not use. + */ public Arrow() { } + /** + * Creates an arrow mesh with the given extent. + * The arrow will start at the origin (0,0,0) and finish + * at the given extent. + * + * @param extent Extent of the arrow from origin + */ public Arrow(Vector3f extent) { float len = extent.length(); Vector3f dir = extent.normalize(); tempQuat.lookAt(dir, Vector3f.UNIT_Y); - tempQuat.normalize(); + tempQuat.normalizeLocal(); float[] newPositions = new float[positions.length]; for (int i = 0; i < positions.length; i += 3) { @@ -87,12 +105,18 @@ public class Arrow extends Mesh { updateCounts(); } + /** + * Sets the arrow's extent. + * This will modify the buffers on the mesh. + * + * @param extent the arrow's extent. + */ public void setArrowExtent(Vector3f extent) { float len = extent.length(); // Vector3f dir = extent.normalize(); tempQuat.lookAt(extent, Vector3f.UNIT_Y); - tempQuat.normalize(); + tempQuat.normalizeLocal(); FloatBuffer buffer = getFloatBuffer(Type.Position); buffer.rewind(); diff --git a/engine/src/core/com/jme3/scene/debug/Grid.java b/engine/src/core/com/jme3/scene/debug/Grid.java index 3cf2181e0..ea6225c04 100644 --- a/engine/src/core/com/jme3/scene/debug/Grid.java +++ b/engine/src/core/com/jme3/scene/debug/Grid.java @@ -39,8 +39,19 @@ import com.jme3.util.BufferUtils; import java.nio.FloatBuffer; import java.nio.ShortBuffer; +/** + * Simple grid shape. + * + * @author Kirill Vainer + */ public class Grid extends Mesh { + /** + * Creates a grid debug shape. + * @param xLines + * @param yLines + * @param lineDist + */ public Grid(int xLines, int yLines, float lineDist){ xLines -= 2; yLines -= 2; @@ -90,4 +101,5 @@ public class Grid extends Mesh { updateBound(); updateCounts(); } + } diff --git a/engine/src/core/com/jme3/scene/mesh/IndexBuffer.java b/engine/src/core/com/jme3/scene/mesh/IndexBuffer.java index 8bc7c21b7..08e92390d 100644 --- a/engine/src/core/com/jme3/scene/mesh/IndexBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/IndexBuffer.java @@ -42,8 +42,35 @@ import java.nio.Buffer; * @author lex */ public abstract class IndexBuffer { + /** + * Returns the vertex index for the given index in the index buffer. + * + * @param i The index inside the index buffer + * @return + */ public abstract int get(int i); + + /** + * Puts the vertex index at the index buffer's index. + * Implementations may throw an {@link UnsupportedOperationException} + * if modifying the IndexBuffer is not supported (e.g. virtual index + * buffers). + */ public abstract void put(int i, int value); + + /** + * Returns the size of the index buffer. + * + * @return the size of the index buffer. + */ public abstract int size(); + + /** + * Returns the underlying data-type specific {@link Buffer}. + * Implementations may return null if there's no underlying + * buffer. + * + * @return the underlying {@link Buffer}. + */ public abstract Buffer getBuffer(); } diff --git a/engine/src/core/com/jme3/scene/mesh/IndexByteBuffer.java b/engine/src/core/com/jme3/scene/mesh/IndexByteBuffer.java index 649c6bdcd..fd3bec410 100644 --- a/engine/src/core/com/jme3/scene/mesh/IndexByteBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/IndexByteBuffer.java @@ -36,7 +36,8 @@ import java.nio.Buffer; import java.nio.ByteBuffer; /** - * + * IndexBuffer implementation for {@link ByteBuffer}s. + * * @author lex */ public class IndexByteBuffer extends IndexBuffer { diff --git a/engine/src/core/com/jme3/scene/mesh/IndexIntBuffer.java b/engine/src/core/com/jme3/scene/mesh/IndexIntBuffer.java index e062cfd0a..336930191 100644 --- a/engine/src/core/com/jme3/scene/mesh/IndexIntBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/IndexIntBuffer.java @@ -36,7 +36,8 @@ import java.nio.Buffer; import java.nio.IntBuffer; /** - * + * IndexBuffer implementation for {@link IntBuffer}s. + * * @author lex */ public class IndexIntBuffer extends IndexBuffer { diff --git a/engine/src/core/com/jme3/scene/mesh/IndexShortBuffer.java b/engine/src/core/com/jme3/scene/mesh/IndexShortBuffer.java index 8abccb752..5017e6fb4 100644 --- a/engine/src/core/com/jme3/scene/mesh/IndexShortBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/IndexShortBuffer.java @@ -36,7 +36,8 @@ import java.nio.Buffer; import java.nio.ShortBuffer; /** - * + * IndexBuffer implementation for {@link ShortBuffer}s. + * * @author lex */ public class IndexShortBuffer extends IndexBuffer { diff --git a/engine/src/core/com/jme3/scene/mesh/VirtualIndexBuffer.java b/engine/src/core/com/jme3/scene/mesh/VirtualIndexBuffer.java index 463e7adce..c1499cc87 100644 --- a/engine/src/core/com/jme3/scene/mesh/VirtualIndexBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/VirtualIndexBuffer.java @@ -3,12 +3,28 @@ package com.jme3.scene.mesh; import com.jme3.scene.Mesh.Mode; import java.nio.Buffer; +/** + * IndexBuffer implementation that generates vertex indices sequentially + * based on a specific Mesh {@link Mode}. + * The generated indices are as if the mesh is in the given mode + * but contains no index buffer, thus this implementation will + * return the indices if the index buffer was there and contained sequential + * triangles. + * Example: + * + * + * @author Kirill Vainer + */ public class VirtualIndexBuffer extends IndexBuffer { protected int numVerts = 0; protected int numIndices = 0; protected Mode meshMode; - + public VirtualIndexBuffer(int numVerts, Mode meshMode){ this.numVerts = numVerts; this.meshMode = meshMode; diff --git a/engine/src/core/com/jme3/scene/mesh/WrappedIndexBuffer.java b/engine/src/core/com/jme3/scene/mesh/WrappedIndexBuffer.java index e4c059cfe..38e833dae 100644 --- a/engine/src/core/com/jme3/scene/mesh/WrappedIndexBuffer.java +++ b/engine/src/core/com/jme3/scene/mesh/WrappedIndexBuffer.java @@ -9,9 +9,12 @@ import java.nio.IntBuffer; import java.nio.ShortBuffer; /** - * WrappedIndexBuffer converts from one representation of mesh - * data to another. For example it can be used to read TriangleStrip data - * as if it was in Triangle format. + * WrappedIndexBuffer converts vertex indices from a non list based + * mesh mode such as {@link Mode#TriangleStrip} or {@link Mode#LineLoop} + * into a list based mode such as {@link Mode#Triangles} or {@link Mode#Lines}. + * As it is often more convenient to read vertex data in list format + * than in a non-list format, using this class is recommended to avoid + * convoluting classes used to process mesh data from an external source. * * @author Kirill Vainer */ diff --git a/engine/src/core/com/jme3/scene/mesh/package.html b/engine/src/core/com/jme3/scene/mesh/package.html new file mode 100644 index 000000000..5362c52fb --- /dev/null +++ b/engine/src/core/com/jme3/scene/mesh/package.html @@ -0,0 +1,25 @@ + + + + + + + + + +The com.jme3.scene.mesh package contains utilities +for reading from {@link com.jme3.scene.mesh.IndexBuffer index buffers}. +Several implementations are provided of the {@link com.jme3.scene.mesh.IndexBuffer} +class: + + + + diff --git a/engine/src/core/com/jme3/scene/package.html b/engine/src/core/com/jme3/scene/package.html new file mode 100644 index 000000000..53f810567 --- /dev/null +++ b/engine/src/core/com/jme3/scene/package.html @@ -0,0 +1,26 @@ + + + + + + + + + +The com.jme3.input package contains the scene graph implementation +in jMonkeyEngine. + +

+ The scene graph is the most important package in jME, as it is the API + used to manage scene elements so that they can be rendered. + The {@link com.jme3.scene.Spatial} class provides a common base class + for all scene graph elements. The {@link com.jme3.scene.Node} class provides + the "branches" in the graph, used to organize elements in a tree + hierarchy. The {@link com.jme3.scene.Geometry} is the leaf class that + will contain a {@link com.jme3.scene.Mesh} object (geometry data + such as vertex positions, normals, etc) and a {@link com.jme3.scene.Material} + object containing information on how the geometry should be shaded. +

+ + + diff --git a/engine/src/core/com/jme3/scene/shape/AbstractBox.java b/engine/src/core/com/jme3/scene/shape/AbstractBox.java index bd1e4baf7..ef2334953 100644 --- a/engine/src/core/com/jme3/scene/shape/AbstractBox.java +++ b/engine/src/core/com/jme3/scene/shape/AbstractBox.java @@ -48,7 +48,7 @@ import java.io.IOException; * a way as to generate an axis-aligned box. *

* This class does not control how the geometry data is generated, see {@link Box} - * and {@link StripBox} for that. + * for that. * * @author Ian Phillips * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $ @@ -87,7 +87,7 @@ public abstract class AbstractBox extends Mesh { } /** - * Convert the indices into the list of vertices that define the box's tri-mesh. + * Convert the indices into the list of vertices that define the box's geometry. */ protected abstract void duUpdateGeometryIndices(); @@ -111,22 +111,30 @@ public abstract class AbstractBox extends Mesh { */ protected abstract void duUpdateGeometryVertices(); - /** Get the centre point of this box. */ + /** + * Get the center point of this box. + */ public final Vector3f getCenter() { return center; } - /** Get the x-axis size (extent) of this box. */ + /** + * Get the x-axis size (extent) of this box. + */ public final float getXExtent() { return xExtent; } - /** Get the y-axis size (extent) of this box. */ + /** + * Get the y-axis size (extent) of this box. + */ public final float getYExtent() { return yExtent; } - /** Get the z-axis size (extent) of this box. */ + /** + * Get the z-axis size (extent) of this box. + */ public final float getZExtent() { return zExtent; } @@ -180,6 +188,7 @@ public abstract class AbstractBox extends Mesh { updateGeometry(center, x, y, z); } + @Override public void read(JmeImporter e) throws IOException { super.read(e); InputCapsule capsule = e.getCapsule(this); @@ -189,6 +198,7 @@ public abstract class AbstractBox extends Mesh { center.set((Vector3f) capsule.readSavable("center", Vector3f.ZERO.clone())); } + @Override public void write(JmeExporter e) throws IOException { super.write(e); OutputCapsule capsule = e.getCapsule(this); diff --git a/engine/src/core/com/jme3/scene/shape/Curve.java b/engine/src/core/com/jme3/scene/shape/Curve.java index db032fb32..fbeda5955 100644 --- a/engine/src/core/com/jme3/scene/shape/Curve.java +++ b/engine/src/core/com/jme3/scene/shape/Curve.java @@ -39,7 +39,11 @@ import java.util.Iterator; import java.util.List; /** - * + * A Curve is a visual, line-based representation of a {@link Spline}. + * The underlying Spline will be sampled N times where N is the number of + * segments as specified in the constructor. Each segment will represent + * one line in the generated mesh. + * * @author Nehon */ public class Curve extends Mesh { @@ -48,8 +52,15 @@ public class Curve extends Mesh { private Vector3f temp = new Vector3f(); /** - * Create a curve mesh + * Serialization only. Do not use. + */ + public Curve(){ + } + + /** + * Create a curve mesh. * Use a CatmullRom spline model that does not cycle. + * * @param controlPoints the control points to use to create this curve * @param nbSubSegments the number of subsegments between the control points */ @@ -59,6 +70,7 @@ public class Curve extends Mesh { /** * Create a curve mesh from a Spline + * * @param spline the spline to use * @param nbSubSegments the number of subsegments between the control points */ diff --git a/engine/src/core/com/jme3/scene/shape/Dome.java b/engine/src/core/com/jme3/scene/shape/Dome.java index 0e9a3dafa..96bc9aac0 100644 --- a/engine/src/core/com/jme3/scene/shape/Dome.java +++ b/engine/src/core/com/jme3/scene/shape/Dome.java @@ -70,7 +70,7 @@ public class Dome extends Mesh { private boolean outsideView = true; /** - * Constructs a dome. By default the dome has not geometry data or center. + * Serialization only. Do not use. */ public Dome() { } @@ -140,25 +140,29 @@ public class Dome extends Mesh { return center; } - /** Get the number of planar segments along the z-axis of the dome. */ + /** + * Get the number of planar segments along the z-axis of the dome. + */ public int getPlanes() { return planes; } - /** Get the number of samples radially around the main axis of the dome. */ + /** + * Get the number of samples radially around the main axis of the dome. + */ public int getRadialSamples() { return radialSamples; } - /** Get the radius of the dome. */ + /** + * Get the radius of the dome. + */ public float getRadius() { return radius; } /** - * Are the triangles connected in such a way as to present aview out from the dome or not. - * - * @return + * Are the triangles connected in such a way as to present a view out from the dome or not. */ public boolean isOutsideView() { return outsideView; @@ -298,6 +302,7 @@ public class Dome extends Mesh { updateBound(); } + @Override public void read(JmeImporter e) throws IOException { super.read(e); InputCapsule capsule = e.getCapsule(this); @@ -307,9 +312,7 @@ public class Dome extends Mesh { center = (Vector3f) capsule.readSavable("center", Vector3f.ZERO.clone()); } - /** - * Generates the connections - */ + @Override public void write(JmeExporter e) throws IOException { super.write(e); OutputCapsule capsule = e.getCapsule(this); diff --git a/engine/src/core/com/jme3/scene/shape/Line.java b/engine/src/core/com/jme3/scene/shape/Line.java index 55f54bc21..1edbba70b 100644 --- a/engine/src/core/com/jme3/scene/shape/Line.java +++ b/engine/src/core/com/jme3/scene/shape/Line.java @@ -40,7 +40,6 @@ import com.jme3.math.Vector3f; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Type; -import com.jme3.util.BufferUtils; import java.io.IOException; import java.nio.FloatBuffer; diff --git a/engine/src/core/com/jme3/scene/shape/PQTorus.java b/engine/src/core/com/jme3/scene/shape/PQTorus.java index 20fd343e3..123009829 100644 --- a/engine/src/core/com/jme3/scene/shape/PQTorus.java +++ b/engine/src/core/com/jme3/scene/shape/PQTorus.java @@ -45,7 +45,6 @@ import static com.jme3.util.BufferUtils.*; import java.io.IOException; import java.nio.FloatBuffer; -import java.nio.IntBuffer; import java.nio.ShortBuffer; /** diff --git a/engine/src/core/com/jme3/scene/shape/Quad.java b/engine/src/core/com/jme3/scene/shape/Quad.java index a9464fc4c..194535851 100644 --- a/engine/src/core/com/jme3/scene/shape/Quad.java +++ b/engine/src/core/com/jme3/scene/shape/Quad.java @@ -32,24 +32,48 @@ package com.jme3.scene.shape; -import com.jme3.scene.*; +import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer.Type; +/** + * Quad represents a rectangular plane in space + * defined by 4 vertices. The quad's lower-left side is contained + * at the local space origin (0, 0, 0), while the upper-right + * side is located at the width/height coordinates (width, height, 0). + * + * @author Kirill Vainer + */ public class Quad extends Mesh { private float width; private float height; /** - * Do not use this constructor. Serialization purposes only. + * Serialization only. Do not use. */ public Quad(){ } + /** + * Create a quad with the given width and height. The quad + * is always created in the XY plane. + * + * @param width The X extent or width + * @param height The Y extent or width + */ public Quad(float width, float height){ updateGeometry(width, height); } + /** + * Create a quad with the given width and height. The quad + * is always created in the XY plane. + * + * @param width The X extent or width + * @param height The Y extent or width + * @param flipCoords If true, the texture coordinates will be flipped + * along the Y axis. + */ public Quad(float width, float height, boolean flipCoords){ updateGeometry(width, height, flipCoords); } diff --git a/engine/src/core/com/jme3/scene/shape/Sphere.java b/engine/src/core/com/jme3/scene/shape/Sphere.java index 1e2034732..8f0ace85a 100644 --- a/engine/src/core/com/jme3/scene/shape/Sphere.java +++ b/engine/src/core/com/jme3/scene/shape/Sphere.java @@ -58,11 +58,16 @@ import java.nio.ShortBuffer; public class Sphere extends Mesh { public enum TextureMode { - /** Wrap texture radially and along z-axis */ + /** + * Wrap texture radially and along z-axis + */ Original, - /** Wrap texure radially, but spherically project along z-axis */ + /** + * Wrap texure radially, but spherically project along z-axis + */ Projected, - /** Apply texture to each pole. Eliminates polar distortion, + /** + * Apply texture to each pole. Eliminates polar distortion, * but mirrors the texture across the equator */ Polar @@ -86,7 +91,7 @@ public class Sphere extends Mesh { protected TextureMode textureMode = TextureMode.Original; /** - * Empty constructor for serialization only, do not use. + * Serialization only. Do not use. */ public Sphere(){ } diff --git a/engine/src/terrain/com/jme3/terrain/MapUtils.java b/engine/src/terrain/com/jme3/terrain/MapUtils.java index 192ebf979..676f83d05 100644 --- a/engine/src/terrain/com/jme3/terrain/MapUtils.java +++ b/engine/src/terrain/com/jme3/terrain/MapUtils.java @@ -4,6 +4,7 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.FloatBuffer; +import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; @@ -12,51 +13,51 @@ import org.novyon.noise.ShaderUtils; public class MapUtils { - public static FloatBuffer clip(FloatBuffer src, int origSize, int newSize, int offset) { - FloatBuffer result = FloatBuffer.allocate(newSize * newSize); - - float[] orig = src.array(); - for (int i = offset; i < offset + newSize; i++) { - result.put(orig, i * origSize + offset, newSize); - } - - return result; - } - - public static BufferedImage toGrayscale16Image(FloatBuffer buff, int size) { - BufferedImage retval = new BufferedImage(size, size, BufferedImage.TYPE_USHORT_GRAY); - buff.rewind(); - for (int y = 0; y < size; y++) { - for (int x = 0; x < size; x++) { - short c = (short) (ShaderUtils.clamp(buff.get(), 0, 1) * 65532); - retval.getRaster().setDataElements(x, y, new short[] { c }); - } - } - return retval; - } - - public static BufferedImage toGrayscaleRGBImage(FloatBuffer buff, int size) { - BufferedImage retval = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - buff.rewind(); - for (int y = 0; y < size; y++) { - for (int x = 0; x < size; x++) { - int c = (int) (ShaderUtils.clamp(buff.get(), 0, 1) * 255); - retval.setRGB(x, y, 0xFF000000 | c << 16 | c << 8 | c); - } - } - return retval; - } - - public static void saveImage(BufferedImage im, String file) { - MapUtils.saveImage(im, new File(file)); - } - - public static void saveImage(BufferedImage im, File file) { - try { - ImageIO.write(im, "PNG", file); - Logger.getLogger(MapUtils.class.getCanonicalName()).info("Saved image as : " + file.getAbsolutePath()); - } catch (IOException e) { - e.printStackTrace(); - } - } + public static FloatBuffer clip(FloatBuffer src, int origSize, int newSize, int offset) { + FloatBuffer result = FloatBuffer.allocate(newSize * newSize); + + float[] orig = src.array(); + for (int i = offset; i < offset + newSize; i++) { + result.put(orig, i * origSize + offset, newSize); + } + + return result; + } + + public static BufferedImage toGrayscale16Image(FloatBuffer buff, int size) { + BufferedImage retval = new BufferedImage(size, size, BufferedImage.TYPE_USHORT_GRAY); + buff.rewind(); + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + short c = (short) (ShaderUtils.clamp(buff.get(), 0, 1) * 65532); + retval.getRaster().setDataElements(x, y, new short[]{c}); + } + } + return retval; + } + + public static BufferedImage toGrayscaleRGBImage(FloatBuffer buff, int size) { + BufferedImage retval = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + buff.rewind(); + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + int c = (int) (ShaderUtils.clamp(buff.get(), 0, 1) * 255); + retval.setRGB(x, y, 0xFF000000 | c << 16 | c << 8 | c); + } + } + return retval; + } + + public static void saveImage(BufferedImage im, String file) { + MapUtils.saveImage(im, new File(file)); + } + + public static void saveImage(BufferedImage im, File file) { + try { + ImageIO.write(im, "PNG", file); + Logger.getLogger(MapUtils.class.getCanonicalName()).log(Level.INFO, "Saved image as : {0}", file.getAbsolutePath()); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/engine/src/terrain/com/jme3/terrain/ProgressMonitor.java b/engine/src/terrain/com/jme3/terrain/ProgressMonitor.java index 43481a2f1..466423152 100644 --- a/engine/src/terrain/com/jme3/terrain/ProgressMonitor.java +++ b/engine/src/terrain/com/jme3/terrain/ProgressMonitor.java @@ -29,7 +29,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package com.jme3.terrain; /** diff --git a/engine/src/terrain/com/jme3/terrain/Terrain.java b/engine/src/terrain/com/jme3/terrain/Terrain.java index 72b783aaa..85dd32e45 100644 --- a/engine/src/terrain/com/jme3/terrain/Terrain.java +++ b/engine/src/terrain/com/jme3/terrain/Terrain.java @@ -29,7 +29,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package com.jme3.terrain; import com.jme3.material.Material; @@ -64,7 +63,7 @@ public interface Terrain { * @return the height, unscaled and uninterpolated */ public float getHeightmapHeight(Vector2f xz); - + /** * Set the height at the specified X-Z coordinate. * To set the height of the terrain and see it, you will have @@ -129,7 +128,7 @@ public interface Terrain { * and the less detailed it will be. */ public int getMaxLod(); - + /** * Called in the update (pre or post, up to you) method of your game. * Calculates the level of detail of the terrain and adjusts its geometry. @@ -139,7 +138,7 @@ public interface Terrain { * @param location often the Camera's location */ public void update(List location); - + /** * Get the spatial instance of this Terrain. Right now just used in the * terrain editor in JMP. @@ -162,7 +161,6 @@ public interface Terrain { */ public void generateEntropy(ProgressMonitor monitor); - /** * Returns the material that this terrain uses. * This does not necessarily have to guarantee the material @@ -195,5 +193,4 @@ public interface Terrain { * texture scales. */ public float getTextureCoordinateScale(); - } diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java b/engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java index 0d67c7a13..f4bd569bd 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/LODGeomap.java @@ -29,7 +29,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package com.jme3.terrain.geomipmap; import com.jme3.export.InputCapsule; @@ -67,341 +66,347 @@ import java.io.IOException; */ public class LODGeomap extends BufferGeomap { - public LODGeomap() {} + public LODGeomap() { + } public LODGeomap(int size, FloatBuffer heightMap) { - super(heightMap, null, size, size, 1); - } - - public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center) { - return this.createMesh(scale, tcScale, tcOffset, offsetAmount, totalSize, center, 1, false,false,false,false); - } - - public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod){ - FloatBuffer pb = writeVertexArray(null, scale, center); - FloatBuffer tb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize); - FloatBuffer nb = writeNormalArray(null, scale); - IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod); - Mesh m = new Mesh(); - m.setMode(Mode.TriangleStrip); - m.setBuffer(Type.Position, 3, pb); - m.setBuffer(Type.Normal, 3, nb); - m.setBuffer(Type.TexCoord, 2, tb); - m.setBuffer(Type.Index, 3, ib); - m.setStatic(); - m.updateBound(); - return m; - } + super(heightMap, null, size, size, 1); + } + public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center) { + return this.createMesh(scale, tcScale, tcOffset, offsetAmount, totalSize, center, 1, false, false, false, false); + } + + public Mesh createMesh(Vector3f scale, Vector2f tcScale, Vector2f tcOffset, float offsetAmount, int totalSize, boolean center, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) { + FloatBuffer pb = writeVertexArray(null, scale, center); + FloatBuffer tb = writeTexCoordArray(null, tcOffset, tcScale, offsetAmount, totalSize); + FloatBuffer nb = writeNormalArray(null, scale); + IntBuffer ib = writeIndexArrayLodDiff(null, lod, rightLod, topLod, leftLod, bottomLod); + Mesh m = new Mesh(); + m.setMode(Mode.TriangleStrip); + m.setBuffer(Type.Position, 3, pb); + m.setBuffer(Type.Normal, 3, nb); + m.setBuffer(Type.TexCoord, 2, tb); + m.setBuffer(Type.Index, 3, ib); + m.setStatic(); + m.updateBound(); + return m; + } protected void removeNormalBuffer() { ndata = null; } - public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize){ - if (store!=null){ - if (store.remaining() < getWidth()*getHeight()*2) - throw new BufferUnderflowException(); - }else{ - store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*2); - } + public FloatBuffer writeTexCoordArray(FloatBuffer store, Vector2f offset, Vector2f scale, float offsetAmount, int totalSize) { + if (store != null) { + if (store.remaining() < getWidth() * getHeight() * 2) { + throw new BufferUnderflowException(); + } + } else { + store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 2); + } - if (offset == null) - offset = new Vector2f(); + if (offset == null) { + offset = new Vector2f(); + } - Vector2f tcStore = new Vector2f(); + Vector2f tcStore = new Vector2f(); - for (int y = 0; y < getHeight(); y++){ + for (int y = 0; y < getHeight(); y++) { - for (int x = 0; x < getWidth(); x++){ - getUV(x,y,tcStore, offset, offsetAmount, totalSize); - float tx = tcStore.x * scale.x; - float ty = tcStore.y * scale.y; - store.put( tx ); - store.put( ty ); - } - } + for (int x = 0; x < getWidth(); x++) { + getUV(x, y, tcStore, offset, offsetAmount, totalSize); + float tx = tcStore.x * scale.x; + float ty = tcStore.y * scale.y; + store.put(tx); + store.put(ty); + } + } - return store; - } + return store; + } - public Vector2f getUV(int x, int y, Vector2f store, Vector2f offset, float offsetAmount, int totalSize){ - float offsetX = offset.x + (offsetAmount * 1.0f);//stepScale.x); + public Vector2f getUV(int x, int y, Vector2f store, Vector2f offset, float offsetAmount, int totalSize) { + float offsetX = offset.x + (offsetAmount * 1.0f);//stepScale.x); float offsetY = offset.y + (offsetAmount * 1.0f);//stepScale.z); - store.set( ( ((float)x)+offsetX) / (float)totalSize, // calculates percentage of texture here - ( ((float)y)+offsetY) / (float)totalSize ); + store.set((((float) x) + offsetX) / (float) totalSize, // calculates percentage of texture here + (((float) y) + offsetY) / (float) totalSize); return store; } - /** - * Create the LOD index array that will seam its edges with its neighbour's LOD. - * This is a scary method!!! It will break your mind. - * - * @param store to store the index buffer - * @param lod level of detail of the mesh - * @param rightLod LOD of the right neighbour - * @param topLod LOD of the top neighbour - * @param leftLod LOD of the left neighbour - * @param bottomLod LOD of the bottom neighbour - * @return the LOD-ified index buffer - */ - public IntBuffer writeIndexArrayLodDiff(IntBuffer store, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod){ - - IntBuffer buffer2 = store; - int numIndexes = calculateNumIndexesLodDiff(lod); - if (store == null) - buffer2 = BufferUtils.createIntBuffer(numIndexes); - VerboseIntBuffer buffer = new VerboseIntBuffer(buffer2); - - - // generate center squares minus the edges - //System.out.println("for (x="+lod+"; x<"+(getWidth()-(2*lod))+"; x+="+lod+")"); - //System.out.println(" for (z="+lod+"; z<"+(getWidth()-(1*lod))+"; z+="+lod+")"); - for (int r=lod; r=1+lod; row-=2*lod) { - int idx = (row)*getWidth()-1-lod; - buffer.put(idx); - idx = (row-lod)*getWidth()-1; - buffer.put(idx); - if (row > lod+1) { //if not the last one - idx = (row-lod)*getWidth()-1-lod; - buffer.put(idx); - idx = (row-lod)*getWidth()-1; - buffer.put(idx); - } else { - - } - } - } else { - buffer.put(corner);//br+1);//degenerate to flip winding order - for (int row=getWidth()-lod; row>lod; row-=lod) { - int idx = row*getWidth()-1; // mult to get row - buffer.put(idx); - buffer.put(idx-lod); - } - - } - - buffer.put(getWidth()-1); - - - //System.out.println("\nbuffer right: "+(buffer.getCount()-runningBufferCount)); - //runningBufferCount = buffer.getCount(); - - - //System.out.println("\ntop:"); - - // top (the order gets reversed here so the diagonals line up) - if (topLod) { // if lower LOD - if (rightLod) - buffer.put(getWidth()-1); - for (int col=getWidth()-1; col>=lod; col-=2*lod) { - int idx = (lod*getWidth())+col-lod; // next row - buffer.put(idx); - idx = col-2*lod; - buffer.put(idx); - if (col > lod*2) { //if not the last one - idx = (lod*getWidth())+col-2*lod; - buffer.put(idx); - idx = col-2*lod; - buffer.put(idx); - } else { - - } - } - } else { - if (rightLod) - buffer.put(getWidth()-1); - for (int col=getWidth()-1-lod; col>0; col-=lod) { - int idx = col + (lod*getWidth()); - buffer.put(idx); - idx = col; - buffer.put(idx); - } - buffer.put(0); - } - buffer.put(0); - - //System.out.println("\nbuffer top: "+(buffer.getCount()-runningBufferCount)); - //runningBufferCount = buffer.getCount(); - - //System.out.println("\nleft:"); - - // left - if (leftLod) { // if lower LOD - if (topLod) - buffer.put(0); - for (int row=0; rowlod) { // if lower LOD + /** + * Create the LOD index array that will seam its edges with its neighbour's LOD. + * This is a scary method!!! It will break your mind. + * + * @param store to store the index buffer + * @param lod level of detail of the mesh + * @param rightLod LOD of the right neighbour + * @param topLod LOD of the top neighbour + * @param leftLod LOD of the left neighbour + * @param bottomLod LOD of the bottom neighbour + * @return the LOD-ified index buffer + */ + public IntBuffer writeIndexArrayLodDiff(IntBuffer store, int lod, boolean rightLod, boolean topLod, boolean leftLod, boolean bottomLod) { + + IntBuffer buffer2 = store; + int numIndexes = calculateNumIndexesLodDiff(lod); + if (store == null) { + buffer2 = BufferUtils.createIntBuffer(numIndexes); + } + VerboseIntBuffer buffer = new VerboseIntBuffer(buffer2); + + + // generate center squares minus the edges + //System.out.println("for (x="+lod+"; x<"+(getWidth()-(2*lod))+"; x+="+lod+")"); + //System.out.println(" for (z="+lod+"; z<"+(getWidth()-(1*lod))+"; z+="+lod+")"); + for (int r = lod; r < getWidth() - (2 * lod); r += lod) { // row + int rowIdx = r * getWidth(); + int nextRowIdx = (r + 1 * lod) * getWidth(); + for (int c = lod; c < getWidth() - (1 * lod); c += lod) { // column + int idx = rowIdx + c; + buffer.put(idx); + idx = nextRowIdx + c; + buffer.put(idx); + } + + // add degenerate triangles + if (r < getWidth() - (3 * lod)) { + int idx = nextRowIdx + getWidth() - (1 * lod) - 1; + buffer.put(idx); + idx = nextRowIdx + (1 * lod); // inset by 1 + buffer.put(idx); + //System.out.println(""); + } + } + //System.out.println("\nright:"); + + //int runningBufferCount = buffer.getCount(); + //System.out.println("buffer start: "+runningBufferCount); + + + // right + int br = getWidth() * (getWidth() - lod) - 1 - lod; + buffer.put(br); // bottom right -1 + int corner = getWidth() * getWidth() - 1; + buffer.put(corner); // bottom right corner + if (rightLod) { // if lower LOD + for (int row = getWidth() - lod; row >= 1 + lod; row -= 2 * lod) { + int idx = (row) * getWidth() - 1 - lod; + buffer.put(idx); + idx = (row - lod) * getWidth() - 1; + buffer.put(idx); + if (row > lod + 1) { //if not the last one + idx = (row - lod) * getWidth() - 1 - lod; + buffer.put(idx); + idx = (row - lod) * getWidth() - 1; + buffer.put(idx); + } else { + } + } + } else { + buffer.put(corner);//br+1);//degenerate to flip winding order + for (int row = getWidth() - lod; row > lod; row -= lod) { + int idx = row * getWidth() - 1; // mult to get row + buffer.put(idx); + buffer.put(idx - lod); + } + + } + + buffer.put(getWidth() - 1); + + + //System.out.println("\nbuffer right: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + + //System.out.println("\ntop:"); + + // top (the order gets reversed here so the diagonals line up) + if (topLod) { // if lower LOD + if (rightLod) { + buffer.put(getWidth() - 1); + } + for (int col = getWidth() - 1; col >= lod; col -= 2 * lod) { + int idx = (lod * getWidth()) + col - lod; // next row + buffer.put(idx); + idx = col - 2 * lod; + buffer.put(idx); + if (col > lod * 2) { //if not the last one + idx = (lod * getWidth()) + col - 2 * lod; + buffer.put(idx); + idx = col - 2 * lod; + buffer.put(idx); + } else { + } + } + } else { + if (rightLod) { + buffer.put(getWidth() - 1); + } + for (int col = getWidth() - 1 - lod; col > 0; col -= lod) { + int idx = col + (lod * getWidth()); + buffer.put(idx); + idx = col; + buffer.put(idx); + } + buffer.put(0); + } + buffer.put(0); + + //System.out.println("\nbuffer top: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + //System.out.println("\nleft:"); + + // left + if (leftLod) { // if lower LOD + if (topLod) { + buffer.put(0); + } + for (int row = 0; row < getWidth() - lod; row += 2 * lod) { + int idx = (row + lod) * getWidth() + lod; + buffer.put(idx); + idx = (row + 2 * lod) * getWidth(); + buffer.put(idx); + if (row < getWidth() - lod - 2 - 1) { //if not the last one + idx = (row + 2 * lod) * getWidth() + lod; + buffer.put(idx); + idx = (row + 2 * lod) * getWidth(); + buffer.put(idx); + } else { + } + } + } else { + if (!topLod) { + buffer.put(0); + } + //buffer.put(getWidth()+1); // degenerate + //buffer.put(0); // degenerate winding-flip + for (int row = lod; row < getWidth() - lod; row += lod) { + int idx = row * getWidth(); + buffer.put(idx); + idx = row * getWidth() + lod; + buffer.put(idx); + } + + } + buffer.put(getWidth() * (getWidth() - 1)); + + + //System.out.println("\nbuffer left: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + //if (true) return buffer.delegate; + //System.out.println("\nbottom"); + + // bottom + if (bottomLod) { // if lower LOD + if (leftLod) { + buffer.put(getWidth() * (getWidth() - 1)); + } + // there was a slight bug here when really high LOD near maxLod + // far right has extra index one row up and all the way to the right, need to skip last index entered + // seemed to be fixed by making "getWidth()-1-2-lod" this: "getWidth()-1-2*lod", which seems more correct + for (int col = 0; col < getWidth() - lod; col += 2 * lod) { + int idx = getWidth() * (getWidth() - 1 - lod) + col + lod; + buffer.put(idx); + idx = getWidth() * (getWidth() - 1) + col + 2 * lod; + buffer.put(idx); + if (col < getWidth() - 1 - 2 * lod) { //if not the last one + idx = getWidth() * (getWidth() - 1 - lod) + col + 2 * lod; + buffer.put(idx); + idx = getWidth() * (getWidth() - 1) + col + 2 * lod; + buffer.put(idx); + } else { + } + } + } else { + if (leftLod) { + buffer.put(getWidth() * (getWidth() - 1)); + } + for (int col = lod; col < getWidth() - lod; col += lod) { + int idx = getWidth() * (getWidth() - 1 - lod) + col; // up + buffer.put(idx); + idx = getWidth() * (getWidth() - 1) + col; // down + buffer.put(idx); + } + //buffer.put(getWidth()*getWidth()-1-lod); // <-- THIS caused holes at the end! + } + + buffer.put(getWidth() * getWidth() - 1); + + //System.out.println("\nbuffer bottom: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + //System.out.println("\nBuffer size: "+buffer.getCount()); + + // fill in the rest of the buffer with degenerates, there should only be a couple + for (int i = buffer.getCount(); i < numIndexes; i++) { + buffer.put(getWidth() * getWidth() - 1); + } + + return buffer.delegate; + } + + public IntBuffer writeIndexArrayLodVariable(IntBuffer store, int lod, int rightLod, int topLod, int leftLod, int bottomLod) { + + IntBuffer buffer2 = store; + int numIndexes = calculateNumIndexesLodDiff(lod); + if (store == null) { + buffer2 = BufferUtils.createIntBuffer(numIndexes); + } + VerboseIntBuffer buffer = new VerboseIntBuffer(buffer2); + + + // generate center squares minus the edges + //System.out.println("for (x="+lod+"; x<"+(getWidth()-(2*lod))+"; x+="+lod+")"); + //System.out.println(" for (z="+lod+"; z<"+(getWidth()-(1*lod))+"; z+="+lod+")"); + for (int r = lod; r < getWidth() - (2 * lod); r += lod) { // row + int rowIdx = r * getWidth(); + int nextRowIdx = (r + 1 * lod) * getWidth(); + for (int c = lod; c < getWidth() - (1 * lod); c += lod) { // column + int idx = rowIdx + c; + buffer.put(idx); + idx = nextRowIdx + c; + buffer.put(idx); + } + + // add degenerate triangles + if (r < getWidth() - (3 * lod)) { + int idx = nextRowIdx + getWidth() - (1 * lod) - 1; + buffer.put(idx); + idx = nextRowIdx + (1 * lod); // inset by 1 + buffer.put(idx); + //System.out.println(""); + } + } + //System.out.println("\nright:"); + + //int runningBufferCount = buffer.getCount(); + //System.out.println("buffer start: "+runningBufferCount); + + + // right + int br = getWidth() * (getWidth() - lod) - 1 - lod; + buffer.put(br); // bottom right -1 + int corner = getWidth() * getWidth() - 1; + buffer.put(corner); // bottom right corner + if (rightLod > lod) { // if lower LOD int idx = corner; - int it = (getWidth()-1)/rightLod; // iterations - int lodDiff = rightLod/lod; - for (int i=it; i>0; i--) { // for each lod level of the neighbour - idx = getWidth()*(i*rightLod+1)-1; - for (int j=1; j<=lodDiff; j++) { // for each section in that lod level - int idxB = idx - (getWidth()*(j*lod)) - lod; + int it = (getWidth() - 1) / rightLod; // iterations + int lodDiff = rightLod / lod; + for (int i = it; i > 0; i--) { // for each lod level of the neighbour + idx = getWidth() * (i * rightLod + 1) - 1; + for (int j = 1; j <= lodDiff; j++) { // for each section in that lod level + int idxB = idx - (getWidth() * (j * lod)) - lod; if (j == lodDiff && i == 1) {// the last one - buffer.put(getWidth()-1); + buffer.put(getWidth() - 1); } else if (j == lodDiff) { buffer.put(idxB); - buffer.put(idxB+lod); + buffer.put(idxB + lod); } else { buffer.put(idxB); buffer.put(idx); @@ -409,87 +414,88 @@ public class LODGeomap extends BufferGeomap { } } // reset winding order - buffer.put(getWidth()*(lod+1)-lod-1); // top-right +1row - buffer.put(getWidth()-1);// top-right - - } else { - buffer.put(corner);//br+1);//degenerate to flip winding order - for (int row=getWidth()-lod; row>lod; row-=lod) { - int idx = row*getWidth()-1; // mult to get row - buffer.put(idx); - buffer.put(idx-lod); - } - buffer.put(getWidth()-1); - } + buffer.put(getWidth() * (lod + 1) - lod - 1); // top-right +1row + buffer.put(getWidth() - 1);// top-right + + } else { + buffer.put(corner);//br+1);//degenerate to flip winding order + for (int row = getWidth() - lod; row > lod; row -= lod) { + int idx = row * getWidth() - 1; // mult to get row + buffer.put(idx); + buffer.put(idx - lod); + } + buffer.put(getWidth() - 1); + } - //System.out.println("\nbuffer right: "+(buffer.getCount()-runningBufferCount)); - //runningBufferCount = buffer.getCount(); + //System.out.println("\nbuffer right: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); - //System.out.println("\ntop:"); + //System.out.println("\ntop:"); - // top (the order gets reversed here so the diagonals line up) - if (topLod>lod) { // if lower LOD - if (rightLod>lod) { + // top (the order gets reversed here so the diagonals line up) + if (topLod > lod) { // if lower LOD + if (rightLod > lod) { // need to flip winding order - buffer.put(getWidth()-1); - buffer.put(getWidth()*lod -1); - buffer.put(getWidth()-1); - } - int idx = getWidth()-1; - int it = (getWidth()-1)/topLod; // iterations - int lodDiff = topLod/lod; - for (int i=it; i>0; i--) { // for each lod level of the neighbour - idx = (i*topLod); - for (int j=1; j<=lodDiff; j++) { // for each section in that lod level - int idxB = lod*getWidth() +(i*topLod) - (j*lod); + buffer.put(getWidth() - 1); + buffer.put(getWidth() * lod - 1); + buffer.put(getWidth() - 1); + } + int idx = getWidth() - 1; + int it = (getWidth() - 1) / topLod; // iterations + int lodDiff = topLod / lod; + for (int i = it; i > 0; i--) { // for each lod level of the neighbour + idx = (i * topLod); + for (int j = 1; j <= lodDiff; j++) { // for each section in that lod level + int idxB = lod * getWidth() + (i * topLod) - (j * lod); if (j == lodDiff && i == 1) {// the last one buffer.put(0); } else if (j == lodDiff) { buffer.put(idxB); - buffer.put(idx-topLod); + buffer.put(idx - topLod); } else { buffer.put(idxB); buffer.put(idx); } } } - } else { - if (rightLod>lod) - buffer.put(getWidth()-1); - for (int col=getWidth()-1-lod; col>0; col-=lod) { - int idx = col + (lod*getWidth()); - buffer.put(idx); - idx = col; - buffer.put(idx); - } - buffer.put(0); - } - buffer.put(0); - - //System.out.println("\nbuffer top: "+(buffer.getCount()-runningBufferCount)); - //runningBufferCount = buffer.getCount(); - - //System.out.println("\nleft:"); - - // left - if (leftLod>lod) { // if lower LOD - - int idx = 0; - int it = (getWidth()-1)/leftLod; // iterations - int lodDiff = leftLod/lod; - for (int i=0; i lod) { + buffer.put(getWidth() - 1); + } + for (int col = getWidth() - 1 - lod; col > 0; col -= lod) { + int idx = col + (lod * getWidth()); + buffer.put(idx); + idx = col; + buffer.put(idx); + } + buffer.put(0); + } + buffer.put(0); + + //System.out.println("\nbuffer top: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + //System.out.println("\nleft:"); + + // left + if (leftLod > lod) { // if lower LOD + + int idx = 0; + int it = (getWidth() - 1) / leftLod; // iterations + int lodDiff = leftLod / lod; + for (int i = 0; i < it; i++) { // for each lod level of the neighbour + idx = getWidth() * (i * leftLod); + for (int j = 1; j <= lodDiff; j++) { // for each section in that lod level + int idxB = idx + (getWidth() * (j * lod)) + lod; + + if (j == lodDiff && i == it - 1) {// the last one + buffer.put(getWidth() * getWidth() - getWidth()); } else if (j == lodDiff) { buffer.put(idxB); - buffer.put(idxB-lod); + buffer.put(idxB - lod); } else { buffer.put(idxB); buffer.put(idx); @@ -497,135 +503,138 @@ public class LODGeomap extends BufferGeomap { } } - } else { - buffer.put(0); - buffer.put(getWidth()*lod + lod); - buffer.put(0); - for (int row=lod; rowlod) { // if lower LOD - if (leftLod>lod) { - buffer.put(getWidth()*(getWidth()-1)); - buffer.put(getWidth()*(getWidth()-lod)); - buffer.put(getWidth()*(getWidth()-1)); - } - - int idx = getWidth()*getWidth() - getWidth(); - int it = (getWidth()-1)/bottomLod; // iterations - int lodDiff = bottomLod/lod; - for (int i=0; i lod) { // if lower LOD + if (leftLod > lod) { + buffer.put(getWidth() * (getWidth() - 1)); + buffer.put(getWidth() * (getWidth() - lod)); + buffer.put(getWidth() * (getWidth() - 1)); + } + + int idx = getWidth() * getWidth() - getWidth(); + int it = (getWidth() - 1) / bottomLod; // iterations + int lodDiff = bottomLod / lod; + for (int i = 0; i < it; i++) { // for each lod level of the neighbour + idx = getWidth() * getWidth() - getWidth() + (i * bottomLod); + for (int j = 1; j <= lodDiff; j++) { // for each section in that lod level + int idxB = idx - (getWidth() * lod) + j * lod; + + if (j == lodDiff && i == it - 1) {// the last one + buffer.put(getWidth() * getWidth() - 1); } else if (j == lodDiff) { buffer.put(idxB); - buffer.put(idx+bottomLod); + buffer.put(idx + bottomLod); } else { buffer.put(idxB); buffer.put(idx); } } } - } else { - if (leftLod>lod) { - buffer.put(getWidth()*(getWidth()-1)); - buffer.put(getWidth()*getWidth() - (getWidth()*lod)+lod); - buffer.put(getWidth()*(getWidth()-1)); - } - for (int col=lod; col lod) { + buffer.put(getWidth() * (getWidth() - 1)); + buffer.put(getWidth() * getWidth() - (getWidth() * lod) + lod); + buffer.put(getWidth() * (getWidth() - 1)); + } + for (int col = lod; col < getWidth() - lod; col += lod) { + int idx = getWidth() * (getWidth() - 1 - lod) + col; // up + buffer.put(idx); + idx = getWidth() * (getWidth() - 1) + col; // down + buffer.put(idx); + } + //buffer.put(getWidth()*getWidth()-1-lod); // <-- THIS caused holes at the end! + } + + buffer.put(getWidth() * getWidth() - 1); + + //System.out.println("\nbuffer bottom: "+(buffer.getCount()-runningBufferCount)); + //runningBufferCount = buffer.getCount(); + + //System.out.println("\nBuffer size: "+buffer.getCount()); + + // fill in the rest of the buffer with degenerates, there should only be a couple + for (int i = buffer.getCount(); i < numIndexes; i++) { + buffer.put(getWidth() * getWidth() - 1); + } + + return buffer.delegate; + } + + + /*private int calculateNumIndexesNormal(int lod) { + int length = getWidth()-1; + int num = ((length/lod)+1)*((length/lod)+1)*2; + System.out.println("num: "+num); + num -= 2*((length/lod)+1); + System.out.println("num2: "+num); + // now get the degenerate indexes that exist between strip rows + num += 2*(((length/lod)+1)-2); // every row except the first and last + System.out.println("Index buffer size: "+num); + return num; + }*/ + /** + * calculate how many indexes there will be. + * This isn't that precise and there might be a couple extra. + */ + private int calculateNumIndexesLodDiff(int lod) { + if (lod == 0) { lod = 1; - int length = getWidth()-1; // make it even for lod calc - int side = (length/lod)+1 -(2); - //System.out.println("side: "+side); - int num = side*side*2; - //System.out.println("num: "+num); - num -= 2*side; // remove one first row and one last row (they are only hit once each) - //System.out.println("num2: "+num); - // now get the degenerate indexes that exist between strip rows - int degenerates = 2*(side-(2)); // every row except the first and last - num += degenerates; - //System.out.println("degenerates: "+degenerates); - - //System.out.println("center, before edges: "+num); - - num += (getWidth()/lod)*2 *4; - num++; - - num+=10;// TODO remove me: extra - //System.out.println("Index buffer size: "+num); - return num; - } + } + int length = getWidth() - 1; // make it even for lod calc + int side = (length / lod) + 1 - (2); + //System.out.println("side: "+side); + int num = side * side * 2; + //System.out.println("num: "+num); + num -= 2 * side; // remove one first row and one last row (they are only hit once each) + //System.out.println("num2: "+num); + // now get the degenerate indexes that exist between strip rows + int degenerates = 2 * (side - (2)); // every row except the first and last + num += degenerates; + //System.out.println("degenerates: "+degenerates); + + //System.out.println("center, before edges: "+num); + + num += (getWidth() / lod) * 2 * 4; + num++; + + num += 10;// TODO remove me: extra + //System.out.println("Index buffer size: "+num); + return num; + } @Override public FloatBuffer writeNormalArray(FloatBuffer store, Vector3f scale) { - if (!isLoaded()) + if (!isLoaded()) { throw new NullPointerException(); + } - if (store!=null){ - if (store.remaining() < getWidth()*getHeight()*3) + if (store != null) { + if (store.remaining() < getWidth() * getHeight() * 3) { throw new BufferUnderflowException(); - }else{ - store = BufferUtils.createFloatBuffer(getWidth()*getHeight()*3); + } + } else { + store = BufferUtils.createFloatBuffer(getWidth() * getHeight() * 3); } store.rewind(); @@ -635,67 +644,67 @@ public class LODGeomap extends BufferGeomap { Vector3f topPoint = new Vector3f(); Vector3f bottomPoint = new Vector3f(); - // calculate normals for each polygon - for (int r=0; r= width - 1) { @@ -933,4 +944,3 @@ public class LODGeomap extends BufferGeomap { super.read(im); } } - diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java index 1ea8cb19c..2c5973101 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainGrid.java @@ -28,7 +28,8 @@ import com.jme3.terrain.heightmap.HeightMapGrid; */ public class TerrainGrid extends TerrainQuad { - private static Logger log = Logger.getLogger(TerrainGrid.class.getCanonicalName()); + private static final Logger log = Logger.getLogger(TerrainGrid.class.getCanonicalName()); + private Vector3f currentCell; private int quarterSize; private int quadSize; diff --git a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java index fbdb40891..089691ada 100644 --- a/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java +++ b/engine/src/terrain/com/jme3/terrain/geomipmap/TerrainQuad.java @@ -111,6 +111,7 @@ public class TerrainQuad extends Node implements Terrain { protected ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() { public Thread newThread(Runnable r) { Thread th = new Thread(r); + th.setName("jME Terrain Thread"); th.setDaemon(true); return th; }