map.lua - Navigation Graph (AI Road Map)
Reference for `map.lua`. Builds and maintains the navigation graph (navgraph) used by AI traffic, GPS routing, and mission waypoints. Loads road data from DecalRoads and manual waypoints, then process
Reference for map.lua. Builds and maintains the navigation graph (navgraph) used by AI traffic, GPS routing, and mission waypoints. Loads road data from DecalRoads and manual waypoints, then processes it into a connected graph.
Key Exports
| Key | Signature | Description |
|---|---|---|
objects | table | Map objects cache |
objectNames | table | Map object names |
M.assureLoad | () | (No description available) |
M.debugDrawTrajectory | (trajectory) | (No description available) |
M.findBestRoad | (pos, dir) | (No description available) |
M.findClosestRoad | (pos, searchRadiusLim) | find road (edge) closest to "position" and return the nodes ids (closestRoadNode1, closestRoadNode2) of that edge and distance to it. |
M.getGraphpath | () | (No description available) |
M.getManualWaypoints | () | (No description available) |
M.getMap | () | (No description available) |
M.getNodeLinkCount | (nId) | (No description available) |
M.getNodesFromPathDist | (path, dist) | (No description available) |
M.getPath | (start, target, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff) | (No description available) |
M.getPathLen | (path) | (No description available) |
M.getPointNodePath | (start, target, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff, wZ) | (No description available) |
M.getPointToPointPath | (startPos, targetPos, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff, wD, wZ) | (No description available) |
M.getRoadRules | () | (No description available) |
M.getState | () | (No description available) |
M.getTrackedObjects | () | (No description available) |
M.isCrashAvoidable | (objectID, pos, radius) | (No description available) |
M.logGraphHashes | () | (No description available) |
M.nameNode | (prefix, idx) | (No description available) |
M.objectData | (objId, isactive, damage, states, objectCollisions) | recieves vehicle data from vehicles |
M.onAddWaypoint | (wp) | TODO: please fix these functions, so users can interactively add/remove/modify the waypoints in the editor and directly see changes. |
M.onDeserialize | (s) | (No description available) |
M.onFilesChanged | (files) | (No description available) |
M.onMissionLoaded | () | (No description available) |
M.onModifiedWaypoint | (wp) | (No description available) |
M.onRemoveWaypoint | (wp) | (No description available) |
M.onSerialize | () | (No description available) |
M.onWaypoint | (args) | (No description available) |
M.optimizePath | (path, s, useRawPos) | (No description available) |
M.request | (objId, objbuildSerial) | (No description available) |
M.safeTeleport | (vehId, posX, posY, posZ, rotX, rotY, rotZ, rotW, checkOnlyStatics_, visibilityPoint_, removeTraffic_, centeredPosition, resetVehicle) | (No description available) |
M.saveSVG | (filename, includeLinks, includeNodes) | (No description available) |
M.setEditorState | (enabled) | (No description available) |
M.setNameForId | (name, id) | (No description available) |
M.setState | (newState) | (No description available) |
M.surfaceNormal | (p, r) | (No description available) |
M.tempObjectData | (objId, isactive, pos, vel, dirVec, dirVecUp, damage, objectCollisions) | used to add explicit vehicle data |
M.toggleDrawNavGraph | () | (No description available) |
M.toggleShuffledPairs | (mode) | for debugging issues in the deterministic build of the navgraph |
M.updateDrivabilities | (changeSet) | (No description available) |
M.updateGFX | (dtReal, dtSim) | (No description available) |
M.drawNavGraphState | variable | (No description available) |
M.load | variable | (No description available) |
M.objectNames | variable | (No description available) |
M.reset | variable | (No description available) |
Graph Building (internal, called via hooks)
The module exposes many internal functions through M but the primary public interface is through lifecycle hooks:
onMissionLoaded()- triggers full navgraph buildupdateGFX(dtReal, dtSim)- per-frame updateonFilesChanged(files)- hot-reload on file changesassureLoad()- ensures map is loadedonWaypoint(args)- waypoint trigger callback
Internals
Graph Structure
map.nodes = {
["nodeName"] = {
pos = vec3, -- world position
radius = number, -- road half-width
links = { -- connections to other nodes
["otherNode"] = {
drivability = number, -- 0-1 surface quality
hiddenInNavi = bool, -- hidden from GPS
oneWay = bool, -- directional road
lanes = string, -- lane config e.g. "--++"
speedLimit = number, -- m/s (nil = auto)
inNode = string, -- direction: traffic flows inNode → outNode
outNode = string,
inPos = vec3, -- edge endpoint positions (may differ from node pos)
outPos = vec3,
inRadius = number, -- edge endpoint radii
outRadius = number,
type = string, -- 'private', nil, etc.
noMerge = bool, -- prevent junction merging
}
},
manual = number, -- 1 if BeamNGWaypoint
noMerge = bool, -- prevent merging
endNode = bool, -- road endpoint
junction = bool, -- merged junction node
}
}Road Data Sources
- DecalRoads: Scene objects with
drivability > 0. Can use subdivision edges or control points. - BeamNGWaypoints: Manual waypoints placed in the editor.
- map.json: Level-specific manual road segment definitions connecting waypoints.
Lane Configuration
+= forward direction (inNode → outNode)-= reverse direction"--++"= 2 lanes each way (left-hand drive)- Right-hand drive swaps lane order
flipLanes()reverses the string for bidirectional edges
Graph Processing Pipeline
- Load -
loadJsonDecalMap()reads DecalRoads, waypoints, and map.json - Merge overlapping nodes - nodes within radius are merged
- Resolve T-junctions - dead-end roads are connected to nearby crossing roads
- Resolve X-junctions - crossing roads get intersection nodes
- Speed limits - auto-calculated from road radius and drivability
- Build spatial indices - kd-trees for edge and node queries
Spatial Indexing
- edgeKdTree: 2D kd-tree of all edges for fast closest-edge queries
- nodeKdTree: 2D kd-tree of all nodes
- Uses
kdTreeBox2Dandquadtreefor spatial queries
Deterministic Building
- Graph hashing via
hashNodeData()andhashEdgeData()for build verification - Optional shuffled pairs iteration for determinism testing
- Careful use of sorted lists and
safeVecSumfor floating-point reproducibility
How It Works
The navgraph is built when a level loads (onMissionLoaded). It reads all DecalRoad objects and BeamNGWaypoint objects from the scene, constructs a graph, then processes it through several refinement passes (overlap merging, junction resolution). The resulting graph supports pathfinding via graphpath and spatial queries for AI navigation.
-- Map is loaded automatically, but can be forced:
map.assureLoad()
-- The graph is accessible (read-only recommended) via internal state
-- AI systems use map functions for pathfinding and closest-road queriesExported Variables
drawNavGraphState- Exported variable - initialized as'off'warnedMapBackwardCompatibility- Exported variable - initialized astrue
Additional Functions
debugDrawTrajectory(trajectory)
(No description available)
findBestRoad(pos, dir)
(No description available)
- Returns:
bestRoad1, bestRoad2, math.sqrt(bestDist)
findClosestRoad(pos, searchRadiusLim)
this is also in vehicle/mapmgr.lua find road (edge) closest to "position" and return the nodes ids (closestRoadNode1, closestRoadNode2) of that edge and distance to it.
getGraphpath()
(No description available)
- Returns:
gp
getManualWaypoints()
(No description available)
- Returns:
manualWaypoints
getMap()
(No description available)
- Returns:
map
getNodeLinkCount(nId)
(No description available)
getNodesFromPathDist(path, dist)
(No description available)
getPath(start, target, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff)
(No description available)
getPathLen(path)
(No description available)
getPointNodePath(start, target, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff, wZ)
(No description available)
getPointToPointPath(startPos, targetPos, cutOffDrivability, dirMult, penaltyAboveCutoff, penaltyBelowCutoff, wD, wZ)
(No description available)
getRoadRules()
(No description available)
- Returns:
rules or {}
getState()
(No description available)
- Returns:
M
getTrackedObjects()
(No description available)
- Returns:
M.objects
isCrashAvoidable(objectID, pos, radius)
(No description available)
logGraphHashes()
(No description available)
nameNode(prefix, idx)
(No description available)
- Returns:
nodeName
objectData(objId, isactive, damage, states, objectCollisions)
recieves vehicle data from vehicles
onAddWaypoint(wp)
TODO: please fix these functions, so users can interactively add/remove/modify the waypoints in the editor and directly see changes.
onDeserialize(s)
(No description available)
onModifiedWaypoint(wp)
(No description available)
onRemoveWaypoint(wp)
(No description available)
onSerialize()
(No description available)
- Returns:
{isEditorEnabled, buildSerial}
optimizePath(path, s, useRawPos)
(No description available)
request(objId, objbuildSerial)
(No description available)
reset()
(No description available)
safeTeleport(vehId, posX, posY, posZ, rotX, rotY, rotZ, rotW, checkOnlyStatics_, visibilityPoint_, removeTraffic_, centeredPosition, resetVehicle)
(No description available)
saveSVG(filename, includeLinks, includeNodes)
(No description available)
setEditorState(enabled)
(No description available)
setNameForId(name, id)
(No description available)
setState(newState)
(No description available)
surfaceNormal(p, r)
(No description available)
- Returns:
p3
tempObjectData(objId, isactive, pos, vel, dirVec, dirVecUp, damage, objectCollisions)
used to add explicit vehicle data
toggleDrawNavGraph()
(No description available)
toggleShuffledPairs(mode)
for debugging issues in the deterministic build of the navgraph
updateDrivabilities(changeSet)
(No description available)
main.lua - GE Lua Entry Point & Game Loop
Reference for `main.lua`. The root entry point for the Game Engine Lua VM - sets up the runtime environment, loads core modules, defines the main update loop, and handles all lifecycle callbacks from
screenshot.lua - Screenshot System
Reference for `screenshot.lua`. Handles screenshot capture, metadata collection, format selection, and optional upload to BeamNG's media server.