buildBarrierMeshes function

List<MeshData> buildBarrierMeshes(
  1. TrackSpline track, {
  2. required int side,
  3. RoadMeshSettings settings = const RoadMeshSettings(),
  4. 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;
}