aboutsummaryrefslogtreecommitdiffstats
path: root/ardor3d-terrain/src/main
diff options
context:
space:
mode:
authorneothemachine <[email protected]>2013-02-21 16:40:08 +0100
committerneothemachine <[email protected]>2013-02-21 16:40:08 +0100
commitf774bd917e9dfd8cf46e5ed66d41aad64477a238 (patch)
tree8d33aa0cf24165710d420c677f3336641223cff8 /ardor3d-terrain/src/main
parentedbc5c757c66d56eb2cffffa4076f0f2bfd6e748 (diff)
normalized line endings
see http://www.hanselman.com/blog/YoureJustAnotherCarriageReturnLineFeedInTheWall.aspx and https://help.github.com/articles/dealing-with-line-endings
Diffstat (limited to 'ardor3d-terrain/src/main')
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/ClipmapLevel.java1258
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/Terrain.java1424
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/TerrainDataProvider.java100
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/ImageHeightMap.java122
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/MidPointHeightMapGenerator.java614
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/RawHeightMap.java492
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainDataProvider.java270
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainSource.java222
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTextureSource.java226
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/awt/AwtTextureSource.java462
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/image/ImageTextureSource.java280
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainDataProvider.java178
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainSource.java266
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTextureSource.java284
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralNormalMapSource.java222
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainDataProvider.java148
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainSource.java194
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTextureSource.java240
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainDataProvider.java182
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainSource.java166
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTextureSource.java222
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamYUpGridTracer.java290
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamZUpGridTracer.java290
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/LevelData.java38
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Region.java498
-rw-r--r--ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Tile.java96
26 files changed, 4392 insertions, 4392 deletions
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/ClipmapLevel.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/ClipmapLevel.java
index 6817b5e..1c48584 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/ClipmapLevel.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/ClipmapLevel.java
@@ -1,630 +1,630 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.client;
-
-import java.nio.FloatBuffer;
-import java.util.Set;
-
-import com.ardor3d.bounding.BoundingBox;
-import com.ardor3d.extension.terrain.util.Region;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.math.Vector3;
-import com.ardor3d.renderer.Camera;
-import com.ardor3d.renderer.Camera.FrustumIntersect;
-import com.ardor3d.renderer.IndexMode;
-import com.ardor3d.scenegraph.FloatBufferData;
-import com.ardor3d.scenegraph.IndexBufferData;
-import com.ardor3d.scenegraph.Mesh;
-import com.ardor3d.scenegraph.event.DirtyType;
-import com.ardor3d.util.geom.BufferUtils;
-
-/**
- * ClipmapLevel is the visual representation of one lod level of height data.
- */
-public class ClipmapLevel extends Mesh {
-
- /**
- * Precalculated useful variables.
- */
- private final int doubleVertexDistance; // vertexDistance * 2;
- private final int frameDistance; // (frameSize - 1) * vertexDistance
-
- /**
- * Gets the distance between two horizontal/vertical vertices. The finest level L = 0 has a distance of
- * vertexDistance = 1. Then every level it doubles so vertexDistance is always 2^L
- */
- private final int vertexDistance;
-
- /**
- * Gets framesize in number of vertices between outer border of current clip and outer border of next finer (inner)
- * clip.
- */
- private final int frameSize;
-
- /**
- * Gets the width of a clip in number of vertices. This is always one less than power of two (2^x - 1)
- */
- private final int clipSideSize;
-
- /**
- * Gets the region of the current clip.
- */
- private final Region clipRegion;
- private final Region intersectionRegion;
-
- /**
- * Value that indicates the height scaling. It is also represents the maximum terrain height.
- */
- private final float heightScale;
-
- private float heightRangeMin = 0.0f;
- private float heightRangeMax = 1.0f;
-
- /**
- * Index to indicate how much vertices are added to the triangle strip.
- */
- private int stripIndex = 0;
-
- /**
- * The used terrain heightfield. This must be set per reference so all clip levels share the same memory for that
- * variable. The values are between 0.0f and 1.0f
- */
- private final TerrainCache cache;
-
- /**
- * Number of components for vertices
- */
- public static final int VERT_SIZE = 4;
-
- /**
- * Camera frustum to test clipmap tiles against for culling
- */
- private final Camera clipmapTestFrustum;
-
- /**
- * Used to handle transformations of the terrain
- */
- private final Vector3 transformedFrustumPos = new Vector3();
-
- /**
- * Should the clipmap generate per vertex normals
- */
- private final boolean generateNormals = false;
-
- /**
- * Bounding box used for culling
- */
- private final BoundingBox frustumCheckBounds = new BoundingBox();
-
- /**
- * Possible nio speedup when storing indices
- */
- private int[] tmpIndices;
-
- /**
- * Should cull blocks outside camera frustum
- */
- private boolean cullingEnabled = true;
-
- /**
- * Creates a new clipmaplevel.
- *
- * @param levelIndex
- * Levelindex of the clipmap. If is 0 this will be the finest level
- * @param clipSideSize
- * Number of vertices per clipside. Must be one less than power of two.
- * @param heightScale
- * Maximum terrainheight and heightscale
- * @param fieldsize
- * Width and heightvalue of the heightfield
- * @param heightfield
- * Heightvalues with a range of 0.0f - 1.0f
- * @exception Exception
- */
- public ClipmapLevel(final int levelIndex, final Camera clipmapTestFrustum, final int clipSideSize,
- final float heightScale, final TerrainCache cache) throws Exception {
- super("Clipmap Level " + levelIndex);
-
- // Check some exception cases
- if (levelIndex < 0) {
- throw new Exception("levelIndex must be positive");
- }
- if (!MathUtils.isPowerOfTwo(clipSideSize + 1)) {
- throw new Exception("clipSideSize must be one less than power of two");
- }
-
- // Apply the values
- this.clipmapTestFrustum = clipmapTestFrustum;
- this.cache = cache;
-
- this.heightScale = heightScale;
- this.clipSideSize = clipSideSize;
-
- // Calculate common variables
- vertexDistance = (int) Math.pow(2, levelIndex);
- frameSize = (clipSideSize + 1) / 4;
- doubleVertexDistance = vertexDistance * 2;
- frameDistance = (frameSize - 1) * vertexDistance;
- clipRegion = new Region(0, 0, (clipSideSize - 1) * vertexDistance, (clipSideSize - 1) * vertexDistance);
- intersectionRegion = new Region(0, 0, clipSideSize * vertexDistance, clipSideSize * vertexDistance);
-
- // Initialize the vertices
- initialize();
- }
-
- /**
- * Initializes the vertices and indices.
- */
- private void initialize() {
- getMeshData().setIndexMode(IndexMode.TriangleStrip);
-
- // clipSideSize is the number of vertices per clipmapside, so number of all vertices is clipSideSize *
- // clipSideSize
- final FloatBuffer vertices = BufferUtils.createVector4Buffer(clipSideSize * clipSideSize);
- getMeshData().setVertexCoords(new FloatBufferData(vertices, 4));
-
- if (generateNormals) {
- final FloatBuffer normals = BufferUtils.createVector3Buffer(clipSideSize * clipSideSize);
- getMeshData().setNormalCoords(new FloatBufferData(normals, 3));
- }
-
- // final FloatBuffer textureCoords = BufferUtils.createVector2Buffer(N * N);
- // getMeshData().setTextureBuffer(textureCoords, 0);
-
- final int indicesSize = 4 * (3 * frameSize * frameSize + clipSideSize * clipSideSize / 2 + 4 * frameSize - 10);
- final IndexBufferData<?> indices = BufferUtils.createIndexBufferData(indicesSize, vertices.capacity() - 1);
- tmpIndices = new int[indicesSize];
- getMeshData().setIndices(indices);
-
- // Go through all rows and fill them with vertexindices.
- for (int z = 0; z < clipSideSize - 1; z++) {
- fillRow(0, clipSideSize - 1, z, z + 1);
- }
- }
-
- public void updateCache() {
- getWorldTransform().applyInverse(clipmapTestFrustum.getLocation(), transformedFrustumPos);
- final int cx = (int) transformedFrustumPos.getX();
- final int cz = (int) transformedFrustumPos.getZ();
-
- // Calculate the new position
- int clipX = cx - (clipSideSize + 1) * vertexDistance / 2;
- int clipY = cz - (clipSideSize + 1) * vertexDistance / 2;
-
- // Calculate the modulo to doubleVertexDistance of the new position.
- // This makes sure that the current level always fits in the hole of the
- // coarser level. The gridspacing of the coarser level is vertexDistance * 2, so here doubleVertexDistance.
- final int modX = MathUtils.moduloPositive(clipX, doubleVertexDistance);
- final int modY = MathUtils.moduloPositive(clipY, doubleVertexDistance);
- clipX = clipX + doubleVertexDistance - modX;
- clipY = clipY + doubleVertexDistance - modY;
-
- cache.setCurrentPosition(clipX / vertexDistance, clipY / vertexDistance);
-
- // TODO
- cache.handleUpdateRequests();
- }
-
- /**
- * Update clipmap vertices
- *
- * @param center
- */
- public void updateVertices() {
- getWorldTransform().applyInverse(clipmapTestFrustum.getLocation(), transformedFrustumPos);
- final int cx = (int) transformedFrustumPos.getX();
- final int cz = (int) transformedFrustumPos.getZ();
-
- // Store the old position to be able to recover it if needed
- final int oldX = clipRegion.getX();
- final int oldZ = clipRegion.getY();
-
- // Calculate the new position
- clipRegion.setX(cx - (clipSideSize + 1) * vertexDistance / 2);
- clipRegion.setY(cz - (clipSideSize + 1) * vertexDistance / 2);
-
- // Calculate the modulo to doubleVertexDistance of the new position.
- // This makes sure that the current level always fits in the hole of the
- // coarser level. The gridspacing of the coarser level is vertexDistance * 2, so here doubleVertexDistance.
- final int modX = MathUtils.moduloPositive(clipRegion.getX(), doubleVertexDistance);
- final int modY = MathUtils.moduloPositive(clipRegion.getY(), doubleVertexDistance);
- clipRegion.setX(clipRegion.getX() + doubleVertexDistance - modX);
- clipRegion.setY(clipRegion.getY() + doubleVertexDistance - modY);
-
- // Calculate the moving distance
- final int dx = clipRegion.getX() - oldX;
- final int dz = clipRegion.getY() - oldZ;
-
- intersectionRegion.setX(clipRegion.getX());
- intersectionRegion.setY(clipRegion.getY());
-
- cache.setCurrentPosition(clipRegion.getX() / vertexDistance, clipRegion.getY() / vertexDistance);
-
- updateVertices(dx, dz);
-
- final Set<Tile> updatedTiles = cache.handleUpdateRequests();
- if (updatedTiles != null) {
- // TODO: only update what's changed
- regenerate();
- }
- }
-
- public void regenerate() {
- updateVertices(clipRegion.getWidth(), clipRegion.getHeight());
- }
-
- /**
- *
- * @param cx
- * @param cz
- */
- private void updateVertices(int dx, int dz) {
- if (dx == 0 && dz == 0) {
- return;
- }
-
- dx = MathUtils.clamp(dx, -clipSideSize + 1, clipSideSize - 1);
- dz = MathUtils.clamp(dz, -clipSideSize + 1, clipSideSize - 1);
-
- // Create some better readable variables.
- // This are just the bounds of the current level (the new region).
- final int xmin = clipRegion.getLeft() / vertexDistance;
- final int xmax = clipRegion.getRight() / vertexDistance;
- final int zmin = clipRegion.getTop() / vertexDistance;
- final int zmax = clipRegion.getBottom() / vertexDistance;
-
- final FloatBuffer vertices = getMeshData().getVertexBuffer();
-
- // Update the L shaped region.
- // This replaces the old data with the new one.
- if (dz > 0) {
- if (dx > 0) {
- cache.updateRegion(vertices, xmax - dx, zmin, dx + 1, zmax - zmin - dz + 1);
- } else if (dx < 0) {
- cache.updateRegion(vertices, xmin, zmin, -dx + 1, zmax - zmin - dz + 1);
- }
-
- cache.updateRegion(vertices, xmin, zmax - dz, xmax - xmin + 1, dz + 1);
- } else {
- if (dx > 0) {
- cache.updateRegion(vertices, xmax - dx, zmin - dz, dx + 1, zmax - zmin + dz + 1);
- } else if (dx < 0) {
- cache.updateRegion(vertices, xmin, zmin - dz, -dx + 1, zmax - zmin + dz + 1);
- }
-
- if (dz < 0) {
- cache.updateRegion(vertices, xmin, zmin, xmax - xmin + 1, -dz + 1);
- }
- }
- markDirty(DirtyType.Bounding);
- }
-
- /**
- * Updates the whole indexarray.
- *
- * @param nextFinerLevel
- * @param frustum
- */
- public void updateIndices(final ClipmapLevel nextFinerLevel) {
- // set the stripindex to zero. We start count vertices from here.
- // The stripindex will tell us how much of the array is used.
- stripIndex = 0;
-
- // MxM Block 1
- fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop(), clipRegion.getTop()
- + frameDistance);
-
- // MxM Block 2
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + 2 * frameDistance, clipRegion.getTop(),
- clipRegion.getTop() + frameDistance);
-
- // MxM Block 3
- fillBlock(clipRegion.getRight() - 2 * frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getTop(), clipRegion.getTop() + frameDistance);
-
- // MxM Block 4
- fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getTop(),
- clipRegion.getTop() + frameDistance);
-
- // MxM Block 5
- fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop() + frameDistance,
- clipRegion.getTop() + 2 * frameDistance);
-
- // MxM Block 6
- fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getTop() + frameDistance,
- clipRegion.getTop() + 2 * frameDistance);
-
- // MxM Block 7
- fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getBottom() - 2
- * frameDistance, clipRegion.getBottom() - frameDistance);
-
- // MxM Block 8
- fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getBottom() - 2
- * frameDistance, clipRegion.getBottom() - frameDistance);
-
- // MxM Block 9
- fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getBottom() - frameDistance,
- clipRegion.getBottom());
-
- // MxM Block 10
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + 2 * frameDistance,
- clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
-
- // MxM Block 11
- fillBlock(clipRegion.getRight() - 2 * frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
-
- // MxM Block 12
- fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getBottom() - frameDistance,
- clipRegion.getBottom());
-
- // Fixup Top
- fillBlock(clipRegion.getLeft() + 2 * frameDistance, clipRegion.getLeft() + 2 * frameDistance
- + doubleVertexDistance, clipRegion.getTop(), clipRegion.getTop() + frameDistance);
-
- // Fixup Left
- fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop() + 2 * frameDistance,
- clipRegion.getTop() + 2 * frameDistance + doubleVertexDistance);
-
- // Fixup Right
- fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(),
- clipRegion.getTop() + 2 * frameDistance, clipRegion.getTop() + 2 * frameDistance + doubleVertexDistance);
-
- // Fixup Bottom
- fillBlock(clipRegion.getLeft() + 2 * frameDistance, clipRegion.getLeft() + 2 * frameDistance
- + doubleVertexDistance, clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
-
- if (nextFinerLevel != null) {
- if ((nextFinerLevel.clipRegion.getX() - clipRegion.getX()) / vertexDistance == frameSize) {
- if ((nextFinerLevel.clipRegion.getY() - clipRegion.getY()) / vertexDistance == frameSize) {
- // Upper Left L Shape
-
- // Up
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + vertexDistance);
- // Left
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance
- + vertexDistance, clipRegion.getTop() + frameDistance + vertexDistance,
- clipRegion.getBottom() - frameDistance);
- } else {
- // Lower Left L Shape
-
- // Left
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance
- + vertexDistance, clipRegion.getTop() + frameDistance, clipRegion.getBottom()
- - frameDistance - vertexDistance);
-
- // Bottom
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getBottom() - frameDistance - vertexDistance, clipRegion.getBottom()
- - frameDistance);
- }
- } else {
- if ((nextFinerLevel.clipRegion.getY() - clipRegion.getY()) / vertexDistance == frameSize) {
- // Upper Right L Shape
-
- // Up
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + vertexDistance);
- // Right
- fillBlock(clipRegion.getRight() - frameDistance - vertexDistance, clipRegion.getRight()
- - frameDistance, clipRegion.getTop() + frameDistance + vertexDistance,
- clipRegion.getBottom() - frameDistance);
- } else {
- // Lower Right L Shape
-
- // Right
- fillBlock(clipRegion.getRight() - frameDistance - vertexDistance, clipRegion.getRight()
- - frameDistance, clipRegion.getTop() + frameDistance, clipRegion.getBottom()
- - frameDistance - vertexDistance);
-
- // Bottom
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
- clipRegion.getBottom() - frameDistance - vertexDistance, clipRegion.getBottom()
- - frameDistance);
- }
- }
- }
-
- // Fill in the middle patch if most detailed layer
- if (nextFinerLevel == null) {
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance + clipSideSize / 2,
- clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + clipSideSize / 2);
-
- fillBlock(clipRegion.getLeft() + frameDistance + clipSideSize / 2, clipRegion.getRight() - frameDistance,
- clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + clipSideSize / 2);
-
- fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance + clipSideSize / 2,
- clipRegion.getTop() + frameDistance + clipSideSize / 2, clipRegion.getBottom() - frameDistance);
-
- fillBlock(clipRegion.getLeft() + frameDistance + clipSideSize / 2, clipRegion.getRight() - frameDistance,
- clipRegion.getTop() + frameDistance + clipSideSize / 2, clipRegion.getBottom() - frameDistance);
- }
-
- final IndexBufferData<?> indices = getMeshData().getIndices();
- indices.clear();
- indices.put(tmpIndices, 0, getStripIndex());
- indices.flip();
- }
-
- /**
- * Fills a specified area to indexarray. This will be added only after a bounding test pass.
- *
- * @param left
- * @param right
- * @param top
- * @param bottom
- */
- private void fillBlock(int left, int right, int top, int bottom) {
- if (cullingEnabled) {
- // Setup the boundingbox of the block to fill.
- // The lowest value is zero, the highest is the scalesize.
- frustumCheckBounds.setCenter((left + right) * 0.5, (heightRangeMax + heightRangeMin) * heightScale * 0.5,
- (top + bottom) * 0.5);
- frustumCheckBounds.setXExtent((left - right) * 0.5);
- frustumCheckBounds.setYExtent((heightRangeMax - heightRangeMin) * heightScale * 0.5);
- frustumCheckBounds.setZExtent((top - bottom) * 0.5);
-
- frustumCheckBounds.transform(getWorldTransform(), frustumCheckBounds);
-
- final int state = clipmapTestFrustum.getPlaneState();
-
- final boolean isVisible = clipmapTestFrustum.contains(frustumCheckBounds) != FrustumIntersect.Outside;
- clipmapTestFrustum.setPlaneState(state);
-
- if (!isVisible) {
- return;
- }
- }
-
- // Same moduloprocedure as when we updated the vertices.
- // Maps the terrainposition to arrayposition.
- left = left / vertexDistance % clipSideSize;
- right = right / vertexDistance % clipSideSize;
- top = top / vertexDistance % clipSideSize;
- bottom = bottom / vertexDistance % clipSideSize;
- left += left < 0 ? clipSideSize : 0;
- right += right < 0 ? clipSideSize : 0;
- top += top < 0 ? clipSideSize : 0;
- bottom += bottom < 0 ? clipSideSize : 0;
-
- // Now fill the block.
- if (bottom < top) {
- // Bottom border is positioned somwhere over the top border,
- // we have a wrapover so we must split up the update in two parts.
-
- // Go from top border to the end of the array and update every row
- for (int z = top; z <= clipSideSize - 2; z++) {
- fillRow(left, right, z, z + 1);
- }
-
- // Update the wrapover row
- fillRow(left, right, clipSideSize - 1, 0);
-
- // Go from arraystart to the bottom border and update every row.
- for (int z = 0; z <= bottom - 1; z++) {
- fillRow(left, right, z, z + 1);
- }
- } else {
- // Top border is over the bottom border. Update from top to bottom.
- for (int z = top; z <= bottom - 1; z++) {
- fillRow(left, right, z, z + 1);
- }
- }
- }
-
- /**
- * Fills a strip of triangles that can be build between vertices row Zn and Zn1.
- *
- * @param startX
- * Start x-coordinate
- * @param endX
- * End x-coordinate
- * @param rowZ
- * Row n
- * @param rowZPlus1
- * Row n + 1
- */
- private void fillRow(final int startX, final int endX, final int rowZ, final int rowZPlus1) {
- addIndex(startX, rowZPlus1);
- if (startX <= endX) {
- for (int x = startX; x <= endX; x++) {
- addIndex(x, rowZPlus1);
- addIndex(x, rowZ);
- }
- } else {
- for (int x = startX; x <= clipSideSize - 1; x++) {
- addIndex(x, rowZPlus1);
- addIndex(x, rowZ);
- }
- for (int x = 0; x <= endX; x++) {
- addIndex(x, rowZPlus1);
- addIndex(x, rowZ);
- }
- }
- addIndex(endX, rowZ);
- }
-
- /**
- * Adds a specific index to indexarray.
- *
- * @param x
- * @param z
- */
- private void addIndex(final int x, final int z) {
- // add the index and increment counter.
- tmpIndices[stripIndex++] = x + z * clipSideSize;
- }
-
- /**
- * Gets the number of triangles that are visible in current frame. This changes every frame.
- */
- public int getStripIndex() {
- return stripIndex;
- }
-
- /**
- * @return the vertexDistance
- */
- public int getVertexDistance() {
- return vertexDistance;
- }
-
- public boolean isReady() {
- return cache.isValid();
- }
-
- public TerrainCache getCache() {
- return cache;
- }
-
- public void setHeightRange(final float heightRangeMin, final float heightRangeMax) {
- this.heightRangeMin = heightRangeMin;
- this.heightRangeMax = heightRangeMax;
- }
-
- public float getHeightRangeMax() {
- return heightRangeMax;
- }
-
- public float getHeightRangeMin() {
- return heightRangeMin;
- }
-
- public int getClipSideSize() {
- return clipSideSize;
- }
-
- public Region getClipRegion() {
- return clipRegion;
- }
-
- public Region getIntersectionRegion() {
- return intersectionRegion;
- }
-
- public float getHeightScale() {
- return heightScale;
- }
-
- public boolean isCullingEnabled() {
- return cullingEnabled;
- }
-
- public void setCullingEnabled(final boolean cullingEnabled) {
- this.cullingEnabled = cullingEnabled;
- }
-
- public void shutdown() {
- cache.shutdown();
- }
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.client;
+
+import java.nio.FloatBuffer;
+import java.util.Set;
+
+import com.ardor3d.bounding.BoundingBox;
+import com.ardor3d.extension.terrain.util.Region;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.renderer.Camera.FrustumIntersect;
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.scenegraph.FloatBufferData;
+import com.ardor3d.scenegraph.IndexBufferData;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.scenegraph.event.DirtyType;
+import com.ardor3d.util.geom.BufferUtils;
+
+/**
+ * ClipmapLevel is the visual representation of one lod level of height data.
+ */
+public class ClipmapLevel extends Mesh {
+
+ /**
+ * Precalculated useful variables.
+ */
+ private final int doubleVertexDistance; // vertexDistance * 2;
+ private final int frameDistance; // (frameSize - 1) * vertexDistance
+
+ /**
+ * Gets the distance between two horizontal/vertical vertices. The finest level L = 0 has a distance of
+ * vertexDistance = 1. Then every level it doubles so vertexDistance is always 2^L
+ */
+ private final int vertexDistance;
+
+ /**
+ * Gets framesize in number of vertices between outer border of current clip and outer border of next finer (inner)
+ * clip.
+ */
+ private final int frameSize;
+
+ /**
+ * Gets the width of a clip in number of vertices. This is always one less than power of two (2^x - 1)
+ */
+ private final int clipSideSize;
+
+ /**
+ * Gets the region of the current clip.
+ */
+ private final Region clipRegion;
+ private final Region intersectionRegion;
+
+ /**
+ * Value that indicates the height scaling. It is also represents the maximum terrain height.
+ */
+ private final float heightScale;
+
+ private float heightRangeMin = 0.0f;
+ private float heightRangeMax = 1.0f;
+
+ /**
+ * Index to indicate how much vertices are added to the triangle strip.
+ */
+ private int stripIndex = 0;
+
+ /**
+ * The used terrain heightfield. This must be set per reference so all clip levels share the same memory for that
+ * variable. The values are between 0.0f and 1.0f
+ */
+ private final TerrainCache cache;
+
+ /**
+ * Number of components for vertices
+ */
+ public static final int VERT_SIZE = 4;
+
+ /**
+ * Camera frustum to test clipmap tiles against for culling
+ */
+ private final Camera clipmapTestFrustum;
+
+ /**
+ * Used to handle transformations of the terrain
+ */
+ private final Vector3 transformedFrustumPos = new Vector3();
+
+ /**
+ * Should the clipmap generate per vertex normals
+ */
+ private final boolean generateNormals = false;
+
+ /**
+ * Bounding box used for culling
+ */
+ private final BoundingBox frustumCheckBounds = new BoundingBox();
+
+ /**
+ * Possible nio speedup when storing indices
+ */
+ private int[] tmpIndices;
+
+ /**
+ * Should cull blocks outside camera frustum
+ */
+ private boolean cullingEnabled = true;
+
+ /**
+ * Creates a new clipmaplevel.
+ *
+ * @param levelIndex
+ * Levelindex of the clipmap. If is 0 this will be the finest level
+ * @param clipSideSize
+ * Number of vertices per clipside. Must be one less than power of two.
+ * @param heightScale
+ * Maximum terrainheight and heightscale
+ * @param fieldsize
+ * Width and heightvalue of the heightfield
+ * @param heightfield
+ * Heightvalues with a range of 0.0f - 1.0f
+ * @exception Exception
+ */
+ public ClipmapLevel(final int levelIndex, final Camera clipmapTestFrustum, final int clipSideSize,
+ final float heightScale, final TerrainCache cache) throws Exception {
+ super("Clipmap Level " + levelIndex);
+
+ // Check some exception cases
+ if (levelIndex < 0) {
+ throw new Exception("levelIndex must be positive");
+ }
+ if (!MathUtils.isPowerOfTwo(clipSideSize + 1)) {
+ throw new Exception("clipSideSize must be one less than power of two");
+ }
+
+ // Apply the values
+ this.clipmapTestFrustum = clipmapTestFrustum;
+ this.cache = cache;
+
+ this.heightScale = heightScale;
+ this.clipSideSize = clipSideSize;
+
+ // Calculate common variables
+ vertexDistance = (int) Math.pow(2, levelIndex);
+ frameSize = (clipSideSize + 1) / 4;
+ doubleVertexDistance = vertexDistance * 2;
+ frameDistance = (frameSize - 1) * vertexDistance;
+ clipRegion = new Region(0, 0, (clipSideSize - 1) * vertexDistance, (clipSideSize - 1) * vertexDistance);
+ intersectionRegion = new Region(0, 0, clipSideSize * vertexDistance, clipSideSize * vertexDistance);
+
+ // Initialize the vertices
+ initialize();
+ }
+
+ /**
+ * Initializes the vertices and indices.
+ */
+ private void initialize() {
+ getMeshData().setIndexMode(IndexMode.TriangleStrip);
+
+ // clipSideSize is the number of vertices per clipmapside, so number of all vertices is clipSideSize *
+ // clipSideSize
+ final FloatBuffer vertices = BufferUtils.createVector4Buffer(clipSideSize * clipSideSize);
+ getMeshData().setVertexCoords(new FloatBufferData(vertices, 4));
+
+ if (generateNormals) {
+ final FloatBuffer normals = BufferUtils.createVector3Buffer(clipSideSize * clipSideSize);
+ getMeshData().setNormalCoords(new FloatBufferData(normals, 3));
+ }
+
+ // final FloatBuffer textureCoords = BufferUtils.createVector2Buffer(N * N);
+ // getMeshData().setTextureBuffer(textureCoords, 0);
+
+ final int indicesSize = 4 * (3 * frameSize * frameSize + clipSideSize * clipSideSize / 2 + 4 * frameSize - 10);
+ final IndexBufferData<?> indices = BufferUtils.createIndexBufferData(indicesSize, vertices.capacity() - 1);
+ tmpIndices = new int[indicesSize];
+ getMeshData().setIndices(indices);
+
+ // Go through all rows and fill them with vertexindices.
+ for (int z = 0; z < clipSideSize - 1; z++) {
+ fillRow(0, clipSideSize - 1, z, z + 1);
+ }
+ }
+
+ public void updateCache() {
+ getWorldTransform().applyInverse(clipmapTestFrustum.getLocation(), transformedFrustumPos);
+ final int cx = (int) transformedFrustumPos.getX();
+ final int cz = (int) transformedFrustumPos.getZ();
+
+ // Calculate the new position
+ int clipX = cx - (clipSideSize + 1) * vertexDistance / 2;
+ int clipY = cz - (clipSideSize + 1) * vertexDistance / 2;
+
+ // Calculate the modulo to doubleVertexDistance of the new position.
+ // This makes sure that the current level always fits in the hole of the
+ // coarser level. The gridspacing of the coarser level is vertexDistance * 2, so here doubleVertexDistance.
+ final int modX = MathUtils.moduloPositive(clipX, doubleVertexDistance);
+ final int modY = MathUtils.moduloPositive(clipY, doubleVertexDistance);
+ clipX = clipX + doubleVertexDistance - modX;
+ clipY = clipY + doubleVertexDistance - modY;
+
+ cache.setCurrentPosition(clipX / vertexDistance, clipY / vertexDistance);
+
+ // TODO
+ cache.handleUpdateRequests();
+ }
+
+ /**
+ * Update clipmap vertices
+ *
+ * @param center
+ */
+ public void updateVertices() {
+ getWorldTransform().applyInverse(clipmapTestFrustum.getLocation(), transformedFrustumPos);
+ final int cx = (int) transformedFrustumPos.getX();
+ final int cz = (int) transformedFrustumPos.getZ();
+
+ // Store the old position to be able to recover it if needed
+ final int oldX = clipRegion.getX();
+ final int oldZ = clipRegion.getY();
+
+ // Calculate the new position
+ clipRegion.setX(cx - (clipSideSize + 1) * vertexDistance / 2);
+ clipRegion.setY(cz - (clipSideSize + 1) * vertexDistance / 2);
+
+ // Calculate the modulo to doubleVertexDistance of the new position.
+ // This makes sure that the current level always fits in the hole of the
+ // coarser level. The gridspacing of the coarser level is vertexDistance * 2, so here doubleVertexDistance.
+ final int modX = MathUtils.moduloPositive(clipRegion.getX(), doubleVertexDistance);
+ final int modY = MathUtils.moduloPositive(clipRegion.getY(), doubleVertexDistance);
+ clipRegion.setX(clipRegion.getX() + doubleVertexDistance - modX);
+ clipRegion.setY(clipRegion.getY() + doubleVertexDistance - modY);
+
+ // Calculate the moving distance
+ final int dx = clipRegion.getX() - oldX;
+ final int dz = clipRegion.getY() - oldZ;
+
+ intersectionRegion.setX(clipRegion.getX());
+ intersectionRegion.setY(clipRegion.getY());
+
+ cache.setCurrentPosition(clipRegion.getX() / vertexDistance, clipRegion.getY() / vertexDistance);
+
+ updateVertices(dx, dz);
+
+ final Set<Tile> updatedTiles = cache.handleUpdateRequests();
+ if (updatedTiles != null) {
+ // TODO: only update what's changed
+ regenerate();
+ }
+ }
+
+ public void regenerate() {
+ updateVertices(clipRegion.getWidth(), clipRegion.getHeight());
+ }
+
+ /**
+ *
+ * @param cx
+ * @param cz
+ */
+ private void updateVertices(int dx, int dz) {
+ if (dx == 0 && dz == 0) {
+ return;
+ }
+
+ dx = MathUtils.clamp(dx, -clipSideSize + 1, clipSideSize - 1);
+ dz = MathUtils.clamp(dz, -clipSideSize + 1, clipSideSize - 1);
+
+ // Create some better readable variables.
+ // This are just the bounds of the current level (the new region).
+ final int xmin = clipRegion.getLeft() / vertexDistance;
+ final int xmax = clipRegion.getRight() / vertexDistance;
+ final int zmin = clipRegion.getTop() / vertexDistance;
+ final int zmax = clipRegion.getBottom() / vertexDistance;
+
+ final FloatBuffer vertices = getMeshData().getVertexBuffer();
+
+ // Update the L shaped region.
+ // This replaces the old data with the new one.
+ if (dz > 0) {
+ if (dx > 0) {
+ cache.updateRegion(vertices, xmax - dx, zmin, dx + 1, zmax - zmin - dz + 1);
+ } else if (dx < 0) {
+ cache.updateRegion(vertices, xmin, zmin, -dx + 1, zmax - zmin - dz + 1);
+ }
+
+ cache.updateRegion(vertices, xmin, zmax - dz, xmax - xmin + 1, dz + 1);
+ } else {
+ if (dx > 0) {
+ cache.updateRegion(vertices, xmax - dx, zmin - dz, dx + 1, zmax - zmin + dz + 1);
+ } else if (dx < 0) {
+ cache.updateRegion(vertices, xmin, zmin - dz, -dx + 1, zmax - zmin + dz + 1);
+ }
+
+ if (dz < 0) {
+ cache.updateRegion(vertices, xmin, zmin, xmax - xmin + 1, -dz + 1);
+ }
+ }
+ markDirty(DirtyType.Bounding);
+ }
+
+ /**
+ * Updates the whole indexarray.
+ *
+ * @param nextFinerLevel
+ * @param frustum
+ */
+ public void updateIndices(final ClipmapLevel nextFinerLevel) {
+ // set the stripindex to zero. We start count vertices from here.
+ // The stripindex will tell us how much of the array is used.
+ stripIndex = 0;
+
+ // MxM Block 1
+ fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop(), clipRegion.getTop()
+ + frameDistance);
+
+ // MxM Block 2
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + 2 * frameDistance, clipRegion.getTop(),
+ clipRegion.getTop() + frameDistance);
+
+ // MxM Block 3
+ fillBlock(clipRegion.getRight() - 2 * frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getTop(), clipRegion.getTop() + frameDistance);
+
+ // MxM Block 4
+ fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getTop(),
+ clipRegion.getTop() + frameDistance);
+
+ // MxM Block 5
+ fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop() + frameDistance,
+ clipRegion.getTop() + 2 * frameDistance);
+
+ // MxM Block 6
+ fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getTop() + frameDistance,
+ clipRegion.getTop() + 2 * frameDistance);
+
+ // MxM Block 7
+ fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getBottom() - 2
+ * frameDistance, clipRegion.getBottom() - frameDistance);
+
+ // MxM Block 8
+ fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getBottom() - 2
+ * frameDistance, clipRegion.getBottom() - frameDistance);
+
+ // MxM Block 9
+ fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getBottom() - frameDistance,
+ clipRegion.getBottom());
+
+ // MxM Block 10
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + 2 * frameDistance,
+ clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
+
+ // MxM Block 11
+ fillBlock(clipRegion.getRight() - 2 * frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
+
+ // MxM Block 12
+ fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(), clipRegion.getBottom() - frameDistance,
+ clipRegion.getBottom());
+
+ // Fixup Top
+ fillBlock(clipRegion.getLeft() + 2 * frameDistance, clipRegion.getLeft() + 2 * frameDistance
+ + doubleVertexDistance, clipRegion.getTop(), clipRegion.getTop() + frameDistance);
+
+ // Fixup Left
+ fillBlock(clipRegion.getLeft(), clipRegion.getLeft() + frameDistance, clipRegion.getTop() + 2 * frameDistance,
+ clipRegion.getTop() + 2 * frameDistance + doubleVertexDistance);
+
+ // Fixup Right
+ fillBlock(clipRegion.getRight() - frameDistance, clipRegion.getRight(),
+ clipRegion.getTop() + 2 * frameDistance, clipRegion.getTop() + 2 * frameDistance + doubleVertexDistance);
+
+ // Fixup Bottom
+ fillBlock(clipRegion.getLeft() + 2 * frameDistance, clipRegion.getLeft() + 2 * frameDistance
+ + doubleVertexDistance, clipRegion.getBottom() - frameDistance, clipRegion.getBottom());
+
+ if (nextFinerLevel != null) {
+ if ((nextFinerLevel.clipRegion.getX() - clipRegion.getX()) / vertexDistance == frameSize) {
+ if ((nextFinerLevel.clipRegion.getY() - clipRegion.getY()) / vertexDistance == frameSize) {
+ // Upper Left L Shape
+
+ // Up
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + vertexDistance);
+ // Left
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance
+ + vertexDistance, clipRegion.getTop() + frameDistance + vertexDistance,
+ clipRegion.getBottom() - frameDistance);
+ } else {
+ // Lower Left L Shape
+
+ // Left
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance
+ + vertexDistance, clipRegion.getTop() + frameDistance, clipRegion.getBottom()
+ - frameDistance - vertexDistance);
+
+ // Bottom
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getBottom() - frameDistance - vertexDistance, clipRegion.getBottom()
+ - frameDistance);
+ }
+ } else {
+ if ((nextFinerLevel.clipRegion.getY() - clipRegion.getY()) / vertexDistance == frameSize) {
+ // Upper Right L Shape
+
+ // Up
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + vertexDistance);
+ // Right
+ fillBlock(clipRegion.getRight() - frameDistance - vertexDistance, clipRegion.getRight()
+ - frameDistance, clipRegion.getTop() + frameDistance + vertexDistance,
+ clipRegion.getBottom() - frameDistance);
+ } else {
+ // Lower Right L Shape
+
+ // Right
+ fillBlock(clipRegion.getRight() - frameDistance - vertexDistance, clipRegion.getRight()
+ - frameDistance, clipRegion.getTop() + frameDistance, clipRegion.getBottom()
+ - frameDistance - vertexDistance);
+
+ // Bottom
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getRight() - frameDistance,
+ clipRegion.getBottom() - frameDistance - vertexDistance, clipRegion.getBottom()
+ - frameDistance);
+ }
+ }
+ }
+
+ // Fill in the middle patch if most detailed layer
+ if (nextFinerLevel == null) {
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance + clipSideSize / 2,
+ clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + clipSideSize / 2);
+
+ fillBlock(clipRegion.getLeft() + frameDistance + clipSideSize / 2, clipRegion.getRight() - frameDistance,
+ clipRegion.getTop() + frameDistance, clipRegion.getTop() + frameDistance + clipSideSize / 2);
+
+ fillBlock(clipRegion.getLeft() + frameDistance, clipRegion.getLeft() + frameDistance + clipSideSize / 2,
+ clipRegion.getTop() + frameDistance + clipSideSize / 2, clipRegion.getBottom() - frameDistance);
+
+ fillBlock(clipRegion.getLeft() + frameDistance + clipSideSize / 2, clipRegion.getRight() - frameDistance,
+ clipRegion.getTop() + frameDistance + clipSideSize / 2, clipRegion.getBottom() - frameDistance);
+ }
+
+ final IndexBufferData<?> indices = getMeshData().getIndices();
+ indices.clear();
+ indices.put(tmpIndices, 0, getStripIndex());
+ indices.flip();
+ }
+
+ /**
+ * Fills a specified area to indexarray. This will be added only after a bounding test pass.
+ *
+ * @param left
+ * @param right
+ * @param top
+ * @param bottom
+ */
+ private void fillBlock(int left, int right, int top, int bottom) {
+ if (cullingEnabled) {
+ // Setup the boundingbox of the block to fill.
+ // The lowest value is zero, the highest is the scalesize.
+ frustumCheckBounds.setCenter((left + right) * 0.5, (heightRangeMax + heightRangeMin) * heightScale * 0.5,
+ (top + bottom) * 0.5);
+ frustumCheckBounds.setXExtent((left - right) * 0.5);
+ frustumCheckBounds.setYExtent((heightRangeMax - heightRangeMin) * heightScale * 0.5);
+ frustumCheckBounds.setZExtent((top - bottom) * 0.5);
+
+ frustumCheckBounds.transform(getWorldTransform(), frustumCheckBounds);
+
+ final int state = clipmapTestFrustum.getPlaneState();
+
+ final boolean isVisible = clipmapTestFrustum.contains(frustumCheckBounds) != FrustumIntersect.Outside;
+ clipmapTestFrustum.setPlaneState(state);
+
+ if (!isVisible) {
+ return;
+ }
+ }
+
+ // Same moduloprocedure as when we updated the vertices.
+ // Maps the terrainposition to arrayposition.
+ left = left / vertexDistance % clipSideSize;
+ right = right / vertexDistance % clipSideSize;
+ top = top / vertexDistance % clipSideSize;
+ bottom = bottom / vertexDistance % clipSideSize;
+ left += left < 0 ? clipSideSize : 0;
+ right += right < 0 ? clipSideSize : 0;
+ top += top < 0 ? clipSideSize : 0;
+ bottom += bottom < 0 ? clipSideSize : 0;
+
+ // Now fill the block.
+ if (bottom < top) {
+ // Bottom border is positioned somwhere over the top border,
+ // we have a wrapover so we must split up the update in two parts.
+
+ // Go from top border to the end of the array and update every row
+ for (int z = top; z <= clipSideSize - 2; z++) {
+ fillRow(left, right, z, z + 1);
+ }
+
+ // Update the wrapover row
+ fillRow(left, right, clipSideSize - 1, 0);
+
+ // Go from arraystart to the bottom border and update every row.
+ for (int z = 0; z <= bottom - 1; z++) {
+ fillRow(left, right, z, z + 1);
+ }
+ } else {
+ // Top border is over the bottom border. Update from top to bottom.
+ for (int z = top; z <= bottom - 1; z++) {
+ fillRow(left, right, z, z + 1);
+ }
+ }
+ }
+
+ /**
+ * Fills a strip of triangles that can be build between vertices row Zn and Zn1.
+ *
+ * @param startX
+ * Start x-coordinate
+ * @param endX
+ * End x-coordinate
+ * @param rowZ
+ * Row n
+ * @param rowZPlus1
+ * Row n + 1
+ */
+ private void fillRow(final int startX, final int endX, final int rowZ, final int rowZPlus1) {
+ addIndex(startX, rowZPlus1);
+ if (startX <= endX) {
+ for (int x = startX; x <= endX; x++) {
+ addIndex(x, rowZPlus1);
+ addIndex(x, rowZ);
+ }
+ } else {
+ for (int x = startX; x <= clipSideSize - 1; x++) {
+ addIndex(x, rowZPlus1);
+ addIndex(x, rowZ);
+ }
+ for (int x = 0; x <= endX; x++) {
+ addIndex(x, rowZPlus1);
+ addIndex(x, rowZ);
+ }
+ }
+ addIndex(endX, rowZ);
+ }
+
+ /**
+ * Adds a specific index to indexarray.
+ *
+ * @param x
+ * @param z
+ */
+ private void addIndex(final int x, final int z) {
+ // add the index and increment counter.
+ tmpIndices[stripIndex++] = x + z * clipSideSize;
+ }
+
+ /**
+ * Gets the number of triangles that are visible in current frame. This changes every frame.
+ */
+ public int getStripIndex() {
+ return stripIndex;
+ }
+
+ /**
+ * @return the vertexDistance
+ */
+ public int getVertexDistance() {
+ return vertexDistance;
+ }
+
+ public boolean isReady() {
+ return cache.isValid();
+ }
+
+ public TerrainCache getCache() {
+ return cache;
+ }
+
+ public void setHeightRange(final float heightRangeMin, final float heightRangeMax) {
+ this.heightRangeMin = heightRangeMin;
+ this.heightRangeMax = heightRangeMax;
+ }
+
+ public float getHeightRangeMax() {
+ return heightRangeMax;
+ }
+
+ public float getHeightRangeMin() {
+ return heightRangeMin;
+ }
+
+ public int getClipSideSize() {
+ return clipSideSize;
+ }
+
+ public Region getClipRegion() {
+ return clipRegion;
+ }
+
+ public Region getIntersectionRegion() {
+ return intersectionRegion;
+ }
+
+ public float getHeightScale() {
+ return heightScale;
+ }
+
+ public boolean isCullingEnabled() {
+ return cullingEnabled;
+ }
+
+ public void setCullingEnabled(final boolean cullingEnabled) {
+ this.cullingEnabled = cullingEnabled;
+ }
+
+ public void shutdown() {
+ cache.shutdown();
+ }
} \ No newline at end of file
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/Terrain.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/Terrain.java
index 5da7e51..cad6281 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/Terrain.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/Terrain.java
@@ -1,712 +1,712 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.client;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.ardor3d.bounding.BoundingBox;
-import com.ardor3d.extension.terrain.util.AbstractBresenhamTracer;
-import com.ardor3d.extension.terrain.util.ClipmapTerrainPicker;
-import com.ardor3d.extension.terrain.util.DoubleBufferedList;
-import com.ardor3d.extension.terrain.util.Region;
-import com.ardor3d.intersection.IntersectionRecord;
-import com.ardor3d.intersection.Pickable;
-import com.ardor3d.math.ColorRGBA;
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.math.Ray3;
-import com.ardor3d.math.Vector3;
-import com.ardor3d.renderer.Camera;
-import com.ardor3d.renderer.ContextCapabilities;
-import com.ardor3d.renderer.ContextManager;
-import com.ardor3d.renderer.Renderer;
-import com.ardor3d.renderer.queue.RenderBucketType;
-import com.ardor3d.renderer.state.BlendState;
-import com.ardor3d.renderer.state.CullState;
-import com.ardor3d.renderer.state.GLSLShaderDataLogic;
-import com.ardor3d.renderer.state.GLSLShaderObjectsState;
-import com.ardor3d.renderer.state.MaterialState;
-import com.ardor3d.renderer.state.MaterialState.MaterialFace;
-import com.ardor3d.renderer.state.TextureState;
-import com.ardor3d.scenegraph.Mesh;
-import com.ardor3d.scenegraph.Node;
-import com.ardor3d.scenegraph.event.DirtyType;
-import com.ardor3d.scenegraph.hint.DataMode;
-import com.ardor3d.util.resource.ResourceLocatorTool;
-import com.google.common.collect.Lists;
-import com.google.common.io.InputSupplier;
-
-/**
- * An implementation of geometry clipmapping
- */
-public class Terrain extends Node implements Pickable {
- /** The Constant logger. */
- private static final Logger logger = Logger.getLogger(Terrain.class.getName());
-
- /** Our picker. */
- private ClipmapTerrainPicker _picker = null;
-
- private List<ClipmapLevel> _clips;
- private int _visibleLevels = 0;
- private int _minVisibleLevel = 0;
- private final Camera _terrainCamera;
- private final int _clipSideSize;
-
- private final BlendState blendState;
-
- private boolean _initialized = false;
-
- /** Shader for rendering clipmap geometry with morphing. */
- private GLSLShaderObjectsState _geometryClipmapShader;
-
- /** Reference to the texture clipmap */
- private final List<TextureClipmap> _textureClipmaps = Lists.newArrayList();
-
- /** Reference to normal map */
- private TextureClipmap _normalClipmap;
- private int _normalUnit = 5;
-
- private final Vector3 transformedFrustumPos = new Vector3();
-
- private final DoubleBufferedList<Region> mailBox = new DoubleBufferedList<Region>();
-
- private InputSupplier<? extends InputStream> vertexShader;
- private InputSupplier<? extends InputStream> pixelShader;
-
- /** Timers for mailbox updates */
- private long oldTime = 0;
- private long updateTimer = 0;
- private final long updateThreashold = 300;
-
- final TextureState clipTextureState = new TextureState();
-
- private final Comparator<Region> regionSorter = new Comparator<Region>() {
- @Override
- public int compare(final Region r1, final Region r2) {
- return r1.getLevel() - r2.getLevel();
- }
- };
-
- public Terrain(final Camera camera, final List<TerrainCache> cacheList, final int clipSideSize,
- final TerrainConfiguration terrainConfiguration) {
- _terrainCamera = camera;
- _clipSideSize = clipSideSize;
-
- _worldBound = new BoundingBox(Vector3.ZERO, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
- Double.POSITIVE_INFINITY);
-
- getSceneHints().setRenderBucketType(RenderBucketType.Opaque);
- final CullState cs = new CullState();
- cs.setEnabled(true);
- cs.setCullFace(CullState.Face.Back);
- setRenderState(cs);
-
- final MaterialState materialState = new MaterialState();
- materialState.setAmbient(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
- materialState.setDiffuse(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
- materialState.setSpecular(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
- materialState.setShininess(MaterialFace.FrontAndBack, 64.0f);
- setRenderState(materialState);
-
- blendState = new BlendState();
- blendState.setBlendEnabled(true);
- blendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
- blendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
- setRenderState(blendState);
-
- // getSceneHints().setLightCombineMode(LightCombineMode.Off);
-
- try {
- _clips = new ArrayList<ClipmapLevel>();
-
- final float heightScale = terrainConfiguration.getScale().getYf();
-
- for (int i = 0; i < cacheList.size(); i++) {
- final TerrainCache cache = cacheList.get(i);
- cache.setMailBox(mailBox);
- final ClipmapLevel clipmap = new ClipmapLevel(i, camera, clipSideSize, heightScale, cache);
- _clips.add(clipmap);
- attachChild(clipmap);
-
- clipmap.getSceneHints().setDataMode(DataMode.Arrays);
-
- // clipmap.getSceneHints().setDataMode(DataMode.VBOInterleaved);
- // final FloatBufferData interleavedData = new FloatBufferData();
- // interleavedData.setVboAccessMode(VBOAccessMode.DynamicDraw);
- // clipmap.getMeshData().setInterleavedData(interleavedData);
-
- // clipmap.getSceneHints().setDataMode(DataMode.VBO);
- // clipmap.getMeshData().getVertexCoords().setVboAccessMode(VBOAccessMode.DynamicDraw);
- // clipmap.getMeshData().getIndices().setVboAccessMode(VBOAccessMode.DynamicDraw);
- }
- } catch (final Exception ex) {
- ex.printStackTrace();
- }
-
- vertexShader = new UrlInputSupplier(ResourceLocatorTool.getClassPathResource(Terrain.class,
- "com/ardor3d/extension/terrain/texturedGeometryClipmapShader.vert"));
- pixelShader = new UrlInputSupplier(ResourceLocatorTool.getClassPathResource(Terrain.class,
- "com/ardor3d/extension/terrain/texturedGeometryClipmapShader.frag"));
-
- // setScale(terrainConfiguration.getScale());
- // TODO: hack. unify scale handling over cache etc
- setScale(terrainConfiguration.getScale().getX(), 1, terrainConfiguration.getScale().getZ());
- setHeightRange(terrainConfiguration.getHeightRangeMin(), terrainConfiguration.getHeightRangeMax());
- }
-
- private final List<Long> timers = Lists.newArrayList();
-
- @Override
- protected void updateChildren(final double time) {
- super.updateChildren(time);
-
- for (int i = _minVisibleLevel; i < _clips.size(); i++) {
- if (_clips.get(i).isReady()) {
- _visibleLevels = i;
- break;
- }
- }
-
- // TODO: improve calcs for removing levels based on height above terrain
- // getWorldTransform().applyInverse(_terrainCamera.getLocation(), transformedFrustumPos);
- // final float heightRangeMax = 1f;
- // if (transformedFrustumPos.getYf() > heightRangeMax) {
- // final float diff = transformedFrustumPos.getYf() - heightRangeMax;
- // final float x = (float) (diff * Math.tan(Math.toRadians(30)));
- // for (int unit = _visibleLevels; unit < _clips.size(); unit++) {
- // final float heightTest = _clipSideSize * MathUtils.pow2(unit) / x;
- // if (heightTest > 1) {
- // _visibleLevels = unit;
- // break;
- // }
- // }
- // }
-
- if (timers.size() < _visibleLevels) {
- for (int unit = 0; unit < _visibleLevels; unit++) {
- timers.add(System.currentTimeMillis());
- }
- }
- for (int unit = 0; unit < _visibleLevels; unit++) {
- final long t = System.currentTimeMillis() - timers.get(unit);
- if (t > 500) {
- timers.set(unit, System.currentTimeMillis());
- _clips.get(unit).updateCache();
- }
- }
-
- // Update vertices.
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- _clips.get(i).updateVertices();
- }
-
- // Update from mailbox
- updateFromMailbox();
-
- // Update indices.
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- if (i == _visibleLevels) {
- // Level 0 has no nested level, so pass null as parameter.
- _clips.get(i).updateIndices(null);
- } else {
- // All other levels i have the level i-1 nested in.
- _clips.get(i).updateIndices(_clips.get(i - 1));
- }
- }
-
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- _clips.get(i).getMeshData().getVertexCoords().setNeedsRefresh(true);
- _clips.get(i).getMeshData().getIndices().setNeedsRefresh(true);
- }
- }
-
- @Override
- public void draw(final Renderer r) {
- updateShader(r);
-
- boolean first = true;
- if (_normalClipmap != null) {
- clipTextureState.setTexture(_normalClipmap.getTexture(), _normalUnit);
- }
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- clipTextureState.setTexture(textureClipmap.getTexture());
- if (first) {
- blendState.setEnabled(false);
- first = false;
- } else {
- blendState.setEnabled(true);
- }
-
- if (_textureClipmaps.size() > 1) {
- r.getQueue().pushBuckets();
- }
-
- for (int i = _clips.size() - 1; i >= 0; i--) {
- final ClipmapLevel clip = _clips.get(i);
- clip.setRenderState(clipTextureState);
- }
-
- if (_textureClipmaps.size() > 1) {
- _geometryClipmapShader.setUniform("scale", 1f / textureClipmap.getScale());
- _geometryClipmapShader.setUniform("textureSize", (float) textureClipmap.getTextureSize());
- _geometryClipmapShader.setUniform("texelSize", 1f / textureClipmap.getTextureSize());
- _geometryClipmapShader.setUniform("levels", (float) textureClipmap.getTextureLevels());
- _geometryClipmapShader.setUniform("validLevels", (float) textureClipmap.getValidLevels() - 1);
- _geometryClipmapShader.setUniform("showDebug", textureClipmap.isShowDebug() ? 1.0f : 0.0f);
- _geometryClipmapShader.setNeedsRefresh(true);
- }
-
- blendState.setNeedsRefresh(true);
- this.updateWorldRenderStates(true);
-
- if (!_initialized) {
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- final ClipmapLevel clip = _clips.get(i);
-
- clip.getMeshData().getIndices().limit(clip.getMeshData().getIndices().capacity());
- }
-
- _initialized = true;
- }
-
- // draw levels from coarse to fine.
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- final ClipmapLevel clip = _clips.get(i);
-
- if (clip.getStripIndex() > 0) {
- clip.draw(r);
- }
- }
-
- if (_textureClipmaps.size() > 1) {
- r.renderBuckets();
- r.getQueue().popBuckets();
- }
- }
- }
-
- private void updateFromMailbox() {
- if (updateTimer > updateThreashold) {
- final List<Region> regionList = mailBox.switchAndGet();
- if (!regionList.isEmpty()) {
- for (int i = regionList.size() - 1; i >= 0; i--) {
- final Region region = regionList.get(i);
-
- final ClipmapLevel clip = _clips.get(region.getLevel());
- final Region clipRegion = clip.getIntersectionRegion();
-
- if (clipRegion.intersects(region)) {
- clipRegion.intersection(region);
- } else {
- regionList.remove(i);
- }
- }
-
- Collections.sort(regionList, regionSorter);
-
- final int start = regionList.size() - 1;
- for (int i = start; i >= 0; i--) {
- final Region region = regionList.get(i);
-
- recursiveAddUpdates(regionList, region.getLevel(), region.getX(), region.getY(), region.getWidth(),
- region.getHeight());
- }
-
- for (int i = regionList.size() - 1; i >= 0; i--) {
- final Region region = regionList.get(i);
-
- final ClipmapLevel clip = _clips.get(region.getLevel());
- final Region clipRegion = clip.getIntersectionRegion();
-
- if (clipRegion.intersects(region)) {
- clipRegion.intersection(region);
- } else {
- regionList.remove(i);
- }
- }
-
- Collections.sort(regionList, regionSorter);
-
- for (int i = regionList.size() - 1; i >= 0; i--) {
- final Region region = regionList.get(i);
- final ClipmapLevel clip = _clips.get(region.getLevel());
- final FloatBuffer vertices = clip.getMeshData().getVertexBuffer();
- final int vertexDistance = clip.getVertexDistance();
-
- clip.getCache().updateRegion(vertices, region.getX() / vertexDistance,
- region.getY() / vertexDistance, region.getWidth() / vertexDistance,
- region.getHeight() / vertexDistance);
- }
- }
- updateTimer %= updateThreashold;
- }
- final long time = System.currentTimeMillis();
- updateTimer += time - oldTime;
- oldTime = time;
- }
-
- private void recursiveAddUpdates(final List<Region> regionList, final int level, final int x, final int y,
- final int width, final int height) {
- if (level == 0) {
- return;
- }
-
- final Region region = new Region(level - 1, x, y, width, height);
- if (!regionList.contains(region)) {
- regionList.add(region);
- recursiveAddUpdates(regionList, region.getLevel(), region.getX(), region.getY(), region.getWidth(),
- region.getHeight());
- }
- }
-
- private final Vector3 _boundsCenter = new Vector3();
- private final Vector3 _boundsExtents = new Vector3();
-
- @Override
- public void updateWorldBound(final boolean recurse) {
- final BoundingBox worldBound = (BoundingBox) _worldBound;
- final Vector3 center = _boundsCenter.set(_terrainCamera.getLocation());
- final double distanceToEdge = _clipSideSize * MathUtils.pow2(_clips.size() - 1) * 0.5;
- final double heightScale = _clips.get(0).getHeightScale();
- final double heightMin = _clips.get(0).getHeightRangeMin() * heightScale;
- final double heightMax = _clips.get(0).getHeightRangeMax() * heightScale;
-
- final Vector3 extents = _boundsExtents.set(distanceToEdge, (heightMax - heightMin) * 0.5, distanceToEdge);
- worldToLocal(center, center);
- worldBound.setXExtent(extents.getX());
- worldBound.setYExtent(extents.getY());
- worldBound.setZExtent(extents.getZ());
- worldBound.setCenter(center.getX(), (heightMax + heightMin) * 0.5, center.getZ());
- worldBound.transform(_worldTransform, worldBound);
- clearDirty(DirtyType.Bounding);
- }
-
- /**
- * Initialize/Update shaders
- */
- public void updateShader(final Renderer r) {
- if (_geometryClipmapShader != null) {
- getWorldTransform().applyInverse(_terrainCamera.getLocation(), transformedFrustumPos);
- _geometryClipmapShader.setUniform("eyePosition", transformedFrustumPos);
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- textureClipmap.update(r, transformedFrustumPos);
- }
- if (_normalClipmap != null) {
- _normalClipmap.update(r, transformedFrustumPos);
- }
-
- return;
- }
-
- reloadShader();
- }
-
- public void reloadShader() {
- final ContextCapabilities caps = ContextManager.getCurrentContext().getCapabilities();
- if (caps.isGLSLSupported()) {
- _geometryClipmapShader = new GLSLShaderObjectsState();
- try {
- _geometryClipmapShader.setVertexShader(vertexShader.getInput());
- _geometryClipmapShader.setFragmentShader(pixelShader.getInput());
- } catch (final IOException ex) {
- Terrain.logger
- .logp(Level.SEVERE, getClass().getName(), "init(Renderer)", "Could not load shaders.", ex);
- }
-
- _geometryClipmapShader.setUniform("texture", 0);
- _geometryClipmapShader.setUniform("clipSideSize", (float) _clipSideSize);
-
- if (!_textureClipmaps.isEmpty()) {
- final TextureClipmap textureClipmap = _textureClipmaps.get(0);
- _geometryClipmapShader.setUniform("scale", 1f / textureClipmap.getScale());
- _geometryClipmapShader.setUniform("textureSize", (float) textureClipmap.getTextureSize());
- _geometryClipmapShader.setUniform("texelSize", 1f / textureClipmap.getTextureSize());
-
- _geometryClipmapShader.setUniform("levels", (float) textureClipmap.getTextureLevels());
- _geometryClipmapShader.setUniform("validLevels", (float) textureClipmap.getValidLevels() - 1);
- _geometryClipmapShader.setUniform("minLevel", 0f);
-
- _geometryClipmapShader.setUniform("showDebug", textureClipmap.isShowDebug() ? 1.0f : 0.0f);
- }
-
- _geometryClipmapShader.setShaderDataLogic(new GLSLShaderDataLogic() {
- public void applyData(final GLSLShaderObjectsState shader, final Mesh mesh, final Renderer renderer) {
- if (mesh instanceof ClipmapLevel) {
- shader.setUniform("vertexDistance", (float) ((ClipmapLevel) mesh).getVertexDistance());
- }
- }
- });
-
- applyToClips();
-
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- textureClipmap.setShaderState(_geometryClipmapShader);
- }
-
- if (_normalClipmap != null) {
- _normalClipmap.setShaderState(_geometryClipmapShader);
- }
-
- updateWorldRenderStates(false);
- }
- }
-
- protected void applyToClips() {
- for (int i = _clips.size() - 1; i >= 0; i--) {
- final ClipmapLevel clip = _clips.get(i);
- clip.setRenderState(_geometryClipmapShader);
- }
- }
-
- public void regenerate(final Renderer renderer) {
- for (int i = _clips.size() - 1; i >= 0; i--) {
- if (!_clips.get(i).isReady()) {
- _visibleLevels = i + 1;
- break;
- }
- }
-
- // Update vertices.
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- _clips.get(i).regenerate();
- }
-
- // Update indices.
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- if (i == _visibleLevels) {
- // Level 0 has no nested level, so pass null as parameter.
- _clips.get(i).updateIndices(null);
- } else {
- // All other levels i have the level i-1 nested in.
- _clips.get(i).updateIndices(_clips.get(i - 1));
- }
- }
-
- for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
- _clips.get(i).getMeshData().getVertexCoords().setNeedsRefresh(true);
- _clips.get(i).getMeshData().getIndices().setNeedsRefresh(true);
- }
-
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- textureClipmap.regenerate(renderer);
- }
-
- if (_normalClipmap != null) {
- _normalClipmap.regenerate(renderer);
- }
- }
-
- /**
- * @return the visibleLevels
- */
- public int getVisibleLevels() {
- return _visibleLevels;
- }
-
- /**
- * @param visibleLevels
- * the visibleLevels to set
- */
- public void setVisibleLevels(final int visibleLevels) {
- _visibleLevels = visibleLevels;
- }
-
- public void setHeightRange(final float heightRangeMin, final float heightRangeMax) {
- for (int i = _clips.size() - 1; i >= 0; i--) {
- final ClipmapLevel clip = _clips.get(i);
- clip.setHeightRange(heightRangeMin, heightRangeMax);
- }
- }
-
- public void setCullingEnabled(final boolean cullingEnabled) {
- for (int i = _clips.size() - 1; i >= 0; i--) {
- final ClipmapLevel clip = _clips.get(i);
- clip.setCullingEnabled(cullingEnabled);
- }
- }
-
- public void makePickable(final Class<? extends AbstractBresenhamTracer> tracerClass, final int maxChecks,
- final Vector3 initialSpacing) throws InstantiationException, IllegalAccessException {
- // init the terrain picker
- _picker = new ClipmapTerrainPicker(_clips, tracerClass, maxChecks, initialSpacing);
- }
-
- public TextureClipmap getTextureClipmap() {
- return _textureClipmaps.get(0);
- }
-
- public List<TextureClipmap> getTextureClipmaps() {
- return _textureClipmaps;
- }
-
- public GLSLShaderObjectsState getGeometryClipmapShader() {
- return _geometryClipmapShader;
- }
-
- public void setGeometryClipmapShader(final GLSLShaderObjectsState shaderState) {
- _geometryClipmapShader = shaderState;
-
- applyToClips();
-
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- textureClipmap.setShaderState(_geometryClipmapShader);
- }
-
- if (_normalClipmap != null) {
- _normalClipmap.setShaderState(_geometryClipmapShader);
- }
- }
-
- public ClipmapTerrainPicker getPicker() {
- return _picker;
- }
-
- @Override
- public boolean supportsBoundsIntersectionRecord() {
- // for now we are not compatible with bounding volume picks
- return false;
- }
-
- @Override
- public boolean supportsPrimitivesIntersectionRecord() {
- return true;
- }
-
- @Override
- public boolean intersectsWorldBound(final Ray3 ray) {
- // XXX: could optimize this by grabbing edges of terrain and checking if we are outside of that...
- // for now we just return true.
- return true;
- }
-
- @Override
- public IntersectionRecord intersectsWorldBoundsWhere(final Ray3 ray) {
- // for now we are not compatible with bounding volume picks
- return null;
- }
-
- @Override
- public IntersectionRecord intersectsPrimitivesWhere(final Ray3 ray) {
- if (_picker != null) {
- final Vector3 normalStore = new Vector3();
- final Vector3 intersect = _picker.getTerrainIntersection(getWorldTransform(), _terrainCamera.getLocation(),
- ray, null, normalStore);
- if (intersect != null) {
- final double distance = intersect.distance(ray.getOrigin());
- final IntersectionRecord record = new IntersectionRecord(new double[] { distance },
- new Vector3[] { intersect }, new Vector3[] { normalStore }, null);
- return record;
- }
- }
- return null;
- }
-
- public List<ClipmapLevel> getClipmaps() {
- return _clips;
- }
-
- public void setVertexShader(final InputSupplier<? extends InputStream> vertexShader) {
- this.vertexShader = vertexShader;
- }
-
- public void setPixelShader(final InputSupplier<? extends InputStream> pixelShader) {
- this.pixelShader = pixelShader;
- }
-
- public void addTextureClipmap(final TextureClipmap textureClipmap) {
- _textureClipmaps.add(textureClipmap);
- }
-
- /**
- * set the minimum (highest resolution) clipmap level visible
- *
- * @param level
- * clamped to valid range
- */
- public void setMinVisibleLevel(final int level) {
- if (level < 0) {
- _minVisibleLevel = 0;
- } else if (level >= _clips.size()) {
- _minVisibleLevel = _clips.size() - 1;
- } else {
- _minVisibleLevel = level;
- }
- }
-
- public int getMinVisibleLevel() {
- return _minVisibleLevel;
- }
-
- /**
- * convenience function to set minimum (highest resolution) texture clipmap level on all TextureClipmaps held by
- * this terrain
- */
- public void setTextureMinVisibleLevel(final int level) {
- for (final TextureClipmap tc : _textureClipmaps) {
- tc.setMinVisibleLevel(level);
- }
- }
-
- public int getTextureMinVisibleLevel() {
- if (!_textureClipmaps.isEmpty()) {
- return _textureClipmaps.get(0).getMinVisibleLevel();
- }
- return 0;
- }
-
- public float getHeightAt(final double x, final double z) {
- final Vector3 heightCalc = new Vector3(x, 0, z);
- worldToLocal(heightCalc, heightCalc);
- final float height = getClipmaps().get(0).getCache().getSubHeight(heightCalc.getXf(), heightCalc.getZf());
- heightCalc.set(x, height, z);
- localToWorld(heightCalc, heightCalc);
- return heightCalc.getYf();
- }
-
- public void shutdown() {
- for (final TextureClipmap textureClipmap : _textureClipmaps) {
- textureClipmap.shutdown();
- }
- for (final ClipmapLevel terrainClipmap : _clips) {
- terrainClipmap.shutdown();
- }
- if (_normalClipmap != null) {
- _normalClipmap.shutdown();
- }
- }
-
- public TextureState getClipTextureState() {
- return clipTextureState;
- }
-
- public void setNormalClipmap(final TextureClipmap normalClipmap) {
- _normalClipmap = normalClipmap;
- }
-
- public TextureClipmap getNormalClipmap() {
- return _normalClipmap;
- }
-
- public int getNormalUnit() {
- return _normalUnit;
- }
-
- public void setNormalUnit(final int unit) {
- _normalUnit = unit;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.ardor3d.bounding.BoundingBox;
+import com.ardor3d.extension.terrain.util.AbstractBresenhamTracer;
+import com.ardor3d.extension.terrain.util.ClipmapTerrainPicker;
+import com.ardor3d.extension.terrain.util.DoubleBufferedList;
+import com.ardor3d.extension.terrain.util.Region;
+import com.ardor3d.intersection.IntersectionRecord;
+import com.ardor3d.intersection.Pickable;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Ray3;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.queue.RenderBucketType;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.CullState;
+import com.ardor3d.renderer.state.GLSLShaderDataLogic;
+import com.ardor3d.renderer.state.GLSLShaderObjectsState;
+import com.ardor3d.renderer.state.MaterialState;
+import com.ardor3d.renderer.state.MaterialState.MaterialFace;
+import com.ardor3d.renderer.state.TextureState;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.scenegraph.Node;
+import com.ardor3d.scenegraph.event.DirtyType;
+import com.ardor3d.scenegraph.hint.DataMode;
+import com.ardor3d.util.resource.ResourceLocatorTool;
+import com.google.common.collect.Lists;
+import com.google.common.io.InputSupplier;
+
+/**
+ * An implementation of geometry clipmapping
+ */
+public class Terrain extends Node implements Pickable {
+ /** The Constant logger. */
+ private static final Logger logger = Logger.getLogger(Terrain.class.getName());
+
+ /** Our picker. */
+ private ClipmapTerrainPicker _picker = null;
+
+ private List<ClipmapLevel> _clips;
+ private int _visibleLevels = 0;
+ private int _minVisibleLevel = 0;
+ private final Camera _terrainCamera;
+ private final int _clipSideSize;
+
+ private final BlendState blendState;
+
+ private boolean _initialized = false;
+
+ /** Shader for rendering clipmap geometry with morphing. */
+ private GLSLShaderObjectsState _geometryClipmapShader;
+
+ /** Reference to the texture clipmap */
+ private final List<TextureClipmap> _textureClipmaps = Lists.newArrayList();
+
+ /** Reference to normal map */
+ private TextureClipmap _normalClipmap;
+ private int _normalUnit = 5;
+
+ private final Vector3 transformedFrustumPos = new Vector3();
+
+ private final DoubleBufferedList<Region> mailBox = new DoubleBufferedList<Region>();
+
+ private InputSupplier<? extends InputStream> vertexShader;
+ private InputSupplier<? extends InputStream> pixelShader;
+
+ /** Timers for mailbox updates */
+ private long oldTime = 0;
+ private long updateTimer = 0;
+ private final long updateThreashold = 300;
+
+ final TextureState clipTextureState = new TextureState();
+
+ private final Comparator<Region> regionSorter = new Comparator<Region>() {
+ @Override
+ public int compare(final Region r1, final Region r2) {
+ return r1.getLevel() - r2.getLevel();
+ }
+ };
+
+ public Terrain(final Camera camera, final List<TerrainCache> cacheList, final int clipSideSize,
+ final TerrainConfiguration terrainConfiguration) {
+ _terrainCamera = camera;
+ _clipSideSize = clipSideSize;
+
+ _worldBound = new BoundingBox(Vector3.ZERO, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
+ Double.POSITIVE_INFINITY);
+
+ getSceneHints().setRenderBucketType(RenderBucketType.Opaque);
+ final CullState cs = new CullState();
+ cs.setEnabled(true);
+ cs.setCullFace(CullState.Face.Back);
+ setRenderState(cs);
+
+ final MaterialState materialState = new MaterialState();
+ materialState.setAmbient(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
+ materialState.setDiffuse(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
+ materialState.setSpecular(MaterialFace.FrontAndBack, new ColorRGBA(1, 1, 1, 1));
+ materialState.setShininess(MaterialFace.FrontAndBack, 64.0f);
+ setRenderState(materialState);
+
+ blendState = new BlendState();
+ blendState.setBlendEnabled(true);
+ blendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
+ blendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
+ setRenderState(blendState);
+
+ // getSceneHints().setLightCombineMode(LightCombineMode.Off);
+
+ try {
+ _clips = new ArrayList<ClipmapLevel>();
+
+ final float heightScale = terrainConfiguration.getScale().getYf();
+
+ for (int i = 0; i < cacheList.size(); i++) {
+ final TerrainCache cache = cacheList.get(i);
+ cache.setMailBox(mailBox);
+ final ClipmapLevel clipmap = new ClipmapLevel(i, camera, clipSideSize, heightScale, cache);
+ _clips.add(clipmap);
+ attachChild(clipmap);
+
+ clipmap.getSceneHints().setDataMode(DataMode.Arrays);
+
+ // clipmap.getSceneHints().setDataMode(DataMode.VBOInterleaved);
+ // final FloatBufferData interleavedData = new FloatBufferData();
+ // interleavedData.setVboAccessMode(VBOAccessMode.DynamicDraw);
+ // clipmap.getMeshData().setInterleavedData(interleavedData);
+
+ // clipmap.getSceneHints().setDataMode(DataMode.VBO);
+ // clipmap.getMeshData().getVertexCoords().setVboAccessMode(VBOAccessMode.DynamicDraw);
+ // clipmap.getMeshData().getIndices().setVboAccessMode(VBOAccessMode.DynamicDraw);
+ }
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+
+ vertexShader = new UrlInputSupplier(ResourceLocatorTool.getClassPathResource(Terrain.class,
+ "com/ardor3d/extension/terrain/texturedGeometryClipmapShader.vert"));
+ pixelShader = new UrlInputSupplier(ResourceLocatorTool.getClassPathResource(Terrain.class,
+ "com/ardor3d/extension/terrain/texturedGeometryClipmapShader.frag"));
+
+ // setScale(terrainConfiguration.getScale());
+ // TODO: hack. unify scale handling over cache etc
+ setScale(terrainConfiguration.getScale().getX(), 1, terrainConfiguration.getScale().getZ());
+ setHeightRange(terrainConfiguration.getHeightRangeMin(), terrainConfiguration.getHeightRangeMax());
+ }
+
+ private final List<Long> timers = Lists.newArrayList();
+
+ @Override
+ protected void updateChildren(final double time) {
+ super.updateChildren(time);
+
+ for (int i = _minVisibleLevel; i < _clips.size(); i++) {
+ if (_clips.get(i).isReady()) {
+ _visibleLevels = i;
+ break;
+ }
+ }
+
+ // TODO: improve calcs for removing levels based on height above terrain
+ // getWorldTransform().applyInverse(_terrainCamera.getLocation(), transformedFrustumPos);
+ // final float heightRangeMax = 1f;
+ // if (transformedFrustumPos.getYf() > heightRangeMax) {
+ // final float diff = transformedFrustumPos.getYf() - heightRangeMax;
+ // final float x = (float) (diff * Math.tan(Math.toRadians(30)));
+ // for (int unit = _visibleLevels; unit < _clips.size(); unit++) {
+ // final float heightTest = _clipSideSize * MathUtils.pow2(unit) / x;
+ // if (heightTest > 1) {
+ // _visibleLevels = unit;
+ // break;
+ // }
+ // }
+ // }
+
+ if (timers.size() < _visibleLevels) {
+ for (int unit = 0; unit < _visibleLevels; unit++) {
+ timers.add(System.currentTimeMillis());
+ }
+ }
+ for (int unit = 0; unit < _visibleLevels; unit++) {
+ final long t = System.currentTimeMillis() - timers.get(unit);
+ if (t > 500) {
+ timers.set(unit, System.currentTimeMillis());
+ _clips.get(unit).updateCache();
+ }
+ }
+
+ // Update vertices.
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ _clips.get(i).updateVertices();
+ }
+
+ // Update from mailbox
+ updateFromMailbox();
+
+ // Update indices.
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ if (i == _visibleLevels) {
+ // Level 0 has no nested level, so pass null as parameter.
+ _clips.get(i).updateIndices(null);
+ } else {
+ // All other levels i have the level i-1 nested in.
+ _clips.get(i).updateIndices(_clips.get(i - 1));
+ }
+ }
+
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ _clips.get(i).getMeshData().getVertexCoords().setNeedsRefresh(true);
+ _clips.get(i).getMeshData().getIndices().setNeedsRefresh(true);
+ }
+ }
+
+ @Override
+ public void draw(final Renderer r) {
+ updateShader(r);
+
+ boolean first = true;
+ if (_normalClipmap != null) {
+ clipTextureState.setTexture(_normalClipmap.getTexture(), _normalUnit);
+ }
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ clipTextureState.setTexture(textureClipmap.getTexture());
+ if (first) {
+ blendState.setEnabled(false);
+ first = false;
+ } else {
+ blendState.setEnabled(true);
+ }
+
+ if (_textureClipmaps.size() > 1) {
+ r.getQueue().pushBuckets();
+ }
+
+ for (int i = _clips.size() - 1; i >= 0; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+ clip.setRenderState(clipTextureState);
+ }
+
+ if (_textureClipmaps.size() > 1) {
+ _geometryClipmapShader.setUniform("scale", 1f / textureClipmap.getScale());
+ _geometryClipmapShader.setUniform("textureSize", (float) textureClipmap.getTextureSize());
+ _geometryClipmapShader.setUniform("texelSize", 1f / textureClipmap.getTextureSize());
+ _geometryClipmapShader.setUniform("levels", (float) textureClipmap.getTextureLevels());
+ _geometryClipmapShader.setUniform("validLevels", (float) textureClipmap.getValidLevels() - 1);
+ _geometryClipmapShader.setUniform("showDebug", textureClipmap.isShowDebug() ? 1.0f : 0.0f);
+ _geometryClipmapShader.setNeedsRefresh(true);
+ }
+
+ blendState.setNeedsRefresh(true);
+ this.updateWorldRenderStates(true);
+
+ if (!_initialized) {
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+
+ clip.getMeshData().getIndices().limit(clip.getMeshData().getIndices().capacity());
+ }
+
+ _initialized = true;
+ }
+
+ // draw levels from coarse to fine.
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+
+ if (clip.getStripIndex() > 0) {
+ clip.draw(r);
+ }
+ }
+
+ if (_textureClipmaps.size() > 1) {
+ r.renderBuckets();
+ r.getQueue().popBuckets();
+ }
+ }
+ }
+
+ private void updateFromMailbox() {
+ if (updateTimer > updateThreashold) {
+ final List<Region> regionList = mailBox.switchAndGet();
+ if (!regionList.isEmpty()) {
+ for (int i = regionList.size() - 1; i >= 0; i--) {
+ final Region region = regionList.get(i);
+
+ final ClipmapLevel clip = _clips.get(region.getLevel());
+ final Region clipRegion = clip.getIntersectionRegion();
+
+ if (clipRegion.intersects(region)) {
+ clipRegion.intersection(region);
+ } else {
+ regionList.remove(i);
+ }
+ }
+
+ Collections.sort(regionList, regionSorter);
+
+ final int start = regionList.size() - 1;
+ for (int i = start; i >= 0; i--) {
+ final Region region = regionList.get(i);
+
+ recursiveAddUpdates(regionList, region.getLevel(), region.getX(), region.getY(), region.getWidth(),
+ region.getHeight());
+ }
+
+ for (int i = regionList.size() - 1; i >= 0; i--) {
+ final Region region = regionList.get(i);
+
+ final ClipmapLevel clip = _clips.get(region.getLevel());
+ final Region clipRegion = clip.getIntersectionRegion();
+
+ if (clipRegion.intersects(region)) {
+ clipRegion.intersection(region);
+ } else {
+ regionList.remove(i);
+ }
+ }
+
+ Collections.sort(regionList, regionSorter);
+
+ for (int i = regionList.size() - 1; i >= 0; i--) {
+ final Region region = regionList.get(i);
+ final ClipmapLevel clip = _clips.get(region.getLevel());
+ final FloatBuffer vertices = clip.getMeshData().getVertexBuffer();
+ final int vertexDistance = clip.getVertexDistance();
+
+ clip.getCache().updateRegion(vertices, region.getX() / vertexDistance,
+ region.getY() / vertexDistance, region.getWidth() / vertexDistance,
+ region.getHeight() / vertexDistance);
+ }
+ }
+ updateTimer %= updateThreashold;
+ }
+ final long time = System.currentTimeMillis();
+ updateTimer += time - oldTime;
+ oldTime = time;
+ }
+
+ private void recursiveAddUpdates(final List<Region> regionList, final int level, final int x, final int y,
+ final int width, final int height) {
+ if (level == 0) {
+ return;
+ }
+
+ final Region region = new Region(level - 1, x, y, width, height);
+ if (!regionList.contains(region)) {
+ regionList.add(region);
+ recursiveAddUpdates(regionList, region.getLevel(), region.getX(), region.getY(), region.getWidth(),
+ region.getHeight());
+ }
+ }
+
+ private final Vector3 _boundsCenter = new Vector3();
+ private final Vector3 _boundsExtents = new Vector3();
+
+ @Override
+ public void updateWorldBound(final boolean recurse) {
+ final BoundingBox worldBound = (BoundingBox) _worldBound;
+ final Vector3 center = _boundsCenter.set(_terrainCamera.getLocation());
+ final double distanceToEdge = _clipSideSize * MathUtils.pow2(_clips.size() - 1) * 0.5;
+ final double heightScale = _clips.get(0).getHeightScale();
+ final double heightMin = _clips.get(0).getHeightRangeMin() * heightScale;
+ final double heightMax = _clips.get(0).getHeightRangeMax() * heightScale;
+
+ final Vector3 extents = _boundsExtents.set(distanceToEdge, (heightMax - heightMin) * 0.5, distanceToEdge);
+ worldToLocal(center, center);
+ worldBound.setXExtent(extents.getX());
+ worldBound.setYExtent(extents.getY());
+ worldBound.setZExtent(extents.getZ());
+ worldBound.setCenter(center.getX(), (heightMax + heightMin) * 0.5, center.getZ());
+ worldBound.transform(_worldTransform, worldBound);
+ clearDirty(DirtyType.Bounding);
+ }
+
+ /**
+ * Initialize/Update shaders
+ */
+ public void updateShader(final Renderer r) {
+ if (_geometryClipmapShader != null) {
+ getWorldTransform().applyInverse(_terrainCamera.getLocation(), transformedFrustumPos);
+ _geometryClipmapShader.setUniform("eyePosition", transformedFrustumPos);
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ textureClipmap.update(r, transformedFrustumPos);
+ }
+ if (_normalClipmap != null) {
+ _normalClipmap.update(r, transformedFrustumPos);
+ }
+
+ return;
+ }
+
+ reloadShader();
+ }
+
+ public void reloadShader() {
+ final ContextCapabilities caps = ContextManager.getCurrentContext().getCapabilities();
+ if (caps.isGLSLSupported()) {
+ _geometryClipmapShader = new GLSLShaderObjectsState();
+ try {
+ _geometryClipmapShader.setVertexShader(vertexShader.getInput());
+ _geometryClipmapShader.setFragmentShader(pixelShader.getInput());
+ } catch (final IOException ex) {
+ Terrain.logger
+ .logp(Level.SEVERE, getClass().getName(), "init(Renderer)", "Could not load shaders.", ex);
+ }
+
+ _geometryClipmapShader.setUniform("texture", 0);
+ _geometryClipmapShader.setUniform("clipSideSize", (float) _clipSideSize);
+
+ if (!_textureClipmaps.isEmpty()) {
+ final TextureClipmap textureClipmap = _textureClipmaps.get(0);
+ _geometryClipmapShader.setUniform("scale", 1f / textureClipmap.getScale());
+ _geometryClipmapShader.setUniform("textureSize", (float) textureClipmap.getTextureSize());
+ _geometryClipmapShader.setUniform("texelSize", 1f / textureClipmap.getTextureSize());
+
+ _geometryClipmapShader.setUniform("levels", (float) textureClipmap.getTextureLevels());
+ _geometryClipmapShader.setUniform("validLevels", (float) textureClipmap.getValidLevels() - 1);
+ _geometryClipmapShader.setUniform("minLevel", 0f);
+
+ _geometryClipmapShader.setUniform("showDebug", textureClipmap.isShowDebug() ? 1.0f : 0.0f);
+ }
+
+ _geometryClipmapShader.setShaderDataLogic(new GLSLShaderDataLogic() {
+ public void applyData(final GLSLShaderObjectsState shader, final Mesh mesh, final Renderer renderer) {
+ if (mesh instanceof ClipmapLevel) {
+ shader.setUniform("vertexDistance", (float) ((ClipmapLevel) mesh).getVertexDistance());
+ }
+ }
+ });
+
+ applyToClips();
+
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ textureClipmap.setShaderState(_geometryClipmapShader);
+ }
+
+ if (_normalClipmap != null) {
+ _normalClipmap.setShaderState(_geometryClipmapShader);
+ }
+
+ updateWorldRenderStates(false);
+ }
+ }
+
+ protected void applyToClips() {
+ for (int i = _clips.size() - 1; i >= 0; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+ clip.setRenderState(_geometryClipmapShader);
+ }
+ }
+
+ public void regenerate(final Renderer renderer) {
+ for (int i = _clips.size() - 1; i >= 0; i--) {
+ if (!_clips.get(i).isReady()) {
+ _visibleLevels = i + 1;
+ break;
+ }
+ }
+
+ // Update vertices.
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ _clips.get(i).regenerate();
+ }
+
+ // Update indices.
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ if (i == _visibleLevels) {
+ // Level 0 has no nested level, so pass null as parameter.
+ _clips.get(i).updateIndices(null);
+ } else {
+ // All other levels i have the level i-1 nested in.
+ _clips.get(i).updateIndices(_clips.get(i - 1));
+ }
+ }
+
+ for (int i = _clips.size() - 1; i >= _visibleLevels; i--) {
+ _clips.get(i).getMeshData().getVertexCoords().setNeedsRefresh(true);
+ _clips.get(i).getMeshData().getIndices().setNeedsRefresh(true);
+ }
+
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ textureClipmap.regenerate(renderer);
+ }
+
+ if (_normalClipmap != null) {
+ _normalClipmap.regenerate(renderer);
+ }
+ }
+
+ /**
+ * @return the visibleLevels
+ */
+ public int getVisibleLevels() {
+ return _visibleLevels;
+ }
+
+ /**
+ * @param visibleLevels
+ * the visibleLevels to set
+ */
+ public void setVisibleLevels(final int visibleLevels) {
+ _visibleLevels = visibleLevels;
+ }
+
+ public void setHeightRange(final float heightRangeMin, final float heightRangeMax) {
+ for (int i = _clips.size() - 1; i >= 0; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+ clip.setHeightRange(heightRangeMin, heightRangeMax);
+ }
+ }
+
+ public void setCullingEnabled(final boolean cullingEnabled) {
+ for (int i = _clips.size() - 1; i >= 0; i--) {
+ final ClipmapLevel clip = _clips.get(i);
+ clip.setCullingEnabled(cullingEnabled);
+ }
+ }
+
+ public void makePickable(final Class<? extends AbstractBresenhamTracer> tracerClass, final int maxChecks,
+ final Vector3 initialSpacing) throws InstantiationException, IllegalAccessException {
+ // init the terrain picker
+ _picker = new ClipmapTerrainPicker(_clips, tracerClass, maxChecks, initialSpacing);
+ }
+
+ public TextureClipmap getTextureClipmap() {
+ return _textureClipmaps.get(0);
+ }
+
+ public List<TextureClipmap> getTextureClipmaps() {
+ return _textureClipmaps;
+ }
+
+ public GLSLShaderObjectsState getGeometryClipmapShader() {
+ return _geometryClipmapShader;
+ }
+
+ public void setGeometryClipmapShader(final GLSLShaderObjectsState shaderState) {
+ _geometryClipmapShader = shaderState;
+
+ applyToClips();
+
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ textureClipmap.setShaderState(_geometryClipmapShader);
+ }
+
+ if (_normalClipmap != null) {
+ _normalClipmap.setShaderState(_geometryClipmapShader);
+ }
+ }
+
+ public ClipmapTerrainPicker getPicker() {
+ return _picker;
+ }
+
+ @Override
+ public boolean supportsBoundsIntersectionRecord() {
+ // for now we are not compatible with bounding volume picks
+ return false;
+ }
+
+ @Override
+ public boolean supportsPrimitivesIntersectionRecord() {
+ return true;
+ }
+
+ @Override
+ public boolean intersectsWorldBound(final Ray3 ray) {
+ // XXX: could optimize this by grabbing edges of terrain and checking if we are outside of that...
+ // for now we just return true.
+ return true;
+ }
+
+ @Override
+ public IntersectionRecord intersectsWorldBoundsWhere(final Ray3 ray) {
+ // for now we are not compatible with bounding volume picks
+ return null;
+ }
+
+ @Override
+ public IntersectionRecord intersectsPrimitivesWhere(final Ray3 ray) {
+ if (_picker != null) {
+ final Vector3 normalStore = new Vector3();
+ final Vector3 intersect = _picker.getTerrainIntersection(getWorldTransform(), _terrainCamera.getLocation(),
+ ray, null, normalStore);
+ if (intersect != null) {
+ final double distance = intersect.distance(ray.getOrigin());
+ final IntersectionRecord record = new IntersectionRecord(new double[] { distance },
+ new Vector3[] { intersect }, new Vector3[] { normalStore }, null);
+ return record;
+ }
+ }
+ return null;
+ }
+
+ public List<ClipmapLevel> getClipmaps() {
+ return _clips;
+ }
+
+ public void setVertexShader(final InputSupplier<? extends InputStream> vertexShader) {
+ this.vertexShader = vertexShader;
+ }
+
+ public void setPixelShader(final InputSupplier<? extends InputStream> pixelShader) {
+ this.pixelShader = pixelShader;
+ }
+
+ public void addTextureClipmap(final TextureClipmap textureClipmap) {
+ _textureClipmaps.add(textureClipmap);
+ }
+
+ /**
+ * set the minimum (highest resolution) clipmap level visible
+ *
+ * @param level
+ * clamped to valid range
+ */
+ public void setMinVisibleLevel(final int level) {
+ if (level < 0) {
+ _minVisibleLevel = 0;
+ } else if (level >= _clips.size()) {
+ _minVisibleLevel = _clips.size() - 1;
+ } else {
+ _minVisibleLevel = level;
+ }
+ }
+
+ public int getMinVisibleLevel() {
+ return _minVisibleLevel;
+ }
+
+ /**
+ * convenience function to set minimum (highest resolution) texture clipmap level on all TextureClipmaps held by
+ * this terrain
+ */
+ public void setTextureMinVisibleLevel(final int level) {
+ for (final TextureClipmap tc : _textureClipmaps) {
+ tc.setMinVisibleLevel(level);
+ }
+ }
+
+ public int getTextureMinVisibleLevel() {
+ if (!_textureClipmaps.isEmpty()) {
+ return _textureClipmaps.get(0).getMinVisibleLevel();
+ }
+ return 0;
+ }
+
+ public float getHeightAt(final double x, final double z) {
+ final Vector3 heightCalc = new Vector3(x, 0, z);
+ worldToLocal(heightCalc, heightCalc);
+ final float height = getClipmaps().get(0).getCache().getSubHeight(heightCalc.getXf(), heightCalc.getZf());
+ heightCalc.set(x, height, z);
+ localToWorld(heightCalc, heightCalc);
+ return heightCalc.getYf();
+ }
+
+ public void shutdown() {
+ for (final TextureClipmap textureClipmap : _textureClipmaps) {
+ textureClipmap.shutdown();
+ }
+ for (final ClipmapLevel terrainClipmap : _clips) {
+ terrainClipmap.shutdown();
+ }
+ if (_normalClipmap != null) {
+ _normalClipmap.shutdown();
+ }
+ }
+
+ public TextureState getClipTextureState() {
+ return clipTextureState;
+ }
+
+ public void setNormalClipmap(final TextureClipmap normalClipmap) {
+ _normalClipmap = normalClipmap;
+ }
+
+ public TextureClipmap getNormalClipmap() {
+ return _normalClipmap;
+ }
+
+ public int getNormalUnit() {
+ return _normalUnit;
+ }
+
+ public void setNormalUnit(final int unit) {
+ _normalUnit = unit;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/TerrainDataProvider.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/TerrainDataProvider.java
index 10e3e8b..e1ca2a7 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/TerrainDataProvider.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/client/TerrainDataProvider.java
@@ -1,50 +1,50 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.client;
-
-import java.util.Map;
-
-/**
- * The TerrainDataProvider is the connection between the terrain core and external data.
- */
-public interface TerrainDataProvider {
- /**
- * Request for all available maps. Returns a Map with mapIDs and map names.
- *
- * @return Available maps
- * @throws Exception
- */
- Map<Integer, String> getAvailableMaps() throws Exception;
-
- /**
- * Request for a TerrainSource of valid type for this Provider.
- *
- * @param mapId
- * @return
- */
- TerrainSource getTerrainSource(int mapId);
-
- /**
- * Request for a TextureSource of valid type for this Provider.
- *
- * @param mapId
- * @return
- */
- TextureSource getTextureSource(int mapId);
-
- /**
- * Request for a normalmap TextureSource of valid type for this Provider.
- *
- * @param mapId
- * @return
- */
- TextureSource getNormalMapSource(int mapId);
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.client;
+
+import java.util.Map;
+
+/**
+ * The TerrainDataProvider is the connection between the terrain core and external data.
+ */
+public interface TerrainDataProvider {
+ /**
+ * Request for all available maps. Returns a Map with mapIDs and map names.
+ *
+ * @return Available maps
+ * @throws Exception
+ */
+ Map<Integer, String> getAvailableMaps() throws Exception;
+
+ /**
+ * Request for a TerrainSource of valid type for this Provider.
+ *
+ * @param mapId
+ * @return
+ */
+ TerrainSource getTerrainSource(int mapId);
+
+ /**
+ * Request for a TextureSource of valid type for this Provider.
+ *
+ * @param mapId
+ * @return
+ */
+ TextureSource getTextureSource(int mapId);
+
+ /**
+ * Request for a normalmap TextureSource of valid type for this Provider.
+ *
+ * @param mapId
+ * @return
+ */
+ TextureSource getNormalMapSource(int mapId);
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/ImageHeightMap.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/ImageHeightMap.java
index 9984173..99a816a 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/ImageHeightMap.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/ImageHeightMap.java
@@ -1,61 +1,61 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.heightmap;
-
-import com.ardor3d.image.Image;
-import com.ardor3d.image.ImageDataFormat;
-import com.ardor3d.math.MathUtils;
-
-public class ImageHeightMap {
-
- public static float[] generateHeightMap(final Image ardorImage, final float min, final float max) {
- if (max <= min) {
- throw new IllegalArgumentException("max must be greater than min");
- }
-
- final ImageDataFormat format = ardorImage.getDataFormat();
- if (format != ImageDataFormat.RGB && format != ImageDataFormat.RGBA && format != ImageDataFormat.Luminance) {
- throw new IllegalArgumentException("Unhandled format (must be Luminance, RGB or RGBA): " + format);
- }
-
- if (ardorImage.getWidth() != ardorImage.getHeight() || !MathUtils.isPowerOfTwo(ardorImage.getWidth())) {
- throw new IllegalArgumentException("Only pow2, square images are supported.");
- }
-
- final int size = ardorImage.getWidth(), comps = format.getComponents();
-
- // initialize the height data attributes
- final float[] heightData = new float[ardorImage.getWidth() * ardorImage.getHeight()];
- final byte[] data = new byte[heightData.length * comps];
- ardorImage.getData(0).get(data);
-
- int index = 0, dataIndex, gray;
- final int rowsize = size * comps;
- final float byteScale = (max - min) / 255f;
- for (int h = 0; h < size; h++) {
- for (int w = 0; w < size; w++) {
- dataIndex = h * rowsize + w * comps;
- if (comps == 1) {
- gray = data[dataIndex] & 0xFF;
- } else {
- final int red = data[dataIndex] & 0xFF;
- final int green = data[dataIndex + 1] & 0xFF;
- final int blue = data[dataIndex + 2] & 0xFF;
-
- gray = (int) (0.30 * red + 0.59 * green + 0.11 * blue);
- }
-
- heightData[index++] = gray * byteScale + min;
- }
- }
- return heightData;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.heightmap;
+
+import com.ardor3d.image.Image;
+import com.ardor3d.image.ImageDataFormat;
+import com.ardor3d.math.MathUtils;
+
+public class ImageHeightMap {
+
+ public static float[] generateHeightMap(final Image ardorImage, final float min, final float max) {
+ if (max <= min) {
+ throw new IllegalArgumentException("max must be greater than min");
+ }
+
+ final ImageDataFormat format = ardorImage.getDataFormat();
+ if (format != ImageDataFormat.RGB && format != ImageDataFormat.RGBA && format != ImageDataFormat.Luminance) {
+ throw new IllegalArgumentException("Unhandled format (must be Luminance, RGB or RGBA): " + format);
+ }
+
+ if (ardorImage.getWidth() != ardorImage.getHeight() || !MathUtils.isPowerOfTwo(ardorImage.getWidth())) {
+ throw new IllegalArgumentException("Only pow2, square images are supported.");
+ }
+
+ final int size = ardorImage.getWidth(), comps = format.getComponents();
+
+ // initialize the height data attributes
+ final float[] heightData = new float[ardorImage.getWidth() * ardorImage.getHeight()];
+ final byte[] data = new byte[heightData.length * comps];
+ ardorImage.getData(0).get(data);
+
+ int index = 0, dataIndex, gray;
+ final int rowsize = size * comps;
+ final float byteScale = (max - min) / 255f;
+ for (int h = 0; h < size; h++) {
+ for (int w = 0; w < size; w++) {
+ dataIndex = h * rowsize + w * comps;
+ if (comps == 1) {
+ gray = data[dataIndex] & 0xFF;
+ } else {
+ final int red = data[dataIndex] & 0xFF;
+ final int green = data[dataIndex + 1] & 0xFF;
+ final int blue = data[dataIndex + 2] & 0xFF;
+
+ gray = (int) (0.30 * red + 0.59 * green + 0.11 * blue);
+ }
+
+ heightData[index++] = gray * byteScale + min;
+ }
+ }
+ return heightData;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/MidPointHeightMapGenerator.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/MidPointHeightMapGenerator.java
index d633fd2..20c26fa 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/MidPointHeightMapGenerator.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/MidPointHeightMapGenerator.java
@@ -1,307 +1,307 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.heightmap;
-
-import java.util.Random;
-import java.util.logging.Logger;
-
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.util.Ardor3dException;
-
-public class MidPointHeightMapGenerator {
- private static final Logger logger = Logger.getLogger(MidPointHeightMapGenerator.class.getName());
-
- private float roughness;
-
- /** Height data information. */
- protected float[] heightData = null;
-
- /** The size of the height map's width. */
- protected int size = 0;
-
- /** Allows scaling the Y height of the map. */
- protected float heightScale = 1.0f;
-
- /** The filter is used to erode the terrain. */
- protected float filter = 0.5f;
-
- /** The range used to normalize terrain */
- private float heightRange = 1f;
-
- private final Random random = new Random();
- private boolean loaded = false;
-
- /**
- * Constructor builds a new heightmap using the midpoint displacement algorithm. Roughness determines how chaotic
- * the terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large
- * effect creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic
- * terrain.
- *
- * @param size
- * the size of the terrain, must be a power of 2.
- * @param roughness
- * how chaotic to make the terrain.
- *
- * @throws Ardor3dException
- * if size is less than or equal to zero or roughtness is less than 0.
- */
- public MidPointHeightMapGenerator(final int size, final float roughness) {
- if (!MathUtils.isPowerOfTwo(size)) {
- throw new Ardor3dException("Size must be (2^N) sized.");
- }
- if (roughness < 0 || size <= 0) {
- throw new Ardor3dException("size and roughness must be " + "greater than 0");
- }
- this.roughness = roughness;
- this.size = size;
- }
-
- /**
- * Constructor builds a new heightmap using the midpoint displacement algorithm. Roughness determines how chaotic
- * the terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large
- * effect creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic
- * terrain.
- *
- * @param size
- * the size of the terrain, must be a power of 2.
- * @param roughness
- * how chaotic to make the terrain.
- *
- * @throws Ardor3dException
- * if size is less than or equal to zero or roughtness is less than 0.
- */
- public MidPointHeightMapGenerator(final int size, final float roughness, final long seed) {
- this(size, roughness);
- random.setSeed(seed);
- }
-
- /**
- * @return the heightData
- */
- public float[] getHeightData() {
- if (!loaded) {
- generateHeightData();
- }
- return heightData;
- }
-
- /**
- * <code>load</code> generates the heightfield using the Midpoint Displacement algorithm. <code>load</code> uses the
- * latest attributes, so a call to <code>load</code> is recommended if attributes have changed using the set
- * methods.
- */
- public boolean generateHeightData() {
- float height;
- double heightReducer;
- float[][] tempBuffer;
-
- // holds the points of the square.
- int ni, nj;
- int mi, mj;
- int pmi, pmj;
-
- height = 1f;
- heightReducer = Math.pow(2, -1 * roughness);
-
- heightData = new float[size * size];
- tempBuffer = new float[size][size];
-
- int counter = size;
- while (counter > 0) {
- // displace the center of the square.
- for (int i = 0; i < size; i += counter) {
- for (int j = 0; j < size; j += counter) {
- // (0,0) point of the local square
- ni = (i + counter) % size;
- nj = (j + counter) % size;
- // middle point of the local square
- mi = i + counter / 2;
- mj = j + counter / 2;
-
- // displace the middle point by the average of the
- // corners, and a random value.
- tempBuffer[mi][mj] = (tempBuffer[i][j] + tempBuffer[ni][j] + tempBuffer[i][nj] + tempBuffer[ni][nj])
- / 4 + random.nextFloat() * height - height / 2;
- }
- }
-
- // next calculate the new midpoints of the line segments.
- for (int i = 0; i < size; i += counter) {
- for (int j = 0; j < size; j += counter) {
- // (0,0) of the local square
- ni = (i + counter) % size;
- nj = (j + counter) % size;
-
- // middle point of the local square.
- mi = i + counter / 2;
- mj = j + counter / 2;
-
- // middle point on the line in the x-axis direction.
- pmi = (i - counter / 2 + size) % size;
- // middle point on the line in the y-axis direction.
- pmj = (j - counter / 2 + size) % size;
-
- // Calculate the square value for the top side of the rectangle
- tempBuffer[mi][j] = (tempBuffer[i][j] + tempBuffer[ni][j] + tempBuffer[mi][pmj] + tempBuffer[mi][mj])
- / 4 + random.nextFloat() * height - height / 2;
-
- // Calculate the square value for the left side of the rectangle
- tempBuffer[i][mj] = (tempBuffer[i][j] + tempBuffer[i][nj] + tempBuffer[pmi][mj] + tempBuffer[mi][mj])
- / 4 + random.nextFloat() * height - height / 2;
-
- }
- }
-
- counter /= 2;
- height *= heightReducer;
- }
-
- normalizeTerrain(tempBuffer);
-
- // transfer the new terrain into the height map.
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- setHeightAtPoint(tempBuffer[i][j], i, j);
- }
- }
-
- MidPointHeightMapGenerator.logger.info("Created Heightmap using Mid Point");
-
- loaded = true;
-
- return true;
- }
-
- /**
- * <code>setRoughness</code> sets the new roughness value of the heightmap. Roughness determines how chaotic the
- * terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large effect
- * creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic terrain.
- *
- * @param roughness
- * how chaotic will the heightmap be.
- */
- public void setRoughness(final float roughness) {
- if (roughness < 0) {
- throw new Ardor3dException("roughness must be greater than 0");
- }
- this.roughness = roughness;
- }
-
- /**
- * <code>setHeightAtPoint</code> sets the height value for a given coordinate.
- *
- * @param height
- * the new height for the coordinate.
- * @param x
- * the x (east/west) coordinate.
- * @param z
- * the z (north/south) coordinate.
- */
- protected void setHeightAtPoint(final float height, final int x, final int z) {
- heightData[x + z * size] = height;
- }
-
- /**
- * <code>normalizeTerrain</code> takes the current terrain data and converts it to values between 0 and
- * NORMALIZE_RANGE.
- *
- * @param tempBuffer
- * the terrain to normalize.
- */
- protected void normalizeTerrain(final float[][] tempBuffer) {
- float currentMin, currentMax;
- float height;
-
- currentMin = tempBuffer[0][0];
- currentMax = tempBuffer[0][0];
-
- // find the min/max values of the height fTemptemptempBuffer
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- if (tempBuffer[i][j] > currentMax) {
- currentMax = tempBuffer[i][j];
- } else if (tempBuffer[i][j] < currentMin) {
- currentMin = tempBuffer[i][j];
- }
- }
- }
-
- // find the range of the altitude
- if (currentMax <= currentMin) {
- return;
- }
-
- height = currentMax - currentMin;
-
- // scale the values to a range of 0-255
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- tempBuffer[i][j] = (tempBuffer[i][j] - currentMin) / height * heightRange;
- }
- }
- }
-
- /**
- * <code>erodeTerrain</code> is a convenience method that applies the FIR filter to a given height map. This
- * simulates water errosion.
- *
- * @param tempBuffer
- * the terrain to filter.
- */
- protected void erodeTerrain(final float[][] tempBuffer) {
- // erode left to right
- float v;
-
- for (int i = 0; i < size; i++) {
- v = tempBuffer[i][0];
- for (int j = 1; j < size; j++) {
- tempBuffer[i][j] = filter * v + (1 - filter) * tempBuffer[i][j];
- v = tempBuffer[i][j];
- }
- }
-
- // erode right to left
- for (int i = size - 1; i >= 0; i--) {
- v = tempBuffer[i][0];
- for (int j = 0; j < size; j++) {
- tempBuffer[i][j] = filter * v + (1 - filter) * tempBuffer[i][j];
- v = tempBuffer[i][j];
- // erodeBand(tempBuffer[size * i + size - 1], -1);
- }
- }
-
- // erode top to bottom
- for (int i = 0; i < size; i++) {
- v = tempBuffer[0][i];
- for (int j = 0; j < size; j++) {
- tempBuffer[j][i] = filter * v + (1 - filter) * tempBuffer[j][i];
- v = tempBuffer[j][i];
- }
- }
-
- // erode from bottom to top
- for (int i = size - 1; i >= 0; i--) {
- v = tempBuffer[0][i];
- for (int j = 0; j < size; j++) {
- tempBuffer[j][i] = filter * v + (1 - filter) * tempBuffer[j][i];
- v = tempBuffer[j][i];
- }
- }
- }
-
- public float getHeightRange() {
- return heightRange;
- }
-
- public void setHeightRange(final float heightRange) {
- this.heightRange = heightRange;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.heightmap;
+
+import java.util.Random;
+import java.util.logging.Logger;
+
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.util.Ardor3dException;
+
+public class MidPointHeightMapGenerator {
+ private static final Logger logger = Logger.getLogger(MidPointHeightMapGenerator.class.getName());
+
+ private float roughness;
+
+ /** Height data information. */
+ protected float[] heightData = null;
+
+ /** The size of the height map's width. */
+ protected int size = 0;
+
+ /** Allows scaling the Y height of the map. */
+ protected float heightScale = 1.0f;
+
+ /** The filter is used to erode the terrain. */
+ protected float filter = 0.5f;
+
+ /** The range used to normalize terrain */
+ private float heightRange = 1f;
+
+ private final Random random = new Random();
+ private boolean loaded = false;
+
+ /**
+ * Constructor builds a new heightmap using the midpoint displacement algorithm. Roughness determines how chaotic
+ * the terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large
+ * effect creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic
+ * terrain.
+ *
+ * @param size
+ * the size of the terrain, must be a power of 2.
+ * @param roughness
+ * how chaotic to make the terrain.
+ *
+ * @throws Ardor3dException
+ * if size is less than or equal to zero or roughtness is less than 0.
+ */
+ public MidPointHeightMapGenerator(final int size, final float roughness) {
+ if (!MathUtils.isPowerOfTwo(size)) {
+ throw new Ardor3dException("Size must be (2^N) sized.");
+ }
+ if (roughness < 0 || size <= 0) {
+ throw new Ardor3dException("size and roughness must be " + "greater than 0");
+ }
+ this.roughness = roughness;
+ this.size = size;
+ }
+
+ /**
+ * Constructor builds a new heightmap using the midpoint displacement algorithm. Roughness determines how chaotic
+ * the terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large
+ * effect creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic
+ * terrain.
+ *
+ * @param size
+ * the size of the terrain, must be a power of 2.
+ * @param roughness
+ * how chaotic to make the terrain.
+ *
+ * @throws Ardor3dException
+ * if size is less than or equal to zero or roughtness is less than 0.
+ */
+ public MidPointHeightMapGenerator(final int size, final float roughness, final long seed) {
+ this(size, roughness);
+ random.setSeed(seed);
+ }
+
+ /**
+ * @return the heightData
+ */
+ public float[] getHeightData() {
+ if (!loaded) {
+ generateHeightData();
+ }
+ return heightData;
+ }
+
+ /**
+ * <code>load</code> generates the heightfield using the Midpoint Displacement algorithm. <code>load</code> uses the
+ * latest attributes, so a call to <code>load</code> is recommended if attributes have changed using the set
+ * methods.
+ */
+ public boolean generateHeightData() {
+ float height;
+ double heightReducer;
+ float[][] tempBuffer;
+
+ // holds the points of the square.
+ int ni, nj;
+ int mi, mj;
+ int pmi, pmj;
+
+ height = 1f;
+ heightReducer = Math.pow(2, -1 * roughness);
+
+ heightData = new float[size * size];
+ tempBuffer = new float[size][size];
+
+ int counter = size;
+ while (counter > 0) {
+ // displace the center of the square.
+ for (int i = 0; i < size; i += counter) {
+ for (int j = 0; j < size; j += counter) {
+ // (0,0) point of the local square
+ ni = (i + counter) % size;
+ nj = (j + counter) % size;
+ // middle point of the local square
+ mi = i + counter / 2;
+ mj = j + counter / 2;
+
+ // displace the middle point by the average of the
+ // corners, and a random value.
+ tempBuffer[mi][mj] = (tempBuffer[i][j] + tempBuffer[ni][j] + tempBuffer[i][nj] + tempBuffer[ni][nj])
+ / 4 + random.nextFloat() * height - height / 2;
+ }
+ }
+
+ // next calculate the new midpoints of the line segments.
+ for (int i = 0; i < size; i += counter) {
+ for (int j = 0; j < size; j += counter) {
+ // (0,0) of the local square
+ ni = (i + counter) % size;
+ nj = (j + counter) % size;
+
+ // middle point of the local square.
+ mi = i + counter / 2;
+ mj = j + counter / 2;
+
+ // middle point on the line in the x-axis direction.
+ pmi = (i - counter / 2 + size) % size;
+ // middle point on the line in the y-axis direction.
+ pmj = (j - counter / 2 + size) % size;
+
+ // Calculate the square value for the top side of the rectangle
+ tempBuffer[mi][j] = (tempBuffer[i][j] + tempBuffer[ni][j] + tempBuffer[mi][pmj] + tempBuffer[mi][mj])
+ / 4 + random.nextFloat() * height - height / 2;
+
+ // Calculate the square value for the left side of the rectangle
+ tempBuffer[i][mj] = (tempBuffer[i][j] + tempBuffer[i][nj] + tempBuffer[pmi][mj] + tempBuffer[mi][mj])
+ / 4 + random.nextFloat() * height - height / 2;
+
+ }
+ }
+
+ counter /= 2;
+ height *= heightReducer;
+ }
+
+ normalizeTerrain(tempBuffer);
+
+ // transfer the new terrain into the height map.
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ setHeightAtPoint(tempBuffer[i][j], i, j);
+ }
+ }
+
+ MidPointHeightMapGenerator.logger.info("Created Heightmap using Mid Point");
+
+ loaded = true;
+
+ return true;
+ }
+
+ /**
+ * <code>setRoughness</code> sets the new roughness value of the heightmap. Roughness determines how chaotic the
+ * terrain will be. Where 1 is perfectly self-similar, > 1 early iterations have a disproportionately large effect
+ * creating smooth terrain, and < 1 late iteraions have a disproportionately large effect creating chaotic terrain.
+ *
+ * @param roughness
+ * how chaotic will the heightmap be.
+ */
+ public void setRoughness(final float roughness) {
+ if (roughness < 0) {
+ throw new Ardor3dException("roughness must be greater than 0");
+ }
+ this.roughness = roughness;
+ }
+
+ /**
+ * <code>setHeightAtPoint</code> sets the height value for a given coordinate.
+ *
+ * @param height
+ * the new height for the coordinate.
+ * @param x
+ * the x (east/west) coordinate.
+ * @param z
+ * the z (north/south) coordinate.
+ */
+ protected void setHeightAtPoint(final float height, final int x, final int z) {
+ heightData[x + z * size] = height;
+ }
+
+ /**
+ * <code>normalizeTerrain</code> takes the current terrain data and converts it to values between 0 and
+ * NORMALIZE_RANGE.
+ *
+ * @param tempBuffer
+ * the terrain to normalize.
+ */
+ protected void normalizeTerrain(final float[][] tempBuffer) {
+ float currentMin, currentMax;
+ float height;
+
+ currentMin = tempBuffer[0][0];
+ currentMax = tempBuffer[0][0];
+
+ // find the min/max values of the height fTemptemptempBuffer
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ if (tempBuffer[i][j] > currentMax) {
+ currentMax = tempBuffer[i][j];
+ } else if (tempBuffer[i][j] < currentMin) {
+ currentMin = tempBuffer[i][j];
+ }
+ }
+ }
+
+ // find the range of the altitude
+ if (currentMax <= currentMin) {
+ return;
+ }
+
+ height = currentMax - currentMin;
+
+ // scale the values to a range of 0-255
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ tempBuffer[i][j] = (tempBuffer[i][j] - currentMin) / height * heightRange;
+ }
+ }
+ }
+
+ /**
+ * <code>erodeTerrain</code> is a convenience method that applies the FIR filter to a given height map. This
+ * simulates water errosion.
+ *
+ * @param tempBuffer
+ * the terrain to filter.
+ */
+ protected void erodeTerrain(final float[][] tempBuffer) {
+ // erode left to right
+ float v;
+
+ for (int i = 0; i < size; i++) {
+ v = tempBuffer[i][0];
+ for (int j = 1; j < size; j++) {
+ tempBuffer[i][j] = filter * v + (1 - filter) * tempBuffer[i][j];
+ v = tempBuffer[i][j];
+ }
+ }
+
+ // erode right to left
+ for (int i = size - 1; i >= 0; i--) {
+ v = tempBuffer[i][0];
+ for (int j = 0; j < size; j++) {
+ tempBuffer[i][j] = filter * v + (1 - filter) * tempBuffer[i][j];
+ v = tempBuffer[i][j];
+ // erodeBand(tempBuffer[size * i + size - 1], -1);
+ }
+ }
+
+ // erode top to bottom
+ for (int i = 0; i < size; i++) {
+ v = tempBuffer[0][i];
+ for (int j = 0; j < size; j++) {
+ tempBuffer[j][i] = filter * v + (1 - filter) * tempBuffer[j][i];
+ v = tempBuffer[j][i];
+ }
+ }
+
+ // erode from bottom to top
+ for (int i = size - 1; i >= 0; i--) {
+ v = tempBuffer[0][i];
+ for (int j = 0; j < size; j++) {
+ tempBuffer[j][i] = filter * v + (1 - filter) * tempBuffer[j][i];
+ v = tempBuffer[j][i];
+ }
+ }
+ }
+
+ public float getHeightRange() {
+ return heightRange;
+ }
+
+ public void setHeightRange(final float heightRange) {
+ this.heightRange = heightRange;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/RawHeightMap.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/RawHeightMap.java
index b87bdb8..032f32d 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/RawHeightMap.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/heightmap/RawHeightMap.java
@@ -1,246 +1,246 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.heightmap;
-
-import java.io.BufferedInputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.logging.Logger;
-
-import com.ardor3d.util.LittleEndianDataInput;
-
-public class RawHeightMap {
- private static final Logger logger = Logger.getLogger(RawHeightMap.class.getName());
-
- public enum HeightMapFormat {
- Byte, Short, UnsignedByte, UnsignedShort, Integer, Float
- }
-
- private HeightMapFormat format;
- private boolean isLittleEndian;
-
- private int size;
- private InputStream stream;
- private float heightData[];
-
- private boolean swapXY;
- private boolean flipX;
- private boolean flipY;
-
- private boolean loaded;
-
- public RawHeightMap(final String filename, final int size) throws Exception {
- // varify that filename and size are valid.
- if (null == filename || size <= 0) {
- throw new Exception("Must supply valid filename and " + "size (> 0)");
- }
- try {
- setup(new FileInputStream(filename), size);
- } catch (final FileNotFoundException e) {
- throw new Exception("height file not found: " + filename);
- }
- }
-
- public RawHeightMap(final InputStream stream, final int size) throws Exception {
- setup(stream, size);
- }
-
- public RawHeightMap(final URL resource, final int size) throws Exception {
- // varify that resource and size are valid.
- if (null == resource || size <= 0) {
- throw new Exception("Must supply valid resource and " + "size (> 0)");
- }
-
- try {
- setup(resource.openStream(), size);
- } catch (final IOException e) {
- throw new Exception("Unable to open height url: " + resource);
- }
- }
-
- private void setup(final InputStream stream, final int size) throws Exception {
- // varify that filename and size are valid.
- if (null == stream || size <= 0) {
- throw new Exception("Must supply valid stream and " + "size (> 0)");
- }
-
- this.stream = stream;
- this.size = size;
- }
-
- /**
- * <code>load</code> fills the height data array with the appropriate data from the set RAW image stream or file.
- *
- * @return true if the load is successful, false otherwise.
- */
- public boolean loadHeightmap() {
- // initialize the height data attributes
- heightData = new float[size * size];
-
- // attempt to connect to the supplied file.
- BufferedInputStream bis = null;
-
- try {
- bis = new BufferedInputStream(stream);
- final DataInputStream dis = new DataInputStream(bis);
- DataInput di = dis;
- if (isLittleEndian) {
- di = new LittleEndianDataInput(dis);
- }
-
- // read the raw file
- for (int y = 0; y < size; y++) {
- for (int x = 0; x < size; x++) {
- int index;
- int xIndex = x;
- int yIndex = y;
-
- if (flipX) {
- xIndex = size - x - 1;
- }
- if (flipY) {
- yIndex = size - y - 1;
- }
-
- if (swapXY) {
- index = xIndex * size + yIndex;
- } else {
- index = yIndex * size + xIndex;
- }
-
- switch (format) {
- case Byte:
- heightData[index] = di.readByte() * 0.5f / Byte.MAX_VALUE + 0.5f;
- break;
- case Short:
- heightData[index] = di.readShort() * 0.5f / Short.MAX_VALUE + 0.5f;
- break;
- case UnsignedByte:
- heightData[index] = di.readUnsignedByte() * 0.5f / Byte.MAX_VALUE;
- break;
- case UnsignedShort:
- heightData[index] = di.readUnsignedShort() * 0.5f / Short.MAX_VALUE;
- break;
- case Integer:
- heightData[index] = di.readInt() * 0.5f / Integer.MAX_VALUE + 0.5f;
- break;
- case Float:
- heightData[index] = di.readFloat() / Float.MAX_VALUE;
- break;
- }
- }
- }
- dis.close();
- } catch (final IOException e1) {
- logger.warning("Error reading height data from stream.");
- return false;
- }
- loaded = true;
- return true;
- }
-
- /**
- * @return the heightData
- */
- public float[] getHeightData() {
- if (!loaded) {
- loadHeightmap();
- }
- return heightData;
- }
-
- /**
- * @return the format
- */
- public HeightMapFormat getFormat() {
- return format;
- }
-
- /**
- * @param format
- * the format to set
- */
- public void setFormat(final HeightMapFormat format) {
- this.format = format;
- }
-
- /**
- * @return the isLittleEndian
- */
- public boolean isLittleEndian() {
- return isLittleEndian;
- }
-
- /**
- * @param isLittleEndian
- * the isLittleEndian to set
- */
- public void setLittleEndian(final boolean isLittleEndian) {
- this.isLittleEndian = isLittleEndian;
- }
-
- /**
- * @return the swapXY
- */
- public boolean isSwapXY() {
- return swapXY;
- }
-
- /**
- * @param swapXY
- * the swapXY to set
- */
- public void setSwapXY(final boolean swapXY) {
- this.swapXY = swapXY;
- }
-
- /**
- * @return the flipX
- */
- public boolean isFlipX() {
- return flipX;
- }
-
- /**
- * @param flipX
- * the flipX to set
- */
- public void setFlipX(final boolean flipX) {
- this.flipX = flipX;
- }
-
- /**
- * @return the flipY
- */
- public boolean isFlipY() {
- return flipY;
- }
-
- /**
- * @param flipY
- * the flipY to set
- */
- public void setFlipY(final boolean flipY) {
- this.flipY = flipY;
- }
-
- /**
- * @return the loaded
- */
- public boolean isLoaded() {
- return loaded;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.heightmap;
+
+import java.io.BufferedInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.logging.Logger;
+
+import com.ardor3d.util.LittleEndianDataInput;
+
+public class RawHeightMap {
+ private static final Logger logger = Logger.getLogger(RawHeightMap.class.getName());
+
+ public enum HeightMapFormat {
+ Byte, Short, UnsignedByte, UnsignedShort, Integer, Float
+ }
+
+ private HeightMapFormat format;
+ private boolean isLittleEndian;
+
+ private int size;
+ private InputStream stream;
+ private float heightData[];
+
+ private boolean swapXY;
+ private boolean flipX;
+ private boolean flipY;
+
+ private boolean loaded;
+
+ public RawHeightMap(final String filename, final int size) throws Exception {
+ // varify that filename and size are valid.
+ if (null == filename || size <= 0) {
+ throw new Exception("Must supply valid filename and " + "size (> 0)");
+ }
+ try {
+ setup(new FileInputStream(filename), size);
+ } catch (final FileNotFoundException e) {
+ throw new Exception("height file not found: " + filename);
+ }
+ }
+
+ public RawHeightMap(final InputStream stream, final int size) throws Exception {
+ setup(stream, size);
+ }
+
+ public RawHeightMap(final URL resource, final int size) throws Exception {
+ // varify that resource and size are valid.
+ if (null == resource || size <= 0) {
+ throw new Exception("Must supply valid resource and " + "size (> 0)");
+ }
+
+ try {
+ setup(resource.openStream(), size);
+ } catch (final IOException e) {
+ throw new Exception("Unable to open height url: " + resource);
+ }
+ }
+
+ private void setup(final InputStream stream, final int size) throws Exception {
+ // varify that filename and size are valid.
+ if (null == stream || size <= 0) {
+ throw new Exception("Must supply valid stream and " + "size (> 0)");
+ }
+
+ this.stream = stream;
+ this.size = size;
+ }
+
+ /**
+ * <code>load</code> fills the height data array with the appropriate data from the set RAW image stream or file.
+ *
+ * @return true if the load is successful, false otherwise.
+ */
+ public boolean loadHeightmap() {
+ // initialize the height data attributes
+ heightData = new float[size * size];
+
+ // attempt to connect to the supplied file.
+ BufferedInputStream bis = null;
+
+ try {
+ bis = new BufferedInputStream(stream);
+ final DataInputStream dis = new DataInputStream(bis);
+ DataInput di = dis;
+ if (isLittleEndian) {
+ di = new LittleEndianDataInput(dis);
+ }
+
+ // read the raw file
+ for (int y = 0; y < size; y++) {
+ for (int x = 0; x < size; x++) {
+ int index;
+ int xIndex = x;
+ int yIndex = y;
+
+ if (flipX) {
+ xIndex = size - x - 1;
+ }
+ if (flipY) {
+ yIndex = size - y - 1;
+ }
+
+ if (swapXY) {
+ index = xIndex * size + yIndex;
+ } else {
+ index = yIndex * size + xIndex;
+ }
+
+ switch (format) {
+ case Byte:
+ heightData[index] = di.readByte() * 0.5f / Byte.MAX_VALUE + 0.5f;
+ break;
+ case Short:
+ heightData[index] = di.readShort() * 0.5f / Short.MAX_VALUE + 0.5f;
+ break;
+ case UnsignedByte:
+ heightData[index] = di.readUnsignedByte() * 0.5f / Byte.MAX_VALUE;
+ break;
+ case UnsignedShort:
+ heightData[index] = di.readUnsignedShort() * 0.5f / Short.MAX_VALUE;
+ break;
+ case Integer:
+ heightData[index] = di.readInt() * 0.5f / Integer.MAX_VALUE + 0.5f;
+ break;
+ case Float:
+ heightData[index] = di.readFloat() / Float.MAX_VALUE;
+ break;
+ }
+ }
+ }
+ dis.close();
+ } catch (final IOException e1) {
+ logger.warning("Error reading height data from stream.");
+ return false;
+ }
+ loaded = true;
+ return true;
+ }
+
+ /**
+ * @return the heightData
+ */
+ public float[] getHeightData() {
+ if (!loaded) {
+ loadHeightmap();
+ }
+ return heightData;
+ }
+
+ /**
+ * @return the format
+ */
+ public HeightMapFormat getFormat() {
+ return format;
+ }
+
+ /**
+ * @param format
+ * the format to set
+ */
+ public void setFormat(final HeightMapFormat format) {
+ this.format = format;
+ }
+
+ /**
+ * @return the isLittleEndian
+ */
+ public boolean isLittleEndian() {
+ return isLittleEndian;
+ }
+
+ /**
+ * @param isLittleEndian
+ * the isLittleEndian to set
+ */
+ public void setLittleEndian(final boolean isLittleEndian) {
+ this.isLittleEndian = isLittleEndian;
+ }
+
+ /**
+ * @return the swapXY
+ */
+ public boolean isSwapXY() {
+ return swapXY;
+ }
+
+ /**
+ * @param swapXY
+ * the swapXY to set
+ */
+ public void setSwapXY(final boolean swapXY) {
+ this.swapXY = swapXY;
+ }
+
+ /**
+ * @return the flipX
+ */
+ public boolean isFlipX() {
+ return flipX;
+ }
+
+ /**
+ * @param flipX
+ * the flipX to set
+ */
+ public void setFlipX(final boolean flipX) {
+ this.flipX = flipX;
+ }
+
+ /**
+ * @return the flipY
+ */
+ public boolean isFlipY() {
+ return flipY;
+ }
+
+ /**
+ * @param flipY
+ * the flipY to set
+ */
+ public void setFlipY(final boolean flipY) {
+ this.flipY = flipY;
+ }
+
+ /**
+ * @return the loaded
+ */
+ public boolean isLoaded() {
+ return loaded;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainDataProvider.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainDataProvider.java
index 3e3b6ae..21e9062 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainDataProvider.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainDataProvider.java
@@ -1,135 +1,135 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.array;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import com.ardor3d.extension.terrain.client.TerrainDataProvider;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
-import com.ardor3d.extension.terrain.util.NormalMapUtil;
-import com.ardor3d.image.Image;
-import com.ardor3d.math.type.ReadOnlyVector3;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-public class ArrayTerrainDataProvider implements TerrainDataProvider {
- private static final int tileSize = 128;
-
- private final List<float[]> heightMaps;
- private final List<Integer> heightMapSizes;
- private final ReadOnlyVector3 scale;
-
- private float heightMax = 1.0f;
- private float heightMin = 0.0f;
-
- private boolean generateNormalMap;
-
- public ArrayTerrainDataProvider(final float[] data, final int size, final ReadOnlyVector3 scale) {
- this(data, size, scale, false);
- }
-
- public ArrayTerrainDataProvider(final float[] data, final int size, final ReadOnlyVector3 scale,
- final boolean generateNormalMap) {
- this.scale = scale;
- this.generateNormalMap = generateNormalMap;
-
- // TODO: calculate clipLevelCount through size and tileSize
- final int clipLevelCount = 6;
-
- int currentSize = size;
- heightMaps = Lists.newArrayList();
- heightMapSizes = Lists.newArrayList();
- heightMaps.add(data);
- heightMapSizes.add(currentSize);
- float[] parentHeightMap = data;
- for (int i = 0; i < clipLevelCount; i++) {
- currentSize /= 2;
- final float[] heightMapMip = new float[currentSize * currentSize];
- heightMaps.add(heightMapMip);
- heightMapSizes.add(currentSize);
- for (int x = 0; x < currentSize; x++) {
- for (int z = 0; z < currentSize; z++) {
- heightMapMip[z * currentSize + x] = parentHeightMap[z * currentSize * 4 + x * 2];
- }
- }
- parentHeightMap = heightMapMip;
- }
-
- Collections.reverse(heightMaps);
- Collections.reverse(heightMapSizes);
- }
-
- @Override
- public Map<Integer, String> getAvailableMaps() throws Exception {
- final Map<Integer, String> maps = Maps.newHashMap();
- maps.put(0, "ArrayBasedMap");
-
- return maps;
- }
-
- @Override
- public TerrainSource getTerrainSource(final int mapId) {
- return new ArrayTerrainSource(tileSize, heightMaps, heightMapSizes, scale, heightMin, heightMax);
- }
-
- @Override
- public TextureSource getTextureSource(final int mapId) {
- return new ArrayTextureSource(tileSize, heightMaps, heightMapSizes);
- }
-
- @Override
- public TextureSource getNormalMapSource(final int mapId) {
- if (generateNormalMap) {
- try {
- final float[] data = heightMaps.get(heightMaps.size() - 1);
- final int size = heightMapSizes.get(heightMapSizes.size() - 1);
- final Image normalImage = NormalMapUtil.constructNormalMap(data, size, scale.getY() / heightMax,
- scale.getX(), scale.getZ());
- return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
- } catch (final Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- public float getHeightMin() {
- return heightMin;
- }
-
- public void setHeightMin(final float heightMin) {
- this.heightMin = heightMin;
- }
-
- public float getHeightMax() {
- return heightMax;
- }
-
- public void setHeightMax(final float heightMax) {
- this.heightMax = heightMax;
- }
-
- public List<Integer> getHeightMapSizes() {
- return heightMapSizes;
- }
-
- public boolean isGenerateNormalMap() {
- return generateNormalMap;
- }
-
- public void setGenerateNormalMap(final boolean generateNormalMap) {
- this.generateNormalMap = generateNormalMap;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.array;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import com.ardor3d.extension.terrain.client.TerrainDataProvider;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
+import com.ardor3d.extension.terrain.util.NormalMapUtil;
+import com.ardor3d.image.Image;
+import com.ardor3d.math.type.ReadOnlyVector3;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class ArrayTerrainDataProvider implements TerrainDataProvider {
+ private static final int tileSize = 128;
+
+ private final List<float[]> heightMaps;
+ private final List<Integer> heightMapSizes;
+ private final ReadOnlyVector3 scale;
+
+ private float heightMax = 1.0f;
+ private float heightMin = 0.0f;
+
+ private boolean generateNormalMap;
+
+ public ArrayTerrainDataProvider(final float[] data, final int size, final ReadOnlyVector3 scale) {
+ this(data, size, scale, false);
+ }
+
+ public ArrayTerrainDataProvider(final float[] data, final int size, final ReadOnlyVector3 scale,
+ final boolean generateNormalMap) {
+ this.scale = scale;
+ this.generateNormalMap = generateNormalMap;
+
+ // TODO: calculate clipLevelCount through size and tileSize
+ final int clipLevelCount = 6;
+
+ int currentSize = size;
+ heightMaps = Lists.newArrayList();
+ heightMapSizes = Lists.newArrayList();
+ heightMaps.add(data);
+ heightMapSizes.add(currentSize);
+ float[] parentHeightMap = data;
+ for (int i = 0; i < clipLevelCount; i++) {
+ currentSize /= 2;
+ final float[] heightMapMip = new float[currentSize * currentSize];
+ heightMaps.add(heightMapMip);
+ heightMapSizes.add(currentSize);
+ for (int x = 0; x < currentSize; x++) {
+ for (int z = 0; z < currentSize; z++) {
+ heightMapMip[z * currentSize + x] = parentHeightMap[z * currentSize * 4 + x * 2];
+ }
+ }
+ parentHeightMap = heightMapMip;
+ }
+
+ Collections.reverse(heightMaps);
+ Collections.reverse(heightMapSizes);
+ }
+
+ @Override
+ public Map<Integer, String> getAvailableMaps() throws Exception {
+ final Map<Integer, String> maps = Maps.newHashMap();
+ maps.put(0, "ArrayBasedMap");
+
+ return maps;
+ }
+
+ @Override
+ public TerrainSource getTerrainSource(final int mapId) {
+ return new ArrayTerrainSource(tileSize, heightMaps, heightMapSizes, scale, heightMin, heightMax);
+ }
+
+ @Override
+ public TextureSource getTextureSource(final int mapId) {
+ return new ArrayTextureSource(tileSize, heightMaps, heightMapSizes);
+ }
+
+ @Override
+ public TextureSource getNormalMapSource(final int mapId) {
+ if (generateNormalMap) {
+ try {
+ final float[] data = heightMaps.get(heightMaps.size() - 1);
+ final int size = heightMapSizes.get(heightMapSizes.size() - 1);
+ final Image normalImage = NormalMapUtil.constructNormalMap(data, size, scale.getY() / heightMax,
+ scale.getX(), scale.getZ());
+ return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ public float getHeightMin() {
+ return heightMin;
+ }
+
+ public void setHeightMin(final float heightMin) {
+ this.heightMin = heightMin;
+ }
+
+ public float getHeightMax() {
+ return heightMax;
+ }
+
+ public void setHeightMax(final float heightMax) {
+ this.heightMax = heightMax;
+ }
+
+ public List<Integer> getHeightMapSizes() {
+ return heightMapSizes;
+ }
+
+ public boolean isGenerateNormalMap() {
+ return generateNormalMap;
+ }
+
+ public void setGenerateNormalMap(final boolean generateNormalMap) {
+ this.generateNormalMap = generateNormalMap;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainSource.java
index 71b6e04..990570c 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTerrainSource.java
@@ -1,111 +1,111 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.array;
-
-import java.util.List;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TerrainConfiguration;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.math.type.ReadOnlyVector3;
-import com.google.common.collect.Sets;
-
-public class ArrayTerrainSource implements TerrainSource {
- private final int tileSize;
- private final List<float[]> heightMaps;
- private final List<Integer> heightMapSizes;
- private final ReadOnlyVector3 scale;
- private final float heightMin;
- private final float heightMax;
-
- private final ThreadLocal<float[]> tileDataPool = new ThreadLocal<float[]>() {
- @Override
- protected float[] initialValue() {
- return new float[tileSize * tileSize];
- }
- };
-
- public ArrayTerrainSource(final int tileSize, final List<float[]> heightMaps, final List<Integer> heightMapSizes,
- final ReadOnlyVector3 scale, final float heightMin, final float heightMax) {
- this.tileSize = tileSize;
- this.heightMaps = heightMaps;
- this.heightMapSizes = heightMapSizes;
- this.scale = scale;
- this.heightMin = heightMin;
- this.heightMax = heightMax;
- }
-
- @Override
- public TerrainConfiguration getConfiguration() throws Exception {
- return new TerrainConfiguration(heightMaps.size(), tileSize, scale, heightMin, heightMax, true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final float[] heightMap = heightMaps.get(clipmapLevel);
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
-
- final float[] data = tileDataPool.get();
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int index = x + y * tileSize;
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
- data[index] = getHeight(heightMap, heightMapSize, heightX, heightY);
- }
- }
- return data;
- }
-
- private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
- if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
- return 0;
- }
-
- return heightMap[y * heightMapSize + x];
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.array;
+
+import java.util.List;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TerrainConfiguration;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.math.type.ReadOnlyVector3;
+import com.google.common.collect.Sets;
+
+public class ArrayTerrainSource implements TerrainSource {
+ private final int tileSize;
+ private final List<float[]> heightMaps;
+ private final List<Integer> heightMapSizes;
+ private final ReadOnlyVector3 scale;
+ private final float heightMin;
+ private final float heightMax;
+
+ private final ThreadLocal<float[]> tileDataPool = new ThreadLocal<float[]>() {
+ @Override
+ protected float[] initialValue() {
+ return new float[tileSize * tileSize];
+ }
+ };
+
+ public ArrayTerrainSource(final int tileSize, final List<float[]> heightMaps, final List<Integer> heightMapSizes,
+ final ReadOnlyVector3 scale, final float heightMin, final float heightMax) {
+ this.tileSize = tileSize;
+ this.heightMaps = heightMaps;
+ this.heightMapSizes = heightMapSizes;
+ this.scale = scale;
+ this.heightMin = heightMin;
+ this.heightMax = heightMax;
+ }
+
+ @Override
+ public TerrainConfiguration getConfiguration() throws Exception {
+ return new TerrainConfiguration(heightMaps.size(), tileSize, scale, heightMin, heightMax, true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final float[] heightMap = heightMaps.get(clipmapLevel);
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+
+ final float[] data = tileDataPool.get();
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int index = x + y * tileSize;
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+ data[index] = getHeight(heightMap, heightMapSize, heightX, heightY);
+ }
+ }
+ return data;
+ }
+
+ private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
+ if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
+ return 0;
+ }
+
+ return heightMap[y * heightMapSize + x];
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTextureSource.java
index b97855f..218d39a 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/array/ArrayTextureSource.java
@@ -1,113 +1,113 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.array;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class ArrayTextureSource implements TextureSource {
- private final int tileSize;
- private final List<float[]> heightMaps;
- private final List<Integer> heightMapSizes;
-
- private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
- @Override
- protected ByteBuffer initialValue() {
- return BufferUtils.createByteBufferOnHeap(tileSize * tileSize);
- }
- };
-
- public ArrayTextureSource(final int tileSize, final List<float[]> heightMaps, final List<Integer> heightMapSizes) {
- this.tileSize = tileSize;
- this.heightMaps = heightMaps;
- this.heightMapSizes = heightMapSizes;
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.Luminance8);
-
- return new TextureConfiguration(heightMaps.size(), textureStoreFormat, tileSize, 1f, true, false);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final float[] heightMap = heightMaps.get(clipmapLevel);
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
-
- final ByteBuffer data = tileDataPool.get();
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int index = (x + y * tileSize) * 1;
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
- final float height = getHeight(heightMap, heightMapSize, heightX, heightY);
- final byte byteHeight = (byte) (height * 255 * 3);
- data.put(index, byteHeight);
- }
- }
- return data;
- }
-
- private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
- if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
- return 0;
- }
-
- return heightMap[y * heightMapSize + x];
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.array;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class ArrayTextureSource implements TextureSource {
+ private final int tileSize;
+ private final List<float[]> heightMaps;
+ private final List<Integer> heightMapSizes;
+
+ private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
+ @Override
+ protected ByteBuffer initialValue() {
+ return BufferUtils.createByteBufferOnHeap(tileSize * tileSize);
+ }
+ };
+
+ public ArrayTextureSource(final int tileSize, final List<float[]> heightMaps, final List<Integer> heightMapSizes) {
+ this.tileSize = tileSize;
+ this.heightMaps = heightMaps;
+ this.heightMapSizes = heightMapSizes;
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.Luminance8);
+
+ return new TextureConfiguration(heightMaps.size(), textureStoreFormat, tileSize, 1f, true, false);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final float[] heightMap = heightMaps.get(clipmapLevel);
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+
+ final ByteBuffer data = tileDataPool.get();
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int index = (x + y * tileSize) * 1;
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+ final float height = getHeight(heightMap, heightMapSize, heightX, heightY);
+ final byte byteHeight = (byte) (height * 255 * 3);
+ data.put(index, byteHeight);
+ }
+ }
+ return data;
+ }
+
+ private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
+ if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
+ return 0;
+ }
+
+ return heightMap[y * heightMapSize + x];
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/awt/AwtTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/awt/AwtTextureSource.java
index ed6b903..e83be4a 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/awt/AwtTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/awt/AwtTextureSource.java
@@ -1,231 +1,231 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.awt;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferInt;
-import java.nio.ByteBuffer;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.math.Transform;
-import com.ardor3d.math.type.ReadOnlyVector4;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class AwtTextureSource implements TextureSource, ElementUpdateListener {
- private static final int tileSize = 128;
- private final int availableClipmapLevels;
-
- private final AwtElementProvider provider;
- private final TextureStoreFormat format;
- private final boolean hasAlpha;
-
- private final BufferedImage _image[];
- private final Set<Tile> _updatedTiles[];
-
- private final ThreadLocal<byte[]> tileDataPool = new ThreadLocal<byte[]>() {
- @Override
- protected byte[] initialValue() {
- return new byte[tileSize * tileSize * (hasAlpha ? 4 : 3)];
- }
- };
-
- @SuppressWarnings("unchecked")
- public AwtTextureSource(final int availableClipmapLevels, final TextureStoreFormat format) {
- if (format != TextureStoreFormat.RGB8 && format != TextureStoreFormat.RGBA8) {
- throw new IllegalArgumentException("Only RGB8 and RGBA8 currently supported.");
- }
-
- this.availableClipmapLevels = availableClipmapLevels;
- this.format = format;
- hasAlpha = format == TextureStoreFormat.RGBA8;
-
- _image = new BufferedImage[availableClipmapLevels];
- _updatedTiles = new Set[availableClipmapLevels];
-
- provider = new AwtElementProvider();
- provider.addElementUpdateListener(this);
-
- for (int i = 0; i < availableClipmapLevels; i++) {
- _image[i] = new BufferedImage(tileSize, tileSize, BufferedImage.TYPE_INT_ARGB);
- _updatedTiles[i] = Sets.newHashSet();
- }
- }
-
- public AwtElementProvider getProvider() {
- return provider;
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, format);
-
- return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- if (_updatedTiles[baseClipmapLevel].isEmpty()) {
- return null;
- }
-
- final Set<Tile> tiles = Sets.newHashSet();
-
- int checkX, checkY;
- for (final Iterator<Tile> it = _updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
- final Tile tile = it.next();
- checkX = tile.getX();
- checkY = tile.getY();
- if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
- tiles.add(tile);
- it.remove();
- }
- }
-
- return tiles;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile sourceTile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- // build a transform that would take us to the local space of the tile.
- final Transform localTransform = new Transform();
- localTransform.setTranslation(-tileX * tileSize, -tileY * tileSize, 0);
- final double scale = 1.0 / MathUtils.pow2(baseClipmapLevel);
- localTransform.setScale(scale);
-
- final double tileInScale = MathUtils.pow2(baseClipmapLevel) * tileSize;
- final double minX = tileInScale * tileX;
- final double minY = tileInScale * tileY;
- final double maxX = minX + tileInScale - 1;
- final double maxY = minY + tileInScale - 1;
-
- // Clear image
- final Graphics2D graphics = (Graphics2D) _image[baseClipmapLevel].getGraphics();
- final Composite composite = graphics.getComposite();
- // TODO: Add: do regular clear with black if no alpha channel right?
- graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
- graphics.fillRect(0, 0, tileSize, tileSize);
- graphics.setComposite(composite);
-
- // get list of elements that intersect the given region
- final List<AbstractAwtElement> elements = Lists.newArrayList(provider.getElements());
- for (final Iterator<AbstractAwtElement> it = elements.iterator(); it.hasNext();) {
- final AbstractAwtElement element = it.next();
-
- // check bounds to toss it or keep it.
- final ReadOnlyVector4 bounds = element.getBounds();
-
- if (bounds.getX() > maxX || bounds.getX() + bounds.getZ() <= minX || bounds.getY() > maxY
- || bounds.getY() + bounds.getW() <= minY) {
- // toss it
- it.remove();
- }
- }
-
- // make our buffer - init to all 0's
- final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * (hasAlpha ? 4 : 3));
-
- // shortcut - no data, return buffer.
- if (elements.isEmpty()) {
- // graphics.setBackground((tileX + tileY) % 2 == 0 ? Color.GREEN : Color.GRAY);
- // graphics.clearRect(0, 0, tileSize, tileSize);
- return data;
- }
-
- // otherwise draw... for each element, apply to our image.
- for (final AbstractAwtElement element : elements) {
- element.drawTo(_image[baseClipmapLevel], localTransform, clipmapLevel);
- }
-
- // if (clipmapLevel == 0) {
- // graphics.setBackground((tileX + tileY) % 2 == 0 ? Color.GREEN : Color.GRAY);
- // graphics.clearRect(0, 0, tileSize, tileSize);
- // }
-
- // grab image contents to buffer
- final byte[] byteArray = tileDataPool.get();
- final DataBufferInt dataBuffer = (DataBufferInt) _image[baseClipmapLevel].getData().getDataBuffer();
- final int[] tmpData = dataBuffer.getData();
- int index = 0;
- for (int i = 0; i < tileSize * tileSize; i++) {
- final int argb = tmpData[i];
- byteArray[index++] = (byte) (argb >> 16 & 0xFF);
- byteArray[index++] = (byte) (argb >> 8 & 0xFF);
- byteArray[index++] = (byte) (argb & 0xFF);
- if (hasAlpha) {
- byteArray[index++] = (byte) (argb >> 24 & 0xFF);
- }
- }
-
- data.put(byteArray);
- data.flip();
-
- // return buffer
- return data;
- }
-
- @Override
- public void elementUpdated(final ReadOnlyVector4 oldBounds, final ReadOnlyVector4 newBounds) {
- addTiles(oldBounds);
- addTiles(newBounds);
- }
-
- protected void addTiles(final ReadOnlyVector4 bounds) {
- for (int i = 0; i < availableClipmapLevels; i++) {
- final double scale = 1.0 / (tileSize * MathUtils.pow2(i));
- final int minX = (int) MathUtils.floor(bounds.getX() * scale);
- final int minY = (int) MathUtils.floor(bounds.getY() * scale);
- final int maxX = (int) MathUtils.floor((bounds.getX() + bounds.getZ() - 1) * scale);
- final int maxY = (int) MathUtils.floor((bounds.getY() + bounds.getW() - 1) * scale);
-
- Tile tile;
- for (int y = minY; y <= maxY; y++) {
- for (int x = minX; x <= maxX; x++) {
- tile = new Tile(x, y);
- _updatedTiles[i].add(tile);
- }
- }
- }
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.awt;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.type.ReadOnlyVector4;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class AwtTextureSource implements TextureSource, ElementUpdateListener {
+ private static final int tileSize = 128;
+ private final int availableClipmapLevels;
+
+ private final AwtElementProvider provider;
+ private final TextureStoreFormat format;
+ private final boolean hasAlpha;
+
+ private final BufferedImage _image[];
+ private final Set<Tile> _updatedTiles[];
+
+ private final ThreadLocal<byte[]> tileDataPool = new ThreadLocal<byte[]>() {
+ @Override
+ protected byte[] initialValue() {
+ return new byte[tileSize * tileSize * (hasAlpha ? 4 : 3)];
+ }
+ };
+
+ @SuppressWarnings("unchecked")
+ public AwtTextureSource(final int availableClipmapLevels, final TextureStoreFormat format) {
+ if (format != TextureStoreFormat.RGB8 && format != TextureStoreFormat.RGBA8) {
+ throw new IllegalArgumentException("Only RGB8 and RGBA8 currently supported.");
+ }
+
+ this.availableClipmapLevels = availableClipmapLevels;
+ this.format = format;
+ hasAlpha = format == TextureStoreFormat.RGBA8;
+
+ _image = new BufferedImage[availableClipmapLevels];
+ _updatedTiles = new Set[availableClipmapLevels];
+
+ provider = new AwtElementProvider();
+ provider.addElementUpdateListener(this);
+
+ for (int i = 0; i < availableClipmapLevels; i++) {
+ _image[i] = new BufferedImage(tileSize, tileSize, BufferedImage.TYPE_INT_ARGB);
+ _updatedTiles[i] = Sets.newHashSet();
+ }
+ }
+
+ public AwtElementProvider getProvider() {
+ return provider;
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, format);
+
+ return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ if (_updatedTiles[baseClipmapLevel].isEmpty()) {
+ return null;
+ }
+
+ final Set<Tile> tiles = Sets.newHashSet();
+
+ int checkX, checkY;
+ for (final Iterator<Tile> it = _updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
+ final Tile tile = it.next();
+ checkX = tile.getX();
+ checkY = tile.getY();
+ if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
+ tiles.add(tile);
+ it.remove();
+ }
+ }
+
+ return tiles;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile sourceTile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ // build a transform that would take us to the local space of the tile.
+ final Transform localTransform = new Transform();
+ localTransform.setTranslation(-tileX * tileSize, -tileY * tileSize, 0);
+ final double scale = 1.0 / MathUtils.pow2(baseClipmapLevel);
+ localTransform.setScale(scale);
+
+ final double tileInScale = MathUtils.pow2(baseClipmapLevel) * tileSize;
+ final double minX = tileInScale * tileX;
+ final double minY = tileInScale * tileY;
+ final double maxX = minX + tileInScale - 1;
+ final double maxY = minY + tileInScale - 1;
+
+ // Clear image
+ final Graphics2D graphics = (Graphics2D) _image[baseClipmapLevel].getGraphics();
+ final Composite composite = graphics.getComposite();
+ // TODO: Add: do regular clear with black if no alpha channel right?
+ graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
+ graphics.fillRect(0, 0, tileSize, tileSize);
+ graphics.setComposite(composite);
+
+ // get list of elements that intersect the given region
+ final List<AbstractAwtElement> elements = Lists.newArrayList(provider.getElements());
+ for (final Iterator<AbstractAwtElement> it = elements.iterator(); it.hasNext();) {
+ final AbstractAwtElement element = it.next();
+
+ // check bounds to toss it or keep it.
+ final ReadOnlyVector4 bounds = element.getBounds();
+
+ if (bounds.getX() > maxX || bounds.getX() + bounds.getZ() <= minX || bounds.getY() > maxY
+ || bounds.getY() + bounds.getW() <= minY) {
+ // toss it
+ it.remove();
+ }
+ }
+
+ // make our buffer - init to all 0's
+ final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * (hasAlpha ? 4 : 3));
+
+ // shortcut - no data, return buffer.
+ if (elements.isEmpty()) {
+ // graphics.setBackground((tileX + tileY) % 2 == 0 ? Color.GREEN : Color.GRAY);
+ // graphics.clearRect(0, 0, tileSize, tileSize);
+ return data;
+ }
+
+ // otherwise draw... for each element, apply to our image.
+ for (final AbstractAwtElement element : elements) {
+ element.drawTo(_image[baseClipmapLevel], localTransform, clipmapLevel);
+ }
+
+ // if (clipmapLevel == 0) {
+ // graphics.setBackground((tileX + tileY) % 2 == 0 ? Color.GREEN : Color.GRAY);
+ // graphics.clearRect(0, 0, tileSize, tileSize);
+ // }
+
+ // grab image contents to buffer
+ final byte[] byteArray = tileDataPool.get();
+ final DataBufferInt dataBuffer = (DataBufferInt) _image[baseClipmapLevel].getData().getDataBuffer();
+ final int[] tmpData = dataBuffer.getData();
+ int index = 0;
+ for (int i = 0; i < tileSize * tileSize; i++) {
+ final int argb = tmpData[i];
+ byteArray[index++] = (byte) (argb >> 16 & 0xFF);
+ byteArray[index++] = (byte) (argb >> 8 & 0xFF);
+ byteArray[index++] = (byte) (argb & 0xFF);
+ if (hasAlpha) {
+ byteArray[index++] = (byte) (argb >> 24 & 0xFF);
+ }
+ }
+
+ data.put(byteArray);
+ data.flip();
+
+ // return buffer
+ return data;
+ }
+
+ @Override
+ public void elementUpdated(final ReadOnlyVector4 oldBounds, final ReadOnlyVector4 newBounds) {
+ addTiles(oldBounds);
+ addTiles(newBounds);
+ }
+
+ protected void addTiles(final ReadOnlyVector4 bounds) {
+ for (int i = 0; i < availableClipmapLevels; i++) {
+ final double scale = 1.0 / (tileSize * MathUtils.pow2(i));
+ final int minX = (int) MathUtils.floor(bounds.getX() * scale);
+ final int minY = (int) MathUtils.floor(bounds.getY() * scale);
+ final int maxX = (int) MathUtils.floor((bounds.getX() + bounds.getZ() - 1) * scale);
+ final int maxY = (int) MathUtils.floor((bounds.getY() + bounds.getW() - 1) * scale);
+
+ Tile tile;
+ for (int y = minY; y <= maxY; y++) {
+ for (int x = minX; x <= maxX; x++) {
+ tile = new Tile(x, y);
+ _updatedTiles[i].add(tile);
+ }
+ }
+ }
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/image/ImageTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/image/ImageTextureSource.java
index 9deb52c..68e0bdc 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/image/ImageTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/image/ImageTextureSource.java
@@ -1,140 +1,140 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.image;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.Image;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class ImageTextureSource implements TextureSource {
- private final int tileSize;
- private final List<byte[]> maps;
- private final List<Integer> heightMapSizes;
-
- private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
- @Override
- protected ByteBuffer initialValue() {
- return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
- }
- };
-
- public ImageTextureSource(final int tileSize, final Image map, final List<Integer> heightMapSizes) {
- this.tileSize = tileSize;
- maps = Lists.newArrayListWithExpectedSize(heightMapSizes.size());
- this.heightMapSizes = Lists.newArrayList(heightMapSizes);
- buildMips(map);
- }
-
- private void buildMips(final Image map) {
- final int max = heightMapSizes.size();
- int currentSize = heightMapSizes.get(max - 1);
- byte[] parentHeightMap = new byte[currentSize * currentSize * 3];
- // populate parentHeightMap from image
- map.getData(0).get(parentHeightMap);
-
- maps.add(parentHeightMap);
- // populate mips
- for (int i = 1; i < max; i++) {
- currentSize = heightMapSizes.get(max - i - 1);
- final byte[] heightMapMip = new byte[currentSize * currentSize * 3];
- for (int x = 0; x < currentSize; x++) {
- for (int z = 0; z < currentSize; z++) {
- heightMapMip[3 * (z * currentSize + x) + 0] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 0];
- heightMapMip[3 * (z * currentSize + x) + 1] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 1];
- heightMapMip[3 * (z * currentSize + x) + 2] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 2];
- }
- }
- parentHeightMap = heightMapMip;
- maps.add(parentHeightMap);
- }
- Collections.reverse(maps);
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.RGB8);
-
- return new TextureConfiguration(maps.size(), textureStoreFormat, tileSize, 1f, true, false);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final byte[] heightMap = maps.get(clipmapLevel);
- final int heightMapSize = heightMapSizes.get(clipmapLevel);
-
- final ByteBuffer data = tileDataPool.get();
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int index = x + y * tileSize;
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
- if (heightX < 0 || heightX >= heightMapSize || heightY < 0 || heightY >= heightMapSize) {
- data.put(index * 3 + 0, (byte) 0);
- data.put(index * 3 + 1, (byte) 0);
- data.put(index * 3 + 2, (byte) 0);
- } else {
- data.put(index * 3 + 0, heightMap[3 * (heightY * heightMapSize + heightX) + 0]);
- data.put(index * 3 + 1, heightMap[3 * (heightY * heightMapSize + heightX) + 1]);
- data.put(index * 3 + 2, heightMap[3 * (heightY * heightMapSize + heightX) + 2]);
- }
- }
- }
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.image;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.Image;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class ImageTextureSource implements TextureSource {
+ private final int tileSize;
+ private final List<byte[]> maps;
+ private final List<Integer> heightMapSizes;
+
+ private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
+ @Override
+ protected ByteBuffer initialValue() {
+ return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
+ }
+ };
+
+ public ImageTextureSource(final int tileSize, final Image map, final List<Integer> heightMapSizes) {
+ this.tileSize = tileSize;
+ maps = Lists.newArrayListWithExpectedSize(heightMapSizes.size());
+ this.heightMapSizes = Lists.newArrayList(heightMapSizes);
+ buildMips(map);
+ }
+
+ private void buildMips(final Image map) {
+ final int max = heightMapSizes.size();
+ int currentSize = heightMapSizes.get(max - 1);
+ byte[] parentHeightMap = new byte[currentSize * currentSize * 3];
+ // populate parentHeightMap from image
+ map.getData(0).get(parentHeightMap);
+
+ maps.add(parentHeightMap);
+ // populate mips
+ for (int i = 1; i < max; i++) {
+ currentSize = heightMapSizes.get(max - i - 1);
+ final byte[] heightMapMip = new byte[currentSize * currentSize * 3];
+ for (int x = 0; x < currentSize; x++) {
+ for (int z = 0; z < currentSize; z++) {
+ heightMapMip[3 * (z * currentSize + x) + 0] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 0];
+ heightMapMip[3 * (z * currentSize + x) + 1] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 1];
+ heightMapMip[3 * (z * currentSize + x) + 2] = parentHeightMap[3 * (z * currentSize * 4 + x * 2) + 2];
+ }
+ }
+ parentHeightMap = heightMapMip;
+ maps.add(parentHeightMap);
+ }
+ Collections.reverse(maps);
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.RGB8);
+
+ return new TextureConfiguration(maps.size(), textureStoreFormat, tileSize, 1f, true, false);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize <= heightMapSize && yy >= 0 && yy * tileSize <= heightMapSize) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final byte[] heightMap = maps.get(clipmapLevel);
+ final int heightMapSize = heightMapSizes.get(clipmapLevel);
+
+ final ByteBuffer data = tileDataPool.get();
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int index = x + y * tileSize;
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+ if (heightX < 0 || heightX >= heightMapSize || heightY < 0 || heightY >= heightMapSize) {
+ data.put(index * 3 + 0, (byte) 0);
+ data.put(index * 3 + 1, (byte) 0);
+ data.put(index * 3 + 2, (byte) 0);
+ } else {
+ data.put(index * 3 + 0, heightMap[3 * (heightY * heightMapSize + heightX) + 0]);
+ data.put(index * 3 + 1, heightMap[3 * (heightY * heightMapSize + heightX) + 1]);
+ data.put(index * 3 + 2, heightMap[3 * (heightY * heightMapSize + heightX) + 2]);
+ }
+ }
+ }
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainDataProvider.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainDataProvider.java
index e737243..4df7c3b 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainDataProvider.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainDataProvider.java
@@ -1,89 +1,89 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.inmemory;
-
-import java.util.List;
-import java.util.Map;
-
-import com.ardor3d.extension.terrain.client.TerrainDataProvider;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
-import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
-import com.ardor3d.extension.terrain.util.NormalMapUtil;
-import com.ardor3d.image.Image;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-public class InMemoryTerrainDataProvider implements TerrainDataProvider {
- private static final int tileSize = 128;
- private final InMemoryTerrainData inMemoryTerrainData;
-
- private boolean generateNormalMap;
-
- public InMemoryTerrainDataProvider(final InMemoryTerrainData inMemoryTerrainData) {
- this(inMemoryTerrainData, false);
- }
-
- public InMemoryTerrainDataProvider(final InMemoryTerrainData inMemoryTerrainData, final boolean generateNormalMap) {
- this.inMemoryTerrainData = inMemoryTerrainData;
- this.generateNormalMap = generateNormalMap;
- }
-
- @Override
- public Map<Integer, String> getAvailableMaps() throws Exception {
- final Map<Integer, String> maps = Maps.newHashMap();
- maps.put(0, "InMemoryData");
-
- return maps;
- }
-
- @Override
- public TerrainSource getTerrainSource(final int mapId) {
- return new InMemoryTerrainSource(tileSize, inMemoryTerrainData);
- }
-
- @Override
- public TextureSource getTextureSource(final int mapId) {
- return new InMemoryTextureSource(tileSize, inMemoryTerrainData);
- }
-
- @Override
- public TextureSource getNormalMapSource(final int mapId) {
- if (generateNormalMap) {
- try {
- final Image normalImage = NormalMapUtil.constructNormalMap(inMemoryTerrainData.getHeightData(),
- inMemoryTerrainData.getSide(), inMemoryTerrainData.getMaxHeight(), inMemoryTerrainData
- .getScale().getX(), inMemoryTerrainData.getScale().getY());
-
- final List<Integer> heightMapSizes = Lists.newArrayList();
- int currentSize = inMemoryTerrainData.getSide();
- heightMapSizes.add(currentSize);
- for (int i = 0; i < inMemoryTerrainData.getClipmapLevels(); i++) {
- currentSize /= 2;
- heightMapSizes.add(currentSize);
- }
- return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
- } catch (final Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- public boolean isGenerateNormalMap() {
- return generateNormalMap;
- }
-
- public void setGenerateNormalMap(final boolean generateNormalMap) {
- this.generateNormalMap = generateNormalMap;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.inmemory;
+
+import java.util.List;
+import java.util.Map;
+
+import com.ardor3d.extension.terrain.client.TerrainDataProvider;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
+import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
+import com.ardor3d.extension.terrain.util.NormalMapUtil;
+import com.ardor3d.image.Image;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class InMemoryTerrainDataProvider implements TerrainDataProvider {
+ private static final int tileSize = 128;
+ private final InMemoryTerrainData inMemoryTerrainData;
+
+ private boolean generateNormalMap;
+
+ public InMemoryTerrainDataProvider(final InMemoryTerrainData inMemoryTerrainData) {
+ this(inMemoryTerrainData, false);
+ }
+
+ public InMemoryTerrainDataProvider(final InMemoryTerrainData inMemoryTerrainData, final boolean generateNormalMap) {
+ this.inMemoryTerrainData = inMemoryTerrainData;
+ this.generateNormalMap = generateNormalMap;
+ }
+
+ @Override
+ public Map<Integer, String> getAvailableMaps() throws Exception {
+ final Map<Integer, String> maps = Maps.newHashMap();
+ maps.put(0, "InMemoryData");
+
+ return maps;
+ }
+
+ @Override
+ public TerrainSource getTerrainSource(final int mapId) {
+ return new InMemoryTerrainSource(tileSize, inMemoryTerrainData);
+ }
+
+ @Override
+ public TextureSource getTextureSource(final int mapId) {
+ return new InMemoryTextureSource(tileSize, inMemoryTerrainData);
+ }
+
+ @Override
+ public TextureSource getNormalMapSource(final int mapId) {
+ if (generateNormalMap) {
+ try {
+ final Image normalImage = NormalMapUtil.constructNormalMap(inMemoryTerrainData.getHeightData(),
+ inMemoryTerrainData.getSide(), inMemoryTerrainData.getMaxHeight(), inMemoryTerrainData
+ .getScale().getX(), inMemoryTerrainData.getScale().getY());
+
+ final List<Integer> heightMapSizes = Lists.newArrayList();
+ int currentSize = inMemoryTerrainData.getSide();
+ heightMapSizes.add(currentSize);
+ for (int i = 0; i < inMemoryTerrainData.getClipmapLevels(); i++) {
+ currentSize /= 2;
+ heightMapSizes.add(currentSize);
+ }
+ return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ public boolean isGenerateNormalMap() {
+ return generateNormalMap;
+ }
+
+ public void setGenerateNormalMap(final boolean generateNormalMap) {
+ this.generateNormalMap = generateNormalMap;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainSource.java
index dc5633a..32a0542 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTerrainSource.java
@@ -1,133 +1,133 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.inmemory;
-
-import java.util.Iterator;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TerrainConfiguration;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.google.common.collect.Sets;
-
-public class InMemoryTerrainSource implements TerrainSource {
- private final int tileSize;
- private final InMemoryTerrainData inMemoryTerrainData;
- private final int availableClipmapLevels;
-
- public InMemoryTerrainSource(final int tileSize, final InMemoryTerrainData inMemoryTerrainData) {
- this.tileSize = tileSize;
- this.inMemoryTerrainData = inMemoryTerrainData;
- availableClipmapLevels = inMemoryTerrainData.getClipmapLevels();
- }
-
- @Override
- public TerrainConfiguration getConfiguration() throws Exception {
- return new TerrainConfiguration(availableClipmapLevels, tileSize, inMemoryTerrainData.getScale(),
- inMemoryTerrainData.getMinHeight(), inMemoryTerrainData.getMaxHeight(), true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int levelSize = 1 << baseClipmapLevel;
- final int size = inMemoryTerrainData.getSide();
-
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> updatedTiles[] = inMemoryTerrainData.getUpdatedTerrainTiles();
- if (updatedTiles == null) {
- return null;
- }
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final Set<Tile> tiles = Sets.newHashSet();
-
- synchronized (updatedTiles[baseClipmapLevel]) {
- if (updatedTiles[baseClipmapLevel].isEmpty()) {
- return null;
- }
-
- int checkX, checkY;
- for (final Iterator<Tile> it = updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
- final Tile tile = it.next();
- checkX = tile.getX();
- checkY = tile.getY();
- if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
- tiles.add(tile);
- it.remove();
- }
- }
- }
-
- return tiles;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final int levelSize = 1 << baseClipmapLevel;
-
- final int size = inMemoryTerrainData.getSide();
-
- final float[] heightData = inMemoryTerrainData.getHeightData();
-
- final float[] data = new float[tileSize * tileSize];
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int index = x + y * tileSize;
-
- final int heightX = (tileX * tileSize + x) * levelSize;
- final int heightY = (tileY * tileSize + y) * levelSize;
- data[index] = getHeight(heightData, size, heightX, heightY);
- }
- }
- return data;
- }
-
- private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
- if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
- return 0;
- }
-
- return heightMap[y * heightMapSize + x];
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.inmemory;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TerrainConfiguration;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.google.common.collect.Sets;
+
+public class InMemoryTerrainSource implements TerrainSource {
+ private final int tileSize;
+ private final InMemoryTerrainData inMemoryTerrainData;
+ private final int availableClipmapLevels;
+
+ public InMemoryTerrainSource(final int tileSize, final InMemoryTerrainData inMemoryTerrainData) {
+ this.tileSize = tileSize;
+ this.inMemoryTerrainData = inMemoryTerrainData;
+ availableClipmapLevels = inMemoryTerrainData.getClipmapLevels();
+ }
+
+ @Override
+ public TerrainConfiguration getConfiguration() throws Exception {
+ return new TerrainConfiguration(availableClipmapLevels, tileSize, inMemoryTerrainData.getScale(),
+ inMemoryTerrainData.getMinHeight(), inMemoryTerrainData.getMaxHeight(), true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int levelSize = 1 << baseClipmapLevel;
+ final int size = inMemoryTerrainData.getSide();
+
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> updatedTiles[] = inMemoryTerrainData.getUpdatedTerrainTiles();
+ if (updatedTiles == null) {
+ return null;
+ }
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final Set<Tile> tiles = Sets.newHashSet();
+
+ synchronized (updatedTiles[baseClipmapLevel]) {
+ if (updatedTiles[baseClipmapLevel].isEmpty()) {
+ return null;
+ }
+
+ int checkX, checkY;
+ for (final Iterator<Tile> it = updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
+ final Tile tile = it.next();
+ checkX = tile.getX();
+ checkY = tile.getY();
+ if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
+ tiles.add(tile);
+ it.remove();
+ }
+ }
+ }
+
+ return tiles;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final int levelSize = 1 << baseClipmapLevel;
+
+ final int size = inMemoryTerrainData.getSide();
+
+ final float[] heightData = inMemoryTerrainData.getHeightData();
+
+ final float[] data = new float[tileSize * tileSize];
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int index = x + y * tileSize;
+
+ final int heightX = (tileX * tileSize + x) * levelSize;
+ final int heightY = (tileY * tileSize + y) * levelSize;
+ data[index] = getHeight(heightData, size, heightX, heightY);
+ }
+ }
+ return data;
+ }
+
+ private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
+ if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
+ return 0;
+ }
+
+ return heightMap[y * heightMapSize + x];
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTextureSource.java
index 32a046d..80fdc82 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/inmemory/InMemoryTextureSource.java
@@ -1,142 +1,142 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.inmemory;
-
-import java.nio.ByteBuffer;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class InMemoryTextureSource implements TextureSource {
- private final int tileSize;
- private final InMemoryTerrainData inMemoryTerrainData;
- private final int availableClipmapLevels;
-
- public InMemoryTextureSource(final int tileSize, final InMemoryTerrainData inMemoryTerrainData) {
- this.tileSize = tileSize;
- this.inMemoryTerrainData = inMemoryTerrainData;
- availableClipmapLevels = inMemoryTerrainData.getClipmapLevels();
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.RGBA8);
-
- return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, true, true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int levelSize = 1 << baseClipmapLevel;
- final int size = inMemoryTerrainData.getSide();
-
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> updatedTiles[] = inMemoryTerrainData.getUpdatedTextureTiles();
- if (updatedTiles == null) {
- return null;
- }
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final Set<Tile> tiles = Sets.newHashSet();
-
- synchronized (updatedTiles[baseClipmapLevel]) {
- if (updatedTiles[baseClipmapLevel].isEmpty()) {
- return null;
- }
-
- int checkX, checkY;
- for (final Iterator<Tile> it = updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
- final Tile tile = it.next();
- checkX = tile.getX();
- checkY = tile.getY();
- if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
- tiles.add(tile);
- it.remove();
- }
- }
- }
-
- return tiles;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int levelSize = 1 << availableClipmapLevels - clipmapLevel - 1;
-
- final int size = inMemoryTerrainData.getSide();
- final byte[] colorData = inMemoryTerrainData.getColorData();
-
- final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 4);
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int heightX = (tileX * tileSize + x) * levelSize;
- final int heightY = (tileY * tileSize + y) * levelSize;
-
- final int indexTile = (y * tileSize + x) * 4;
- final int index = heightY * size + heightX;
-
- if (heightX < 0 || heightX >= size || heightY < 0 || heightY >= size) {
- data.put(indexTile + 0, (byte) 0);
- data.put(indexTile + 1, (byte) 0);
- data.put(indexTile + 2, (byte) 0);
- data.put(indexTile + 3, (byte) 255);
- } else {
- data.put(indexTile + 0, colorData[index * 4 + 0]);
- data.put(indexTile + 1, colorData[index * 4 + 1]);
- data.put(indexTile + 2, colorData[index * 4 + 2]);
- data.put(indexTile + 3, colorData[index * 4 + 3]);
- }
- }
- }
-
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.inmemory;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.providers.inmemory.data.InMemoryTerrainData;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class InMemoryTextureSource implements TextureSource {
+ private final int tileSize;
+ private final InMemoryTerrainData inMemoryTerrainData;
+ private final int availableClipmapLevels;
+
+ public InMemoryTextureSource(final int tileSize, final InMemoryTerrainData inMemoryTerrainData) {
+ this.tileSize = tileSize;
+ this.inMemoryTerrainData = inMemoryTerrainData;
+ availableClipmapLevels = inMemoryTerrainData.getClipmapLevels();
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.RGBA8);
+
+ return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, true, true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int levelSize = 1 << baseClipmapLevel;
+ final int size = inMemoryTerrainData.getSide();
+
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> updatedTiles[] = inMemoryTerrainData.getUpdatedTextureTiles();
+ if (updatedTiles == null) {
+ return null;
+ }
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final Set<Tile> tiles = Sets.newHashSet();
+
+ synchronized (updatedTiles[baseClipmapLevel]) {
+ if (updatedTiles[baseClipmapLevel].isEmpty()) {
+ return null;
+ }
+
+ int checkX, checkY;
+ for (final Iterator<Tile> it = updatedTiles[baseClipmapLevel].iterator(); it.hasNext();) {
+ final Tile tile = it.next();
+ checkX = tile.getX();
+ checkY = tile.getY();
+ if (checkX >= tileX && checkX < tileX + numTilesX && checkY >= tileY && checkY < tileY + numTilesY) {
+ tiles.add(tile);
+ it.remove();
+ }
+ }
+ }
+
+ return tiles;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int levelSize = 1 << availableClipmapLevels - clipmapLevel - 1;
+
+ final int size = inMemoryTerrainData.getSide();
+ final byte[] colorData = inMemoryTerrainData.getColorData();
+
+ final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 4);
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int heightX = (tileX * tileSize + x) * levelSize;
+ final int heightY = (tileY * tileSize + y) * levelSize;
+
+ final int indexTile = (y * tileSize + x) * 4;
+ final int index = heightY * size + heightX;
+
+ if (heightX < 0 || heightX >= size || heightY < 0 || heightY >= size) {
+ data.put(indexTile + 0, (byte) 0);
+ data.put(indexTile + 1, (byte) 0);
+ data.put(indexTile + 2, (byte) 0);
+ data.put(indexTile + 3, (byte) 255);
+ } else {
+ data.put(indexTile + 0, colorData[index * 4 + 0]);
+ data.put(indexTile + 1, colorData[index * 4 + 1]);
+ data.put(indexTile + 2, colorData[index * 4 + 2]);
+ data.put(indexTile + 3, colorData[index * 4 + 3]);
+ }
+ }
+ }
+
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralNormalMapSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralNormalMapSource.java
index df07262..ec4313b 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralNormalMapSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralNormalMapSource.java
@@ -1,111 +1,111 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.procedural;
-
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.math.Vector3;
-import com.ardor3d.math.functions.Function3D;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Maps;
-
-public class ProceduralNormalMapSource implements TextureSource {
- private final Function3D function;
-
- private static final int tileSize = 128;
- private static final int availableClipmapLevels = 8;
-
- private final ReentrantLock textureLock = new ReentrantLock();
- private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
- @Override
- protected ByteBuffer initialValue() {
- return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
- }
- };
-
- public ProceduralNormalMapSource(final Function3D function) {
- this.function = function;
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.RGB8);
-
- return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, false);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final ByteBuffer data = tileDataPool.get();
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final Vector3 normal = new Vector3();
- textureLock.lock();
- try {
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- if (Thread.interrupted()) {
- return null;
- }
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
-
- normal.setZ(1);
- final double eval1 = function.eval(heightX - 1 << baseClipmapLevel, heightY << baseClipmapLevel, 0);
- final double eval2 = function.eval(heightX + 1 << baseClipmapLevel, heightY << baseClipmapLevel, 0);
- final double eval3 = function.eval(heightX << baseClipmapLevel, heightY - 1 << baseClipmapLevel, 0);
- final double eval4 = function.eval(heightX << baseClipmapLevel, heightY + 1 << baseClipmapLevel, 0);
-
- normal.setX((eval1 - eval2) / 2.);
- normal.setY((eval3 - eval4) / 2.);
- normal.normalizeLocal();
-
- final int index = (x + y * tileSize) * 3;
- data.put(index, (byte) (normal.getX() * 255));
- data.put(index + 1, (byte) (normal.getY() * 255));
- data.put(index + 2, (byte) (normal.getZ() * 255));
- }
- }
- } finally {
- textureLock.unlock();
- }
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.procedural;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.functions.Function3D;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Maps;
+
+public class ProceduralNormalMapSource implements TextureSource {
+ private final Function3D function;
+
+ private static final int tileSize = 128;
+ private static final int availableClipmapLevels = 8;
+
+ private final ReentrantLock textureLock = new ReentrantLock();
+ private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
+ @Override
+ protected ByteBuffer initialValue() {
+ return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
+ }
+ };
+
+ public ProceduralNormalMapSource(final Function3D function) {
+ this.function = function;
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.RGB8);
+
+ return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, false);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final ByteBuffer data = tileDataPool.get();
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final Vector3 normal = new Vector3();
+ textureLock.lock();
+ try {
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ if (Thread.interrupted()) {
+ return null;
+ }
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+
+ normal.setZ(1);
+ final double eval1 = function.eval(heightX - 1 << baseClipmapLevel, heightY << baseClipmapLevel, 0);
+ final double eval2 = function.eval(heightX + 1 << baseClipmapLevel, heightY << baseClipmapLevel, 0);
+ final double eval3 = function.eval(heightX << baseClipmapLevel, heightY - 1 << baseClipmapLevel, 0);
+ final double eval4 = function.eval(heightX << baseClipmapLevel, heightY + 1 << baseClipmapLevel, 0);
+
+ normal.setX((eval1 - eval2) / 2.);
+ normal.setY((eval3 - eval4) / 2.);
+ normal.normalizeLocal();
+
+ final int index = (x + y * tileSize) * 3;
+ data.put(index, (byte) (normal.getX() * 255));
+ data.put(index + 1, (byte) (normal.getY() * 255));
+ data.put(index + 2, (byte) (normal.getZ() * 255));
+ }
+ }
+ } finally {
+ textureLock.unlock();
+ }
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainDataProvider.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainDataProvider.java
index 575a514..6d1c8e3 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainDataProvider.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainDataProvider.java
@@ -1,74 +1,74 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.procedural;
-
-import java.util.Map;
-
-import com.ardor3d.extension.terrain.client.TerrainDataProvider;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.math.functions.Function3D;
-import com.ardor3d.math.type.ReadOnlyVector3;
-import com.google.common.collect.Maps;
-
-public class ProceduralTerrainDataProvider implements TerrainDataProvider {
- private final Function3D function;
- private final ReadOnlyVector3 scale;
- private final float minHeight;
- private final float maxHeight;
-
- private boolean generateNormalMap;
-
- public ProceduralTerrainDataProvider(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
- final float maxHeight) {
- this(function, scale, minHeight, maxHeight, false);
- }
-
- public ProceduralTerrainDataProvider(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
- final float maxHeight, final boolean generateNormalMap) {
- this.function = function;
- this.scale = scale;
- this.minHeight = minHeight;
- this.maxHeight = maxHeight;
- this.generateNormalMap = generateNormalMap;
- }
-
- @Override
- public Map<Integer, String> getAvailableMaps() throws Exception {
- final Map<Integer, String> maps = Maps.newHashMap();
- maps.put(0, "ProceduralMap");
-
- return maps;
- }
-
- @Override
- public TerrainSource getTerrainSource(final int mapId) {
- return new ProceduralTerrainSource(function, scale, minHeight, maxHeight);
- }
-
- @Override
- public TextureSource getTextureSource(final int mapId) {
- return new ProceduralTextureSource(function);
- }
-
- @Override
- public TextureSource getNormalMapSource(final int mapId) {
- return new ProceduralNormalMapSource(function);
- }
-
- public boolean isGenerateNormalMap() {
- return generateNormalMap;
- }
-
- public void setGenerateNormalMap(final boolean generateNormalMap) {
- this.generateNormalMap = generateNormalMap;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.procedural;
+
+import java.util.Map;
+
+import com.ardor3d.extension.terrain.client.TerrainDataProvider;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.math.functions.Function3D;
+import com.ardor3d.math.type.ReadOnlyVector3;
+import com.google.common.collect.Maps;
+
+public class ProceduralTerrainDataProvider implements TerrainDataProvider {
+ private final Function3D function;
+ private final ReadOnlyVector3 scale;
+ private final float minHeight;
+ private final float maxHeight;
+
+ private boolean generateNormalMap;
+
+ public ProceduralTerrainDataProvider(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
+ final float maxHeight) {
+ this(function, scale, minHeight, maxHeight, false);
+ }
+
+ public ProceduralTerrainDataProvider(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
+ final float maxHeight, final boolean generateNormalMap) {
+ this.function = function;
+ this.scale = scale;
+ this.minHeight = minHeight;
+ this.maxHeight = maxHeight;
+ this.generateNormalMap = generateNormalMap;
+ }
+
+ @Override
+ public Map<Integer, String> getAvailableMaps() throws Exception {
+ final Map<Integer, String> maps = Maps.newHashMap();
+ maps.put(0, "ProceduralMap");
+
+ return maps;
+ }
+
+ @Override
+ public TerrainSource getTerrainSource(final int mapId) {
+ return new ProceduralTerrainSource(function, scale, minHeight, maxHeight);
+ }
+
+ @Override
+ public TextureSource getTextureSource(final int mapId) {
+ return new ProceduralTextureSource(function);
+ }
+
+ @Override
+ public TextureSource getNormalMapSource(final int mapId) {
+ return new ProceduralNormalMapSource(function);
+ }
+
+ public boolean isGenerateNormalMap() {
+ return generateNormalMap;
+ }
+
+ public void setGenerateNormalMap(final boolean generateNormalMap) {
+ this.generateNormalMap = generateNormalMap;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainSource.java
index 19515b7..4fae73a 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTerrainSource.java
@@ -1,97 +1,97 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.procedural;
-
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-
-import com.ardor3d.extension.terrain.client.TerrainConfiguration;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.math.functions.Function3D;
-import com.ardor3d.math.type.ReadOnlyVector3;
-
-public class ProceduralTerrainSource implements TerrainSource {
- private final Function3D function;
- private final ReadOnlyVector3 scale;
- private final float minHeight;
- private final float maxHeight;
-
- private static final int tileSize = 128;
- private static final int availableClipmapLevels = 8;
-
- private final ReentrantLock terrainLock = new ReentrantLock();
- private final ThreadLocal<float[]> tileDataPool = new ThreadLocal<float[]>() {
- @Override
- protected float[] initialValue() {
- return new float[tileSize * tileSize];
- }
- };
-
- public ProceduralTerrainSource(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
- final float maxHeight) {
- this.function = function;
- this.scale = scale;
- this.minHeight = minHeight;
- this.maxHeight = maxHeight;
- }
-
- @Override
- public TerrainConfiguration getConfiguration() throws Exception {
- return new TerrainConfiguration(availableClipmapLevels, tileSize, scale, minHeight, maxHeight, false);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final float[] data = tileDataPool.get();
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- terrainLock.lock();
- try {
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- if (Thread.interrupted()) {
- return null;
- }
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
-
- final int index = x + y * tileSize;
- data[index] = (float) function.eval(heightX << baseClipmapLevel, heightY << baseClipmapLevel, 0);
- }
- }
- } finally {
- terrainLock.unlock();
- }
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.procedural;
+
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.ardor3d.extension.terrain.client.TerrainConfiguration;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.math.functions.Function3D;
+import com.ardor3d.math.type.ReadOnlyVector3;
+
+public class ProceduralTerrainSource implements TerrainSource {
+ private final Function3D function;
+ private final ReadOnlyVector3 scale;
+ private final float minHeight;
+ private final float maxHeight;
+
+ private static final int tileSize = 128;
+ private static final int availableClipmapLevels = 8;
+
+ private final ReentrantLock terrainLock = new ReentrantLock();
+ private final ThreadLocal<float[]> tileDataPool = new ThreadLocal<float[]>() {
+ @Override
+ protected float[] initialValue() {
+ return new float[tileSize * tileSize];
+ }
+ };
+
+ public ProceduralTerrainSource(final Function3D function, final ReadOnlyVector3 scale, final float minHeight,
+ final float maxHeight) {
+ this.function = function;
+ this.scale = scale;
+ this.minHeight = minHeight;
+ this.maxHeight = maxHeight;
+ }
+
+ @Override
+ public TerrainConfiguration getConfiguration() throws Exception {
+ return new TerrainConfiguration(availableClipmapLevels, tileSize, scale, minHeight, maxHeight, false);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final float[] data = tileDataPool.get();
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ terrainLock.lock();
+ try {
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ if (Thread.interrupted()) {
+ return null;
+ }
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+
+ final int index = x + y * tileSize;
+ data[index] = (float) function.eval(heightX << baseClipmapLevel, heightY << baseClipmapLevel, 0);
+ }
+ }
+ } finally {
+ terrainLock.unlock();
+ }
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTextureSource.java
index 0a48626..3b1b4dc 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/procedural/ProceduralTextureSource.java
@@ -1,120 +1,120 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.procedural;
-
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.image.util.GeneratedImageFactory;
-import com.ardor3d.math.ColorRGBA;
-import com.ardor3d.math.functions.Function3D;
-import com.ardor3d.math.type.ReadOnlyColorRGBA;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Maps;
-
-public class ProceduralTextureSource implements TextureSource {
- private final Function3D function;
-
- private static final int tileSize = 128;
- private static final int availableClipmapLevels = 8;
-
- private final ReadOnlyColorRGBA[] terrainColors;
-
- private final ReentrantLock textureLock = new ReentrantLock();
- private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
- @Override
- protected ByteBuffer initialValue() {
- return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
- }
- };
-
- public ProceduralTextureSource(final Function3D function) {
- this.function = function;
-
- terrainColors = new ReadOnlyColorRGBA[256];
- terrainColors[0] = new ColorRGBA(0, 0, .5f, 1);
- terrainColors[95] = new ColorRGBA(0, 0, 1, 1);
- terrainColors[127] = new ColorRGBA(0, .5f, 1, 1);
- terrainColors[137] = new ColorRGBA(240 / 255f, 240 / 255f, 64 / 255f, 1);
- terrainColors[143] = new ColorRGBA(32 / 255f, 160 / 255f, 0, 1);
- terrainColors[175] = new ColorRGBA(224 / 255f, 224 / 255f, 0, 1);
- terrainColors[223] = new ColorRGBA(128 / 255f, 128 / 255f, 128 / 255f, 1);
- terrainColors[255] = ColorRGBA.WHITE;
- GeneratedImageFactory.fillInColorTable(terrainColors);
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.RGB8);
-
- return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, false);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final ByteBuffer data = tileDataPool.get();
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- textureLock.lock();
- try {
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- if (Thread.interrupted()) {
- return null;
- }
-
- final int heightX = tileX * tileSize + x;
- final int heightY = tileY * tileSize + y;
-
- final double eval = function.eval(heightX << baseClipmapLevel, heightY << baseClipmapLevel, 0) * 0.4167f + 0.5f;
- final byte colIndex = (byte) (eval * 255);
-
- final ReadOnlyColorRGBA c = terrainColors[colIndex & 0xFF];
-
- final int index = (x + y * tileSize) * 3;
- data.put(index, (byte) (c.getRed() * 255));
- data.put(index + 1, (byte) (c.getGreen() * 255));
- data.put(index + 2, (byte) (c.getBlue() * 255));
- }
- }
- } finally {
- textureLock.unlock();
- }
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.procedural;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.image.util.GeneratedImageFactory;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.functions.Function3D;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Maps;
+
+public class ProceduralTextureSource implements TextureSource {
+ private final Function3D function;
+
+ private static final int tileSize = 128;
+ private static final int availableClipmapLevels = 8;
+
+ private final ReadOnlyColorRGBA[] terrainColors;
+
+ private final ReentrantLock textureLock = new ReentrantLock();
+ private final ThreadLocal<ByteBuffer> tileDataPool = new ThreadLocal<ByteBuffer>() {
+ @Override
+ protected ByteBuffer initialValue() {
+ return BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 3);
+ }
+ };
+
+ public ProceduralTextureSource(final Function3D function) {
+ this.function = function;
+
+ terrainColors = new ReadOnlyColorRGBA[256];
+ terrainColors[0] = new ColorRGBA(0, 0, .5f, 1);
+ terrainColors[95] = new ColorRGBA(0, 0, 1, 1);
+ terrainColors[127] = new ColorRGBA(0, .5f, 1, 1);
+ terrainColors[137] = new ColorRGBA(240 / 255f, 240 / 255f, 64 / 255f, 1);
+ terrainColors[143] = new ColorRGBA(32 / 255f, 160 / 255f, 0, 1);
+ terrainColors[175] = new ColorRGBA(224 / 255f, 224 / 255f, 0, 1);
+ terrainColors[223] = new ColorRGBA(128 / 255f, 128 / 255f, 128 / 255f, 1);
+ terrainColors[255] = ColorRGBA.WHITE;
+ GeneratedImageFactory.fillInColorTable(terrainColors);
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.RGB8);
+
+ return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, false, false);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final ByteBuffer data = tileDataPool.get();
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ textureLock.lock();
+ try {
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ if (Thread.interrupted()) {
+ return null;
+ }
+
+ final int heightX = tileX * tileSize + x;
+ final int heightY = tileY * tileSize + y;
+
+ final double eval = function.eval(heightX << baseClipmapLevel, heightY << baseClipmapLevel, 0) * 0.4167f + 0.5f;
+ final byte colIndex = (byte) (eval * 255);
+
+ final ReadOnlyColorRGBA c = terrainColors[colIndex & 0xFF];
+
+ final int index = (x + y * tileSize) * 3;
+ data.put(index, (byte) (c.getRed() * 255));
+ data.put(index + 1, (byte) (c.getGreen() * 255));
+ data.put(index + 2, (byte) (c.getBlue() * 255));
+ }
+ }
+ } finally {
+ textureLock.unlock();
+ }
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainDataProvider.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainDataProvider.java
index 3d7878b..c41b4bf 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainDataProvider.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainDataProvider.java
@@ -1,91 +1,91 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.simplearray;
-
-import java.util.List;
-import java.util.Map;
-
-import com.ardor3d.extension.terrain.client.TerrainDataProvider;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
-import com.ardor3d.extension.terrain.util.NormalMapUtil;
-import com.ardor3d.image.Image;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-public class SimpleArrayTerrainDataProvider implements TerrainDataProvider {
- private static final int tileSize = 128;
-
- private final float[] heightData;
- private final byte[] colorData;
- private final int side;
-
- private boolean generateNormalMap;
-
- public SimpleArrayTerrainDataProvider(final float[] heightData, final byte[] colorData, final int side) {
- this(heightData, colorData, side, false);
- }
-
- public SimpleArrayTerrainDataProvider(final float[] heightData, final byte[] colorData, final int side,
- final boolean generateNormalMap) {
- this.heightData = heightData;
- this.colorData = colorData;
- this.side = side;
- this.generateNormalMap = generateNormalMap;
- }
-
- @Override
- public Map<Integer, String> getAvailableMaps() throws Exception {
- final Map<Integer, String> maps = Maps.newHashMap();
- maps.put(0, "InMemoryData");
-
- return maps;
- }
-
- @Override
- public TerrainSource getTerrainSource(final int mapId) {
- return new SimpleArrayTerrainSource(tileSize, heightData, side);
- }
-
- @Override
- public TextureSource getTextureSource(final int mapId) {
- return new SimpleArrayTextureSource(tileSize, colorData, side);
- }
-
- @Override
- public TextureSource getNormalMapSource(final int mapId) {
- if (generateNormalMap) {
- try {
- final Image normalImage = NormalMapUtil.constructNormalMap(heightData, side, 1, 1, 1);
- final List<Integer> heightMapSizes = Lists.newArrayList();
- int currentSize = side;
- heightMapSizes.add(currentSize);
- for (int i = 0; i < 8; i++) {
- currentSize /= 2;
- heightMapSizes.add(currentSize);
- }
- return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
- } catch (final Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- public boolean isGenerateNormalMap() {
- return generateNormalMap;
- }
-
- public void setGenerateNormalMap(final boolean generateNormalMap) {
- this.generateNormalMap = generateNormalMap;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.simplearray;
+
+import java.util.List;
+import java.util.Map;
+
+import com.ardor3d.extension.terrain.client.TerrainDataProvider;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.providers.image.ImageTextureSource;
+import com.ardor3d.extension.terrain.util.NormalMapUtil;
+import com.ardor3d.image.Image;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class SimpleArrayTerrainDataProvider implements TerrainDataProvider {
+ private static final int tileSize = 128;
+
+ private final float[] heightData;
+ private final byte[] colorData;
+ private final int side;
+
+ private boolean generateNormalMap;
+
+ public SimpleArrayTerrainDataProvider(final float[] heightData, final byte[] colorData, final int side) {
+ this(heightData, colorData, side, false);
+ }
+
+ public SimpleArrayTerrainDataProvider(final float[] heightData, final byte[] colorData, final int side,
+ final boolean generateNormalMap) {
+ this.heightData = heightData;
+ this.colorData = colorData;
+ this.side = side;
+ this.generateNormalMap = generateNormalMap;
+ }
+
+ @Override
+ public Map<Integer, String> getAvailableMaps() throws Exception {
+ final Map<Integer, String> maps = Maps.newHashMap();
+ maps.put(0, "InMemoryData");
+
+ return maps;
+ }
+
+ @Override
+ public TerrainSource getTerrainSource(final int mapId) {
+ return new SimpleArrayTerrainSource(tileSize, heightData, side);
+ }
+
+ @Override
+ public TextureSource getTextureSource(final int mapId) {
+ return new SimpleArrayTextureSource(tileSize, colorData, side);
+ }
+
+ @Override
+ public TextureSource getNormalMapSource(final int mapId) {
+ if (generateNormalMap) {
+ try {
+ final Image normalImage = NormalMapUtil.constructNormalMap(heightData, side, 1, 1, 1);
+ final List<Integer> heightMapSizes = Lists.newArrayList();
+ int currentSize = side;
+ heightMapSizes.add(currentSize);
+ for (int i = 0; i < 8; i++) {
+ currentSize /= 2;
+ heightMapSizes.add(currentSize);
+ }
+ return new ImageTextureSource(tileSize, normalImage, heightMapSizes);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ public boolean isGenerateNormalMap() {
+ return generateNormalMap;
+ }
+
+ public void setGenerateNormalMap(final boolean generateNormalMap) {
+ this.generateNormalMap = generateNormalMap;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainSource.java
index 05d1747..3b52fe1 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTerrainSource.java
@@ -1,83 +1,83 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.simplearray;
-
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TerrainConfiguration;
-import com.ardor3d.extension.terrain.client.TerrainSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.math.Vector3;
-
-public class SimpleArrayTerrainSource implements TerrainSource {
- private final int tileSize;
- private final float[] heightData;
- private final int size;
- private final int availableClipmapLevels = 8;
-
- public SimpleArrayTerrainSource(final int tileSize, final float[] heightData, final int size) {
- this.tileSize = tileSize;
- this.heightData = heightData;
- this.size = size;
- }
-
- @Override
- public TerrainConfiguration getConfiguration() throws Exception {
- return new TerrainConfiguration(availableClipmapLevels, tileSize, new Vector3(1, 1, 1), 0.0f, 1.0f, true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final int levelSize = 1 << baseClipmapLevel;
-
- final float[] data = new float[tileSize * tileSize];
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int index = x + y * tileSize;
-
- final int heightX = (tileX * tileSize + x) * levelSize;
- final int heightY = (tileY * tileSize + y) * levelSize;
- data[index] = getHeight(heightData, size, heightX, heightY);
- }
- }
- return data;
- }
-
- private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
- if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
- return 0;
- }
-
- return heightMap[y * heightMapSize + x];
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.simplearray;
+
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TerrainConfiguration;
+import com.ardor3d.extension.terrain.client.TerrainSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.math.Vector3;
+
+public class SimpleArrayTerrainSource implements TerrainSource {
+ private final int tileSize;
+ private final float[] heightData;
+ private final int size;
+ private final int availableClipmapLevels = 8;
+
+ public SimpleArrayTerrainSource(final int tileSize, final float[] heightData, final int size) {
+ this.tileSize = tileSize;
+ this.heightData = heightData;
+ this.size = size;
+ }
+
+ @Override
+ public TerrainConfiguration getConfiguration() throws Exception {
+ return new TerrainConfiguration(availableClipmapLevels, tileSize, new Vector3(1, 1, 1), 0.0f, 1.0f, true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public float[] getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final int levelSize = 1 << baseClipmapLevel;
+
+ final float[] data = new float[tileSize * tileSize];
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int index = x + y * tileSize;
+
+ final int heightX = (tileX * tileSize + x) * levelSize;
+ final int heightY = (tileY * tileSize + y) * levelSize;
+ data[index] = getHeight(heightData, size, heightX, heightY);
+ }
+ }
+ return data;
+ }
+
+ private float getHeight(final float[] heightMap, final int heightMapSize, final int x, final int y) {
+ if (x < 0 || x >= heightMapSize || y < 0 || y >= heightMapSize) {
+ return 0;
+ }
+
+ return heightMap[y * heightMapSize + x];
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTextureSource.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTextureSource.java
index 02fa121..924265d 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTextureSource.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/providers/simplearray/SimpleArrayTextureSource.java
@@ -1,111 +1,111 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.providers.simplearray;
-
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.Set;
-
-import com.ardor3d.extension.terrain.client.TextureConfiguration;
-import com.ardor3d.extension.terrain.client.TextureSource;
-import com.ardor3d.extension.terrain.util.Tile;
-import com.ardor3d.image.TextureStoreFormat;
-import com.ardor3d.util.geom.BufferUtils;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class SimpleArrayTextureSource implements TextureSource {
- private final int tileSize;
- private final byte[] colorData;
- private final int size;
- private final int availableClipmapLevels = 8;
-
- public SimpleArrayTextureSource(final int tileSize, final byte[] colorData, final int size) {
- this.tileSize = tileSize;
- this.colorData = colorData;
- this.size = size;
- }
-
- @Override
- public TextureConfiguration getConfiguration() throws Exception {
- final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
- textureStoreFormat.put(0, TextureStoreFormat.RGBA8);
-
- return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, true, true);
- }
-
- @Override
- public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- final Set<Tile> validTiles = Sets.newHashSet();
-
- final int levelSize = 1 << availableClipmapLevels - clipmapLevel;
-
- for (int y = 0; y < numTilesY; y++) {
- for (int x = 0; x < numTilesX; x++) {
- final int xx = tileX + x;
- final int yy = tileY + y;
- if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
- final Tile tile = new Tile(xx, yy);
- validTiles.add(tile);
- }
- }
- }
-
- return validTiles;
- }
-
- @Override
- public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
- final int numTilesY) throws Exception {
- return null;
- }
-
- @Override
- public int getContributorId(final int clipmapLevel, final Tile tile) {
- return 0;
- }
-
- @Override
- public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
- final int tileX = tile.getX();
- final int tileY = tile.getY();
-
- final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
-
- final int levelSize = 1 << baseClipmapLevel;
-
- final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 4);
- for (int y = 0; y < tileSize; y++) {
- for (int x = 0; x < tileSize; x++) {
- final int heightX = (tileX * tileSize + x) * levelSize;
- final int heightY = (tileY * tileSize + y) * levelSize;
-
- final int indexTile = (y * tileSize + x) * 4;
- final int index = heightY * size + heightX;
-
- if (heightX < 0 || heightX >= size || heightY < 0 || heightY >= size) {
- data.put(indexTile + 0, (byte) 0);
- data.put(indexTile + 1, (byte) 0);
- data.put(indexTile + 2, (byte) 0);
- data.put(indexTile + 3, (byte) 0);
- } else {
- data.put(indexTile + 0, colorData[index * 4 + 0]);
- data.put(indexTile + 1, colorData[index * 4 + 1]);
- data.put(indexTile + 2, colorData[index * 4 + 2]);
- data.put(indexTile + 3, colorData[index * 4 + 3]);
- }
- }
- }
-
- return data;
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.providers.simplearray;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+
+import com.ardor3d.extension.terrain.client.TextureConfiguration;
+import com.ardor3d.extension.terrain.client.TextureSource;
+import com.ardor3d.extension.terrain.util.Tile;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.util.geom.BufferUtils;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class SimpleArrayTextureSource implements TextureSource {
+ private final int tileSize;
+ private final byte[] colorData;
+ private final int size;
+ private final int availableClipmapLevels = 8;
+
+ public SimpleArrayTextureSource(final int tileSize, final byte[] colorData, final int size) {
+ this.tileSize = tileSize;
+ this.colorData = colorData;
+ this.size = size;
+ }
+
+ @Override
+ public TextureConfiguration getConfiguration() throws Exception {
+ final Map<Integer, TextureStoreFormat> textureStoreFormat = Maps.newHashMap();
+ textureStoreFormat.put(0, TextureStoreFormat.RGBA8);
+
+ return new TextureConfiguration(availableClipmapLevels, textureStoreFormat, tileSize, 1f, true, true);
+ }
+
+ @Override
+ public Set<Tile> getValidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ final Set<Tile> validTiles = Sets.newHashSet();
+
+ final int levelSize = 1 << availableClipmapLevels - clipmapLevel;
+
+ for (int y = 0; y < numTilesY; y++) {
+ for (int x = 0; x < numTilesX; x++) {
+ final int xx = tileX + x;
+ final int yy = tileY + y;
+ if (xx >= 0 && xx * tileSize * levelSize <= size && yy >= 0 && yy * tileSize * levelSize <= size) {
+ final Tile tile = new Tile(xx, yy);
+ validTiles.add(tile);
+ }
+ }
+ }
+
+ return validTiles;
+ }
+
+ @Override
+ public Set<Tile> getInvalidTiles(final int clipmapLevel, final int tileX, final int tileY, final int numTilesX,
+ final int numTilesY) throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getContributorId(final int clipmapLevel, final Tile tile) {
+ return 0;
+ }
+
+ @Override
+ public ByteBuffer getTile(final int clipmapLevel, final Tile tile) throws Exception {
+ final int tileX = tile.getX();
+ final int tileY = tile.getY();
+
+ final int baseClipmapLevel = availableClipmapLevels - clipmapLevel - 1;
+
+ final int levelSize = 1 << baseClipmapLevel;
+
+ final ByteBuffer data = BufferUtils.createByteBufferOnHeap(tileSize * tileSize * 4);
+ for (int y = 0; y < tileSize; y++) {
+ for (int x = 0; x < tileSize; x++) {
+ final int heightX = (tileX * tileSize + x) * levelSize;
+ final int heightY = (tileY * tileSize + y) * levelSize;
+
+ final int indexTile = (y * tileSize + x) * 4;
+ final int index = heightY * size + heightX;
+
+ if (heightX < 0 || heightX >= size || heightY < 0 || heightY >= size) {
+ data.put(indexTile + 0, (byte) 0);
+ data.put(indexTile + 1, (byte) 0);
+ data.put(indexTile + 2, (byte) 0);
+ data.put(indexTile + 3, (byte) 0);
+ } else {
+ data.put(indexTile + 0, colorData[index * 4 + 0]);
+ data.put(indexTile + 1, colorData[index * 4 + 1]);
+ data.put(indexTile + 2, colorData[index * 4 + 2]);
+ data.put(indexTile + 3, colorData[index * 4 + 3]);
+ }
+ }
+ }
+
+ return data;
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamYUpGridTracer.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamYUpGridTracer.java
index 53e8c2c..6ea35cd 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamYUpGridTracer.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamYUpGridTracer.java
@@ -1,145 +1,145 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.util;
-
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.math.Ray3;
-import com.ardor3d.math.Vector2;
-import com.ardor3d.math.Vector3;
-import com.ardor3d.math.type.ReadOnlyVector3;
-
-/**
- * An implementation of AbstractBresenhamTracer that works on the XZ plane, with positive Y as up.
- */
-public class BresenhamYUpGridTracer extends AbstractBresenhamTracer {
-
- // a "near zero" value we will use to determine if the walkRay is
- // perpendicular to the grid.
- protected static double TOLERANCE = 0.0000001;
-
- private int _stepXDirection;
- private int _stepZDirection;
-
- // from current position along ray
- private double _distToNextXIntersection, _distToNextZIntersection;
- private double _distBetweenXIntersections, _distBetweenZIntersections;
-
- @Override
- public void startWalk(final Ray3 walkRay) {
- // store ray
- _walkRay.set(walkRay);
-
- // simplify access to direction
- final ReadOnlyVector3 direction = _walkRay.getDirection();
-
- // Move start point to grid space
- final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null);
-
- _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX());
- _gridLocation[1] = (int) MathUtils.floor(start.getZ() / _gridSpacing.getZ());
-
- final double invDirX = 1.0 / direction.getX();
- final double invDirZ = 1.0 / direction.getZ();
-
- // Check which direction on the X world axis we are moving.
- if (direction.getX() > BresenhamYUpGridTracer.TOLERANCE) {
- _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX;
- _distBetweenXIntersections = _gridSpacing.getX() * invDirX;
- _stepXDirection = 1;
- } else if (direction.getX() < -BresenhamYUpGridTracer.TOLERANCE) {
- _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX();
- _distBetweenXIntersections = -_gridSpacing.getX() * invDirX;
- _stepXDirection = -1;
- } else {
- _distToNextXIntersection = Double.MAX_VALUE;
- _distBetweenXIntersections = Double.MAX_VALUE;
- _stepXDirection = 0;
- }
-
- // Check which direction on the Z world axis we are moving.
- if (direction.getZ() > BresenhamYUpGridTracer.TOLERANCE) {
- _distToNextZIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getZ() - start.getZ()) * invDirZ;
- _distBetweenZIntersections = _gridSpacing.getZ() * invDirZ;
- _stepZDirection = 1;
- } else if (direction.getZ() < -BresenhamYUpGridTracer.TOLERANCE) {
- _distToNextZIntersection = (start.getZ() - _gridLocation[1] * _gridSpacing.getZ()) * -direction.getZ();
- _distBetweenZIntersections = -_gridSpacing.getZ() * invDirZ;
- _stepZDirection = -1;
- } else {
- _distToNextZIntersection = Double.MAX_VALUE;
- _distBetweenZIntersections = Double.MAX_VALUE;
- _stepZDirection = 0;
- }
-
- // Reset some variables
- _rayLocation.set(start);
- _totalTravel = 0.0;
- _stepDirection = Direction.None;
- }
-
- @Override
- public void next() {
- // Walk us to our next location based on distances to next X or Z grid
- // line.
- if (_distToNextXIntersection < _distToNextZIntersection) {
- _totalTravel = _distToNextXIntersection;
- _gridLocation[0] += _stepXDirection;
- _distToNextXIntersection += _distBetweenXIntersections;
- switch (_stepXDirection) {
- case -1:
- _stepDirection = Direction.NegativeX;
- break;
- case 0:
- _stepDirection = Direction.None;
- break;
- case 1:
- _stepDirection = Direction.PositiveX;
- break;
- }
- } else {
- _totalTravel = _distToNextZIntersection;
- _gridLocation[1] += _stepZDirection;
- _distToNextZIntersection += _distBetweenZIntersections;
- switch (_stepZDirection) {
- case -1:
- _stepDirection = Direction.NegativeZ;
- break;
- case 0:
- _stepDirection = Direction.None;
- break;
- case 1:
- _stepDirection = Direction.PositiveZ;
- break;
- }
- }
-
- _rayLocation.set(_walkRay.getDirection()).multiplyLocal(_totalTravel).addLocal(_walkRay.getOrigin());
- }
-
- @Override
- public boolean isRayPerpendicularToGrid() {
- return _stepXDirection == 0 && _stepZDirection == 0;
- }
-
- @Override
- public Vector3 get3DPoint(final double gridX, final double gridY, final double height, final Vector3 store) {
- final Vector3 rVal = store != null ? store : new Vector3();
-
- return rVal.set(gridX, height, gridY);
- }
-
- @Override
- public Vector2 get2DPoint(final ReadOnlyVector3 worldLocation, final Vector2 store) {
- final Vector2 rVal = store != null ? store : new Vector2();
-
- return rVal.set(worldLocation.getX(), worldLocation.getZ());
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.util;
+
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Ray3;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyVector3;
+
+/**
+ * An implementation of AbstractBresenhamTracer that works on the XZ plane, with positive Y as up.
+ */
+public class BresenhamYUpGridTracer extends AbstractBresenhamTracer {
+
+ // a "near zero" value we will use to determine if the walkRay is
+ // perpendicular to the grid.
+ protected static double TOLERANCE = 0.0000001;
+
+ private int _stepXDirection;
+ private int _stepZDirection;
+
+ // from current position along ray
+ private double _distToNextXIntersection, _distToNextZIntersection;
+ private double _distBetweenXIntersections, _distBetweenZIntersections;
+
+ @Override
+ public void startWalk(final Ray3 walkRay) {
+ // store ray
+ _walkRay.set(walkRay);
+
+ // simplify access to direction
+ final ReadOnlyVector3 direction = _walkRay.getDirection();
+
+ // Move start point to grid space
+ final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null);
+
+ _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX());
+ _gridLocation[1] = (int) MathUtils.floor(start.getZ() / _gridSpacing.getZ());
+
+ final double invDirX = 1.0 / direction.getX();
+ final double invDirZ = 1.0 / direction.getZ();
+
+ // Check which direction on the X world axis we are moving.
+ if (direction.getX() > BresenhamYUpGridTracer.TOLERANCE) {
+ _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX;
+ _distBetweenXIntersections = _gridSpacing.getX() * invDirX;
+ _stepXDirection = 1;
+ } else if (direction.getX() < -BresenhamYUpGridTracer.TOLERANCE) {
+ _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX();
+ _distBetweenXIntersections = -_gridSpacing.getX() * invDirX;
+ _stepXDirection = -1;
+ } else {
+ _distToNextXIntersection = Double.MAX_VALUE;
+ _distBetweenXIntersections = Double.MAX_VALUE;
+ _stepXDirection = 0;
+ }
+
+ // Check which direction on the Z world axis we are moving.
+ if (direction.getZ() > BresenhamYUpGridTracer.TOLERANCE) {
+ _distToNextZIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getZ() - start.getZ()) * invDirZ;
+ _distBetweenZIntersections = _gridSpacing.getZ() * invDirZ;
+ _stepZDirection = 1;
+ } else if (direction.getZ() < -BresenhamYUpGridTracer.TOLERANCE) {
+ _distToNextZIntersection = (start.getZ() - _gridLocation[1] * _gridSpacing.getZ()) * -direction.getZ();
+ _distBetweenZIntersections = -_gridSpacing.getZ() * invDirZ;
+ _stepZDirection = -1;
+ } else {
+ _distToNextZIntersection = Double.MAX_VALUE;
+ _distBetweenZIntersections = Double.MAX_VALUE;
+ _stepZDirection = 0;
+ }
+
+ // Reset some variables
+ _rayLocation.set(start);
+ _totalTravel = 0.0;
+ _stepDirection = Direction.None;
+ }
+
+ @Override
+ public void next() {
+ // Walk us to our next location based on distances to next X or Z grid
+ // line.
+ if (_distToNextXIntersection < _distToNextZIntersection) {
+ _totalTravel = _distToNextXIntersection;
+ _gridLocation[0] += _stepXDirection;
+ _distToNextXIntersection += _distBetweenXIntersections;
+ switch (_stepXDirection) {
+ case -1:
+ _stepDirection = Direction.NegativeX;
+ break;
+ case 0:
+ _stepDirection = Direction.None;
+ break;
+ case 1:
+ _stepDirection = Direction.PositiveX;
+ break;
+ }
+ } else {
+ _totalTravel = _distToNextZIntersection;
+ _gridLocation[1] += _stepZDirection;
+ _distToNextZIntersection += _distBetweenZIntersections;
+ switch (_stepZDirection) {
+ case -1:
+ _stepDirection = Direction.NegativeZ;
+ break;
+ case 0:
+ _stepDirection = Direction.None;
+ break;
+ case 1:
+ _stepDirection = Direction.PositiveZ;
+ break;
+ }
+ }
+
+ _rayLocation.set(_walkRay.getDirection()).multiplyLocal(_totalTravel).addLocal(_walkRay.getOrigin());
+ }
+
+ @Override
+ public boolean isRayPerpendicularToGrid() {
+ return _stepXDirection == 0 && _stepZDirection == 0;
+ }
+
+ @Override
+ public Vector3 get3DPoint(final double gridX, final double gridY, final double height, final Vector3 store) {
+ final Vector3 rVal = store != null ? store : new Vector3();
+
+ return rVal.set(gridX, height, gridY);
+ }
+
+ @Override
+ public Vector2 get2DPoint(final ReadOnlyVector3 worldLocation, final Vector2 store) {
+ final Vector2 rVal = store != null ? store : new Vector2();
+
+ return rVal.set(worldLocation.getX(), worldLocation.getZ());
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamZUpGridTracer.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamZUpGridTracer.java
index 9e39102..eaa288b 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamZUpGridTracer.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/BresenhamZUpGridTracer.java
@@ -1,145 +1,145 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.util;
-
-import com.ardor3d.math.MathUtils;
-import com.ardor3d.math.Ray3;
-import com.ardor3d.math.Vector2;
-import com.ardor3d.math.Vector3;
-import com.ardor3d.math.type.ReadOnlyVector3;
-
-/**
- * An implementation of AbstractBresenhamTracer that works on the XY plane, with positive Z as up.
- */
-public class BresenhamZUpGridTracer extends AbstractBresenhamTracer {
-
- // a "near zero" value we will use to determine if the walkRay is
- // perpendicular to the grid.
- protected static double TOLERANCE = 0.0000001;
-
- private int _stepXDirection;
- private int _stepYDirection;
-
- // from current position along ray
- private double _distToNextXIntersection, _distToNextYIntersection;
- private double _distBetweenXIntersections, _distBetweenYIntersections;
-
- @Override
- public void startWalk(final Ray3 walkRay) {
- // store ray
- _walkRay.set(walkRay);
-
- // simplify access to direction
- final ReadOnlyVector3 direction = _walkRay.getDirection();
-
- // Move start point to grid space
- final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null);
-
- _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX());
- _gridLocation[1] = (int) MathUtils.floor(start.getY() / _gridSpacing.getY());
-
- final double invDirX = 1.0 / direction.getX();
- final double invDirY = 1.0 / direction.getY();
-
- // Check which direction on the X world axis we are moving.
- if (direction.getX() > BresenhamZUpGridTracer.TOLERANCE) {
- _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX;
- _distBetweenXIntersections = _gridSpacing.getX() * invDirX;
- _stepXDirection = 1;
- } else if (direction.getX() < -BresenhamZUpGridTracer.TOLERANCE) {
- _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX();
- _distBetweenXIntersections = -_gridSpacing.getX() * invDirX;
- _stepXDirection = -1;
- } else {
- _distToNextXIntersection = Double.MAX_VALUE;
- _distBetweenXIntersections = Double.MAX_VALUE;
- _stepXDirection = 0;
- }
-
- // Check which direction on the Y world axis we are moving.
- if (direction.getY() > BresenhamZUpGridTracer.TOLERANCE) {
- _distToNextYIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getY() - start.getY()) * invDirY;
- _distBetweenYIntersections = _gridSpacing.getY() * invDirY;
- _stepYDirection = 1;
- } else if (direction.getY() < -BresenhamZUpGridTracer.TOLERANCE) {
- _distToNextYIntersection = (start.getY() - _gridLocation[1] * _gridSpacing.getY()) * -direction.getY();
- _distBetweenYIntersections = -_gridSpacing.getY() * invDirY;
- _stepYDirection = -1;
- } else {
- _distToNextYIntersection = Double.MAX_VALUE;
- _distBetweenYIntersections = Double.MAX_VALUE;
- _stepYDirection = 0;
- }
-
- // Reset some variables
- _rayLocation.set(start);
- _totalTravel = 0.0;
- _stepDirection = Direction.None;
- }
-
- @Override
- public void next() {
- // Walk us to our next location based on distances to next X or Y grid
- // line.
- if (_distToNextXIntersection < _distToNextYIntersection) {
- _totalTravel = _distToNextXIntersection;
- _gridLocation[0] += _stepXDirection;
- _distToNextXIntersection += _distBetweenXIntersections;
- switch (_stepXDirection) {
- case -1:
- _stepDirection = Direction.NegativeX;
- break;
- case 0:
- _stepDirection = Direction.None;
- break;
- case 1:
- _stepDirection = Direction.PositiveX;
- break;
- }
- } else {
- _totalTravel = _distToNextYIntersection;
- _gridLocation[1] += _stepYDirection;
- _distToNextYIntersection += _distBetweenYIntersections;
- switch (_stepYDirection) {
- case -1:
- _stepDirection = Direction.NegativeY;
- break;
- case 0:
- _stepDirection = Direction.None;
- break;
- case 1:
- _stepDirection = Direction.PositiveY;
- break;
- }
- }
-
- _rayLocation.set(_walkRay.getDirection()).multiplyLocal(_totalTravel).addLocal(_walkRay.getOrigin());
- }
-
- @Override
- public boolean isRayPerpendicularToGrid() {
- return _stepXDirection == 0 && _stepYDirection == 0;
- }
-
- @Override
- public Vector3 get3DPoint(final double gridX, final double gridY, final double height, final Vector3 store) {
- final Vector3 rVal = store != null ? store : new Vector3();
-
- return rVal.set(gridX, gridY, height);
- }
-
- @Override
- public Vector2 get2DPoint(final ReadOnlyVector3 worldLocation, final Vector2 store) {
- final Vector2 rVal = store != null ? store : new Vector2();
-
- return rVal.set(worldLocation.getX(), worldLocation.getY());
- }
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.util;
+
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Ray3;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyVector3;
+
+/**
+ * An implementation of AbstractBresenhamTracer that works on the XY plane, with positive Z as up.
+ */
+public class BresenhamZUpGridTracer extends AbstractBresenhamTracer {
+
+ // a "near zero" value we will use to determine if the walkRay is
+ // perpendicular to the grid.
+ protected static double TOLERANCE = 0.0000001;
+
+ private int _stepXDirection;
+ private int _stepYDirection;
+
+ // from current position along ray
+ private double _distToNextXIntersection, _distToNextYIntersection;
+ private double _distBetweenXIntersections, _distBetweenYIntersections;
+
+ @Override
+ public void startWalk(final Ray3 walkRay) {
+ // store ray
+ _walkRay.set(walkRay);
+
+ // simplify access to direction
+ final ReadOnlyVector3 direction = _walkRay.getDirection();
+
+ // Move start point to grid space
+ final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null);
+
+ _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX());
+ _gridLocation[1] = (int) MathUtils.floor(start.getY() / _gridSpacing.getY());
+
+ final double invDirX = 1.0 / direction.getX();
+ final double invDirY = 1.0 / direction.getY();
+
+ // Check which direction on the X world axis we are moving.
+ if (direction.getX() > BresenhamZUpGridTracer.TOLERANCE) {
+ _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX;
+ _distBetweenXIntersections = _gridSpacing.getX() * invDirX;
+ _stepXDirection = 1;
+ } else if (direction.getX() < -BresenhamZUpGridTracer.TOLERANCE) {
+ _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX();
+ _distBetweenXIntersections = -_gridSpacing.getX() * invDirX;
+ _stepXDirection = -1;
+ } else {
+ _distToNextXIntersection = Double.MAX_VALUE;
+ _distBetweenXIntersections = Double.MAX_VALUE;
+ _stepXDirection = 0;
+ }
+
+ // Check which direction on the Y world axis we are moving.
+ if (direction.getY() > BresenhamZUpGridTracer.TOLERANCE) {
+ _distToNextYIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getY() - start.getY()) * invDirY;
+ _distBetweenYIntersections = _gridSpacing.getY() * invDirY;
+ _stepYDirection = 1;
+ } else if (direction.getY() < -BresenhamZUpGridTracer.TOLERANCE) {
+ _distToNextYIntersection = (start.getY() - _gridLocation[1] * _gridSpacing.getY()) * -direction.getY();
+ _distBetweenYIntersections = -_gridSpacing.getY() * invDirY;
+ _stepYDirection = -1;
+ } else {
+ _distToNextYIntersection = Double.MAX_VALUE;
+ _distBetweenYIntersections = Double.MAX_VALUE;
+ _stepYDirection = 0;
+ }
+
+ // Reset some variables
+ _rayLocation.set(start);
+ _totalTravel = 0.0;
+ _stepDirection = Direction.None;
+ }
+
+ @Override
+ public void next() {
+ // Walk us to our next location based on distances to next X or Y grid
+ // line.
+ if (_distToNextXIntersection < _distToNextYIntersection) {
+ _totalTravel = _distToNextXIntersection;
+ _gridLocation[0] += _stepXDirection;
+ _distToNextXIntersection += _distBetweenXIntersections;
+ switch (_stepXDirection) {
+ case -1:
+ _stepDirection = Direction.NegativeX;
+ break;
+ case 0:
+ _stepDirection = Direction.None;
+ break;
+ case 1:
+ _stepDirection = Direction.PositiveX;
+ break;
+ }
+ } else {
+ _totalTravel = _distToNextYIntersection;
+ _gridLocation[1] += _stepYDirection;
+ _distToNextYIntersection += _distBetweenYIntersections;
+ switch (_stepYDirection) {
+ case -1:
+ _stepDirection = Direction.NegativeY;
+ break;
+ case 0:
+ _stepDirection = Direction.None;
+ break;
+ case 1:
+ _stepDirection = Direction.PositiveY;
+ break;
+ }
+ }
+
+ _rayLocation.set(_walkRay.getDirection()).multiplyLocal(_totalTravel).addLocal(_walkRay.getOrigin());
+ }
+
+ @Override
+ public boolean isRayPerpendicularToGrid() {
+ return _stepXDirection == 0 && _stepYDirection == 0;
+ }
+
+ @Override
+ public Vector3 get3DPoint(final double gridX, final double gridY, final double height, final Vector3 store) {
+ final Vector3 rVal = store != null ? store : new Vector3();
+
+ return rVal.set(gridX, gridY, height);
+ }
+
+ @Override
+ public Vector2 get2DPoint(final ReadOnlyVector3 worldLocation, final Vector2 store) {
+ final Vector2 rVal = store != null ? store : new Vector2();
+
+ return rVal.set(worldLocation.getX(), worldLocation.getY());
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/LevelData.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/LevelData.java
index e2e3964..589f844 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/LevelData.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/LevelData.java
@@ -1,19 +1,19 @@
-
-package com.ardor3d.extension.terrain.util;
-
-import java.nio.ByteBuffer;
-
-public class LevelData {
- public int unit;
- public int x = Integer.MAX_VALUE, y = Integer.MAX_VALUE;
- public int offsetX, offsetY;
- public int textureOffsetX, textureOffsetY;
- public Region clipRegion;
-
- public ByteBuffer sliceData;
-
- public LevelData(final int unit, final int textureSize) {
- this.unit = unit;
- clipRegion = new Region(unit, 0, 0, textureSize, textureSize);
- }
-}
+
+package com.ardor3d.extension.terrain.util;
+
+import java.nio.ByteBuffer;
+
+public class LevelData {
+ public int unit;
+ public int x = Integer.MAX_VALUE, y = Integer.MAX_VALUE;
+ public int offsetX, offsetY;
+ public int textureOffsetX, textureOffsetY;
+ public Region clipRegion;
+
+ public ByteBuffer sliceData;
+
+ public LevelData(final int unit, final int textureSize) {
+ this.unit = unit;
+ clipRegion = new Region(unit, 0, 0, textureSize, textureSize);
+ }
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Region.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Region.java
index 19a280a..d46d85f 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Region.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Region.java
@@ -1,249 +1,249 @@
-/**
- * Copyright (c) 2008-2012 Ardor Labs, Inc.
- *
- * This file is part of Ardor3D.
- *
- * Ardor3D is free software: you can redistribute it and/or modify it
- * under the terms of its license which may be found in the accompanying
- * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
- */
-
-package com.ardor3d.extension.terrain.util;
-
-/**
- * Used to calculate clipmap block boundaries etc
- */
-public class Region {
- private int x;
- private int y;
- private int width;
- private int height;
-
- private int left;
- private int right;
- private int top;
- private int bottom;
-
- private final int level;
-
- public Region(final int x, final int y, final int width, final int height) {
- this(0, x, y, width, height);
- }
-
- public Region(final int level, final int x, final int y, final int width, final int height) {
- this.level = level;
-
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
-
- left = x;
- right = x + width;
- top = y;
- bottom = y + height;
- }
-
- /**
- * @return the x
- */
- public int getX() {
- return x;
- }
-
- /**
- * @return the y
- */
- public int getY() {
- return y;
- }
-
- /**
- * @param x
- * the x to set
- */
- public void setX(final int x) {
- this.x = x;
- left = x;
- right = x + width;
- }
-
- /**
- * @param y
- * the y to set
- */
- public void setY(final int y) {
- this.y = y;
- top = y;
- bottom = y + height;
- }
-
- public void setWidth(final int width) {
- this.width = width;
- right = x + width;
- }
-
- public void setHeight(final int height) {
- this.height = height;
- bottom = y + height;
- }
-
- /**
- * @return the left
- */
- public int getLeft() {
- return left;
- }
-
- /**
- * @return the right
- */
- public int getRight() {
- return right;
- }
-
- /**
- * @return the top
- */
- public int getTop() {
- return top;
- }
-
- /**
- * @return the bottom
- */
- public int getBottom() {
- return bottom;
- }
-
- /**
- * @return the width
- */
- public int getWidth() {
- return width;
- }
-
- /**
- * @return the height
- */
- public int getHeight() {
- return height;
- }
-
- public boolean intersects(final Region r) {
- int tw = width;
- int th = height;
- int rw = r.width;
- int rh = r.height;
- if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
- return false;
- }
- final int tx = x;
- final int ty = y;
- final int rx = r.x;
- final int ry = r.y;
- rw += rx;
- rh += ry;
- tw += tx;
- th += ty;
- // overflow || intersect
- return (rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry);
- }
-
- public Region intersection(final Region r) {
- int tx1 = x;
- int ty1 = y;
- final int rx1 = r.x;
- final int ry1 = r.y;
- long tx2 = tx1;
- tx2 += width;
- long ty2 = ty1;
- ty2 += height;
- long rx2 = rx1;
- rx2 += r.width;
- long ry2 = ry1;
- ry2 += r.height;
- if (tx1 < rx1) {
- tx1 = rx1;
- }
- if (ty1 < ry1) {
- ty1 = ry1;
- }
- if (tx2 > rx2) {
- tx2 = rx2;
- }
- if (ty2 > ry2) {
- ty2 = ry2;
- }
- tx2 -= tx1;
- ty2 -= ty1;
- // tx2,ty2 will never overflow (they will never be
- // larger than the smallest of the two source w,h)
- // they might underflow, though...
- if (tx2 < Integer.MIN_VALUE) {
- tx2 = Integer.MIN_VALUE;
- }
- if (ty2 < Integer.MIN_VALUE) {
- ty2 = Integer.MIN_VALUE;
- }
-
- r.setX(tx1);
- r.setY(ty1);
- r.setWidth((int) tx2);
- r.setHeight((int) ty2);
-
- return r;
- }
-
- public int getLevel() {
- return level;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + height;
- result = prime * result + level;
- result = prime * result + width;
- result = prime * result + x;
- result = prime * result + y;
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (!(obj instanceof Region)) {
- return false;
- }
- final Region other = (Region) obj;
- if (height != other.height) {
- return false;
- }
- if (level != other.level) {
- return false;
- }
- if (width != other.width) {
- return false;
- }
- if (x != other.x) {
- return false;
- }
- if (y != other.y) {
- return false;
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "Region [level=" + level + ", x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]";
- }
-
-}
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.terrain.util;
+
+/**
+ * Used to calculate clipmap block boundaries etc
+ */
+public class Region {
+ private int x;
+ private int y;
+ private int width;
+ private int height;
+
+ private int left;
+ private int right;
+ private int top;
+ private int bottom;
+
+ private final int level;
+
+ public Region(final int x, final int y, final int width, final int height) {
+ this(0, x, y, width, height);
+ }
+
+ public Region(final int level, final int x, final int y, final int width, final int height) {
+ this.level = level;
+
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ left = x;
+ right = x + width;
+ top = y;
+ bottom = y + height;
+ }
+
+ /**
+ * @return the x
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * @return the y
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * @param x
+ * the x to set
+ */
+ public void setX(final int x) {
+ this.x = x;
+ left = x;
+ right = x + width;
+ }
+
+ /**
+ * @param y
+ * the y to set
+ */
+ public void setY(final int y) {
+ this.y = y;
+ top = y;
+ bottom = y + height;
+ }
+
+ public void setWidth(final int width) {
+ this.width = width;
+ right = x + width;
+ }
+
+ public void setHeight(final int height) {
+ this.height = height;
+ bottom = y + height;
+ }
+
+ /**
+ * @return the left
+ */
+ public int getLeft() {
+ return left;
+ }
+
+ /**
+ * @return the right
+ */
+ public int getRight() {
+ return right;
+ }
+
+ /**
+ * @return the top
+ */
+ public int getTop() {
+ return top;
+ }
+
+ /**
+ * @return the bottom
+ */
+ public int getBottom() {
+ return bottom;
+ }
+
+ /**
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ public boolean intersects(final Region r) {
+ int tw = width;
+ int th = height;
+ int rw = r.width;
+ int rh = r.height;
+ if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
+ return false;
+ }
+ final int tx = x;
+ final int ty = y;
+ final int rx = r.x;
+ final int ry = r.y;
+ rw += rx;
+ rh += ry;
+ tw += tx;
+ th += ty;
+ // overflow || intersect
+ return (rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry);
+ }
+
+ public Region intersection(final Region r) {
+ int tx1 = x;
+ int ty1 = y;
+ final int rx1 = r.x;
+ final int ry1 = r.y;
+ long tx2 = tx1;
+ tx2 += width;
+ long ty2 = ty1;
+ ty2 += height;
+ long rx2 = rx1;
+ rx2 += r.width;
+ long ry2 = ry1;
+ ry2 += r.height;
+ if (tx1 < rx1) {
+ tx1 = rx1;
+ }
+ if (ty1 < ry1) {
+ ty1 = ry1;
+ }
+ if (tx2 > rx2) {
+ tx2 = rx2;
+ }
+ if (ty2 > ry2) {
+ ty2 = ry2;
+ }
+ tx2 -= tx1;
+ ty2 -= ty1;
+ // tx2,ty2 will never overflow (they will never be
+ // larger than the smallest of the two source w,h)
+ // they might underflow, though...
+ if (tx2 < Integer.MIN_VALUE) {
+ tx2 = Integer.MIN_VALUE;
+ }
+ if (ty2 < Integer.MIN_VALUE) {
+ ty2 = Integer.MIN_VALUE;
+ }
+
+ r.setX(tx1);
+ r.setY(ty1);
+ r.setWidth((int) tx2);
+ r.setHeight((int) ty2);
+
+ return r;
+ }
+
+ public int getLevel() {
+ return level;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + height;
+ result = prime * result + level;
+ result = prime * result + width;
+ result = prime * result + x;
+ result = prime * result + y;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof Region)) {
+ return false;
+ }
+ final Region other = (Region) obj;
+ if (height != other.height) {
+ return false;
+ }
+ if (level != other.level) {
+ return false;
+ }
+ if (width != other.width) {
+ return false;
+ }
+ if (x != other.x) {
+ return false;
+ }
+ if (y != other.y) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Region [level=" + level + ", x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]";
+ }
+
+}
diff --git a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Tile.java b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Tile.java
index afefc37..7210382 100644
--- a/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Tile.java
+++ b/ardor3d-terrain/src/main/java/com/ardor3d/extension/terrain/util/Tile.java
@@ -1,48 +1,48 @@
-
-package com.ardor3d.extension.terrain.util;
-
-import java.io.Serializable;
-
-public class Tile implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private final int x, y;
-
- public Tile(final int x, final int y) {
- this.x = x;
- this.y = y;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- @Override
- public int hashCode() {
- int result = 17;
- result += 31 * result + x;
- result += 31 * result + y;
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof Tile)) {
- return false;
- }
- final Tile other = (Tile) obj;
- return x == other.x && y == other.y;
- }
-
- @Override
- public String toString() {
- return "Tile [x=" + x + ", y=" + y + "]";
- }
-}
+
+package com.ardor3d.extension.terrain.util;
+
+import java.io.Serializable;
+
+public class Tile implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final int x, y;
+
+ public Tile(final int x, final int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result += 31 * result + x;
+ result += 31 * result + y;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Tile)) {
+ return false;
+ }
+ final Tile other = (Tile) obj;
+ return x == other.x && y == other.y;
+ }
+
+ @Override
+ public String toString() {
+ return "Tile [x=" + x + ", y=" + y + "]";
+ }
+}