Skip to content
Shapemetry

Types - Mesh

API reference for ./geometry/mesh on @huukhanhnguyen/types.

See the Guide for the package's role.

API reference

Signatures are generated from the live package .d.ts - not hand-written.

Mesh

type

Opaque n-gon polygon mesh — design topology stored as faces, triangles only at the doors (render tessellation, STL/GLB writers, GLB import). Flat per-VERTEX attribute arrays parallel to positions (NOTE the difference from shell tables: here vertex i's uv is uvs[2i..2i+1], its normal normals[3i..3i+2], its skin influences skin.indices[4i..4i+3]). Sniff: geometry has positions AND faces — unique among stream shapes (shells have loops, curves have vertices+edges without faces). Closed BY TYPE (the boundary law): only the mesh→mesh op family consumes it; boolean/BOM/tableSource/nesting/watertight filter it out by type.

Kept DISTINCT from the tessellation TriangleMesh wire type (see triangleMesh.ts) on purpose: the stream shape carries the skin BINDING object (SkinBinding, like a face) while the tessellation expands it to skinIndices/skinWeights arrays (+ skeleton), and the tessellation adds the groups bake-time field a stream entity never has. Tessellation always carries triangle indices.

type Mesh
// = {
    /** Vertex positions, flat [x,y,z] per vertex. */
    positions: number[];
    /** N-gon faces: each entry is one CCW outer loop of vertex indices into
     *  `positions`, length ≥ 3. Non-planar faces allowed; no holes (a hole
     *  would be a second loop — not stored). A triangle is a 3-gon. */
    faces: number[][];
    /**
     * Sparse flagged edges for interaction/crease (GLB import, etc.).
     * Runtime builds a full edge table from `faces`; only flagged edges are
     * persisted as `[v1, v2, flags]` triples.
     */
    edges?: [number, number, number][];
    /** Per-vertex [u,v] texture coordinates (glTF TEXCOORD_0). */
    uvs?: number[];
    /** Second UV set (glTF TEXCOORD_1) — AO/lightmaps. Parallel to `uvs`. */
    uvs2?: number[];
    /** Per-vertex [x,y,z] normals (smooth shading). Absent = a renderer
     *  derives them (render() computes area-weighted vertex normals). */
    normals?: number[];
    /** Per-vertex [r,g,b] or [r,g,b,a] colors (glTF COLOR_0). */
    colors?: number[];
    /** Skeletal binding of this mesh's vertices — see SkinBinding
     *  (indices/weights are 4 entries PER VERTEX here). */
    skin?: SkinBinding;
    /** Morph targets — see MorphTarget (offsets are per-VERTEX position
     *  deltas here — already the tessellation layout, no remap at render). */
    morphs?: MorphTarget[];
    /** `Track.key` reference (2026-08-14) — this mesh's OWN weights channel.
     *  One track covers every entry in `morphs` at once: its
     *  `values[i].length` must equal `morphs.length`, in the SAME order —
     *  glTF packs one node's whole `weights` array into a single channel
     *  (confirmed against the spec: `node.weights` count MUST match the
     *  referenced mesh's morph target count), so one track already covers
     *  it — no per-target track to re-merge at export. Consumer-holds-the-
     *  reference, same as `SkeletonJoint`'s `*Track` fields. Absent = this
     *  mesh's morph weights never animate (still usable as a static pose
     *  via each target's own authored weight elsewhere, out of scope here). */
    weightsTrack?: string;
}

MorphTarget

type

One morph target: per-point POSITION DELTAS, flat [dx,dy,dz] per point across all loops (same parallel-to-loops convention as uvs). Static shape data — never animated itself; Mesh.weightsTrack is what varies over time (the blend weight of every target here, together).

type MorphTarget
// = {
    name?: string;
    offsets: number[];
}

ScatterTriangle

type

One triangle with its measures precomputed — what area-weighted sampling (scatter, point-cloud seeding) walks. Not an entity: a bare geometric sample, which is why it carries area and normal rather than an id.

type ScatterTriangle
// = {
    a: Point;
    b: Point;
    c: Point;
    area: number;
    normal: Vector;
}

SkinBinding

type

Skin binding for a mesh's points (skeletal deformation) — glTF SKIN semantics. skeleton names a skeletons[] lane entry (chain key) in the same model or component scope; indices/weights hold 4 entries PER POINT (flat across all loops, same parallel-to-loops convention as uvs/normals): point i's influences are indices[4i..4i+3] (joint ordinals into the skeleton's flat joint list) with weights[4i..4i+3]. Written by faceSkeleton or imported from GLB — never hand-authored.

type SkinBinding
// = {
    skeleton: string;
    indices: number[];
    weights: number[];
}
Last updated: 📖 2 min readEdit on GitHub