A placement's surface in world coordinates
32-bit, display onlyEvery triangle corner of the selected object with its normal and UV, in world coordinates, for the bake.
Positions are the placement matrix times each corner, written to Float64Array. Faces that are not a mesh get one normal per triangle from a cross product. The arrays feed the bake that writes pictures.
/** A placement's surface in world coordinates: {pos, nrm, uv (null without UVs), tris} — a mesh renders `def.rendered`. */
export function surfaceOf(mdl, path) {
const ctx = mdl.context(path);
if (!ctx) return null;
const def = ctx.def, m = ctx.m, pos = [], nrm = [], uv = [];
if (def.mesh) {
const R = def.rendered, T = R.triangulate(), P = R.P, hV = R.hV, CN = R.cornerNormals(), U = R.attrArray('uv');
for (let i = 0; i < T.n; i++) for (let q = 0; q < 3; q++) {
const h = T.tri[i * 3 + q], v = hV[h] * 3, w = apply(m, [P[v], P[v + 1], P[v + 2]]), n = norm(applyDir(m, [CN[h * 3], CN[h * 3 + 1], CN[h * 3 + 2]]));
pos.push(...w); nrm.push(...n);
if (U) uv.push(U[h * 2], U[h * 2 + 1]);
}
return { pos: new Float64Array(pos), nrm: new Float64Array(nrm), uv: U ? new Float64Array(uv) : null, mesh: true };
}
const t = defTriangles(def);
for (let i = 0; i < t.length; i += 9) {
const a = apply(m, [t[i], t[i + 1], t[i + 2]]), b = apply(m, [t[i + 3], t[i + 4], t[i + 5]]), c = apply(m, [t[i + 6], t[i + 7], t[i + 8]]), n = norm(cross(sub(b, a), sub(c, a)));
pos.push(...a, ...b, ...c); nrm.push(...n, ...n, ...n);
}
return { pos: new Float64Array(pos), nrm: new Float64Array(nrm), uv: null, mesh: false };
}