Skip to content
Shapemetry

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) // TriangleMesh
  • Brep.tessellate(document, deflection?) — tessellates every face of the document. Omitting deflection uses the kernel's face-measured default (what Brep.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`
}
  • indices drive the triangles: mesh.indices.length / 3 triangles.
  • edges are the display polylines for wireframe/crease overlays: { type: 'smooth' | 'boundary' | 'unset', positions }. Draw boundary edges to show the outline, smooth for tangent lines on curved blends.
  • groups are 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 out

Where next

Last updated: 📖 2 min readEdit on GitHub