I recently came across a tweet from Pico Tanks on where they create regions, defined by a shape, where players can hide. What stands out to me the most, is how the trees in those regions never seem to overlap. After looking more into this, I found an algorithm called Poisson disk sampling.
I got inspired by @PicoTanks Spline based object placement so I decided to try and create my own. #gamedev #madewithunity #screenshotsaturday #indiedev pic.twitter.com/fdj9jxysFT
— Cédric Van Huffelen (@Shaderic_) October 13, 2018
The reason why Poisson disk sampling produces a natural pattern is the way the points are generated. Instead of generating a random X and Y coordinate, each point is generated between a minimum and maximum distance between each other.
Before we start generating the points we have to set up all the needed inputs. The algorithm itself only
takes
in
r and k as input. r is the minimum distance between the samples and k is a
constant
which is the maximum samples before rejection. First, we initialize a 2D grid for storing the
samples.
The
cell
size of this grid is bounded by r/√n where n is the number of dimensions (2 in this
case) so that
each cell will contain at most 1 sample.
In step 1 we generate the initial sample that is randomly chosen from the domain. This sample is inserted into the grid and added to the active list, this active list holds the current samples which we generate new samples from.
After we have our initial sample, while the active list is not empty, we choose a random index from that list and generate up to k points around it. These points lay between r and 2*r distance from the current index. For each point, we check if it is between r distance from any of the samples saved in the grid and since the points are generated between r and 2*r, we can skip unnecessary checks by only checking the neighboring cells of the current index. If we found a point that is adequately far from existing samples, we save it to the grid and the active list. If after k samples, no such points are found, we remove the current index from the active list.
To know which points are inside the shape, I found a very fast and short algorithm on the Unity3D wiki.
The basic idea is to run a semi-infinite ray horizontally out from the test point and count how many edges it crosses.
At each crossing, a boolean is switched between true and false. At the end of the ray, this boolean is returned.
Poisson Disk Sampling in Arbitrary Dimensions
Poly contains point from Wiki.Unity3d