uv-unwrap

UVs for a mesh, worked out from its shape. A garment exported to Blender gets a layout an artist can paint on and a pattern can run across, without anyone marking seams: the mesh is cut along the two planes through its middle, the one between left and right and the one between front and back, so a ball falls into four pieces and a pair of trousers into a front and back for each leg, the way a sewing pattern has them. Each piece is flattened by least-squares conformal maps (Lévy et al. 2002), which keeps angles, so a check stays square; scaled to its true area; turned so the mesh's up is up; and the pieces are packed into the unit square.

The seams are straight. A vertex within a quarter of an edge of a plane is taken as on it, and a triangle that crosses a plane is cut where its edges meet it, so the seam runs through existing vertices where they are close and through new points between them where they are not. unwrapUvs returns the mesh as cut, with a vertex on a seam once for each piece it borders: its positions, and for each vertex the input vertices it is made of (ref, weight, four each), so normals, weights or anything else per vertex carry over (carryUnwrapped). metresPerUnit is how many metres one UV unit spans, for a tiling texture at its real size.

import { unwrapUvs, carryUnwrapped } from 'tosijs-3d'

const u = unwrapUvs(positions, triangles)
// u.triangles index u.positions and u.uvs
const normals = carryUnwrapped(inputNormals, 3, u)

Seams are the two planes by default, through the middle of the mesh's bounds: seams: { x: 0, z: false } puts the left/right seam at x = 0 and makes no front/back seam. A piece the planes leave in several parts (two legs in one quarter) becomes several pieces. A closed piece with no boundary of its own (a sphere quarter has one; a whole sphere would not) is fine, because the planes always open it.