Terrain and Object Generation
C++
Overview
I wanted to create a system that could take a height map and populate it with objects, allowing a user to generate a map and fill it with something like trees quickly
Terrain Generation
The first thing I needed was terrain for my objects to generate on. I created a perlin noise generator to generate a heightmap, then created a simple mesh with a vertex at each point along the heightmap. However, this resulted in fairly smooth terrain, which I wanted to be more extreme for testing, so I created a simple random-walk generator, which would also create a heightmap.
Perlin Noise
Random Walk
Object Generation
Poisson disc distribution
To distribute the objects evenly, I used a Poisson disc distribution. The program starts by creating an object at a random position, and adding it to its list of objects. It will then attempt to spawn a certain number of new objects around the original, and if it succeeds, those objects will be added to the list. This process repeats until the end of the list is reached.
For each spawn attempt, the program will choose a random position in a ring around the original object’s position, and see if that spot meets the object's spawn conditions (see Spawn Conditions). If it does, the program will check if the new object is colliding with any of the existing objects, and if no collisions are detected, the attempt will succeed.
This continues until there are no more objects in the list, at which point the list is returned.
Spawn conditions
One of the primary things I wanted to accomplish was making sure objects would fit in with their surroundings, such as by making sure they wouldn't clip into the terrain too much. To do this, I added settings that could be tweaked when spawning an object to determine what terrain it should be allowed to spawn on.
One of these conditions was how much the object overlapped the ground, and where the overlap should start/ end. When spawning an object, the program would get the height range of the area it was spawning, and see if the object could be spawned at a position where the anything above the overlap max would be above ground, and anything below the overlap min would be below ground.
Initially, this could be checked fairly easily looking at the height map of the area. However, it became more complicated when I began implementing rotation
Overlap preview (Red is min, blue is max)
As part of this, I wanted to implement a system to make objects detect the slope of the surface they were on and try to match it, or not spawn if the slop was too steep.
To do this, I used an “Ordinary Least Squares” approximation, which is used to determine the line of best fit for a collection of points. This approximation is normally just used for points in 2D space though, so to get it to work with the 3D slope, I calculated the x slope & z slope separately, then combined them for the final rotation.
This also