Tessellate for Display
Renderers need triangles; the kernel speaks B-Rep documents. Brep.tessellate is the bridge.
The one call
import { Brep, Shell } from '@huukhanhnguyen/geometry'
const part = Brep.subtract(Brep.box(100, 100, 100), Brep.translate(Brep.sphere(60), 50, 50, 50))
const mesh = Brep.tessellate(part, 0.5) // TriangleMeshBrep.tessellate(document, deflection?)— tessellates every face of the document. Omittingdeflectionuses the kernel's face-measured default (whatBrep.measurementDeflection(document)returns).Shell.tessellate(document, deflection)— the fast path when you know the document holds exactly one shell.
Deflection semantics
deflection is the maximum sag — the largest allowed distance between the true curved surface and its triangle approximation, in model units. Smaller = finer = more triangles. Planar faces are always exact regardless of deflection; it only costs you on curves. A value around 1/200 of the part size is a sane display default; drop it for close-ups, raise it for thumbnails.
The TriangleMesh channel layout
Flat, non-interleaved plain number[] — nothing to decode:
type TriangleMesh = {
positions: number[] // [x,y,z, …] per vertex
normals?: number[] // [x,y,z, …] per vertex (matches positions)
indices: number[] // 3 corner indices per triangle
uvs?: number[] // [u,v, …] per vertex
edges?: MeshEdge[] // display edges — see below
groups?: MeshGroup[] // material spans in `indices`
}indicesdrive the triangles:mesh.indices.length / 3triangles.edgesare the display polylines for wireframe/crease overlays:{ type: 'smooth' | 'boundary' | 'unset', positions }. Drawboundaryedges to show the outline,smoothfor tangent lines on curved blends.groupsare authored material spans. Tessellation is a one-way arrow — the soup keeps no pointer back to the B-Rep faces that produced it.
These channels feed THREE.BufferGeometry directly — see Rendering with three.js.
N-gon meshes: Mesh.tessellate
The half-edge Mesh API speaks a different payload — Mesh, the n-gon stream shape ({ positions: number[], faces: number[][] }). Mesh.tessellate converts one into the same TriangleMesh, one-shot (the arena handle is loaded and freed inside the call):
import { Shell, Brep, Mesh } from '@huukhanhnguyen/geometry'
const tri = Mesh.tessellate({
positions: [0, 0, 0, 100, 0, 0, 100, 100, 0, 0, 100, 0],
faces: [[0, 1, 2, 3]], // one quad — n-gons allowed
})For a live Mesh arena handle instead, Mesh.tessellateJson(handle) returns the same content as a JSON string. See Mesh and memory.
Triangle-soup utilities
The TriangleMesh namespace (same package, different subject) works on packed soups — Float64Array in/out, used by model's subdivision domain:
import { Shell, Brep, TriangleMesh } from '@huukhanhnguyen/geometry'
const welded = TriangleMesh.weld(new Float64Array(positions), new Uint32Array(indices))
// tolerance defaults to 1e-4; merges duplicate vertices, packed soup outWhere next
- Rendering with three.js — channels → GPU.
- Mesh and memory — arena handles, subdivide, weld.
- glTF, USD and drawing export — tessellation-based exporters.