Auto-fix for GEOMETRY_AABB_NOT_TIGHT — re-quantises
positionsCompressed into a tight AABB so every u16 step
resolves a smaller world-space increment. World positions are
preserved up to a tiny rounding error introduced by the
re-quantisation.
Algebra:
Old encoding: w = oldMin + oldRange · u_old / 65535.
True world bounds: walk positionsCompressed, find u16
[minU, maxU] per axis, then
tightMin = oldMin + oldRange · minU / 65535,
tightMax = oldMin + oldRange · maxU / 65535.
New encoding: w = tightMin + tightRange · u_new / 65535.
Substituting and solving:
u_new = (u_old - minU) · 65535 / (maxU - minU).
The arithmetic stays in u16 space — no float decompression
needed.
Quality gain scales with how loose the original AABB was. A
1% fill becomes 100% — quantisation step shrinks 100×.
Edge case: a collapsed axis (minU === maxU) means every
vertex sits at the same coordinate on that axis. The fix
encodes them all as 0 and the new AABB collapses too, which
is consistent and decodes losslessly.
Idempotent: re-running on a tight geometry computes
minU = 0, maxU = 65535, scaling factor 1 → no-op. Returns
{fixed: false} when the geometry is already tight on every
axis.
Mutates geom.positionsCompressed (Uint16Array) and
geom.aabb (Float32Array) via the typed-cast pattern shared
across the geometry-fix family.
Auto-fix for
GEOMETRY_AABB_NOT_TIGHT— re-quantisespositionsCompressedinto a tight AABB so every u16 step resolves a smaller world-space increment. World positions are preserved up to a tiny rounding error introduced by the re-quantisation.Algebra:
w = oldMin + oldRange · u_old / 65535.positionsCompressed, find u16[minU, maxU]per axis, thentightMin = oldMin + oldRange · minU / 65535,tightMax = oldMin + oldRange · maxU / 65535.w = tightMin + tightRange · u_new / 65535. Substituting and solving:u_new = (u_old - minU) · 65535 / (maxU - minU). The arithmetic stays in u16 space — no float decompression needed.Quality gain scales with how loose the original AABB was. A 1% fill becomes 100% — quantisation step shrinks 100×.
Edge case: a collapsed axis (
minU === maxU) means every vertex sits at the same coordinate on that axis. The fix encodes them all as0and the new AABB collapses too, which is consistent and decodes losslessly.Idempotent: re-running on a tight geometry computes
minU = 0,maxU = 65535, scaling factor 1 → no-op. Returns{fixed: false}when the geometry is already tight on every axis.Mutates
geom.positionsCompressed(Uint16Array) andgeom.aabb(Float32Array) via the typed-cast pattern shared across the geometry-fix family.