A Catmull-Rom path
Open the live demo · Read the source · View on GitHub
A cubic spline is naturally parameterised by a number that runs one unit a
segment, and that number moves at a different speed everywhere along the
curve. CatmullRom measures the curve once when it is built and takes
distance in metres everywhere after that, which is what anything driving
along a track actually wants.
Step 1: Build a closed loop #
Four points, a little over a metre from the centre, joined into a loop.
late final CatmullRom _track = CatmullRom(<Vector3>[
Vector3(1.2, 0, 0),
Vector3(0, 0, 1.2),
Vector3(-1.2, 0, 0),
Vector3(0, 0, -1.2),
]);
Step 2: Sample it by distance #
sampleAt writes the point a given distance along the curve into a vector.
wrap brings a distance back into range, looping past the end of a closed
curve instead of clamping.
@override
void update(DemoContext context, double dt) {
distance = _track.wrap(distance + dt * 2.0);
_track.sampleAt(distance, _point);
_car.setPositionFrom(_point);
}
The car on this page advances two metres a second along the loop, wrapping back to the start once it has gone all the way round.
Step 3: Check it closes #
// A closed loop through four points three metres from the centre comes
// back to its own start.
final start = Vector3.zero();
_track.sampleAt(0.0, start);
final afterALap = Vector3.zero();
_track.sampleAt(_track.length, afterALap);
final gap = (start - afterALap).length;
Sampling at zero and at the curve's own length gives the same point, because a closed curve is exactly that: one loop, with no seam to fall off of.