Splines: Detect poles relative to the other derivative

With animated control points the pole is only nearly degenerate, so the
vanishing derivative is rounding noise rather than exactly zero, and the
absolute threshold missed it. The resulting random normals still showed
as dark patches on Pac-Man Arrangement's ghosts (#12354).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-30 13:20:01 -06:00
1 parent d32636e91b
commit 0715f43ab8
2 files changed
+13 -7

No files matched your search

+8 -5
View File
@@ -393,13 +393,16 @@ public:
const Vec3f derivV = tess_pos.SampleV(wv.deriv);
Vec3f nrm = Cross(derivU, derivV);
if (nrm.Length2() < 1e-20f) {
const float lenU2 = derivU.Length2();
const float lenV2 = derivV.Length2();
if (std::min(lenU2, lenV2) <= 1e-8f * std::max(lenU2, lenV2)) {
// A pole: a patch edge whose control points all meet at one point, like the top
// of a dome. One derivative vanishes there, so the cross product is zero and the
// normal would be NaN (dark spots on Pac-Man Arrangement's ghosts, #12354). Use
// the limit instead: next to an edge where dP/dv = 0, dP/dv ~ (u - u_edge) * d2P/dudv.
// of a dome. One derivative vanishes there, so the cross product is zero, or with
// animated control points just rounding noise, and the normal would be NaN or
// random (dark patches on Pac-Man Arrangement's ghosts, #12354). Use the limit
// instead: next to an edge where dP/dv = 0, dP/dv ~ (u - u_edge) * d2P/dudv.
const Vec3f derivUV = tess_nrm.SampleV(wv.deriv);
if (derivV.Length2() <= derivU.Length2()) {
if (lenV2 <= lenU2) {
nrm = Cross(derivU, derivUV);
if (tile_u * 2 > surface.tess_u) {
nrm = -nrm;