fix(tess): sample a solid's faces as finely as the edges drawn over them

The shaded surface of a curved solid was visibly coarser than its own
wireframe: the wire ran along the true rim while the facets cut inside it.

Two things were wrong, and only one was the tolerance.

`facet_res` is a resolution multiplier — the same one `scale_lod` divides the
fallback sampler's chord fraction by — and the kernel path was using it as a
sag in world units. At the default that asks for a whole unit of departure, so
nothing smaller than a metre subdivided at all and a face was only ever as
round as its own boundary. It is a fraction of each surface's own radius now,
which carries no assumption about the drawing's units.

And it is the *edges'* fraction, shared from `EDGE_CHORD_FRAC` rather than
copied. Those edges are drawn over these faces; sampling the two differently
is what put the wire across a facet instead of along its corners. `facet_res`
is deliberately not applied either, since the edges it must line up with are
built once at highest detail and never scaled.

A torus is measured by its tube rather than its ring — the tube is the tighter
bend, and sampling to the ring leaves the section a hexagon.

The primitive-volume test claimed a mesh can never read over its true size.
That holds for a convex solid, where every chord lies inside; a torus is not
one, and across the inside of its tube the chords fall outside the material.
It passed before only because the sampling was too coarse to show it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5 committed 2026-08-10 03:17:12 +03:00
1 parent afb4fd4733
commit 60f5bca0d4
3 files changed
+110 -10

No files matched your search

+10 -4
View File
@@ -382,10 +382,16 @@ mod tests {
for (body, expected) in cases {
let got = volume(&body);
assert!(got > 0.0, "wound inwards: {got}");
// Facets are chords and lie inside, so a mesh reads short and
// never over.
assert!(got > 0.94 * expected, "{got} vs {expected}");
assert!(got <= expected * 1.000_001, "{got} vs {expected}");
// Close either way, rather than short and never over. A chord does
// lie inside the surface it spans, so a convex solid can only read
// short — but a torus is not convex, and across the inside of its
// tube the chords fall outside the material and add a little. What
// is being checked is that the mesh is the shape asked for, and a
// per cent covers both.
assert!(
(got - expected).abs() < 0.01 * expected,
"{got} vs {expected}"
);
}
}