MeshRoad is a spline-based road object that generates real mesh geometry from nodes.
Use it when the road needs actual thickness, side faces, bridges, ramps, or geometry that is not just a decal projected onto terrain.
For painted road surfaces, markings, AI paths, and terrain-projected roads, DecalRoad is usually the better first choice.
A simple MeshRoad entry in items.level.json:
{
"class": "MeshRoad",
"name": "bridge_meshroad_01",
"__parent": "MissionGroup",
"topMaterial": "road_asphalt",
"bottomMaterial": "road_concrete",
"sideMaterial": "road_concrete",
"textureLength": 8,
"breakAngle": 3,
"widthSubdivisions": 0,
"nodes": [
[0, 0, 5, 8, 0.5, 0, 0, 1],
[40, 0, 5, 8, 0.5, 0, 0, 1],
[80, 10, 7, 8, 0.5, 0, 0, 1]
]
}
Each node is stored as:
[x, y, z, width, depth, normalX, normalY, normalZ]
| Field | Type | Description |
|---|---|---|
class |
string | Must be "MeshRoad". |
name |
string | Scene object name. |
__parent |
string | Parent group. |
topMaterial |
string | Material for the upper road surface. |
bottomMaterial |
string | Material for the underside. |
sideMaterial |
string | Material for side, front, and back faces. |
textureLength |
number | Length in meters before the material repeats along the road. |
breakAngle |
number | Angle threshold in degrees used when generating road slices from the spline. |
widthSubdivisions |
integer | Number of widthwise subdivisions for generated vertices. |
nodes |
array | Ordered node list. Each node is [x, y, z, width, depth, normalX, normalY, normalZ]. |
MeshRoad stores its shape as an ordered list of nodes.
Example:
"nodes": [
[0, 0, 5, 8, 0.5, 0, 0, 1],
[40, 0, 5, 8, 0.5, 0, 0, 1],
[80, 10, 7, 8, 0.5, 0, 0, 1]
]
Each node contains:
| Index | Meaning |
|---|---|
0 |
X position |
1 |
Y position |
2 |
Z position |
3 |
Road width |
4 |
Road depth/thickness |
5 |
Normal X |
6 |
Normal Y |
7 |
Normal Z |
The road mesh is generated between consecutive nodes.
MeshRoad nodes like DecalRoad nodes. MeshRoad nodes include depth and normal data.In the World Editor, create a MeshRoad when you need generated road geometry instead of a projected road decal.
Typical workflow:
MeshRoad object.topMaterial, bottomMaterial, and sideMaterial.textureLength, breakAngle, and widthSubdivisions.Use fewer, well-placed nodes for smooth roads. Add nodes where the road must intentionally change direction, width, depth, height, or banking.
MeshRoad ignores normal object scale edits. Use nodes, width, depth, and generated geometry settings to shape the road.MeshRoad does not connect nodes with straight mesh spans directly.
When regenerated, the engine:
CatmullRom<MeshRoadSplineNode> spline from those nodes.This means the centerline, width, depth, and normal are all interpolated along the spline.
The smoothing algorithm is Catmull-Rom interpolation.
The engine builds a spline using the author nodes:
position + width + depth + normal
For each node span, it evaluates the spline and measures the approximate span length. The span is sampled into smaller steps before deciding where final road slices should be placed.
Catmull-Rom interpolation gives smooth curves through the control nodes. It is convenient for road authoring, but it also means tight or uneven node spacing can create unwanted bends or overshoot.
Good authoring practice:
breakAngle controls how many generated slices are kept from the sampled spline.
During generation, the engine compares the current sampled direction with the direction at the last kept slice. A new slice is kept when:
breakAngle.Example:
"breakAngle": 3
Lower values create more slices and smoother generated geometry, especially on curves.
Higher values create fewer slices, which can reduce geometry but may make curves more angular.
breakAngle values can increase generated vertices, triangles, collision data, and editing cost. Use the lowest value that gives the required visual and driving smoothness.Each generated slice gets a local frame:
| Vector | Meaning |
|---|---|
fvec |
Forward direction along the road. |
rvec |
Right direction across the road width. |
uvec |
Up direction from the node/spline normal. |
The engine uses the slice normal and neighboring slice positions to calculate these vectors.
It then computes:
| Point | Meaning |
|---|---|
p1 |
Center point of the road slice. |
p0 |
Top-left edge point. |
p2 |
Top-right edge point. |
pb0 |
Bottom-left edge point. |
pb2 |
Bottom-right edge point. |
Width expands from the center along rvec. Depth extends downward along uvec.
If normals are inconsistent, the generated frame can twist. This is the most common cause of banking or side-face artifacts on generated mesh roads.
widthSubdivisions adds extra vertices across the top surface width.
Example:
"widthSubdivisions": 2
The top surface uses:
2 + widthSubdivisions
vertices per slice.
This can help wide roads or banked sections shade and deform more smoothly across their width. It also increases vertex and triangle count.
Bottom and side surfaces are not subdivided widthwise in the same way as the top surface.
textureLength controls the V coordinate along the road.
During vertex generation, the engine measures distance between consecutive slices and increments the texture coordinate by:
sliceDistance / textureLength
Example:
"textureLength": 8
Lower values make the texture repeat more often. Higher values stretch the texture over longer road distance.
| Use case | Recommended class |
|---|---|
| Road marking or surface projected onto terrain | DecalRoad |
| AI/navigation path data | DecalRoad |
| Bridge deck with visible sides | MeshRoad |
| Raised ramp or custom road geometry | MeshRoad |
| Road on existing mesh with decal material | DecalRoad with overObjects |
MeshRoad creates geometry. DecalRoad renders a decal on existing geometry.
MeshRoad can use three separate materials:
"topMaterial": "road_asphalt",
"bottomMaterial": "road_concrete",
"sideMaterial": "road_concrete"
Materials should tile cleanly along the road length.
textureLength controls how often the material repeats:
"textureLength": 8
For tools that generate roads:
breakAngle instead of blindly adding excessive author nodes.DecalRoad if the output is only a projected visual road.MeshRoad when generated geometry, thickness, or bridge-like behavior is required.textureLength is too large.sideMaterial or bottomMaterial is missing.DecalRoad format instead of the eight-value MeshRoad format.breakAngle is too high.breakAngle is too low or node spacing is excessive.See also: DecalRoad
, Material file format
, Navigation map (map.json)
, Level object files (items.level.json)
.
Was this article helpful?