Procedural engine for sim racing track generation: The basic roadmap

As we have previously seen, Voronoi has been chosen as starting point for our engine. There is a very trivial and powerful reason for this choice: Voronoi cells make the design of the tracks natural and realistic.

Voronoi is able to imitate several complex and/or natural textures. The same roads and terrains which have generated tracks can be built procedurally with those mathematical techniques.

Camilla will also use Voronoi to generate city race tracks.
Camilla will also use Voronoi to generate city race tracks.

Camilla will also use Voronoi to generate city race tracks. Playing with the initial distribution of the points, we can be able to create textures and weavings of variable density and geometry: big, small and jagged cells. We can have all these features in a unique map, creating the background for a realistic race track.

 

Variation of weavings and cell density.
Variation of weavings and cell density.

 

Camilla

Camilla, our procedural engine, is composed by several logical layers. Each one of them is independently managed, allowing us for a smoother code management and a better control on its parts.

camilla

Layer 1, the lowest level layer, creates a raw map that will be enhanced by higher level layers.

Layer 1
Layer 1

 

Camilla contains different algorithms to generate Voronoi cells. We now prefer the algorithm allowing us to better handle bendings even if it reduces variety a little bit. Layers will be alternated and mixed depending on what kind of race track (common, city, oval, etc.) we have to generate.

 

Phase 1

The algorithm generates points on the initial schematics, creating a Voronoi map similar to the pictured ones.

 

Phase 2

Taking in account some constraints such as:

  • Minimum and maximum track length
  • Minimum length of some sections
  • Minimum and maximum angles for curves
  • Number of attempts
  • (and others…)

after finding a solution for routing broken lines, the engine adds a start-finish straight in the most natural way.

The result is a track composed by broken lines, with a design really similar to the final one.

 

Phase 3

In this phase, the engine analyzes the track, recognizing the different layouts and the main types of bends.

  • Start-finish straight
  • Generic straight
  • Short and long bends
  • Zig-Zag
  • Hairpins
  • Sharp bends
  • Chicanes
  • Short straights

 

The engine recognizes each section of the track with different colors
The engine recognises each section of the track with different colors

Look at the image above to understand how the engine recognises each section of the track with different colors. This knowledge allows Camilla to make smart choices after identifying the track layout.

 

Phase 4

The track, until now, is composed by broken lines, really sharp bends and no smooth edges. This is what I believe it’s the best starting point to avoid tracks where everything is too soft. However, we need to start smoothing edges.

Each section (e.g.: the green one, recognized as a possible long bend) isn’t always converted in the same way. Depending on the seed, it can be converted into a long bend, but also in a series of left sharp bends, as it happens in the official Instanbul race track.

The same concept applies to every other section.

At this stage we also start using mathematical instruments such as splines, trying to avoid losing control. There’s a rule that works and we should apply at the end of each acknowledged layout: we have to finish with a small straight section.

At the end of Phase 4 we have a perfect map of a race track, with a perfectly designed layout.

Next time we will see how we move from this stage to what you see in the following screenshot:
Final result.
Final result.