test: /fp:precise reproduced the residue byte for byte — instrument instead of guessing
An /fp:precise build returned the identical 454 samples, identical max delta, identical coordinate. A different float model producing byte-identical output is proof that rounding is not the cause, so the /fp:fast explanation is dead. That is three failed hypotheses on one discrepancy (FVector round-trip, then "check the roughness window", then /fp:fast), each reasoned from plausibility and each costing a build. So: stop reasoning, print. FVoxelOpStack::EvalSample exposes the full sample, and MazeEquivalence now dumps the worst point in raw hex -- both densities, the stack's internal SDF, and the carve factor reconstructed from each side. The recovered carve localises it: identical carve + differing density means the fault is after the conversion; differing carve means it is in the SDF (lattice edges or VoxelSDF::Capsule) or in SmoothStep01. Note for whoever reads the docs next: AUDIT C9 and OPSTACK-PLAN 2.6 currently assert the /fp:fast story as the explanation for THIS residue. That specific claim is falsified and needs walking back once the dump identifies the real cause. C9's other half -- that UBT's FP default differs by toolchain and the MP model assumes bit-reproducible terrain -- stands independently; it was read out of VCToolChain.cs and ClangToolChain.cs, not inferred from this test. Phase 1 step 3 (wiring the stack into GetDensityAt) is paused until this is understood. Small unexplained numeric differences do not get smaller when you build on top of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -83,10 +83,19 @@ public:
|
||||
* Returns INTERNAL-convention density (positive = solid). The caller negates once for MC.
|
||||
*/
|
||||
float EvalInternal(float WorldX, float WorldY, float WorldZ) const
|
||||
{
|
||||
return EvalSample(WorldX, WorldY, WorldZ).Density;
|
||||
}
|
||||
|
||||
/** L'état COMPLET (densité + SDF) après toute la pile. Diagnostic : quand une comparaison
|
||||
* avec l'ancien chemin diverge, c'est le canal SDF qui dit si l'écart naît avant ou après
|
||||
* la conversion. / The full state after the stack — the SDF channel is what says whether a
|
||||
* divergence is born before or after the carve. */
|
||||
FVoxelOpSample EvalSample(float WorldX, float WorldY, float WorldZ) const
|
||||
{
|
||||
FVoxelOpSample S;
|
||||
for (const TUniquePtr<IVoxelDensityOp>& Op : Ops) { Op->Eval(WorldX, WorldY, WorldZ, S); }
|
||||
return S.Density;
|
||||
return S;
|
||||
}
|
||||
|
||||
/** Le même, négaté pour le mesher (négatif = solide). */
|
||||
|
||||
Reference in New Issue
Block a user