Terrain

Gorilla3D provides a simple terrain component for generation from height-map image. Besides the default usage, different procedural builders are available: diamond square, mandelbrot, perlin-noise (linear, cosine and cubic), plateau algorithms. The resolution / number of vertices is configurable.

For detailed information about the component and its methods, check out: Gorilla.Terrain

DesignTime

You can generate a terrain at design time by different ways.

From Heightmap

  1. Drop a TGorillaTerrain component onto your GorillaViewport
  2. Select the TGorillaTerrain instance
  3. Go to “Heightmap” property in object inspector
  4. Open the editor dialog and load a 2D image from file
  5. The heightmap will be stored inside the IDE formular file (*.fmx)

Autogenerate with Editor

When you select your TGorillaTerrain component in structure view of the IDE, you can right click onto and a popup will show.

Here you can select between the embedded procedural terrain generation algorithms.

Choose one of the “Random Terrain <ALGORITHM>” options.

After you have clicked, you need to click into the viewport in your form to refresh rendering.

Planting

The framework brings you a great feature called “Planting” to the terrain component.

After you have loaded a terrain from heightmap or by procedural generation, you can use this functionality.

It will need another TGorillaModel component as template and will perform an instancing onto the selected terrain.

This means all instances will automatically be adjusted to the shape of the terrain.

When clicking the “Planting” option a new dialog will open where you can configure some settings for the planting algorithm.

Configuration

The algorithm will create instances for all meshes inside the selected template / source model.

Basically the algorithm splits the terrain into cells for more realistic placement.

