public class TerrainQuad extends Node implements Terrain
TerrainQuad is a heightfield-based terrain system. Heightfield terrain is fast and can render large areas, and allows for easy Level of Detail control. However it does not permit caves easily. TerrainQuad is a quad tree, meaning that the root quad has four children, and each of those children have four children. All the way down until you reach the bottom, the actual geometry, the TerrainPatches. If you look at a TerrainQuad in wireframe mode with the TerrainLODControl attached, you will see blocks that change their LOD level together; these are the TerrainPatches. The TerrainQuad is just an organizational structure for the TerrainPatches so patches that are not in the view frustum get culled quickly. TerrainQuads size are a power of 2, plus 1. So 513x513, or 1025x1025 etc. Each point in the terrain is one unit apart from its neighbour. So a 513x513 terrain will be 513 units wide and 513 units long. Patch size can be specified on the terrain. This sets how large each geometry (TerrainPatch) is. It also must be a power of 2 plus 1 so the terrain can be subdivided equally.
The height of the terrain can be modified at runtime using setHeight()
A terrain quad is a node in the quad tree of the terrain system. The root terrain quad will be the only one that receives the update() call every frame and it will determine if there has been any LOD change.
The leaves of the terrain quad tree are Terrain Patches. These have the real geometry mesh.
Heightmap coordinates start from the bottom left of the world and work towards the top right.
+x ^ | ......N = length of heightmap | : : | : : | 0.....: +---------> +z (world coordinates)
Modifier and Type | Class and Description |
---|---|
protected class |
TerrainQuad.LocationHeight |
Spatial.BatchHint, Spatial.CullHint, Spatial.DFSMode
Modifier and Type | Field and Description |
---|---|
protected NeighbourFinder |
neighbourFinder |
protected Vector2f |
offset |
protected float |
offsetAmount |
protected int |
patchSize |
protected int |
quadrant |
protected int |
size |
protected Vector3f |
stepScale |
protected int |
totalSize |
batchHint, controls, cullHint, frustrumIntersects, key, localLights, localOverrides, localTransform, name, parent, queueBucket, queueDistance, refreshFlags, RF_BOUND, RF_CHILD_LIGHTLIST, RF_LIGHTLIST, RF_MATPARAM_OVERRIDE, RF_TRANSFORM, shadowMode, userData, worldBound, worldLights, worldOverrides, worldTransform
Modifier | Constructor and Description |
---|---|
|
TerrainQuad() |
|
TerrainQuad(java.lang.String name,
int patchSize,
int totalSize,
float[] heightMap)
Creates a terrain with:
the total, real-world, size of the terrain
the patchSize, or the size of each geometry tile of the terrain
the heightmap that defines the height of the terrain
|
|
TerrainQuad(java.lang.String name,
int patchSize,
int totalSize,
int quadSize,
Vector3f scale,
float[] heightMap)
Deprecated.
|
|
TerrainQuad(java.lang.String name,
int patchSize,
int size,
Vector3f scale,
float[] heightMap)
Deprecated.
|
protected |
TerrainQuad(java.lang.String name,
int patchSize,
int quadSize,
Vector3f scale,
float[] heightMap,
int totalSize,
Vector2f offset,
float offsetAmount) |
Modifier and Type | Method and Description |
---|---|
void |
adjustHeight(java.util.List<Vector2f> xz,
java.util.List<java.lang.Float> height)
Raise/lower the height at many points.
|
void |
adjustHeight(Vector2f xz,
float delta)
Raise/lower the height in one call (instead of getHeight then setHeight).
|
void |
attachBoundChildren(Node parent)
A handy method that will attach all bounding boxes of this terrain
to the node you supply.
|
protected void |
cacheTerrainTransforms()
Caches the transforms (except rotation) so the LOD calculator,
which runs on a separate thread, can access them safely.
|
protected boolean |
calculateLod(java.util.List<Vector3f> location,
java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updates,
LodCalculator lodCalculator) |
void |
clearCaches()
Removes any cached references this terrain is holding, in particular
the TerrainPatch's neighbour references.
|
TerrainQuad |
clone()
Creates a clone of the asset.
|
TerrainQuad |
clone(boolean cloneMaterials) |
void |
cloneFields(Cloner cloner,
java.lang.Object original)
Called internally by com.jme3.util.clone.Cloner.
|
int |
collideWith(Collidable other,
CollisionResults results)
Check collision with another Collidable.
|
float[] |
createHeightSubBlock(float[] heightMap,
int x,
int y,
int side) |
protected void |
createQuad(int blockSize,
float[] heightMap)
Quadrants, world coordinates, and heightmap coordinates (Y-up):
-z
-u |
-v 1|3
-x ----+---- x
2|4 u
| v
z
createQuad generates four new quads from this quad. |
protected void |
createQuadPatch(float[] heightMap)
createQuadPatch creates four child patches from this quad. |
protected TerrainPatch |
findDownPatch(TerrainPatch tp) |
protected TerrainQuad |
findDownQuad() |
protected TerrainPatch |
findLeftPatch(TerrainPatch tp) |
protected TerrainQuad |
findLeftQuad() |
protected void |
findNeighboursLod(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated) |
void |
findPick(Ray toTest,
java.util.List<TerrainPickData> results)
Gather the terrain patches that intersect the given ray (toTest).
|
protected TerrainPatch |
findRightPatch(TerrainPatch tp) |
protected TerrainQuad |
findRightQuad() |
protected TerrainPatch |
findTopPatch(TerrainPatch tp) |
protected TerrainQuad |
findTopQuad() |
protected void |
fixEdges(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated)
Find any neighbours that should have their edges seamed because another neighbour
changed its LOD to a greater value (less detailed)
|
void |
fixNormalEdges(BoundingBox affectedArea)
fix the normals on the edge of the terrain patches.
|
void |
fixNormals(BoundingBox affectedArea)
Find what terrain patches need normal recalculations and update
their normals;
|
void |
generateDebugTangents(Material mat) |
void |
generateEntropy(ProgressMonitor progressMonitor)
Generate the entropy values for the terrain for the "perspective" LOD
calculator.
|
void |
getAllTerrainPatches(java.util.List<TerrainPatch> holder)
Retrieve all Terrain Patches from all children and store them
in the 'holder' list
|
void |
getAllTerrainPatchesWithTranslation(java.util.Map<TerrainPatch,Vector3f> holder,
Vector3f translation) |
protected float |
getHeight(int x,
int z,
float xm,
float zm)
gets an interpolated value at the specified point
|
float |
getHeight(Vector2f xz)
Get the interpolated height of the terrain at the specified point.
|
float[] |
getHeightMap()
Get the heightmap of the entire terrain.
|
protected float |
getHeightmapHeight(int x,
int z)
This will just get the heightmap value at the supplied point,
not an interpolated (actual) height value.
|
float |
getHeightmapHeight(Vector2f xz)
Get the heightmap height at the specified X-Z coordinate.
|
Material |
getMaterial()
Returns the material that this terrain uses.
|
Material |
getMaterial(Vector3f worldLocation)
Returns the material that this terrain uses.
|
int |
getMaxLod()
This is calculated by the specific LOD algorithm.
|
protected Vector3f |
getMeshNormal(int x,
int z) |
protected Vector3f |
getNormal(float x,
float z,
Vector2f xz) |
Vector3f |
getNormal(Vector2f xz)
Get the normal vector for the surface of the terrain at the specified
X-Z coordinate.
|
int |
getNumMajorSubdivisions() |
protected TerrainPatch |
getPatch(int quad) |
int |
getPatchSize() |
protected TerrainQuad |
getQuad(int quad) |
int |
getQuadrant() |
int |
getTerrainSize()
Used for painting to get the number of vertices along the edge of the
terrain.
|
int |
getTotalSize() |
protected boolean |
isPointOnTerrain(int x,
int z) |
protected boolean |
isRootQuad() |
protected boolean |
needToRecalculateNormals() |
void |
read(JmeImporter importer) |
void |
recalculateAllNormals()
Forces the recalculation of all normals on the terrain.
|
protected void |
reIndexPages(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated,
boolean usesVariableLod) |
void |
resetCachedNeighbours()
Reset the cached references of neighbours.
|
protected void |
setHeight(java.util.List<TerrainQuad.LocationHeight> locations,
boolean overrideHeight) |
void |
setHeight(java.util.List<Vector2f> xz,
java.util.List<java.lang.Float> height)
Set the height at many points.
|
protected void |
setHeight(java.util.List<Vector2f> xz,
java.util.List<java.lang.Float> height,
boolean overrideHeight) |
void |
setHeight(Vector2f xz,
float height)
Set the height at the specified X-Z coordinate.
|
void |
setLocked(boolean locked)
lock or unlock the meshes of this terrain.
|
protected void |
setNeedToRecalculateNormals()
This will cause all normals for this terrain quad to be recalculated
|
void |
setNeighbourFinder(NeighbourFinder neighbourFinder) |
protected void |
setNormalRecalcNeeded(Vector2f changedPoint)
Signal if the normal vectors for the terrain need to be recalculated.
|
protected void |
setParent(Node parent)
Called by
Node.attachChild(Spatial) and
Node.detachChild(Spatial) - don't call directly. |
void |
setQuadrant(short quadrant) |
void |
setSupportMultipleCollisions(boolean set)
When colliding with this terrain, is a report of all collisions wanted or only the closest collision?
If only the closest collision is required, the collision calculation will be faster. Note: If no collision happens, it takes as long as a collision with multipleCollisions on would take. |
protected void |
split(int blockSize,
float[] heightMap)
split divides the heightmap data for four children. |
protected void |
updateNormals()
update the normals if there were any height changes recently.
|
void |
write(JmeExporter e) |
attachChild, attachChildAt, breadthFirstTraversal, deepClone, depthFirstTraversal, descendantMatches, descendantMatches, descendantMatches, detachAllChildren, detachChild, detachChildAt, detachChildNamed, getChild, getChild, getChildIndex, getChildren, getQuantity, getTriangleCount, getVertexCount, hasChild, oldDeepClone, setLightListRefresh, setLodLevel, setMaterial, setMatParamOverrideRefresh, setModelBound, setTransformRefresh, swapChildren, updateGeometricState, updateLogicalState, updateModelBound, updateWorldBound
addControl, addControlAt, addLight, addMatParamOverride, breadthFirstTraversal, center, checkCulling, clearMatParamOverrides, depthFirstTraversal, forceRefresh, getBatchHint, getControl, getControl, getCullHint, getKey, getLastFrustumIntersection, getLocalBatchHint, getLocalCullHint, getLocalLightList, getLocalMatParamOverrides, getLocalQueueBucket, getLocalRotation, getLocalScale, getLocalShadowMode, getLocalToWorldMatrix, getLocalTransform, getLocalTranslation, getName, getNumControls, getParent, getQueueBucket, getShadowMode, getUserData, getUserDataKeys, getWorldBound, getWorldLightList, getWorldMatParamOverrides, getWorldRotation, getWorldScale, getWorldTransform, getWorldTranslation, hasAncestor, jmeClone, localToWorld, lookAt, matches, move, move, oldClone, removeControl, removeControl, removeFromParent, removeLight, removeMatParamOverride, rotate, rotate, rotateUpTo, runControlRender, scale, scale, setBatchHint, setBoundRefresh, setCullHint, setKey, setLastFrustumIntersection, setLocalRotation, setLocalRotation, setLocalScale, setLocalScale, setLocalScale, setLocalTransform, setLocalTranslation, setLocalTranslation, setName, setQueueBucket, setRequiresUpdates, setShadowMode, setUserData, toString, updateMatParamOverrides, updateWorldLightList, updateWorldTransforms, worldToLocal
protected Vector2f offset
protected int totalSize
protected int size
protected int patchSize
protected Vector3f stepScale
protected float offsetAmount
protected int quadrant
protected NeighbourFinder neighbourFinder
public TerrainQuad()
public TerrainQuad(java.lang.String name, int patchSize, int totalSize, float[] heightMap)
A TerrainQuad of totalSize 513x513 will be 513 units wide and 513 units long. PatchSize is just used to subdivide the terrain into tiles that can be culled.
name
- the name of the scene element. This is required for
identification and comparison purposes.patchSize
- size of the individual patches (geometry). Power of 2 plus 1,
must be smaller than totalSize. (e.g. 33, 65...)totalSize
- the size of this entire terrain (on one side). Power of 2 plus 1
(e.g. 513, 1025, 2049...)heightMap
- The height map to generate the terrain from (a flat
height map will be generated if this is null). The size of one side of the heightmap
must match the totalSize. So a 513x513 heightmap is needed for a terrain with totalSize of 513.@Deprecated public TerrainQuad(java.lang.String name, int patchSize, int size, Vector3f scale, float[] heightMap)
name
- the name of the scene element. This is required for
identification and comparison purposes.patchSize
- size of the individual patchessize
- size of this quad, can be between totalSize and patchSizescale
- heightMap
- The height map to generate the terrain from (a flat
height map will be generated if this is null)@Deprecated public TerrainQuad(java.lang.String name, int patchSize, int totalSize, int quadSize, Vector3f scale, float[] heightMap)
name
- the name of the scene element. This is required for
identification and comparison purposes.patchSize
- size of the individual patchestotalSize
- the size of this entire terrain tree (on one side)quadSize
- scale
- heightMap
- The height map to generate the terrain from (a flat
height map will be generated if this is null)public void setNeighbourFinder(NeighbourFinder neighbourFinder)
public void recalculateAllNormals()
protected void updateNormals()
protected void cacheTerrainTransforms()
public void generateEntropy(ProgressMonitor progressMonitor)
generateEntropy
in interface Terrain
progressMonitor
- optionalprotected boolean isRootQuad()
public Material getMaterial()
Terrain
getMaterial
in interface Terrain
public Material getMaterial(Vector3f worldLocation)
Terrain
getMaterial
in interface Terrain
worldLocation
- the location, in world coordinates, of where
we are interested in the underlying texture.public int getNumMajorSubdivisions()
getNumMajorSubdivisions
in interface Terrain
protected boolean calculateLod(java.util.List<Vector3f> location, java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updates, LodCalculator lodCalculator)
protected void findNeighboursLod(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated)
public void resetCachedNeighbours()
protected void fixEdges(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated)
protected void reIndexPages(java.util.HashMap<java.lang.String,UpdatedTerrainPatch> updated, boolean usesVariableLod)
protected void split(int blockSize, float[] heightMap)
split
divides the heightmap data for four children. The
children are either quads or patches. This is dependent on the size of the
children. If the child's size is less than or equal to the set block
size, then patches are created, otherwise, quads are created.blockSize
- the blocks size to test against.heightMap
- the height data.protected void createQuad(int blockSize, float[] heightMap)
createQuad
generates four new quads from this quad.
The heightmap's top left (0,0) coordinate is at the bottom, -x,-z
coordinate of the terrain, so it grows in the positive x.z direction.public void generateDebugTangents(Material mat)
protected void createQuadPatch(float[] heightMap)
createQuadPatch
creates four child patches from this quad.public float[] createHeightSubBlock(float[] heightMap, int x, int y, int side)
public void attachBoundChildren(Node parent)
parent
- that will get the bounding box shapes of the terrain attached toprotected void setNormalRecalcNeeded(Vector2f changedPoint)
changedPoint
- a location to includeprotected boolean needToRecalculateNormals()
protected void setNeedToRecalculateNormals()
public float getHeightmapHeight(Vector2f xz)
Terrain
getHeightmapHeight
in interface Terrain
xz
- world coordinateprotected float getHeightmapHeight(int x, int z)
protected Vector3f getMeshNormal(int x, int z)
public float getHeight(Vector2f xz)
protected float getHeight(int x, int z, float xm, float zm)
public Vector3f getNormal(Vector2f xz)
Terrain
public void setHeight(Vector2f xz, float height)
Terrain
public void adjustHeight(Vector2f xz, float delta)
Terrain
adjustHeight
in interface Terrain
xz
- world coordinate to adjust the terrain heightdelta
- +- value to adjust the height bypublic void setHeight(java.util.List<Vector2f> xz, java.util.List<java.lang.Float> height)
Terrain
public void adjustHeight(java.util.List<Vector2f> xz, java.util.List<java.lang.Float> height)
Terrain
adjustHeight
in interface Terrain
xz
- a list of coordinates where the height will be adjustedheight
- +- value to adjust the height by, that matches the xz coordinatesprotected void setHeight(java.util.List<Vector2f> xz, java.util.List<java.lang.Float> height, boolean overrideHeight)
protected void setHeight(java.util.List<TerrainQuad.LocationHeight> locations, boolean overrideHeight)
protected boolean isPointOnTerrain(int x, int z)
public int getTerrainSize()
Terrain
getTerrainSize
in interface Terrain
public void setLocked(boolean locked)
public int getQuadrant()
public void setQuadrant(short quadrant)
protected TerrainPatch getPatch(int quad)
protected TerrainQuad getQuad(int quad)
protected TerrainPatch findRightPatch(TerrainPatch tp)
protected TerrainPatch findDownPatch(TerrainPatch tp)
protected TerrainPatch findTopPatch(TerrainPatch tp)
protected TerrainPatch findLeftPatch(TerrainPatch tp)
protected TerrainQuad findRightQuad()
protected TerrainQuad findDownQuad()
protected TerrainQuad findTopQuad()
protected TerrainQuad findLeftQuad()
public void fixNormals(BoundingBox affectedArea)
public void fixNormalEdges(BoundingBox affectedArea)
public int collideWith(Collidable other, CollisionResults results)
Collidable
collideWith
in interface Collidable
collideWith
in class Node
other
- The object to check collision againstresults
- Will contain the list of CollisionResult
s.public void findPick(Ray toTest, java.util.List<TerrainPickData> results)
toTest
- results
- public void getAllTerrainPatches(java.util.List<TerrainPatch> holder)
holder
- must not be null, will be populated when returnspublic void getAllTerrainPatchesWithTranslation(java.util.Map<TerrainPatch,Vector3f> holder, Vector3f translation)
public void read(JmeImporter importer) throws java.io.IOException
public void write(JmeExporter e) throws java.io.IOException
public TerrainQuad clone()
CloneableSmartAsset
Object.clone()
for more info on how this method
should be implemented.clone
in interface CloneableSmartAsset
clone
in class Spatial
Mesh.cloneForAnim()
public TerrainQuad clone(boolean cloneMaterials)
clone
in class Node
cloneMaterials
- true to clone materials, false to share themMesh.cloneForAnim()
public void cloneFields(Cloner cloner, java.lang.Object original)
cloneFields
in interface JmeCloneable
cloneFields
in class Node
cloner
- The cloner that is performing the cloning operation. The
cloneFields method can call back into the cloner to make
clones of its subordinate fields.original
- The original object from which this object was cloned.
This is provided for the very rare case that this object needs
to refer to its original for some reason. In general, all of
the relevant values should have been transferred during the
shallow clone, and this object need only clone what it wants.protected void setParent(Node parent)
Spatial
Node.attachChild(Spatial)
and
Node.detachChild(Spatial)
- don't call directly.
setParent
sets the parent of this node.public void clearCaches()
public int getMaxLod()
Terrain
public int getPatchSize()
public int getTotalSize()
public float[] getHeightMap()
Terrain
getHeightMap
in interface Terrain
public void setSupportMultipleCollisions(boolean set)
set
- Whether to support multiple collisions or not