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:
+ *
+ * - {@link Mode#Triangles}: 0, 1, 2 | 3, 4, 5 | 6, 7, 8 | ...
+ * - {@link Mode#TriangleStrip}: 0, 1, 2 | 2, 1, 3 | 2, 3, 4 | ...
+ * - {@link Mode#TriangleFan}: 0, 1, 2 | 0, 2, 3 | 0, 3, 4 | ...
+ *
+ *
+ * @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:
+
+ - {@link com.jme3.scene.mesh.IndexByteBuffer} - For reading 8-bit index buffers
+ - {@link com.jme3.scene.mesh.IndexShortBuffer} - For reading 16-bit index buffers
+ - {@link com.jme3.scene.mesh.IndexIntBuffer} - For reading 32-bit index buffers
+ - {@link com.jme3.scene.mesh.VirtualIndexBuffer} - For reading "virtual indices", for
+ those meshes that do not have an index buffer
+ - {@link com.jme3.scene.mesh.WrappedIndexBuffer} - For converting from
+ non-list based mode indices to list based
+
+
+
+
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;
}