Setting Description
Clear Instances Clears all previously available instances in the source.
Minimum Scale If “Random Scaling” is activated, this is the lowest limit for scaling.
Instance Scale A basis scaling of each instance (will be multiplied with source scale if “Apply Source Transformation” is activated.
Space Adjustment between cell-center and source size.
Padding Increasing this value will compress cells for planting. Objects will be placed closer together.
Random Y-Rotation This is not suitable for all kind of source models. Depending on the internal transformation of submeshes.
Random Scaling This will randomly scale instances with limitations given by “Minimum Scale”.
Apply Random Grid-OffsetTerrain is splitted into equal size grid cells. To produce a more realistic look, you can add some random offset to the cell-center.
Apply Source TransformationIt will apply the transformation of the owner model. This is not suitable for all kind of models, depending on the internal transformation of submeshes.
Count The number of instances that should be created. This should be adjusted to the GPU you are using and the outcome you expect.

Source Models

The planting algorithm is straight forward and treats all submeshes inside the source model equaly on creating instances.

Therefore it can produce unexpected results.

The source model should contain a flat hierarchy without or less transformation of sub-meshes.

NOTICE: The applied instance transformation is absolute and not relative to the source model!

Runtime

From Heightmap

Form1.pas
uses
  Gorilla.Terrain,
  Gorilla.Material.Lambert;
 
procedure TForm1.FormCreate(Sender: TObject);
var LTexturePath : String;
begin
  LTexturePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
 
  FTerrain := TGorillaTerrain.Create(fGorilla);
  FTerrain.Parent := FGorillaViewport;
 
  // set resolution of terrain to 256 x 256 sections
  // this generates 65.536 cells with 131.072 triangles and 393.216 vertices.
  FTerrain.ResolutionX := 256;
  FTerrain.ResolutionY := 256;
 
  // here we load the height map image
  FTerrain.HeightMap.LoadFromFile(LTexturePath + 'terrain-h.jpg');
 
  // adjust terrain size and scaling
  FTerrain.Scale.X := 100;
  FTerrain.Scale.Y := 10;
  FTerrain.Scale.Z := 100;
 
  // build terrain mesh from previously loaded heightmap
  // 1st param: static buffering for large number of vertices.
  // 2nd param: decimation disabled
  FTerrain.RebuildTerrain(true, false);
 
  // apply a material as texture to it
  FTerrainMaterial := TGorillaLambertMaterialSource.Create(FTerrain);
  FTerrainMaterial.Parent := FTerrain;
  FTerrainMaterial.Texture.LoadFromFile(LTexturePath + 'terrain-c.jpg');
  FTerrain.MaterialSource := FTerrainMaterial;
end;

Procedural Generation

Form1.pas
uses
  Gorilla.Terrain,
  Gorilla.Material.Lambert;
 
procedure TForm1.FormCreate(Sender: TObject);
var LTexturePath : String;
begin
  LTexturePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
 
  FTerrain := TGorillaTerrain.Create(fGorilla);
  FTerrain.Parent := FGorillaViewport;
 
  // set resolution of terrain to 256 x 256 sections
  // this generates 65.536 cells with 131.072 triangles and 393.216 vertices.
  FTerrain.ResolutionX := 256;
  FTerrain.ResolutionY := 256;
 
  // adjust terrain size and scaling
  FTerrain.Scale.X := 100;
  FTerrain.Scale.Y := 10;
  FTerrain.Scale.Z := 100;
 
  // build a random terrain by a predefined procedural algorithm
  FTerrain.RandomTerrain(TRandomTerrainAlgorithmType.DiamondSquare);
 
  // apply a material as texture to it
  FTerrainMaterial := TGorillaLambertMaterialSource.Create(FTerrain);
  FTerrainMaterial.Parent := FTerrain;
  FTerrainMaterial.Texture.LoadFromFile(LTexturePath + 'terrain-c.jpg');
  FTerrain.MaterialSource := FTerrainMaterial;
end;

NOTICE: Once you build a random terrain, you are able to store the heightmap bitmap and reload later.

Terrain-Algorithms

Algorithm Notice
Hill A basic procedural hill algorithm. The algorithm will produce smooth hills by radius settings and a given count.
DiamondSquare A very popular algorithm to build random terrain. The algorithm creates randomly lows and highs for a realisic terrain.
Mandelbrot Creates the typical mandelbrot pattern: https://en.wikipedia.org/wiki/Mandelbrot_set This is a fixed result, but you could use this as basis for further computation.
PerlinNoise Perlin noise terrains are a good choice for random terrain. The component provides different mathmatical interpolation methods (linear, cosine, cubic).
Plateau A plateau terrain is described by a specific number of high and flat areas, while the rest is much lower. The algorithm extends the TDiamondSquareTerrain.
Brownian Brownian terrains or brownian surface is based on the diamond square based terrain algorithm: https://en.wikipedia.org/wiki/Brownian_surface The component computes peaks by a specific number of random particles. Afterwards the complete terrain will be smooth to create a realistic landscape.

Creating an individual procedural terrain algorithm

You can also develop your own procedural algorithm by extending TRandomTerrainAlgorithm or any descendant. In the example below, we generate a random terrain:

MyTerrainAlg.pas
type
  TMyTerrainAlgorithm = class(TRandomTerrainAlgorithm)
    protected
      procedure Generate();
    public
      function GetHeightMap() : TBitmap; override;    
  end;  
 
{ TMyTerrainAlgorithm }
 
 
procedure TMyTerrainAlgorithm.Generate();
var x, z: Integer;
       i : Integer;
begin
  System.SetLength(FData, 256);
  for i := 0 to High(FData) do
    System.SetLength(FData[i], 256);
 
  for x := 0 to 255 do
    for z := 0 to 255 do
    begin
      FData[x, z] := Random(100) / 100;
    end;
end;
 
function TMyTerrainAlgorithm.GetHeightMap() : TBitmap;
begin
  Generate();
 
  result := inherited;
end;
 
LMyTerrainAlgorithm := TMyTerrainAlgorithm.Create();
try
  FTerrain.RandomTerrain(LMyTerrainAlgorithm);
finally
  FreeAndNil(LMyTerrainAlgorithm);
end;

Resolution

It is recommend to use 2 ^ X resolution sizes for your terrain. Set resolution by the published properties “ResolutionX” and “ResolutionY”.

The table below lists common terrain sizes and their resulting vertices.

Size Vertex-Count Index-Count Triangles Memory-Size
16 x 16 289 1536 512 26.952 Bytes
32 x 32 1089 6144 2048 102.984 Bytes
64 x 64 4225 24.576 8192 402.504 Bytes
128 x 128 16.641 98.304 32.768 1.591.368 Bytes
256 x 256 66.049 393.216 131.072 6.328.392 Bytes
512 x 512 263.169 1.572.864 524.288 25.239.624 Bytes
1024 x 1024 1.050.625 6.291.456 2.097.152 100.810.824 Bytes
2048 x 2048 4.198.401 25.165.824 8.388.608 402.948.168 Bytes

Notice: When using terrain on Android, remember the 16-Bit vertex and index limitation. You are allowed to use at max 65536 indices per mesh on Android systems.

Smoothing

In case you are using a height-map smaller than your terrain-resolution, the resulting terrain could show some unlovely steps. Therefore the component provides the published “Smoothing” property. Set a value between 1 and 20 to apply smoothing algorithm onto your heightmap. A value of zero means that smoothing is deactivated.

Decimation

Due to optimization reasons the component provides an experimental decimation algorithm.

// 1st parameter - static buffering of vertex data
// 2nd parameter - decimation algorithm execution
FTerrain.RebuildTerrain(true, >>>true<<<);

Generating a procedural terrain by algorithm, activate decimation like this:

// 1st parameter - type of terrain algorithm
// 2nd parameter - static buffering of vertex data
// 3rd parameter - decimation algorithm execution
FTerrain.RandomTerrain(TRandomTerrainAlgorithmType.DiamondSquare, true, >>>true<<<);

Next step: Skybox