Physics · function

hullShape

The convex hull of a point cloud, with its separating features enumerated.

Explained in Your first game, Rigid bodies.

function hullShape(points: ArrayLike<number>, radius?: number): ConvexShape
import { hullShape } from '@driftengine/physics';

Parameters

ParameterTypeDescription
pointsArrayLike<number>
radius?number

In depth

Brute force by design: every point triple proposes a plane, and a plane with every point on one side is a face. Edges are point pairs lying on two distinct faces. No incremental hull, no floating-point pivoting — the same input yields the same features in the same order on every machine, which the replay contract needs from anything that feeds collision.

Every length here is Math.sqrt of a sum of squares rather than Math.hypot, and that is what makes the sentence above true rather than merely intended. ECMAScript declines to specify hypot precisely, so two engines may differ by an ulp — and an ulp here is not a slightly different axis. proposePlane's normal classifies every point against COPLANAR_M, so it decides whether a plane becomes a face at all; appendDirection's is compared against DIR_DEDUP, so it decides how many separating axes exist and in what order. SAT then takes a minimum over that list.

hypot is the more accurate of the two, guarding against intermediate overflow at magnitudes a collision shape does not reach. What would make this wrong is a shape built at astronomical or atomic scale, where that guard is worth more than the reproducibility; the answer then is an explicit rescale rather than the call back. Asserted by scripts/determinism.test.mjs.