Normalized mode shapes
32-bit in partSamples each mode at the plot vertices and scales it to a largest displacement of 1.
uᵥ = sample(modeᵥ) ÷ max |u|
The samples are rounded to 32-bit when written into the Float32Array and rounded again after the division. The maximum itself is taken from the 64-bit samples, so the largest value ends up within about one 32-bit rounding of 1.
const shapes = r.shapes.map((u) => {
const nv = pm.positions.length / 3, out = new Float32Array(nv * 3), t = new Float64Array(3);
let mx = 0;
for (let v = 0; v < nv; v++) { sampleField(r.model, u, 3, [pm.positions[3 * v], pm.positions[3 * v + 1], pm.positions[3 * v + 2]], t); out.set(t, 3 * v); mx = Math.max(mx, Math.hypot(t[0], t[1], t[2])); }
for (let i = 0; i < out.length; i++) out[i] /= mx || 1;
ctx.transfer(out.buffer);
return out;
});