Endless Terrain

TerrainGrid is DEPRECATED.

TerrainGrid is an extension built on top of the TerraMonkey tools like TerrainQuad and HeightMap, that provides “infinite Terrain paging routines.
Thanks to Gábor (@anthyon) and Brent (@sploreg) for this contribution!

Sample Code

The classes with source code can be found in the org.jme3.terrain.geomipmapping and org.jme3.terrain.heightmap packages. Also there are 3 tests prepared in the jme3test.terrain package:

Specification

TerrainGrid is made up of the TerrainGrid class, and the HeightMapGrid and TerrainGridListener interfaces.

  • TerrainGrid is the central class of the system. It takes care for handling camera movement in LODUpdate, loading and unloading terrain tiles on demand, and notifying any registered listeners of changes.

  • TerrainGridListener defines two events to listen to:

    • gridMoved(Vector3f): gets the new center as parameter after terrain update, so any objects can be added or removed as needed.

    • Material tileLoaded(Material material, Vector3f cell): notifies the system about a tile being loaded. Parameters are a cloned value of the material added to the TerrainGrid, and the cell of the new tile. The system can change the material according to this information (eg. load required alphamaps, etc).

Multiple listeners can be added to the TerrainGrid, they will be called in the order of addition, so it’s possible to have multiple changes to the material before completing the load of the tile.

HeightMapGrid adds the possibility of loading terrain tiles on demand instead of having a simple height array. There’s no predefined way of how to store these tiles, it only takes care of loading one HeightMap object at given location at a time.

Motivation

After playing around with the terrain in jME3, soon comes the requirement of having larger explorable lands. Increasing the size of one TerrainQuad leads to more memory usage, while it will still be easy to reach the worlds boundaries. That’s why TerrainGrid was designed. It extends the TerraindQuad class and uses 4 HeightMaps (dark blue) as the four sub-quad. This means that a terrain of size 513 will use tiles of 257. Also an LRUCache is built into the terrain package, so surrounding tiles (green) can be pre-cached on a different thread, lowering the loading time. The quads are updated as the camera approaches the boundary of the light blue section.

Rationale

The design of the TerrainGrid system was chosen carefully, so that minimal effort needs to be taken to switch from previous TerrainQuad uses. It has the same constructors with the small exception that instead of an array of heightmap it takes a HeightMapGrid instance. All other parameters are forwarded down to the underlying TerrainQuad system. There exist also two basic HeightMapGrid implementations:

  • ImageBasedHeightMapGrid: uses a sequentially numbered, 16 bit grayscale heightmaps. The physical filename of these files can be generated through the Namer interface. When a tile cannot be found by the assetManager, an empty (all-zero) heightmap is created, and a warning is added to the log.

  • FractalHeightMapGrid: uses a noise library to create a landscape on the fly. The shape of the terrain can be controlled by the various parameters and postfilters of the fractals. With the help of this grid implementation there’s no limitation – above of floating point precision limits – how far the camera can get. The tiles generated this way can be cached to the filesystem, for later modification. The FractalHeightMapGrid will always load from cache if a tile exists there!

Usage

  1. instantiate a TerrainGrid object

  2. set material, listeners, translation, scale, etc.

  3. add a LODControl instance to the object

  4. call initialize with the camera location

  5. (optional) add it to the physicsSpace as you would a TerrainQuad

Further information about terrain and TerrainQuad can be found in the wiki at: