jonrob.net



Game Engine Devlog Part 3 - Terrain and tooling

I've been doing backend engine development for a while now with little resembling a game to show for it, so this week I've implemented terrain generation which will be the foundation of a city building game. I also made some improvements to the build process to speed up development and to help improve code quality.

Terrain

Previously the only polygons that I've constructed as opposed to being loaded in from a geometric definition file have been for the UI elements and that's not really appropriate here. So I spent an hour brainstorming all the information I need for each vertex, a reasonable way to access that, and then created some data structures to contain it, having this plan in place made implementation fairly easy.

I've split the world into "quads" which each consist of 16x16 "cells", each cell is made up of 5 vertices, originally I was going to use 4 vertices per cell but when adjusting their height I realised some extra work is required to avoid a polarised world as in image [2] where the leftmost square starts ramping up from the middle of the cell and all cells ramping from the near right to the far left have a ramp that encompasses the entire cell, this could have been made to work by changing which vertices make up each triangle based on their height, instead I avoid the problem entirely by putting a vertex in the middle of each cell with a height that is the mean of it's 4 surrounding vertices.

The quad system exists for easy memory management, there is a pool of unused quads to pull from when adding more, and then they are placed in a lookup table for quick retrieval.

After implementing the above, it was just a case of implementing some primitives for creating and manipulating the environment then manipulating vertex heights with some Simplex noise. Currently I'm using 5 octaves of Simplex noise, the individual octaves are shown in images [4][5][6][7][8] and they are added together to create the final terrain map [3].

The video [1] shows quads disappearing, they remain in the vertex buffer and only what is within the drawdistance is drawn.

Shell

I've added the terrain primitives to the engines' tclsh and this let me easily test the edge cases with instant feedback without having to recompile. This is the first time I've had serious use from the shell I showcased in the last devlog and it's really sped up development so was definitely worth implementing.

Compilers

The project has exceeded 12k lines of code now, which isn't a massive number, but with that the compile time is also going up. Here are the times for a full recompile:

Compiler Time
Clang 18917ms
GCC 16027ms
Visual Studio 16095ms

Whilst I don't need to recompile everything everytime, it is still taking around 3 seconds to compile and link small changes and since I'm figuring out a lot of this as I go I'd like that to be as quick as possible.
Instead of looking into why this takes so long to compile I decided to add support to the project for another compiler, TCC, they claim it can compile the Links browser 9x faster than GCC. It took a few hours to get this working, mostly because I couldn't get it to link the project so won't be able to use it as a C interpreter, but it was definitely worth it for this full project compile time:

Compiler Time
TCC 00514ms

That's a 36X speedup from Clang, and a 31x speedup on GCC and Visual Studio. Success!

Static Code Analysis

I've started using splint, at first it was daunting since it threw out 4k+ warnings with the -weak flag, but I've been through the report, and it made some valid points. I'll be continuing to use this and intend to start using it earlier on in future projects.

I also started using the Clang static analyser "scan-build", this is also really good and something I intend to use earlier on in future projects

(1) Terrain generation demo

(2) Polarised world

(3) Assembled terrain

(4) Lowest frequency, highest amplitude terrain component

(5) Low-mid frequency, hid-mid amplitude terrain component

(6) Mid frequency, mid amplitude terrain component

(7) Mid-high frequency, mid-low amplitude terrain component

(8) Highest frequency, lowest amplitude terrain component