API ReferenceGE Extensionsutil
Procedural Track (Gymkhana Generator)
Generates randomized gymkhana / autocross tracks from seed-based procedural parameters.
Generates randomized gymkhana / autocross tracks from seed-based procedural parameters.
Overview
util_procTrack creates complete procedural gymkhana tracks by subdividing rectangles into node graphs, finding Hamiltonian paths, generating winding roads with curves and gates, and spawning all game objects (DecalRoads, pylons, gates, waypoints). Tracks are fully deterministic given a seed.
Extension path: lua/ge/extensions/util/procTrack.lua
Exports (M)
| Function | Signature | Description |
|---|---|---|
getDefaultParams | () → table | Returns a fresh default parameter table for gymkhana generation. |
makeGymkhana | (params) | Main entry point - generates a complete track from params. |
reGenerate | (seed) | Re-generates the track with a new seed, preserving scenario/populate/after functions. |
checkParams | () | Validates and fills in missing params (seed, node count, density). |
makeBaseNodePositions | () → graph | Creates the base node graph via rectangle subdivision. |
makePath | (graph) → path|nil | Finds a Hamiltonian path through the graph using DFS + backtracking. |
createWindingPath | (path) → nodes | Computes winding road geometry (arcs, angles, radii) around path nodes. |
createWindingRoad | (nodes) | Spawns DecalRoad objects for the track surface. |
createPylons | (nodes) | Spawns pylons, circles, barrels, gates as visual markers. |
decorateStartAndFinish | (nodes) | Places start/finish gate decorations. |
createWaypointsForScenario | (nodes) | Creates BeamNGWaypoint objects and configures scenario lap config. |
getSeed | () → number|nil | Returns the current track seed. |
intToWords | (int) → string | Converts a seed integer to a human-readable word string. |
wordsToInt | (word) → number | Converts a word string back to a seed integer. |
Path-Finding Internals (exported to M during generation)
| Function | Signature | Description |
|---|
Utility Exports
| Function | Signature | Description |
|---|---|---|
dist | (a,b,x,y) → number | 2D Euclidean distance. |
getPosition | (x,y,z) → {x,y,z} | Transforms local coords to world coords using root position/angle. |
getRotationDeg | (deg) → number | Transforms local angle to world angle in degrees. |
makePylon | (pos, size, rot, skin) | Spawns a barrier segment TSStatic. |
makeGate | (pos, rot) | Spawns a gate TSStatic. |
makeConcreteRing | (pos, radius) | Spawns a scaled concrete ring TSStatic. |
makeBarrel | (pos, rot, skin) | Spawns a barrel marker TSStatic. |
Internals
Generation Pipeline
- checkParams - seeds RNG, calculates node count from area/density, loads
util/rectangleGen. - makeBaseNodePositions - calls
rectangleGen.getGraph()to subdivide rectangles into a graph with neighbor info. - makePath - depth-first search with backtracking for a Hamiltonian path (NP-complete; uses heuristic limits).
- createWindingPath - computes angles, radii, loop/gate decisions, arc geometry using the belt problem.
- createWindingRoad - emits TorqueScript to create DecalRoad objects.
- createPylons - emits pylons, circles, barrels, gates as TSStatic objects.
- createWaypointsForScenario - sets up BeamNGWaypoint nodes and scenario lap configuration.
Key Parameters
| Parameter | Default | Description |
|---|---|---|
rootX/Y/Z | 240/-20/34.35 | World origin of the track. |
rootAngleRad | 0 | Rotation of the entire track. |
rectModeParams.density | 0.85 | Nodes per 1000m². |
rectModeParams.minNodes | 6 | Minimum node count. |
rectModeParams.maxNodes | 27 | Maximum node count. |
path.loopChance | 0.75 | Chance of a curve becoming a loop-around. |
path.gateChance | 0.8 | Chance of a straight becoming a gate. |
path.closed | false | Whether to create a closed circuit. |
Seed Word Encoding
Seeds are encoded/decoded using a 500-word list, giving ~62.5 billion unique tracks.
How It Works
- Call
makeGymkhana(params)with custom or default parameters. - The system subdivides the arena into rectangles, places nodes at their centers.
- A path is found through all nodes (Hamiltonian path via DFS).
- Winding road geometry is computed using belt-problem math for smooth curves.
- TorqueScript spawns all game objects into a
GymkhanaArenaSimGroup. - Waypoints are created for scenario integration.
Lua Examples
-- Generate a gymkhana track with default params
local params = extensions.util_procTrack.getDefaultParams()
params.seed = 12345
extensions.util_procTrack.makeGymkhana(params)
-- Re-generate with a new seed
extensions.util_procTrack.reGenerate(67890)
-- Convert seed to/from words
local words = extensions.util_procTrack.intToWords(12345)
local seed = extensions.util_procTrack.wordsToInt(words)Additional Exports
M.checkParams- (undocumented)M.createPylons- (undocumented)M.createWaypointsForScenario- (undocumented)M.createWindingPath- (undocumented)M.createWindingRoad- (undocumented)M.currentEdgeNotOK- (undocumented)M.decorateStartAndFinish- (undocumented)M.determineInOutAngle- (undocumented)M.dist- (undocumented)M.edgeCreatesSplitGraph- (undocumented)M.getBaseInformationFromPath- (undocumented)M.getDefaultParams- (undocumented)M.getPathRoadNodes- (undocumented)M.getPosition- (undocumented)M.getRotationDeg- (undocumented)M.getSeed- (undocumented)M.intToWords- (undocumented)M.isInList- (undocumented)M.makeBarrel- (undocumented)M.makeBaseNodePositions- (undocumented)M.makeConcreteRing- (undocumented)M.makeGate- (undocumented)M.makeGymkhana- (undocumented)M.makePath- (undocumented)M.makePylon- (undocumented)M.reGenerate- (undocumented)M.wordsToInt- (undocumented)