buildBarrierMeshes function
- TrackSpline track, {
- required int side,
- RoadMeshSettings settings = const RoadMeshSettings(),
- VertexLayout? layout,
The walls, where the track says there are walls.
Built as separate strips rather than one long one, because a barrier that runs half the lap has a beginning and an end and the geometry has to as well — the alternative is a wall closing across the road at the point the band stops.
Implementation
List<MeshData> buildBarrierMeshes(
TrackSpline track, {
required int side,
RoadMeshSettings settings = const RoadMeshSettings(),
VertexLayout? layout,
}) {
// The standard layout, not a leaner one. The engine's shaders read a
// tangent and a vertex colour whether or not a mesh has anything to say
// about them, and a road built with the eight-float layout crashes the
// shadow pass reading past the end of its vertices.
final chosen = layout ?? VertexLayout.standard;
final left = side < 0;
final sign = left ? -1.0 : 1.0;
final meshes = <MeshData>[];
// One builder per run of barrier. Nulled between runs rather than reset,
// because "there is no wall here" and "there is a wall of no length" are
// different things and only one of them should produce a mesh.
MeshBuilder? current;
var previousTop = -1;
var previousBottom = -1;
void close() {
final builder = current;
if (builder != null && builder.indexCount > 0) meshes.add(builder.build());
current = null;
previousTop = -1;
previousBottom = -1;
}
final frame = TrackFrame();
final foot = Vector3.zero();
final head = Vector3.zero();
final normal = Vector3.zero();
for (final s in _stations(track, settings)) {
if (!track.barrierAt(s, left: left)) {
close();
continue;
}
final builder = current ??= MeshBuilder(chosen);
track.frameAt(s, frame);
final lateral = sign * track.widthAt(s) / 2.0;
foot
..setFrom(frame.position)
..addScaled(frame.right, lateral);
head
..setFrom(foot)
..addScaled(frame.up, settings.barrierHeight);
// Facing the road, so the side a car sees is the side that is lit.
normal
..setFrom(frame.right)
..scale(-sign);
final v = s / settings.metresPerTile;
final bottom = builder.addVertex(
position: foot,
normal: normal,
texcoord: Vector2(v, 1.0),
);
final top = builder.addVertex(
position: head,
normal: normal,
texcoord: Vector2(v, 0.0),
);
if (previousBottom >= 0) {
if (left) {
builder.addQuad(previousBottom, bottom, top, previousTop);
} else {
builder.addQuad(previousBottom, previousTop, top, bottom);
}
}
previousBottom = bottom;
previousTop = top;
}
close();
return meshes;
}