Mass prism mesh
32-bit, display onlyThe triangles of the walls and roof of a mass.
Positions are pushed as absolute project coordinates and then copied into a Float32Array, before any shift to a local origin. The result goes to the 3D view only.
/** The mass as a closed prism: walls from zBottom up to the roof (z0 + height) and the roof. Absolute project coordinates. */
export function massMesh(m, z0, zBottom = z0) {
const P = signedArea(m.pts) < 0 ? m.pts.slice().reverse() : m.pts, n = P.length, top = z0 + massHeight(m), bot = Math.min(zBottom, z0);
const pos = [], nor = [], ind = [];
for (let i = 0; i < n; i++) {
const a = P[i], b = P[(i + 1) % n], L = Math.hypot(b.x - a.x, b.y - a.y);
if (L < 1e-12) continue;
const nx = (b.y - a.y) / L, ny = -(b.x - a.x) / L, k = pos.length / 3; // outward for a counter-clockwise outline
pos.push(a.x, a.y, bot, b.x, b.y, bot, b.x, b.y, top, a.x, a.y, top);
for (let q = 0; q < 4; q++) nor.push(nx, ny, 0);
ind.push(k, k + 1, k + 2, k, k + 2, k + 3);
}
const k0 = pos.length / 3;
for (const p of P) { pos.push(p.x, p.y, top); nor.push(0, 0, 1); }
for (const i of triangulate(P)) ind.push(k0 + i);
return { positions: new Float32Array(pos), normals: new Float32Array(nor), indices: new Uint32Array(ind) };
}