Physics · interface
TriangleMesh
A static triangle mesh as a collision shape: the triangles, their planes, and the tree over them.
Explained in Your first game, Rigid bodies.
interface TriangleMeshimport type { TriangleMesh } from '@driftengine/physics';In depth
Static only, and the limit is enforced rather than documented. PhysicsWorld.addBody refuses
one on anything but a static body and colliderFromShape refuses one outright. A moving concave
mesh needs its tree rebuilt or refitted every tick and needs a mass tensor a triangle soup does
not have — and the usual answer to a moving concave thing is convex decomposition, which is a row
of its own. Most consumers want exactly this: the level is a mesh and everything in it is a
hull, a box or a sphere.
The tree is DynamicTree, built once and never moved. A second acceleration structure would
be a second thing to get right, and the one this package already has is an AABB tree with a
tested query — its incremental machinery simply goes unused. What that costs is the 10 cm fat
margin every proxy carries, which for a small triangle means a query returns a few candidates it
did not need; the narrow phase rejects them in one separating-axis test each. What would make it
wrong is a mesh of millimetre triangles, where the margin dwarfs the geometry and every query
returns most of the mesh.
The interior-edge data is the half that decides whether it feels right. A box sliding across
two triangles catches on their shared edge, because at the seam the narrow phase finds the edge
rather than the face and pushes the box back along it — the classic symptom is a character
stumbling on a perfectly flat floor every metre. Each edge is therefore classified once, here,
as convex or not, and meshContact.ts uses that to replace an edge normal with the face's.
Properties
| Name | Type | Description |
|---|---|---|
positionsreadonly | Float32Array | xyz per vertex, in the mesh's own space. |
indicesreadonly | Uint32Array | Three vertex indices per triangle. |
triangleCountreadonly | number | |
planesreadonly | Float32Array | nx, ny, nz, d per triangle: the outward plane, with d = n · v0. |
convexEdgesreadonly | Uint8Array | Three bits per triangle, one per edge: set where the fold at that edge turns away from the
front face, or where the edge has no neighbour at all.MoreEdge |
treereadonly | DynamicTree | null | Over triangle indices, built once — and null for a heightfield, which needs none.MoreA field's candidates are an index range rather than a tree query: the cells a box covers are
arithmetic on its own bounds. See |
fieldreadonlyoptional | Heightfield | Set where the triangles are generated from a heightfield rather than stored.MoreThe arrays above are then empty and nothing reads them: |