mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Splines: Use the limit normal at a pole instead of NaN
Where all the control points along a patch edge meet at one point, like the top of a dome, one derivative is zero and so is the cross product, and normalizing it gave NaN. Use the limit instead, built from the mixed second derivative. Fixes the dark spots on the ghosts' heads in Pac-Man Arrangement (#12354). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
1b4eca0184
commit
f87a07b1a3
1 file changed
+20
-1
@@ -391,7 +391,26 @@ public:
|
||||
const Vec3f derivU = tess_nrm.SampleV(wv.basis);
|
||||
const Vec3f derivV = tess_pos.SampleV(wv.deriv);
|
||||
|
||||
vert.nrm = Cross(derivU, derivV).Normalized(useSSE4);
|
||||
Vec3f nrm = Cross(derivU, derivV);
|
||||
if (nrm.Length2() < 1e-20f) {
|
||||
// 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.
|
||||
const Vec3f derivUV = tess_nrm.SampleV(wv.deriv);
|
||||
if (derivV.Length2() <= derivU.Length2()) {
|
||||
nrm = Cross(derivU, derivUV);
|
||||
if (tile_u * 2 > surface.tess_u) {
|
||||
nrm = -nrm;
|
||||
}
|
||||
} else {
|
||||
nrm = Cross(derivUV, derivV);
|
||||
if (tile_v * 2 > surface.tess_v) {
|
||||
nrm = -nrm;
|
||||
}
|
||||
}
|
||||
}
|
||||
vert.nrm = nrm.NormalizedOr001(useSSE4);
|
||||
if constexpr (patchFacing)
|
||||
vert.nrm *= -1.0f;
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user