*/\r
public class TerrainPatch extends Geometry {\r
\r
- protected LODGeomap geomap;\r
- protected int lod = -1; // this terrain patch's LOD\r
- private int maxLod = -1;\r
- protected int previousLod = -1;\r
- protected int lodLeft, lodTop, lodRight, lodBottom; // it's neighbour's LODs\r
- \r
- protected int size;\r
+ protected LODGeomap geomap;\r
+ protected int lod = -1; // this terrain patch's LOD\r
+ private int maxLod = -1;\r
+ protected int previousLod = -1;\r
+ protected int lodLeft, lodTop, lodRight, lodBottom; // it's neighbour's LODs\r
+\r
+ protected int size;\r
\r
- protected int totalSize;\r
+ protected int totalSize;\r
\r
- protected short quadrant = 1;\r
+ protected short quadrant = 1;\r
\r
- // x/z step\r
- protected Vector3f stepScale;\r
+ // x/z step\r
+ protected Vector3f stepScale;\r
\r
- // center of the block in relation to (0,0,0)\r
- protected Vector2f offset;\r
+ // center of the block in relation to (0,0,0)\r
+ protected Vector2f offset;\r
\r
- // amount the block has been shifted.\r
- protected float offsetAmount;\r
+ // amount the block has been shifted.\r
+ protected float offsetAmount;\r
\r
protected LodCalculator lodCalculator;\r
protected LodCalculatorFactory lodCalculatorFactory;\r
super("TerrainPatch");\r
}\r
\r
- public TerrainPatch(String name) {\r
- super(name);\r
- }\r
- \r
- public TerrainPatch(String name, int size) {\r
- this(name, size, new Vector3f(1,1,1), null, new Vector3f(0,0,0));\r
- }\r
- \r
- /**\r
- * Constructor instantiates a new <code>TerrainPatch</code> object. The\r
- * parameters and heightmap data are then processed to generate a\r
- * <code>TriMesh</code> object for rendering.\r
- * \r
- * @param name\r
- * the name of the terrain block.\r
- * @param size\r
- * the size of the heightmap.\r
- * @param stepScale\r
- * the scale for the axes.\r
- * @param heightMap\r
- * the height data.\r
- * @param origin\r
- * the origin offset of the block.\r
- */\r
- public TerrainPatch(String name, int size, Vector3f stepScale,\r
- float[] heightMap, Vector3f origin) {\r
- this(name, size, stepScale, heightMap, origin, size, new Vector2f(), 0);\r
- }\r
-\r
- /**\r
- * Constructor instantiates a new <code>TerrainPatch</code> object. The\r
- * parameters and heightmap data are then processed to generate a\r
- * <code>TriMesh</code> object for renderering.\r
- * \r
- * @param name\r
- * the name of the terrain block.\r
- * @param size\r
- * the size of the block.\r
- * @param stepScale\r
- * the scale for the axes.\r
- * @param heightMap\r
- * the height data.\r
- * @param origin\r
- * the origin offset of the block.\r
- * @param totalSize\r
- * the total size of the terrain. (Higher if the block is part of\r
- * a <code>TerrainPage</code> tree.\r
- * @param offset\r
- * the offset for texture coordinates.\r
- * @param offsetAmount\r
- * the total offset amount. Used for texture coordinates.\r
- */\r
- public TerrainPatch(String name, int size, Vector3f stepScale,\r
- float[] heightMap, Vector3f origin, int totalSize,\r
- Vector2f offset, float offsetAmount) {\r
- super(name);\r
- this.size = size;\r
- this.stepScale = stepScale;\r
- this.totalSize = totalSize;\r
- this.offsetAmount = offsetAmount;\r
- this.offset = offset;\r
-\r
- setLocalTranslation(origin);\r
- \r
- FloatBuffer heightBuffer = BufferUtils.createFloatBuffer(size*size);\r
- heightBuffer.put(heightMap);\r
- \r
- geomap = new LODGeomap(size, heightBuffer);\r
- Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false);\r
- setMesh(m);\r
- \r
- }\r
+ public TerrainPatch(String name) {\r
+ super(name);\r
+ }\r
+\r
+ public TerrainPatch(String name, int size) {\r
+ this(name, size, new Vector3f(1,1,1), null, new Vector3f(0,0,0));\r
+ }\r
+\r
+ /**\r
+ * Constructor instantiates a new <code>TerrainPatch</code> object. The\r
+ * parameters and heightmap data are then processed to generate a\r
+ * <code>TriMesh</code> object for rendering.\r
+ *\r
+ * @param name\r
+ * the name of the terrain block.\r
+ * @param size\r
+ * the size of the heightmap.\r
+ * @param stepScale\r
+ * the scale for the axes.\r
+ * @param heightMap\r
+ * the height data.\r
+ * @param origin\r
+ * the origin offset of the block.\r
+ */\r
+ public TerrainPatch(String name, int size, Vector3f stepScale,\r
+ float[] heightMap, Vector3f origin) {\r
+ this(name, size, stepScale, heightMap, origin, size, new Vector2f(), 0);\r
+ }\r
+\r
+ /**\r
+ * Constructor instantiates a new <code>TerrainPatch</code> object. The\r
+ * parameters and heightmap data are then processed to generate a\r
+ * <code>TriMesh</code> object for renderering.\r
+ *\r
+ * @param name\r
+ * the name of the terrain block.\r
+ * @param size\r
+ * the size of the block.\r
+ * @param stepScale\r
+ * the scale for the axes.\r
+ * @param heightMap\r
+ * the height data.\r
+ * @param origin\r
+ * the origin offset of the block.\r
+ * @param totalSize\r
+ * the total size of the terrain. (Higher if the block is part of\r
+ * a <code>TerrainPage</code> tree.\r
+ * @param offset\r
+ * the offset for texture coordinates.\r
+ * @param offsetAmount\r
+ * the total offset amount. Used for texture coordinates.\r
+ */\r
+ public TerrainPatch(String name, int size, Vector3f stepScale,\r
+ float[] heightMap, Vector3f origin, int totalSize,\r
+ Vector2f offset, float offsetAmount) {\r
+ super(name);\r
+ this.size = size;\r
+ this.stepScale = stepScale;\r
+ this.totalSize = totalSize;\r
+ this.offsetAmount = offsetAmount;\r
+ this.offset = offset;\r
+\r
+ setLocalTranslation(origin);\r
+\r
+ FloatBuffer heightBuffer = BufferUtils.createFloatBuffer(size*size);\r
+ heightBuffer.put(heightMap);\r
+\r
+ geomap = new LODGeomap(size, heightBuffer);\r
+ Mesh m = geomap.createMesh(stepScale, new Vector2f(1,1), offset, offsetAmount, totalSize, false);\r
+ setMesh(m);\r
+\r
+ }\r
\r
/**\r
* This calculation is slow, so don't use it often.\r
return lodEntropy;\r
}\r
\r
- public FloatBuffer getHeightmap() {\r
- return geomap.getHeightData();\r
- }\r
- \r
- /**\r
- * The maximum lod supported by this terrain patch.\r
- * If the patch size is 32 then the returned value would be log2(32)-2 = 3\r
- * You can then use that value, 3, to see how many times you can divide 32 by 2 \r
- * before the terrain gets too un-detailed (can't stitch it any further).\r
- * @return\r
- */\r
- public int getMaxLod() {\r
- if (maxLod < 0)\r
- maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide\r
- \r
- return maxLod;\r
- }\r
+ public FloatBuffer getHeightmap() {\r
+ return geomap.getHeightData();\r
+ }\r
+\r
+ /**\r
+ * The maximum lod supported by this terrain patch.\r
+ * If the patch size is 32 then the returned value would be log2(32)-2 = 3\r
+ * You can then use that value, 3, to see how many times you can divide 32 by 2\r
+ * before the terrain gets too un-detailed (can't stitch it any further).\r
+ * @return\r
+ */\r
+ public int getMaxLod() {\r
+ if (maxLod < 0)\r
+ maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide\r
+\r
+ return maxLod;\r
+ }\r
\r
\r
\r
* @param updates update objects that may or may not contain this terrain patch\r
* @return true if the geometry needs re-indexing\r
*/\r
- protected boolean calculateLod(List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates) {\r
+ protected boolean calculateLod(List<Vector3f> locations, HashMap<String,UpdatedTerrainPatch> updates) {\r
return lodCalculator.calculateLod(locations, updates);\r
}\r
\r
- protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated) {\r
- \r
- UpdatedTerrainPatch utp = updated.get(getName());\r
- \r
- if (utp != null && (utp.isReIndexNeeded() || utp.isFixEdges()) ) {\r
- int pow = (int) Math.pow(2, utp.getNewLod());\r
- boolean left = utp.getLeftLod() > utp.getNewLod();\r
- boolean top = utp.getTopLod() > utp.getNewLod();\r
- boolean right = utp.getRightLod() > utp.getNewLod();\r
- boolean bottom = utp.getBottomLod() > utp.getNewLod();\r
- \r
+ protected void reIndexGeometry(HashMap<String,UpdatedTerrainPatch> updated) {\r
+\r
+ UpdatedTerrainPatch utp = updated.get(getName());\r
+\r
+ if (utp != null && (utp.isReIndexNeeded() || utp.isFixEdges()) ) {\r
+ int pow = (int) Math.pow(2, utp.getNewLod());\r
+ boolean left = utp.getLeftLod() > utp.getNewLod();\r
+ boolean top = utp.getTopLod() > utp.getNewLod();\r
+ boolean right = utp.getRightLod() > utp.getNewLod();\r
+ boolean bottom = utp.getBottomLod() > utp.getNewLod();\r
+\r
IntBuffer ib = null;\r
if (lodCalculator.usesVariableLod())\r
ib = geomap.writeIndexArrayLodVariable(null, pow, (int) Math.pow(2, utp.getRightLod()), (int) Math.pow(2, utp.getTopLod()), (int) Math.pow(2, utp.getLeftLod()), (int) Math.pow(2, utp.getBottomLod()));\r
else\r
ib = geomap.writeIndexArrayLodDiff(null, pow, right, top, left, bottom);\r
- utp.setNewIndexBuffer(ib);\r
- }\r
- \r
- }\r
+ utp.setNewIndexBuffer(ib);\r
+ }\r
+\r
+ }\r
\r
\r
public Vector2f getTex(float x, float z, Vector2f store) {\r
getMesh().setDynamic();\r
}\r
\r
- /**\r
- * Returns the offset amount this terrain block uses for textures.\r
- * \r
- * @return The current offset amount.\r
- */\r
- public float getOffsetAmount() {\r
- return offsetAmount;\r
- }\r
-\r
- /**\r
- * Returns the step scale that stretches the height map.\r
- * \r
- * @return The current step scale.\r
- */\r
- public Vector3f getStepScale() {\r
- return stepScale;\r
- }\r
-\r
- /**\r
- * Returns the total size of the terrain.\r
- * \r
- * @return The terrain's total size.\r
- */\r
- public int getTotalSize() {\r
- return totalSize;\r
- }\r
-\r
- /**\r
- * Returns the size of this terrain block.\r
- * \r
- * @return The current block size.\r
- */\r
- public int getSize() {\r
- return size;\r
- }\r
-\r
- /**\r
- * Returns the current offset amount. This is used when building texture\r
- * coordinates.\r
- * \r
- * @return The current offset amount.\r
- */\r
- public Vector2f getOffset() {\r
- return offset;\r
- }\r
-\r
- /**\r
- * Sets the value for the current offset amount to use when building texture\r
- * coordinates. Note that this does <b>NOT </b> rebuild the terrain at all.\r
- * This is mostly used for outside constructors of terrain blocks.\r
- * \r
- * @param offset\r
- * The new texture offset.\r
- */\r
- public void setOffset(Vector2f offset) {\r
- this.offset = offset;\r
- }\r
-\r
- /**\r
- * Sets the size of this terrain block. Note that this does <b>NOT </b>\r
- * rebuild the terrain at all. This is mostly used for outside constructors\r
- * of terrain blocks.\r
- * \r
- * @param size\r
- * The new size.\r
- */\r
- public void setSize(int size) {\r
- this.size = size;\r
- \r
- maxLod = -1; // reset it\r
- }\r
-\r
- /**\r
- * Sets the total size of the terrain . Note that this does <b>NOT </b>\r
- * rebuild the terrain at all. This is mostly used for outside constructors\r
- * of terrain blocks.\r
- * \r
- * @param totalSize\r
- * The new total size.\r
- */\r
- public void setTotalSize(int totalSize) {\r
- this.totalSize = totalSize;\r
- }\r
-\r
- /**\r
- * Sets the step scale of this terrain block's height map. Note that this\r
- * does <b>NOT </b> rebuild the terrain at all. This is mostly used for\r
- * outside constructors of terrain blocks.\r
- * \r
- * @param stepScale\r
- * The new step scale.\r
- */\r
- public void setStepScale(Vector3f stepScale) {\r
- this.stepScale = stepScale;\r
- }\r
-\r
- /**\r
- * Sets the offset of this terrain texture map. Note that this does <b>NOT\r
- * </b> rebuild the terrain at all. This is mostly used for outside\r
- * constructors of terrain blocks.\r
- * \r
- * @param offsetAmount\r
- * The new texture offset.\r
- */\r
- public void setOffsetAmount(float offsetAmount) {\r
- this.offsetAmount = offsetAmount;\r
- }\r
- \r
- /**\r
- * @return Returns the quadrant.\r
- */\r
- public short getQuadrant() {\r
- return quadrant;\r
- }\r
-\r
- /**\r
- * @param quadrant\r
- * The quadrant to set.\r
- */\r
- public void setQuadrant(short quadrant) {\r
- this.quadrant = quadrant;\r
- }\r
-\r
- public int getLod() {\r
- return lod;\r
- }\r
-\r
- public void setLod(int lod) {\r
- this.lod = lod;\r
- }\r
-\r
- public int getPreviousLod() {\r
- return previousLod;\r
- }\r
-\r
- public void setPreviousLod(int previousLod) {\r
- this.previousLod = previousLod;\r
- }\r
-\r
- protected int getLodLeft() {\r
- return lodLeft;\r
- }\r
-\r
- protected void setLodLeft(int lodLeft) {\r
- this.lodLeft = lodLeft;\r
- }\r
-\r
- protected int getLodTop() {\r
- return lodTop;\r
- }\r
-\r
- protected void setLodTop(int lodTop) {\r
- this.lodTop = lodTop;\r
- }\r
-\r
- protected int getLodRight() {\r
- return lodRight;\r
- }\r
-\r
- protected void setLodRight(int lodRight) {\r
- this.lodRight = lodRight;\r
- }\r
-\r
- protected int getLodBottom() {\r
- return lodBottom;\r
- }\r
-\r
- protected void setLodBottom(int lodBottom) {\r
- this.lodBottom = lodBottom;\r
- }\r
+ /**\r
+ * Returns the offset amount this terrain block uses for textures.\r
+ *\r
+ * @return The current offset amount.\r
+ */\r
+ public float getOffsetAmount() {\r
+ return offsetAmount;\r
+ }\r
+\r
+ /**\r
+ * Returns the step scale that stretches the height map.\r
+ *\r
+ * @return The current step scale.\r
+ */\r
+ public Vector3f getStepScale() {\r
+ return stepScale;\r
+ }\r
+\r
+ /**\r
+ * Returns the total size of the terrain.\r
+ *\r
+ * @return The terrain's total size.\r
+ */\r
+ public int getTotalSize() {\r
+ return totalSize;\r
+ }\r
+\r
+ /**\r
+ * Returns the size of this terrain block.\r
+ *\r
+ * @return The current block size.\r
+ */\r
+ public int getSize() {\r
+ return size;\r
+ }\r
+\r
+ /**\r
+ * Returns the current offset amount. This is used when building texture\r
+ * coordinates.\r
+ *\r
+ * @return The current offset amount.\r
+ */\r
+ public Vector2f getOffset() {\r
+ return offset;\r
+ }\r
+\r
+ /**\r
+ * Sets the value for the current offset amount to use when building texture\r
+ * coordinates. Note that this does <b>NOT </b> rebuild the terrain at all.\r
+ * This is mostly used for outside constructors of terrain blocks.\r
+ *\r
+ * @param offset\r
+ * The new texture offset.\r
+ */\r
+ public void setOffset(Vector2f offset) {\r
+ this.offset = offset;\r
+ }\r
+\r
+ /**\r
+ * Sets the size of this terrain block. Note that this does <b>NOT </b>\r
+ * rebuild the terrain at all. This is mostly used for outside constructors\r
+ * of terrain blocks.\r
+ *\r
+ * @param size\r
+ * The new size.\r
+ */\r
+ public void setSize(int size) {\r
+ this.size = size;\r
+\r
+ maxLod = -1; // reset it\r
+ }\r
+\r
+ /**\r
+ * Sets the total size of the terrain . Note that this does <b>NOT </b>\r
+ * rebuild the terrain at all. This is mostly used for outside constructors\r
+ * of terrain blocks.\r
+ *\r
+ * @param totalSize\r
+ * The new total size.\r
+ */\r
+ public void setTotalSize(int totalSize) {\r
+ this.totalSize = totalSize;\r
+ }\r
+\r
+ /**\r
+ * Sets the step scale of this terrain block's height map. Note that this\r
+ * does <b>NOT </b> rebuild the terrain at all. This is mostly used for\r
+ * outside constructors of terrain blocks.\r
+ *\r
+ * @param stepScale\r
+ * The new step scale.\r
+ */\r
+ public void setStepScale(Vector3f stepScale) {\r
+ this.stepScale = stepScale;\r
+ }\r
+\r
+ /**\r
+ * Sets the offset of this terrain texture map. Note that this does <b>NOT\r
+ * </b> rebuild the terrain at all. This is mostly used for outside\r
+ * constructors of terrain blocks.\r
+ *\r
+ * @param offsetAmount\r
+ * The new texture offset.\r
+ */\r
+ public void setOffsetAmount(float offsetAmount) {\r
+ this.offsetAmount = offsetAmount;\r
+ }\r
+\r
+ /**\r
+ * @return Returns the quadrant.\r
+ */\r
+ public short getQuadrant() {\r
+ return quadrant;\r
+ }\r
+\r
+ /**\r
+ * @param quadrant\r
+ * The quadrant to set.\r
+ */\r
+ public void setQuadrant(short quadrant) {\r
+ this.quadrant = quadrant;\r
+ }\r
+\r
+ public int getLod() {\r
+ return lod;\r
+ }\r
+\r
+ public void setLod(int lod) {\r
+ this.lod = lod;\r
+ }\r
+\r
+ public int getPreviousLod() {\r
+ return previousLod;\r
+ }\r
+\r
+ public void setPreviousLod(int previousLod) {\r
+ this.previousLod = previousLod;\r
+ }\r
+\r
+ protected int getLodLeft() {\r
+ return lodLeft;\r
+ }\r
+\r
+ protected void setLodLeft(int lodLeft) {\r
+ this.lodLeft = lodLeft;\r
+ }\r
+\r
+ protected int getLodTop() {\r
+ return lodTop;\r
+ }\r
+\r
+ protected void setLodTop(int lodTop) {\r
+ this.lodTop = lodTop;\r
+ }\r
+\r
+ protected int getLodRight() {\r
+ return lodRight;\r
+ }\r
+\r
+ protected void setLodRight(int lodRight) {\r
+ this.lodRight = lodRight;\r
+ }\r
+\r
+ protected int getLodBottom() {\r
+ return lodBottom;\r
+ }\r
+\r
+ protected void setLodBottom(int lodBottom) {\r
+ this.lodBottom = lodBottom;\r
+ }\r
\r
public LodCalculator getLodCalculator() {\r
return lodCalculator;\r
*/\r
public class TerrainQuad extends Node implements Terrain {\r
\r
- protected Vector2f offset;\r
+ protected Vector2f offset;\r
\r
- protected int totalSize; // the size of this entire terrain tree (on one side)\r
+ protected int totalSize; // the size of this entire terrain tree (on one side)\r
\r
- protected int size; // size of this quad, can be between totalSize and patchSize\r
+ protected int size; // size of this quad, can be between totalSize and patchSize\r
\r
protected int patchSize; // size of the individual patches\r
\r
- protected Vector3f stepScale;\r
+ protected Vector3f stepScale;\r
\r
- protected float offsetAmount;\r
+ protected float offsetAmount;\r
\r
- protected int quadrant = 1; // 1=upper left, 2=lower left, 3=upper right, 4=lower right\r
+ protected int quadrant = 1; // 1=upper left, 2=lower left, 3=upper right, 4=lower right\r
\r
- protected LodCalculatorFactory lodCalculatorFactory;\r
+ protected LodCalculatorFactory lodCalculatorFactory;\r
\r
\r
- protected List<Vector3f> lastCameraLocations; // used for LOD calc\r
- private boolean lodCalcRunning = false;\r
- private boolean usingLOD = true;\r
- private int maxLod = -1;\r
- private HashMap<String,UpdatedTerrainPatch> updatedPatches;\r
- private final Object updatePatchesLock = new Object();\r
+ protected List<Vector3f> lastCameraLocations; // used for LOD calc\r
+ private boolean lodCalcRunning = false;\r
+ private boolean usingLOD = true;\r
+ private int maxLod = -1;\r
+ private HashMap<String,UpdatedTerrainPatch> updatedPatches;\r
+ private final Object updatePatchesLock = new Object();\r
private BoundingBox affectedAreaBBox; // only set in the root quad\r
\r
private TerrainPicker picker;\r
\r
\r
- protected ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {\r
- public Thread newThread(Runnable r) {\r
- Thread th = new Thread(r);\r
- th.setDaemon(true);\r
- return th;\r
- }\r
- });\r
+ protected ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {\r
+ public Thread newThread(Runnable r) {\r
+ Thread th = new Thread(r);\r
+ th.setDaemon(true);\r
+ return th;\r
+ }\r
+ });\r
\r
\r
- public TerrainQuad() {\r
- super("Terrain");\r
- }\r
+ public TerrainQuad() {\r
+ super("Terrain");\r
+ }\r
\r
- public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap) {\r
- this(name, patchSize, totalSize, heightMap, null);\r
- }\r
+ public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap) {\r
+ this(name, patchSize, totalSize, heightMap, null);\r
+ }\r
\r
public TerrainQuad(String name, int patchSize, int totalSize, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
this(name, patchSize, totalSize, Vector3f.UNIT_XYZ, heightMap, lodCalculatorFactory);\r
}\r
\r
- public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
- this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory);\r
+ public TerrainQuad(String name, int patchSize, int size, Vector3f scale, float[] heightMap, LodCalculatorFactory lodCalculatorFactory) {\r
+ this(name, patchSize, size, scale, heightMap, size, new Vector2f(), 0, lodCalculatorFactory);\r
affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size);\r
fixNormalEdges(affectedAreaBBox);\r
addControl(new NormalRecalcControl(this));\r
- }\r
+ }\r
\r
- protected TerrainQuad(String name, int patchSize, int size,\r
- Vector3f stepScale, float[] heightMap, int totalSize,\r
- Vector2f offset, float offsetAmount,\r
- LodCalculatorFactory lodCalculatorFactory)\r
- {\r
- super(name);\r
- if (!FastMath.isPowerOfTwo(size - 1)) {\r
- throw new RuntimeException("size given: " + size + " Terrain quad sizes may only be (2^N + 1)");\r
- }\r
+ protected TerrainQuad(String name, int patchSize, int size,\r
+ Vector3f stepScale, float[] heightMap, int totalSize,\r
+ Vector2f offset, float offsetAmount,\r
+ LodCalculatorFactory lodCalculatorFactory)\r
+ {\r
+ super(name);\r
+ if (!FastMath.isPowerOfTwo(size - 1)) {\r
+ throw new RuntimeException("size given: " + size + " Terrain quad sizes may only be (2^N + 1)");\r
+ }\r
\r
- if (heightMap == null)\r
- heightMap = generateDefaultHeightMap(size);\r
+ if (heightMap == null)\r
+ heightMap = generateDefaultHeightMap(size);\r
\r
- this.offset = offset;\r
- this.offsetAmount = offsetAmount;\r
- this.totalSize = totalSize;\r
- this.size = size;\r
+ this.offset = offset;\r
+ this.offsetAmount = offsetAmount;\r
+ this.totalSize = totalSize;\r
+ this.size = size;\r
this.patchSize = patchSize;\r
- this.stepScale = stepScale;\r
- this.lodCalculatorFactory = lodCalculatorFactory;\r
- split(patchSize, heightMap);\r
- }\r
-\r
- public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {\r
- if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).setLodCalculatorFactory(lodCalculatorFactory);\r
- } else if (child instanceof TerrainPatch) {\r
- ((TerrainPatch) child).setLodCalculator(lodCalculatorFactory.createCalculator((TerrainPatch) child));\r
- }\r
- }\r
- }\r
- }\r
+ this.stepScale = stepScale;\r
+ this.lodCalculatorFactory = lodCalculatorFactory;\r
+ split(patchSize, heightMap);\r
+ }\r
\r
+ public void setLodCalculatorFactory(LodCalculatorFactory lodCalculatorFactory) {\r
+ if (children != null) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).setLodCalculatorFactory(lodCalculatorFactory);\r
+ } else if (child instanceof TerrainPatch) {\r
+ ((TerrainPatch) child).setLodCalculator(lodCalculatorFactory.createCalculator((TerrainPatch) child));\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- /**\r
- * Create just a flat heightmap\r
- */\r
- private float[] generateDefaultHeightMap(int size) {\r
- float[] heightMap = new float[size*size];\r
- return heightMap;\r
- }\r
\r
- /**\r
- * Call from the update() method of a terrain controller to update\r
- * the LOD values of each patch.\r
- * This will perform the geometry calculation in a background thread and\r
- * do the actual update on the opengl thread.\r
- */\r
- public void update(List<Vector3f> locations) {\r
+ /**\r
+ * Create just a flat heightmap\r
+ */\r
+ private float[] generateDefaultHeightMap(int size) {\r
+ float[] heightMap = new float[size*size];\r
+ return heightMap;\r
+ }\r
\r
+ /**\r
+ * Call from the update() method of a terrain controller to update\r
+ * the LOD values of each patch.\r
+ * This will perform the geometry calculation in a background thread and\r
+ * do the actual update on the opengl thread.\r
+ */\r
+ public void update(List<Vector3f> locations) {\r
updateLOD(locations);\r
- }\r
+ }\r
\r
/**\r
* update the normals if there were any height changes recently.\r
// do all of the LOD calculations\r
protected void updateLOD(List<Vector3f> locations) {\r
// update any existing ones that need updating\r
- updateQuadLODs();\r
+ updateQuadLODs();\r
\r
- if (lastCameraLocations != null) {\r
- if (lastCameraLocationsTheSame(locations))\r
- return; // don't update if in same spot\r
- else\r
- lastCameraLocations = cloneVectorList(locations);\r
- }\r
- else {\r
- lastCameraLocations = cloneVectorList(locations);\r
- return;\r
- }\r
+ if (lastCameraLocations != null) {\r
+ if (lastCameraLocationsTheSame(locations))\r
+ return; // don't update if in same spot\r
+ else\r
+ lastCameraLocations = cloneVectorList(locations);\r
+ }\r
+ else {\r
+ lastCameraLocations = cloneVectorList(locations);\r
+ return;\r
+ }\r
\r
- if (isLodCalcRunning()) {\r
- return;\r
- }\r
+ if (isLodCalcRunning()) {\r
+ return;\r
+ }\r
\r
- if (getParent() instanceof TerrainQuad) {\r
- return; // we just want the root quad to perform this.\r
- }\r
+ if (getParent() instanceof TerrainQuad) {\r
+ return; // we just want the root quad to perform this.\r
+ }\r
\r
- UpdateLOD updateLodThread = new UpdateLOD(locations);\r
- executor.execute(updateLodThread);\r
+ UpdateLOD updateLodThread = new UpdateLOD(locations);\r
+ executor.execute(updateLodThread);\r
}\r
\r
- private synchronized boolean isLodCalcRunning() {\r
- return lodCalcRunning;\r
- }\r
+ private synchronized boolean isLodCalcRunning() {\r
+ return lodCalcRunning;\r
+ }\r
\r
- private synchronized void setLodCalcRunning(boolean running) {\r
- lodCalcRunning = running;\r
- }\r
+ private synchronized void setLodCalcRunning(boolean running) {\r
+ lodCalcRunning = running;\r
+ }\r
\r
private List<Vector3f> cloneVectorList(List<Vector3f> locations) {\r
- List<Vector3f> cloned = new ArrayList<Vector3f>();\r
- for(Vector3f l : locations)\r
- cloned.add(l.clone());\r
- return cloned;\r
+ List<Vector3f> cloned = new ArrayList<Vector3f>();\r
+ for(Vector3f l : locations)\r
+ cloned.add(l.clone());\r
+ return cloned;\r
}\r
\r
private boolean lastCameraLocationsTheSame(List<Vector3f> locations) {\r
- boolean theSame = true;\r
- for (Vector3f l : locations) {\r
- for (Vector3f v : lastCameraLocations) {\r
- if (!v.equals(l) ) {\r
- theSame = false;\r
- return false;\r
- }\r
+ boolean theSame = true;\r
+ for (Vector3f l : locations) {\r
+ for (Vector3f v : lastCameraLocations) {\r
+ if (!v.equals(l) ) {\r
+ theSame = false;\r
+ return false;\r
}\r
}\r
- return theSame;\r
+ }\r
+ return theSame;\r
}\r
\r
private int collideWithRay(Ray ray, CollisionResults results) {\r
}\r
\r
if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).generateEntropy(progressMonitor);\r
- } else if (child instanceof TerrainPatch) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).generateEntropy(progressMonitor);\r
+ } else if (child instanceof TerrainPatch) {\r
((TerrainPatch) child).generateLodEntropies();\r
if (progressMonitor != null)\r
progressMonitor.incrementProgress(1);\r
return 1f/(float)totalSize;\r
}\r
\r
- /**\r
- * Calculates the LOD of all child terrain patches.\r
- */\r
- private class UpdateLOD implements Runnable {\r
- private List<Vector3f> camLocations;\r
+ /**\r
+ * Calculates the LOD of all child terrain patches.\r
+ */\r
+ private class UpdateLOD implements Runnable {\r
+ private List<Vector3f> camLocations;\r
\r
- UpdateLOD(List<Vector3f> location) {\r
- camLocations = location;\r
- }\r
+ UpdateLOD(List<Vector3f> location) {\r
+ camLocations = location;\r
+ }\r
\r
- public void run() {\r
- long start = System.currentTimeMillis();\r
- if (isLodCalcRunning()) {\r
- //System.out.println("thread already running");\r
- return;\r
- }\r
- //System.out.println("spawned thread "+toString());\r
- setLodCalcRunning(true);\r
+ public void run() {\r
+ long start = System.currentTimeMillis();\r
+ if (isLodCalcRunning()) {\r
+ //System.out.println("thread already running");\r
+ return;\r
+ }\r
+ //System.out.println("spawned thread "+toString());\r
+ setLodCalcRunning(true);\r
\r
- // go through each patch and calculate its LOD based on camera distance\r
- HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();\r
- boolean lodChanged = calculateLod(camLocations, updated); // 'updated' gets populated here\r
+ // go through each patch and calculate its LOD based on camera distance\r
+ HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();\r
+ boolean lodChanged = calculateLod(camLocations, updated); // 'updated' gets populated here\r
\r
- if (!lodChanged) {\r
- // not worth updating anything else since no one's LOD changed\r
- setLodCalcRunning(false);\r
- return;\r
- }\r
- // then calculate its neighbour LOD values for seaming in the shader\r
- findNeighboursLod(updated);\r
+ if (!lodChanged) {\r
+ // not worth updating anything else since no one's LOD changed\r
+ setLodCalcRunning(false);\r
+ return;\r
+ }\r
+ // then calculate its neighbour LOD values for seaming in the shader\r
+ findNeighboursLod(updated);\r
\r
- fixEdges(updated); // 'updated' can get added to here\r
+ fixEdges(updated); // 'updated' can get added to here\r
\r
- reIndexPages(updated);\r
+ reIndexPages(updated);\r
\r
- setUpdateQuadLODs(updated); // set back to main ogl thread\r
+ setUpdateQuadLODs(updated); // set back to main ogl thread\r
\r
- setLodCalcRunning(false);\r
- //double duration = (System.currentTimeMillis()-start);\r
- //System.out.println("terminated in "+duration);\r
- }\r
+ setLodCalcRunning(false);\r
+ //double duration = (System.currentTimeMillis()-start);\r
+ //System.out.println("terminated in "+duration);\r
+ }\r
+ }\r
\r
+ private void setUpdateQuadLODs(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ synchronized (updatePatchesLock) {\r
+ updatedPatches = updated;\r
+ }\r
+ }\r
\r
+ /**\r
+ * Back on the ogl thread: update the terrain patch geometries\r
+ * @param updatedPatches to be updated\r
+ */\r
+ private void updateQuadLODs() {\r
+ synchronized (updatePatchesLock) {\r
+ //if (true)\r
+ // return;\r
+ if (updatedPatches == null || updatedPatches.isEmpty())\r
+ return;\r
+\r
+ //TODO do the actual geometry update here\r
+ for (UpdatedTerrainPatch utp : updatedPatches.values()) {\r
+ utp.updateAll();\r
+ }\r
\r
- }\r
+ updatedPatches.clear();\r
+ }\r
+ }\r
\r
- private void setUpdateQuadLODs(HashMap<String,UpdatedTerrainPatch> updated) {\r
- synchronized (updatePatchesLock) {\r
- updatedPatches = updated;\r
- }\r
- }\r
+ protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates) {\r
\r
- /**\r
- * Back on the ogl thread: update the terrain patch geometries\r
- * @param updatedPatches to be updated\r
- */\r
- private void updateQuadLODs() {\r
- synchronized (updatePatchesLock) {\r
- //if (true)\r
- // return;\r
- if (updatedPatches == null || updatedPatches.isEmpty())\r
- return;\r
-\r
- //TODO do the actual geometry update here\r
- for (UpdatedTerrainPatch utp : updatedPatches.values()) {\r
- utp.updateAll();\r
- }\r
+ boolean lodChanged = false;\r
\r
- updatedPatches.clear();\r
- }\r
- }\r
+ if (children != null) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ boolean b = ((TerrainQuad) child).calculateLod(location, updates);\r
+ if (b)\r
+ lodChanged = true;\r
+ } else if (child instanceof TerrainPatch) {\r
+ boolean b = ((TerrainPatch) child).calculateLod(location, updates);\r
+ if (b)\r
+ lodChanged = true;\r
+ }\r
+ }\r
+ }\r
\r
- protected boolean calculateLod(List<Vector3f> location, HashMap<String,UpdatedTerrainPatch> updates) {\r
+ return lodChanged;\r
+ }\r
\r
- boolean lodChanged = false;\r
+ protected synchronized void findNeighboursLod(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ if (children != null) {\r
+ for (int x = children.size(); --x >= 0;) {\r
+ Spatial child = children.get(x);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).findNeighboursLod(updated);\r
+ } else if (child instanceof TerrainPatch) {\r
+\r
+ TerrainPatch patch = (TerrainPatch) child;\r
+ if (!patch.searchedForNeighboursAlready) {\r
+ // set the references to the neighbours\r
+ patch.rightNeighbour = findRightPatch(patch);\r
+ patch.bottomNeighbour = findDownPatch(patch);\r
+ patch.leftNeighbour = findLeftPatch(patch);\r
+ patch.topNeighbour = findTopPatch(patch);\r
+ patch.searchedForNeighboursAlready = true;\r
+ }\r
+ TerrainPatch right = patch.rightNeighbour;\r
+ TerrainPatch down = patch.bottomNeighbour;\r
\r
- if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- boolean b = ((TerrainQuad) child).calculateLod(location, updates);\r
- if (b)\r
- lodChanged = true;\r
- } else if (child instanceof TerrainPatch) {\r
- boolean b = ((TerrainPatch) child).calculateLod(location, updates);\r
- if (b)\r
- lodChanged = true;\r
- }\r
- }\r
- }\r
+ UpdatedTerrainPatch utp = updated.get(patch.getName());\r
+ if (utp == null) {\r
+ utp = new UpdatedTerrainPatch(patch, patch.lod);\r
+ updated.put(utp.getName(), utp);\r
+ }\r
\r
- return lodChanged;\r
- }\r
+ if (right != null) {\r
+ UpdatedTerrainPatch utpR = updated.get(right.getName());\r
+ if (utpR == null) {\r
+ utpR = new UpdatedTerrainPatch(right, right.lod);\r
+ updated.put(utpR.getName(), utpR);\r
+ }\r
\r
- protected synchronized void findNeighboursLod(HashMap<String,UpdatedTerrainPatch> updated) {\r
- if (children != null) {\r
- for (int x = children.size(); --x >= 0;) {\r
- Spatial child = children.get(x);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).findNeighboursLod(updated);\r
- } else if (child instanceof TerrainPatch) {\r
+ utp.setRightLod(utpR.getNewLod());\r
+ utpR.setLeftLod(utp.getNewLod());\r
+ }\r
+ if (down != null) {\r
+ UpdatedTerrainPatch utpD = updated.get(down.getName());\r
+ if (utpD == null) {\r
+ utpD = new UpdatedTerrainPatch(down, down.lod);\r
+ updated.put(utpD.getName(), utpD);\r
+ }\r
\r
- TerrainPatch patch = (TerrainPatch) child;\r
- if (!patch.searchedForNeighboursAlready) {\r
- // set the references to the neighbours\r
- patch.rightNeighbour = findRightPatch(patch);\r
- patch.bottomNeighbour = findDownPatch(patch);\r
- patch.leftNeighbour = findLeftPatch(patch);\r
- patch.topNeighbour = findTopPatch(patch);\r
- patch.searchedForNeighboursAlready = true;\r
- }\r
- TerrainPatch right = patch.rightNeighbour;\r
- TerrainPatch down = patch.bottomNeighbour;\r
-\r
- UpdatedTerrainPatch utp = updated.get(patch.getName());\r
- if (utp == null) {\r
- utp = new UpdatedTerrainPatch(patch, patch.lod);\r
- updated.put(utp.getName(), utp);\r
- }\r
-\r
- if (right != null) {\r
- UpdatedTerrainPatch utpR = updated.get(right.getName());\r
- if (utpR == null) {\r
- utpR = new UpdatedTerrainPatch(right, right.lod);\r
- updated.put(utpR.getName(), utpR);\r
- }\r
-\r
- utp.setRightLod(utpR.getNewLod());\r
- utpR.setLeftLod(utp.getNewLod());\r
- }\r
- if (down != null) {\r
- UpdatedTerrainPatch utpD = updated.get(down.getName());\r
- if (utpD == null) {\r
- utpD = new UpdatedTerrainPatch(down, down.lod);\r
- updated.put(utpD.getName(), utpD);\r
- }\r
-\r
- utp.setBottomLod(utpD.getNewLod());\r
- utpD.setTopLod(utp.getNewLod());\r
- }\r
-\r
- }\r
- }\r
- }\r
- }\r
+ utp.setBottomLod(utpD.getNewLod());\r
+ utpD.setTopLod(utp.getNewLod());\r
+ }\r
\r
- /**\r
- * Find any neighbours that should have their edges seamed because another neighbour\r
- * changed its LOD to a greater value (less detailed)\r
- */\r
- protected synchronized void fixEdges(HashMap<String,UpdatedTerrainPatch> updated) {\r
- if (children != null) {\r
- for (int x = children.size(); --x >= 0;) {\r
- Spatial child = children.get(x);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).fixEdges(updated);\r
- } else if (child instanceof TerrainPatch) {\r
- TerrainPatch patch = (TerrainPatch) child;\r
- UpdatedTerrainPatch utp = updated.get(patch.getName());\r
-\r
- if(utp.lodChanged()) {\r
- if (!patch.searchedForNeighboursAlready) {\r
- // set the references to the neighbours\r
- patch.rightNeighbour = findRightPatch(patch);\r
- patch.bottomNeighbour = findDownPatch(patch);\r
- patch.leftNeighbour = findLeftPatch(patch);\r
- patch.topNeighbour = findTopPatch(patch);\r
- patch.searchedForNeighboursAlready = true;\r
- }\r
- TerrainPatch right = patch.rightNeighbour;\r
- TerrainPatch down = patch.bottomNeighbour;\r
- TerrainPatch top = patch.topNeighbour;\r
- TerrainPatch left = patch.leftNeighbour;\r
- if (right != null) {\r
- UpdatedTerrainPatch utpR = updated.get(right.getName());\r
- if (utpR == null) {\r
- utpR = new UpdatedTerrainPatch(right, right.lod);\r
- updated.put(utpR.getName(), utpR);\r
- }\r
- utpR.setFixEdges(true);\r
- }\r
- if (down != null) {\r
- UpdatedTerrainPatch utpD = updated.get(down.getName());\r
- if (utpD == null) {\r
- utpD = new UpdatedTerrainPatch(down, down.lod);\r
- updated.put(utpD.getName(), utpD);\r
- }\r
- utpD.setFixEdges(true);\r
- }\r
- if (top != null){\r
- UpdatedTerrainPatch utpT = updated.get(top.getName());\r
- if (utpT == null) {\r
- utpT = new UpdatedTerrainPatch(top, top.lod);\r
- updated.put(utpT.getName(), utpT);\r
- }\r
- utpT.setFixEdges(true);\r
- }\r
- if (left != null){\r
- UpdatedTerrainPatch utpL = updated.get(left.getName());\r
- if (utpL == null) {\r
- utpL = new UpdatedTerrainPatch(left, left.lod);\r
- updated.put(utpL.getName(), utpL);\r
- }\r
- utpL.setFixEdges(true);\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated) {\r
- if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).reIndexPages(updated);\r
- } else if (child instanceof TerrainPatch) {\r
- ((TerrainPatch) child).reIndexGeometry(updated);\r
- }\r
- }\r
- }\r
- }\r
+ /**\r
+ * Find any neighbours that should have their edges seamed because another neighbour\r
+ * changed its LOD to a greater value (less detailed)\r
+ */\r
+ protected synchronized void fixEdges(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ if (children != null) {\r
+ for (int x = children.size(); --x >= 0;) {\r
+ Spatial child = children.get(x);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).fixEdges(updated);\r
+ } else if (child instanceof TerrainPatch) {\r
+ TerrainPatch patch = (TerrainPatch) child;\r
+ UpdatedTerrainPatch utp = updated.get(patch.getName());\r
+\r
+ if(utp.lodChanged()) {\r
+ if (!patch.searchedForNeighboursAlready) {\r
+ // set the references to the neighbours\r
+ patch.rightNeighbour = findRightPatch(patch);\r
+ patch.bottomNeighbour = findDownPatch(patch);\r
+ patch.leftNeighbour = findLeftPatch(patch);\r
+ patch.topNeighbour = findTopPatch(patch);\r
+ patch.searchedForNeighboursAlready = true;\r
+ }\r
+ TerrainPatch right = patch.rightNeighbour;\r
+ TerrainPatch down = patch.bottomNeighbour;\r
+ TerrainPatch top = patch.topNeighbour;\r
+ TerrainPatch left = patch.leftNeighbour;\r
+ if (right != null) {\r
+ UpdatedTerrainPatch utpR = updated.get(right.getName());\r
+ if (utpR == null) {\r
+ utpR = new UpdatedTerrainPatch(right, right.lod);\r
+ updated.put(utpR.getName(), utpR);\r
+ }\r
+ utpR.setFixEdges(true);\r
+ }\r
+ if (down != null) {\r
+ UpdatedTerrainPatch utpD = updated.get(down.getName());\r
+ if (utpD == null) {\r
+ utpD = new UpdatedTerrainPatch(down, down.lod);\r
+ updated.put(utpD.getName(), utpD);\r
+ }\r
+ utpD.setFixEdges(true);\r
+ }\r
+ if (top != null){\r
+ UpdatedTerrainPatch utpT = updated.get(top.getName());\r
+ if (utpT == null) {\r
+ utpT = new UpdatedTerrainPatch(top, top.lod);\r
+ updated.put(utpT.getName(), utpT);\r
+ }\r
+ utpT.setFixEdges(true);\r
+ }\r
+ if (left != null){\r
+ UpdatedTerrainPatch utpL = updated.get(left.getName());\r
+ if (utpL == null) {\r
+ utpL = new UpdatedTerrainPatch(left, left.lod);\r
+ updated.put(utpL.getName(), utpL);\r
+ }\r
+ utpL.setFixEdges(true);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- /**\r
- * <code>split</code> divides the heightmap data for four children. The\r
- * children are either pages or blocks. This is dependent on the size of the\r
- * children. If the child's size is less than or equal to the set block\r
- * size, then blocks are created, otherwise, pages are created.\r
- *\r
- * @param blockSize\r
- * the blocks size to test against.\r
- * @param heightMap\r
- * the height data.\r
- */\r
- protected void split(int blockSize, float[] heightMap) {\r
- if ((size >> 1) + 1 <= blockSize) {\r
- createQuadPatch(heightMap);\r
- } else {\r
- createQuad(blockSize, heightMap);\r
- }\r
+ protected synchronized void reIndexPages(HashMap<String,UpdatedTerrainPatch> updated) {\r
+ if (children != null) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).reIndexPages(updated);\r
+ } else if (child instanceof TerrainPatch) {\r
+ ((TerrainPatch) child).reIndexGeometry(updated);\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- }\r
+ /**\r
+ * <code>split</code> divides the heightmap data for four children. The\r
+ * children are either pages or blocks. This is dependent on the size of the\r
+ * children. If the child's size is less than or equal to the set block\r
+ * size, then blocks are created, otherwise, pages are created.\r
+ *\r
+ * @param blockSize\r
+ * the blocks size to test against.\r
+ * @param heightMap\r
+ * the height data.\r
+ */\r
+ protected void split(int blockSize, float[] heightMap) {\r
+ if ((size >> 1) + 1 <= blockSize) {\r
+ createQuadPatch(heightMap);\r
+ } else {\r
+ createQuad(blockSize, heightMap);\r
+ }\r
\r
- /**\r
- * <code>createQuadPage</code> generates four new pages from this page.\r
- */\r
- protected void createQuad(int blockSize, float[] heightMap) {\r
- // create 4 terrain pages\r
- int quarterSize = size >> 2;\r
-\r
- int split = (size + 1) >> 1;\r
-\r
- Vector2f tempOffset = new Vector2f();\r
- offsetAmount += quarterSize;\r
-\r
- if (lodCalculatorFactory == null)\r
- lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
-\r
- // 1 upper left\r
- float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
-\r
- Vector3f origin1 = new Vector3f(-quarterSize * stepScale.x, 0,\r
- -quarterSize * stepScale.z);\r
-\r
- tempOffset.x = offset.x;\r
- tempOffset.y = offset.y;\r
- tempOffset.x += origin1.x;\r
- tempOffset.y += origin1.z;\r
-\r
- TerrainQuad page1 = new TerrainQuad(getName() + "Quad1", blockSize,\r
- split, stepScale, heightBlock1, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
- page1.setLocalTranslation(origin1);\r
- page1.quadrant = 1;\r
- this.attachChild(page1);\r
-\r
- // 2 lower left\r
- float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,\r
- split);\r
-\r
- Vector3f origin2 = new Vector3f(-quarterSize * stepScale.x, 0,\r
- quarterSize * stepScale.z);\r
-\r
- tempOffset = new Vector2f();\r
- tempOffset.x = offset.x;\r
- tempOffset.y = offset.y;\r
- tempOffset.x += origin2.x;\r
- tempOffset.y += origin2.z;\r
-\r
- TerrainQuad page2 = new TerrainQuad(getName() + "Quad2", blockSize,\r
- split, stepScale, heightBlock2, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
- page2.setLocalTranslation(origin2);\r
- page2.quadrant = 2;\r
- this.attachChild(page2);\r
-\r
- // 3 upper right\r
- float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,\r
- split);\r
-\r
- Vector3f origin3 = new Vector3f(quarterSize * stepScale.x, 0,\r
- -quarterSize * stepScale.z);\r
-\r
- tempOffset = new Vector2f();\r
- tempOffset.x = offset.x;\r
- tempOffset.y = offset.y;\r
- tempOffset.x += origin3.x;\r
- tempOffset.y += origin3.z;\r
-\r
- TerrainQuad page3 = new TerrainQuad(getName() + "Quad3", blockSize,\r
- split, stepScale, heightBlock3, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
- page3.setLocalTranslation(origin3);\r
- page3.quadrant = 3;\r
- this.attachChild(page3);\r
- // //\r
- // 4 lower right\r
- float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,\r
- split - 1, split);\r
-\r
- Vector3f origin4 = new Vector3f(quarterSize * stepScale.x, 0,\r
- quarterSize * stepScale.z);\r
-\r
- tempOffset = new Vector2f();\r
- tempOffset.x = offset.x;\r
- tempOffset.y = offset.y;\r
- tempOffset.x += origin4.x;\r
- tempOffset.y += origin4.z;\r
-\r
- TerrainQuad page4 = new TerrainQuad(getName() + "Quad4", blockSize,\r
- split, stepScale, heightBlock4, totalSize, tempOffset,\r
- offsetAmount, lodCalculatorFactory);\r
- page4.setLocalTranslation(origin4);\r
- page4.quadrant = 4;\r
- this.attachChild(page4);\r
+ }\r
\r
- }\r
+ /**\r
+ * <code>createQuadPage</code> generates four new pages from this page.\r
+ */\r
+ protected void createQuad(int blockSize, float[] heightMap) {\r
+ // create 4 terrain pages\r
+ int quarterSize = size >> 2;\r
+\r
+ int split = (size + 1) >> 1;\r
+\r
+ Vector2f tempOffset = new Vector2f();\r
+ offsetAmount += quarterSize;\r
+\r
+ if (lodCalculatorFactory == null)\r
+ lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+\r
+ // 1 upper left\r
+ float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
+\r
+ Vector3f origin1 = new Vector3f(-quarterSize * stepScale.x, 0,\r
+ -quarterSize * stepScale.z);\r
+\r
+ tempOffset.x = offset.x;\r
+ tempOffset.y = offset.y;\r
+ tempOffset.x += origin1.x;\r
+ tempOffset.y += origin1.z;\r
+\r
+ TerrainQuad page1 = new TerrainQuad(getName() + "Quad1", blockSize,\r
+ split, stepScale, heightBlock1, totalSize, tempOffset,\r
+ offsetAmount, lodCalculatorFactory);\r
+ page1.setLocalTranslation(origin1);\r
+ page1.quadrant = 1;\r
+ this.attachChild(page1);\r
+\r
+ // 2 lower left\r
+ float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,\r
+ split);\r
+\r
+ Vector3f origin2 = new Vector3f(-quarterSize * stepScale.x, 0,\r
+ quarterSize * stepScale.z);\r
+\r
+ tempOffset = new Vector2f();\r
+ tempOffset.x = offset.x;\r
+ tempOffset.y = offset.y;\r
+ tempOffset.x += origin2.x;\r
+ tempOffset.y += origin2.z;\r
+\r
+ TerrainQuad page2 = new TerrainQuad(getName() + "Quad2", blockSize,\r
+ split, stepScale, heightBlock2, totalSize, tempOffset,\r
+ offsetAmount, lodCalculatorFactory);\r
+ page2.setLocalTranslation(origin2);\r
+ page2.quadrant = 2;\r
+ this.attachChild(page2);\r
+\r
+ // 3 upper right\r
+ float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,\r
+ split);\r
+\r
+ Vector3f origin3 = new Vector3f(quarterSize * stepScale.x, 0,\r
+ -quarterSize * stepScale.z);\r
+\r
+ tempOffset = new Vector2f();\r
+ tempOffset.x = offset.x;\r
+ tempOffset.y = offset.y;\r
+ tempOffset.x += origin3.x;\r
+ tempOffset.y += origin3.z;\r
+\r
+ TerrainQuad page3 = new TerrainQuad(getName() + "Quad3", blockSize,\r
+ split, stepScale, heightBlock3, totalSize, tempOffset,\r
+ offsetAmount, lodCalculatorFactory);\r
+ page3.setLocalTranslation(origin3);\r
+ page3.quadrant = 3;\r
+ this.attachChild(page3);\r
+ // //\r
+ // 4 lower right\r
+ float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,\r
+ split - 1, split);\r
+\r
+ Vector3f origin4 = new Vector3f(quarterSize * stepScale.x, 0,\r
+ quarterSize * stepScale.z);\r
+\r
+ tempOffset = new Vector2f();\r
+ tempOffset.x = offset.x;\r
+ tempOffset.y = offset.y;\r
+ tempOffset.x += origin4.x;\r
+ tempOffset.y += origin4.z;\r
+\r
+ TerrainQuad page4 = new TerrainQuad(getName() + "Quad4", blockSize,\r
+ split, stepScale, heightBlock4, totalSize, tempOffset,\r
+ offsetAmount, lodCalculatorFactory);\r
+ page4.setLocalTranslation(origin4);\r
+ page4.quadrant = 4;\r
+ this.attachChild(page4);\r
+\r
+ }\r
\r
public void generateDebugTangents(Material mat) {\r
for (int x = children.size(); --x >= 0;) {\r
}\r
}\r
}\r
- /**\r
- * <code>createQuadBlock</code> creates four child blocks from this page.\r
- */\r
- protected void createQuadPatch(float[] heightMap) {\r
- // create 4 terrain blocks\r
- int quarterSize = size >> 2;\r
- int halfSize = size >> 1;\r
- int split = (size + 1) >> 1;\r
-\r
- if (lodCalculatorFactory == null)\r
- lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
-\r
- offsetAmount += quarterSize;\r
-\r
- // 1 upper left\r
- float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
-\r
- Vector3f origin1 = new Vector3f(-halfSize * stepScale.x, 0, -halfSize\r
- * stepScale.z);\r
-\r
- Vector2f tempOffset1 = new Vector2f();\r
- tempOffset1.x = offset.x;\r
- tempOffset1.y = offset.y;\r
- tempOffset1.x += origin1.x / 2;\r
- tempOffset1.y += origin1.z / 2;\r
-\r
- TerrainPatch patch1 = new TerrainPatch(getName() + "Patch1", split,\r
- stepScale, heightBlock1, origin1, totalSize, tempOffset1,\r
- offsetAmount);\r
- patch1.setQuadrant((short) 1);\r
- this.attachChild(patch1);\r
- patch1.setModelBound(new BoundingBox());\r
- patch1.updateModelBound();\r
- patch1.setLodCalculator(lodCalculatorFactory);\r
+\r
+ /**\r
+ * <code>createQuadBlock</code> creates four child blocks from this page.\r
+ */\r
+ protected void createQuadPatch(float[] heightMap) {\r
+ // create 4 terrain blocks\r
+ int quarterSize = size >> 2;\r
+ int halfSize = size >> 1;\r
+ int split = (size + 1) >> 1;\r
+\r
+ if (lodCalculatorFactory == null)\r
+ lodCalculatorFactory = new LodDistanceCalculatorFactory(); // set a default one\r
+\r
+ offsetAmount += quarterSize;\r
+\r
+ // 1 upper left\r
+ float[] heightBlock1 = createHeightSubBlock(heightMap, 0, 0, split);\r
+\r
+ Vector3f origin1 = new Vector3f(-halfSize * stepScale.x, 0, -halfSize\r
+ * stepScale.z);\r
+\r
+ Vector2f tempOffset1 = new Vector2f();\r
+ tempOffset1.x = offset.x;\r
+ tempOffset1.y = offset.y;\r
+ tempOffset1.x += origin1.x / 2;\r
+ tempOffset1.y += origin1.z / 2;\r
+\r
+ TerrainPatch patch1 = new TerrainPatch(getName() + "Patch1", split,\r
+ stepScale, heightBlock1, origin1, totalSize, tempOffset1,\r
+ offsetAmount);\r
+ patch1.setQuadrant((short) 1);\r
+ this.attachChild(patch1);\r
+ patch1.setModelBound(new BoundingBox());\r
+ patch1.updateModelBound();\r
+ patch1.setLodCalculator(lodCalculatorFactory);\r
TangentBinormalGenerator.generate(patch1);\r
\r
- // 2 lower left\r
- float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,\r
- split);\r
-\r
- Vector3f origin2 = new Vector3f(-halfSize * stepScale.x, 0, 0);\r
-\r
- Vector2f tempOffset2 = new Vector2f();\r
- tempOffset2.x = offset.x;\r
- tempOffset2.y = offset.y;\r
- tempOffset2.x += origin1.x / 2;\r
- tempOffset2.y += quarterSize * stepScale.z;\r
-\r
- TerrainPatch patch2 = new TerrainPatch(getName() + "Patch2", split,\r
- stepScale, heightBlock2, origin2, totalSize, tempOffset2,\r
- offsetAmount);\r
- patch2.setQuadrant((short) 2);\r
- this.attachChild(patch2);\r
- patch2.setModelBound(new BoundingBox());\r
- patch2.updateModelBound();\r
- patch2.setLodCalculator(lodCalculatorFactory);\r
+ // 2 lower left\r
+ float[] heightBlock2 = createHeightSubBlock(heightMap, 0, split - 1,\r
+ split);\r
+\r
+ Vector3f origin2 = new Vector3f(-halfSize * stepScale.x, 0, 0);\r
+\r
+ Vector2f tempOffset2 = new Vector2f();\r
+ tempOffset2.x = offset.x;\r
+ tempOffset2.y = offset.y;\r
+ tempOffset2.x += origin1.x / 2;\r
+ tempOffset2.y += quarterSize * stepScale.z;\r
+\r
+ TerrainPatch patch2 = new TerrainPatch(getName() + "Patch2", split,\r
+ stepScale, heightBlock2, origin2, totalSize, tempOffset2,\r
+ offsetAmount);\r
+ patch2.setQuadrant((short) 2);\r
+ this.attachChild(patch2);\r
+ patch2.setModelBound(new BoundingBox());\r
+ patch2.updateModelBound();\r
+ patch2.setLodCalculator(lodCalculatorFactory);\r
TangentBinormalGenerator.generate(patch2);\r
\r
- // 3 upper right\r
- float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,\r
- split);\r
-\r
- Vector3f origin3 = new Vector3f(0, 0, -halfSize * stepScale.z);\r
-\r
- Vector2f tempOffset3 = new Vector2f();\r
- tempOffset3.x = offset.x;\r
- tempOffset3.y = offset.y;\r
- tempOffset3.x += quarterSize * stepScale.x;\r
- tempOffset3.y += origin3.z / 2;\r
-\r
- TerrainPatch patch3 = new TerrainPatch(getName() + "Patch3", split,\r
- stepScale, heightBlock3, origin3, totalSize, tempOffset3,\r
- offsetAmount);\r
- patch3.setQuadrant((short) 3);\r
- this.attachChild(patch3);\r
- patch3.setModelBound(new BoundingBox());\r
- patch3.updateModelBound();\r
- patch3.setLodCalculator(lodCalculatorFactory);\r
+ // 3 upper right\r
+ float[] heightBlock3 = createHeightSubBlock(heightMap, split - 1, 0,\r
+ split);\r
+\r
+ Vector3f origin3 = new Vector3f(0, 0, -halfSize * stepScale.z);\r
+\r
+ Vector2f tempOffset3 = new Vector2f();\r
+ tempOffset3.x = offset.x;\r
+ tempOffset3.y = offset.y;\r
+ tempOffset3.x += quarterSize * stepScale.x;\r
+ tempOffset3.y += origin3.z / 2;\r
+\r
+ TerrainPatch patch3 = new TerrainPatch(getName() + "Patch3", split,\r
+ stepScale, heightBlock3, origin3, totalSize, tempOffset3,\r
+ offsetAmount);\r
+ patch3.setQuadrant((short) 3);\r
+ this.attachChild(patch3);\r
+ patch3.setModelBound(new BoundingBox());\r
+ patch3.updateModelBound();\r
+ patch3.setLodCalculator(lodCalculatorFactory);\r
TangentBinormalGenerator.generate(patch3);\r
\r
- // 4 lower right\r
- float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,\r
- split - 1, split);\r
-\r
- Vector3f origin4 = new Vector3f(0, 0, 0);\r
-\r
- Vector2f tempOffset4 = new Vector2f();\r
- tempOffset4.x = offset.x;\r
- tempOffset4.y = offset.y;\r
- tempOffset4.x += quarterSize * stepScale.x;\r
- tempOffset4.y += quarterSize * stepScale.z;\r
-\r
- TerrainPatch patch4 = new TerrainPatch(getName() + "Patch4", split,\r
- stepScale, heightBlock4, origin4, totalSize, tempOffset4,\r
- offsetAmount);\r
- patch4.setQuadrant((short) 4);\r
- this.attachChild(patch4);\r
- patch4.setModelBound(new BoundingBox());\r
- patch4.updateModelBound();\r
- patch4.setLodCalculator(lodCalculatorFactory);\r
+ // 4 lower right\r
+ float[] heightBlock4 = createHeightSubBlock(heightMap, split - 1,\r
+ split - 1, split);\r
+\r
+ Vector3f origin4 = new Vector3f(0, 0, 0);\r
+\r
+ Vector2f tempOffset4 = new Vector2f();\r
+ tempOffset4.x = offset.x;\r
+ tempOffset4.y = offset.y;\r
+ tempOffset4.x += quarterSize * stepScale.x;\r
+ tempOffset4.y += quarterSize * stepScale.z;\r
+\r
+ TerrainPatch patch4 = new TerrainPatch(getName() + "Patch4", split,\r
+ stepScale, heightBlock4, origin4, totalSize, tempOffset4,\r
+ offsetAmount);\r
+ patch4.setQuadrant((short) 4);\r
+ this.attachChild(patch4);\r
+ patch4.setModelBound(new BoundingBox());\r
+ patch4.updateModelBound();\r
+ patch4.setLodCalculator(lodCalculatorFactory);\r
TangentBinormalGenerator.generate(patch4);\r
- }\r
+ }\r
\r
- public float[] createHeightSubBlock(float[] heightMap, int x,\r
- int y, int side) {\r
- float[] rVal = new float[side * side];\r
- int bsize = (int) FastMath.sqrt(heightMap.length);\r
- int count = 0;\r
- for (int i = y; i < side + y; i++) {\r
- for (int j = x; j < side + x; j++) {\r
- if (j < bsize && i < bsize)\r
- rVal[count] = heightMap[j + (i * bsize)];\r
- count++;\r
- }\r
- }\r
- return rVal;\r
- }\r
+ public float[] createHeightSubBlock(float[] heightMap, int x,\r
+ int y, int side) {\r
+ float[] rVal = new float[side * side];\r
+ int bsize = (int) FastMath.sqrt(heightMap.length);\r
+ int count = 0;\r
+ for (int i = y; i < side + y; i++) {\r
+ for (int j = x; j < side + x; j++) {\r
+ if (j < bsize && i < bsize)\r
+ rVal[count] = heightMap[j + (i * bsize)];\r
+ count++;\r
+ }\r
+ }\r
+ return rVal;\r
+ }\r
\r
/**\r
* A handy method that will attach all bounding boxes of this terrain\r
}\r
\r
\r
- public int getQuadrant() {\r
- return quadrant;\r
- }\r
+ public int getQuadrant() {\r
+ return quadrant;\r
+ }\r
\r
- public void setQuadrant(short quadrant) {\r
- this.quadrant = quadrant;\r
- }\r
+ public void setQuadrant(short quadrant) {\r
+ this.quadrant = quadrant;\r
+ }\r
\r
\r
- protected TerrainPatch getPatch(int quad) {\r
- if (children != null)\r
- for (int x = children.size(); --x >= 0;) {\r
- Spatial child = children.get(x);\r
- if (child instanceof TerrainPatch) {\r
- TerrainPatch tb = (TerrainPatch) child;\r
- if (tb.getQuadrant() == quad)\r
- return tb;\r
- }\r
- }\r
- return null;\r
- }\r
+ protected TerrainPatch getPatch(int quad) {\r
+ if (children != null)\r
+ for (int x = children.size(); --x >= 0;) {\r
+ Spatial child = children.get(x);\r
+ if (child instanceof TerrainPatch) {\r
+ TerrainPatch tb = (TerrainPatch) child;\r
+ if (tb.getQuadrant() == quad)\r
+ return tb;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
\r
- protected TerrainQuad getQuad(int quad) {\r
- if (children != null)\r
- for (int x = children.size(); --x >= 0;) {\r
- Spatial child = children.get(x);\r
- if (child instanceof TerrainQuad) {\r
- TerrainQuad tq = (TerrainQuad) child;\r
- if (tq.getQuadrant() == quad)\r
- return tq;\r
- }\r
- }\r
- return null;\r
- }\r
+ protected TerrainQuad getQuad(int quad) {\r
+ if (children != null)\r
+ for (int x = children.size(); --x >= 0;) {\r
+ Spatial child = children.get(x);\r
+ if (child instanceof TerrainQuad) {\r
+ TerrainQuad tq = (TerrainQuad) child;\r
+ if (tq.getQuadrant() == quad)\r
+ return tq;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
\r
- protected TerrainPatch findRightPatch(TerrainPatch tp) {\r
- if (tp.getQuadrant() == 1)\r
- return getPatch(3);\r
- else if (tp.getQuadrant() == 2)\r
- return getPatch(4);\r
- else if (tp.getQuadrant() == 3) {\r
- // find the page to the right and ask it for child 1.\r
- TerrainQuad quad = findRightQuad();\r
- if (quad != null)\r
- return quad.getPatch(1);\r
- } else if (tp.getQuadrant() == 4) {\r
- // find the page to the right and ask it for child 2.\r
- TerrainQuad quad = findRightQuad();\r
- if (quad != null)\r
- return quad.getPatch(2);\r
- }\r
+ protected TerrainPatch findRightPatch(TerrainPatch tp) {\r
+ if (tp.getQuadrant() == 1)\r
+ return getPatch(3);\r
+ else if (tp.getQuadrant() == 2)\r
+ return getPatch(4);\r
+ else if (tp.getQuadrant() == 3) {\r
+ // find the page to the right and ask it for child 1.\r
+ TerrainQuad quad = findRightQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(1);\r
+ } else if (tp.getQuadrant() == 4) {\r
+ // find the page to the right and ask it for child 2.\r
+ TerrainQuad quad = findRightQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(2);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainPatch findDownPatch(TerrainPatch tp) {\r
- if (tp.getQuadrant() == 1)\r
- return getPatch(2);\r
- else if (tp.getQuadrant() == 3)\r
- return getPatch(4);\r
- else if (tp.getQuadrant() == 2) {\r
- // find the page below and ask it for child 1.\r
- TerrainQuad quad = findDownQuad();\r
- if (quad != null)\r
- return quad.getPatch(1);\r
- } else if (tp.getQuadrant() == 4) {\r
- TerrainQuad quad = findDownQuad();\r
- if (quad != null)\r
- return quad.getPatch(3);\r
- }\r
+ protected TerrainPatch findDownPatch(TerrainPatch tp) {\r
+ if (tp.getQuadrant() == 1)\r
+ return getPatch(2);\r
+ else if (tp.getQuadrant() == 3)\r
+ return getPatch(4);\r
+ else if (tp.getQuadrant() == 2) {\r
+ // find the page below and ask it for child 1.\r
+ TerrainQuad quad = findDownQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(1);\r
+ } else if (tp.getQuadrant() == 4) {\r
+ TerrainQuad quad = findDownQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(3);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
\r
- protected TerrainPatch findTopPatch(TerrainPatch tp) {\r
- if (tp.getQuadrant() == 2)\r
- return getPatch(1);\r
- else if (tp.getQuadrant() == 4)\r
- return getPatch(3);\r
- else if (tp.getQuadrant() == 1) {\r
- // find the page above and ask it for child 2.\r
- TerrainQuad quad = findTopQuad();\r
- if (quad != null)\r
- return quad.getPatch(2);\r
- } else if (tp.getQuadrant() == 3) {\r
- TerrainQuad quad = findTopQuad();\r
- if (quad != null)\r
- return quad.getPatch(4);\r
- }\r
+ protected TerrainPatch findTopPatch(TerrainPatch tp) {\r
+ if (tp.getQuadrant() == 2)\r
+ return getPatch(1);\r
+ else if (tp.getQuadrant() == 4)\r
+ return getPatch(3);\r
+ else if (tp.getQuadrant() == 1) {\r
+ // find the page above and ask it for child 2.\r
+ TerrainQuad quad = findTopQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(2);\r
+ } else if (tp.getQuadrant() == 3) {\r
+ TerrainQuad quad = findTopQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(4);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainPatch findLeftPatch(TerrainPatch tp) {\r
- if (tp.getQuadrant() == 3)\r
- return getPatch(1);\r
- else if (tp.getQuadrant() == 4)\r
- return getPatch(2);\r
- else if (tp.getQuadrant() == 1) {\r
- // find the page above and ask it for child 2.\r
- TerrainQuad quad = findLeftQuad();\r
- if (quad != null)\r
- return quad.getPatch(3);\r
- } else if (tp.getQuadrant() == 2) {\r
- TerrainQuad quad = findLeftQuad();\r
- if (quad != null)\r
- return quad.getPatch(4);\r
- }\r
+ protected TerrainPatch findLeftPatch(TerrainPatch tp) {\r
+ if (tp.getQuadrant() == 3)\r
+ return getPatch(1);\r
+ else if (tp.getQuadrant() == 4)\r
+ return getPatch(2);\r
+ else if (tp.getQuadrant() == 1) {\r
+ // find the page above and ask it for child 2.\r
+ TerrainQuad quad = findLeftQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(3);\r
+ } else if (tp.getQuadrant() == 2) {\r
+ TerrainQuad quad = findLeftQuad();\r
+ if (quad != null)\r
+ return quad.getPatch(4);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainQuad findRightQuad() {\r
- if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
- return null;\r
-\r
- TerrainQuad pQuad = (TerrainQuad) getParent();\r
-\r
- if (quadrant == 1)\r
- return pQuad.getQuad(3);\r
- else if (quadrant == 2)\r
- return pQuad.getQuad(4);\r
- else if (quadrant == 3) {\r
- TerrainQuad quad = pQuad.findRightQuad();\r
- if (quad != null)\r
- return quad.getQuad(1);\r
- } else if (quadrant == 4) {\r
- TerrainQuad quad = pQuad.findRightQuad();\r
- if (quad != null)\r
- return quad.getQuad(2);\r
- }\r
+ protected TerrainQuad findRightQuad() {\r
+ if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
+ return null;\r
+\r
+ TerrainQuad pQuad = (TerrainQuad) getParent();\r
+\r
+ if (quadrant == 1)\r
+ return pQuad.getQuad(3);\r
+ else if (quadrant == 2)\r
+ return pQuad.getQuad(4);\r
+ else if (quadrant == 3) {\r
+ TerrainQuad quad = pQuad.findRightQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(1);\r
+ } else if (quadrant == 4) {\r
+ TerrainQuad quad = pQuad.findRightQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(2);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainQuad findDownQuad() {\r
- if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
- return null;\r
-\r
- TerrainQuad pQuad = (TerrainQuad) getParent();\r
-\r
- if (quadrant == 1)\r
- return pQuad.getQuad(2);\r
- else if (quadrant == 3)\r
- return pQuad.getQuad(4);\r
- else if (quadrant == 2) {\r
- TerrainQuad quad = pQuad.findDownQuad();\r
- if (quad != null)\r
- return quad.getQuad(1);\r
- } else if (quadrant == 4) {\r
- TerrainQuad quad = pQuad.findDownQuad();\r
- if (quad != null)\r
- return quad.getQuad(3);\r
- }\r
+ protected TerrainQuad findDownQuad() {\r
+ if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
+ return null;\r
+\r
+ TerrainQuad pQuad = (TerrainQuad) getParent();\r
+\r
+ if (quadrant == 1)\r
+ return pQuad.getQuad(2);\r
+ else if (quadrant == 3)\r
+ return pQuad.getQuad(4);\r
+ else if (quadrant == 2) {\r
+ TerrainQuad quad = pQuad.findDownQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(1);\r
+ } else if (quadrant == 4) {\r
+ TerrainQuad quad = pQuad.findDownQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(3);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainQuad findTopQuad() {\r
- if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
- return null;\r
-\r
- TerrainQuad pQuad = (TerrainQuad) getParent();\r
-\r
- if (quadrant == 2)\r
- return pQuad.getQuad(1);\r
- else if (quadrant == 4)\r
- return pQuad.getQuad(3);\r
- else if (quadrant == 1) {\r
- TerrainQuad quad = pQuad.findTopQuad();\r
- if (quad != null)\r
- return quad.getQuad(2);\r
- } else if (quadrant == 3) {\r
- TerrainQuad quad = pQuad.findTopQuad();\r
- if (quad != null)\r
- return quad.getQuad(4);\r
- }\r
+ protected TerrainQuad findTopQuad() {\r
+ if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
+ return null;\r
+\r
+ TerrainQuad pQuad = (TerrainQuad) getParent();\r
+\r
+ if (quadrant == 2)\r
+ return pQuad.getQuad(1);\r
+ else if (quadrant == 4)\r
+ return pQuad.getQuad(3);\r
+ else if (quadrant == 1) {\r
+ TerrainQuad quad = pQuad.findTopQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(2);\r
+ } else if (quadrant == 3) {\r
+ TerrainQuad quad = pQuad.findTopQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(4);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
- protected TerrainQuad findLeftQuad() {\r
- if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
- return null;\r
-\r
- TerrainQuad pQuad = (TerrainQuad) getParent();\r
-\r
- if (quadrant == 3)\r
- return pQuad.getQuad(1);\r
- else if (quadrant == 4)\r
- return pQuad.getQuad(2);\r
- else if (quadrant == 1) {\r
- TerrainQuad quad = pQuad.findLeftQuad();\r
- if (quad != null)\r
- return quad.getQuad(3);\r
- } else if (quadrant == 2) {\r
- TerrainQuad quad = pQuad.findLeftQuad();\r
- if (quad != null)\r
- return quad.getQuad(4);\r
- }\r
+ protected TerrainQuad findLeftQuad() {\r
+ if (getParent() == null || !(getParent() instanceof TerrainQuad))\r
+ return null;\r
+\r
+ TerrainQuad pQuad = (TerrainQuad) getParent();\r
+\r
+ if (quadrant == 3)\r
+ return pQuad.getQuad(1);\r
+ else if (quadrant == 4)\r
+ return pQuad.getQuad(2);\r
+ else if (quadrant == 1) {\r
+ TerrainQuad quad = pQuad.findLeftQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(3);\r
+ } else if (quadrant == 2) {\r
+ TerrainQuad quad = pQuad.findLeftQuad();\r
+ if (quad != null)\r
+ return quad.getQuad(4);\r
+ }\r
\r
- return null;\r
- }\r
+ return null;\r
+ }\r
\r
/**\r
* Find what terrain patches need normal recalculations and update\r
}\r
}\r
\r
- /**\r
- * fix the normals on the edge of the terrain patches.\r
- */\r
- protected void fixNormalEdges(BoundingBox affectedArea) {\r
- if (children == null)\r
+ /**\r
+ * fix the normals on the edge of the terrain patches.\r
+ */\r
+ protected void fixNormalEdges(BoundingBox affectedArea) {\r
+ if (children == null)\r
return;\r
\r
for (int x = children.size(); --x >= 0;) {\r
}\r
} // for each child\r
\r
- }\r
+ }\r
\r
\r
\r
}\r
\r
\r
- /**\r
- * Retrieve all Terrain Patches from all children and store them\r
- * in the 'holder' list\r
- * @param holder must not be null, will be populated when returns\r
- */\r
- public void getAllTerrainPatches(List<TerrainPatch> holder) {\r
- if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).getAllTerrainPatches(holder);\r
- } else if (child instanceof TerrainPatch) {\r
- holder.add((TerrainPatch)child);\r
- }\r
- }\r
- }\r
- }\r
+ /**\r
+ * Retrieve all Terrain Patches from all children and store them\r
+ * in the 'holder' list\r
+ * @param holder must not be null, will be populated when returns\r
+ */\r
+ public void getAllTerrainPatches(List<TerrainPatch> holder) {\r
+ if (children != null) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).getAllTerrainPatches(holder);\r
+ } else if (child instanceof TerrainPatch) {\r
+ holder.add((TerrainPatch)child);\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- public void getAllTerrainPatchesWithTranslation(Map<TerrainPatch,Vector3f> holder, Vector3f translation) {\r
- if (children != null) {\r
- for (int i = children.size(); --i >= 0;) {\r
- Spatial child = children.get(i);\r
- if (child instanceof TerrainQuad) {\r
- ((TerrainQuad) child).getAllTerrainPatchesWithTranslation(holder, translation.clone().add(child.getLocalTranslation()));\r
- } else if (child instanceof TerrainPatch) {\r
- //if (holder.size() < 4)\r
- holder.put((TerrainPatch)child, translation.clone().add(child.getLocalTranslation()));\r
- }\r
- }\r
- }\r
- }\r
+ public void getAllTerrainPatchesWithTranslation(Map<TerrainPatch,Vector3f> holder, Vector3f translation) {\r
+ if (children != null) {\r
+ for (int i = children.size(); --i >= 0;) {\r
+ Spatial child = children.get(i);\r
+ if (child instanceof TerrainQuad) {\r
+ ((TerrainQuad) child).getAllTerrainPatchesWithTranslation(holder, translation.clone().add(child.getLocalTranslation()));\r
+ } else if (child instanceof TerrainPatch) {\r
+ //if (holder.size() < 4)\r
+ holder.put((TerrainPatch)child, translation.clone().add(child.getLocalTranslation()));\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- @Override\r
- public void read(JmeImporter e) throws IOException {\r
- super.read(e);\r
- InputCapsule c = e.getCapsule(this);\r
- size = c.readInt("size", 0);\r
- stepScale = (Vector3f) c.readSavable("stepScale", null);\r
- offset = (Vector2f) c.readSavable("offset", new Vector2f(0,0));\r
- offsetAmount = c.readFloat("offsetAmount", 0);\r
- quadrant = c.readInt("quadrant", 0);\r
- totalSize = c.readInt("totalSize", 0);\r
- lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);\r
+ @Override\r
+ public void read(JmeImporter e) throws IOException {\r
+ super.read(e);\r
+ InputCapsule c = e.getCapsule(this);\r
+ size = c.readInt("size", 0);\r
+ stepScale = (Vector3f) c.readSavable("stepScale", null);\r
+ offset = (Vector2f) c.readSavable("offset", new Vector2f(0,0));\r
+ offsetAmount = c.readFloat("offsetAmount", 0);\r
+ quadrant = c.readInt("quadrant", 0);\r
+ totalSize = c.readInt("totalSize", 0);\r
+ lodCalculatorFactory = (LodCalculatorFactory) c.readSavable("lodCalculatorFactory", null);\r
\r
// the terrain is re-built on load, so we need to run this once\r
//affectedAreaBBox = new BoundingBox(new Vector3f(0,0,0), size, Float.MAX_VALUE, size);\r
//updateNormals();\r
- }\r
+ }\r
\r
- @Override\r
- public void write(JmeExporter e) throws IOException {\r
- super.write(e);\r
- OutputCapsule c = e.getCapsule(this);\r
- c.write(size, "size", 0);\r
+ @Override\r
+ public void write(JmeExporter e) throws IOException {\r
+ super.write(e);\r
+ OutputCapsule c = e.getCapsule(this);\r
+ c.write(size, "size", 0);\r
c.write(totalSize, "totalSize", 0);\r
- c.write(stepScale, "stepScale", null);\r
- c.write(offset, "offset", new Vector2f(0,0));\r
- c.write(offsetAmount, "offsetAmount", 0);\r
- c.write(quadrant, "quadrant", 0);\r
+ c.write(stepScale, "stepScale", null);\r
+ c.write(offset, "offset", new Vector2f(0,0));\r
+ c.write(offsetAmount, "offsetAmount", 0);\r
+ c.write(quadrant, "quadrant", 0);\r
c.write(lodCalculatorFactory, "lodCalculatorFactory", null);\r
- }\r
+ }\r
\r
@Override\r
public TerrainQuad clone() {\r
normalControl.setTerrain(this);\r
\r
return quadClone;\r
- }\r
+ }\r
\r
\r
- public int getMaxLod() {\r
- if (maxLod < 0)\r
- maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide\r
+ public int getMaxLod() {\r
+ if (maxLod < 0)\r
+ maxLod = Math.max(1, (int) (FastMath.log(size-1)/FastMath.log(2)) -1); // -1 forces our minimum of 4 triangles wide\r
\r
- return maxLod;\r
- }\r
+ return maxLod;\r
+ }\r
\r
- public void useLOD(boolean useLod) {\r
- usingLOD = useLod;\r
- }\r
+ public void useLOD(boolean useLod) {\r
+ usingLOD = useLod;\r
+ }\r
\r
- public boolean isUsingLOD() {\r
- return usingLOD;\r
- }\r
+ public boolean isUsingLOD() {\r
+ return usingLOD;\r
+}\r
\r
public int getPatchSize() {\r
return patchSize;\r
}\r
\r
\r
- public float[] getHeightMap() {\r
+ public float[] getHeightMap() {\r
\r
//if (true)\r
// return heightMap;\r
}\r
\r
return hm;\r
- }\r
+ }\r
}\r
\r