research(step2f): coherent caves pass every gate, worst 572 ms idle -- look still to be judged in game

Editor-only, default off (voxel.ResearchParameterizedCave 1; the live skip proofs now decline
automatically). Jittered elliptical chambers of varied size and height with rock between them,
narrow tunnels, capped shafts, occasional pillars/ledges/stalactites/stalagmites/hanging masses;
detail bands at 48/24/12 samples (shortest 3 m), bound 3.822.
Gates, step 2e -> step 2f R29 (worst of 8 profiles), each rejecting 2e:
  crumbs < 1 m^3 2,290 -> 0; dihedral >45 deg 40.7% -> 2.2%; lattice detail energy 0.83 -> 0.007
  (RMS floor kept: 0.484 >= 0.40); LOD1 distance p95 0.709 -> 0.377 samples; grid autocorrelation
  0.667 -> 0.348; solid share 2.7% -> 79-82%; roof/floor openings 26,657 -> 0.
Speed, 259^3 ring, six workers, idle machine (20 GB free): 527-572 ms, worst TerracedBasin 572.3 ms
(R27 591 ms, R28 603 ms: run-to-run spread is ~5%). Proof audit 0 violations, undersized control
caught; seams pass; 1 vs 6 worker hash 876069a813c83cee; TraversalSeeds pass.
Captures are UNLIT (lit runs showed only sky; three D3D12 device-removed crashes): they show the
material's tiling, not the cave forms, so the look is not yet judged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-01 05:50:20 +02:00
1 parent d6555df5fa
commit ca78352e43
16 files changed
+8070 -80

No files matched your search

@@ -2551,10 +2551,20 @@ struct FStep2dBrickProofAudit
float FirstViolationDensity = 0.0f;
float FirstViolationCenterMacro = 0.0f;
float FirstViolationSampleMacro = 0.0f;
float FirstViolationCenterRoomMacro = 0.0f;
float FirstViolationSampleRoomMacro = 0.0f;
float FirstViolationSampleDetail = 0.0f;
float FirstViolationMacroDeltaPerVoxel = 0.0f;
float FirstViolationPathMaxGradient = 0.0f;
float FirstViolationTinyStepMaxGradient = 0.0f;
FVector FirstViolationPathMaxFrom = FVector::ZeroVector;
FVector FirstViolationPathMaxTo = FVector::ZeroVector;
float FirstViolationPathMaxFromMacro = 0.0f;
float FirstViolationPathMaxToMacro = 0.0f;
float FirstViolationPathMaxFromRoomMacro = 0.0f;
float FirstViolationPathMaxToRoomMacro = 0.0f;
FString FirstViolationPathMaxFromRoomDiagnostic;
FString FirstViolationPathMaxToRoomDiagnostic;
bool bFirstViolationWasInsideBrick = false;
bool bFirstViolationClaimedAir = false;
uint64 DeliberatelyUndersizedBoundClaimsChecked = 0;
@@ -2653,6 +2663,15 @@ FStep2dBrickProofAudit AuditStep2dBrickProofs(
: VoxelForgeRedefinedDensityField::Evaluate(
Generator, SamplePoint.X, SamplePoint.Y, SamplePoint.Z,
nullptr, 0.0f);
if (bParameterized)
{
Result.FirstViolationCenterRoomMacro =
VoxelForgeRedefinedDensityField::EvaluateParameterizedMacroOnly(
Generator, ProofCentre.X, ProofCentre.Y, ProofCentre.Z);
Result.FirstViolationSampleRoomMacro =
VoxelForgeRedefinedDensityField::EvaluateParameterizedMacroOnly(
Generator, SamplePoint.X, SamplePoint.Y, SamplePoint.Z);
}
Result.FirstViolationSampleDetail = Density
- Result.FirstViolationSampleMacro;
const float CentreDistance = (SamplePoint - ProofCentre).Size();
@@ -2664,6 +2683,7 @@ FStep2dBrickProofAudit AuditStep2dBrickProofs(
{
constexpr int32 PathSteps = 32;
float PreviousMacro = Result.FirstViolationSampleMacro;
FVector PreviousPoint = SamplePoint;
for (int32 PathStep = 1; PathStep <= PathSteps; ++PathStep)
{
const float Alpha = static_cast<float>(PathStep) / PathSteps;
@@ -2674,11 +2694,35 @@ FStep2dBrickProofAudit AuditStep2dBrickProofs(
Generator, Point.X, Point.Y, Point.Z, nullptr, 0.0f)
: VoxelForgeRedefinedDensityField::Evaluate(
Generator, Point.X, Point.Y, Point.Z, nullptr, 0.0f);
Result.FirstViolationPathMaxGradient = FMath::Max(
Result.FirstViolationPathMaxGradient,
FMath::Abs(PathMacro - PreviousMacro)
* PathSteps / CentreDistance);
const float PathGradient = FMath::Abs(
PathMacro - PreviousMacro) * PathSteps / CentreDistance;
if (PathGradient > Result.FirstViolationPathMaxGradient)
{
Result.FirstViolationPathMaxGradient = PathGradient;
Result.FirstViolationPathMaxFrom = PreviousPoint;
Result.FirstViolationPathMaxTo = Point;
Result.FirstViolationPathMaxFromMacro = PreviousMacro;
Result.FirstViolationPathMaxToMacro = PathMacro;
if (bParameterized)
{
Result.FirstViolationPathMaxFromRoomMacro =
VoxelForgeRedefinedDensityField::EvaluateParameterizedMacroOnly(
Generator, PreviousPoint.X, PreviousPoint.Y,
PreviousPoint.Z);
Result.FirstViolationPathMaxToRoomMacro =
VoxelForgeRedefinedDensityField::EvaluateParameterizedMacroOnly(
Generator, Point.X, Point.Y, Point.Z);
Result.FirstViolationPathMaxFromRoomDiagnostic =
VoxelForgeRedefinedDensityField::DescribeParameterizedMacroAt(
Generator, PreviousPoint.X, PreviousPoint.Y,
PreviousPoint.Z);
Result.FirstViolationPathMaxToRoomDiagnostic =
VoxelForgeRedefinedDensityField::DescribeParameterizedMacroAt(
Generator, Point.X, Point.Y, Point.Z);
}
}
PreviousMacro = PathMacro;
PreviousPoint = Point;
}
}
constexpr float TinyStep = 0.01f;
@@ -3173,12 +3217,27 @@ struct FStep2fFragmentMetrics
int64 SolidCrumbsBelowOneCubicMeter = 0;
int64 AirCrumbVoxelSamples = 0;
int64 SolidCrumbVoxelSamples = 0;
int64 AirCrumbsAfterBoundaryPadding = -1;
int64 SolidCrumbsAfterBoundaryPadding = -1;
int32 LargestAirComponentVoxels = 0;
int32 LargestSolidComponentVoxels = 0;
struct FCrumbComponent
{
bool bAir = false;
int32 Samples = 0;
FIntVector Min = FIntVector::ZeroValue;
FIntVector Max = FIntVector::ZeroValue;
FIntVector Root = FIntVector::ZeroValue;
int32 SignMismatchSamples = 0;
float DensityAtRoot = 0.0f;
float DensityAtMin = 0.0f;
};
TArray<FCrumbComponent> CrumbComponents;
};
FStep2fFragmentMetrics ComputeStep2fFragmentMetrics(
const TArray<float>& Density, int32 Dimension)
const TArray<float>& Density, int32 Dimension,
int32 CoreInset = 0, int32 CoreDimension = 0)
{
FStep2fFragmentMetrics Result;
const int32 Count = Density.Num();
@@ -3252,7 +3311,20 @@ FStep2fFragmentMetrics ComputeStep2fFragmentMetrics(
}
}
}
TSet<int32> ComponentsIntersectingCore;
if (CoreDimension > 0 && CoreInset >= 0
&& CoreInset + CoreDimension <= Dimension)
{
for (int32 Z = CoreInset; Z < CoreInset + CoreDimension; ++Z)
for (int32 Y = CoreInset; Y < CoreInset + CoreDimension; ++Y)
for (int32 X = CoreInset; X < CoreInset + CoreDimension; ++X)
{
const int32 Index = (Z * Dimension + Y) * Dimension + X;
ComponentsIntersectingCore.Add(FindRoot(Index));
}
}
constexpr int32 VoxelsPerCubicMeter = 4 * 4 * 4;
TMap<int32, FStep2fFragmentMetrics::FCrumbComponent> CrumbByRoot;
for (int32 Index = 0; Index < Count; ++Index)
{
if (Parent[Index] >= 0)
@@ -3261,15 +3333,29 @@ FStep2fFragmentMetrics ComputeStep2fFragmentMetrics(
}
const int32 ComponentVoxels = -Parent[Index];
const bool bAir = Density[Index] > 0.0f;
const bool bIntersectsCore = ComponentsIntersectingCore.IsEmpty()
|| ComponentsIntersectingCore.Contains(Index);
if (bAir)
{
++Result.AirComponents;
Result.LargestAirComponentVoxels = FMath::Max(
Result.LargestAirComponentVoxels, ComponentVoxels);
if (ComponentVoxels < VoxelsPerCubicMeter)
if (ComponentVoxels < VoxelsPerCubicMeter && bIntersectsCore)
{
++Result.AirCrumbsBelowOneCubicMeter;
Result.AirCrumbVoxelSamples += ComponentVoxels;
if (Result.CrumbComponents.Num() + CrumbByRoot.Num() < 32)
{
FStep2fFragmentMetrics::FCrumbComponent& Crumb =
CrumbByRoot.Add(Index);
Crumb.bAir = true;
Crumb.Samples = ComponentVoxels;
Crumb.Min = FIntVector(Dimension, Dimension, Dimension);
Crumb.Max = FIntVector::ZeroValue;
Crumb.Root = FIntVector(Index % Dimension,
(Index / Dimension) % Dimension, Index / (Dimension * Dimension));
Crumb.DensityAtRoot = Density[Index];
}
}
}
else
@@ -3277,13 +3363,59 @@ FStep2fFragmentMetrics ComputeStep2fFragmentMetrics(
++Result.SolidComponents;
Result.LargestSolidComponentVoxels = FMath::Max(
Result.LargestSolidComponentVoxels, ComponentVoxels);
if (ComponentVoxels < VoxelsPerCubicMeter)
if (ComponentVoxels < VoxelsPerCubicMeter && bIntersectsCore)
{
++Result.SolidCrumbsBelowOneCubicMeter;
Result.SolidCrumbVoxelSamples += ComponentVoxels;
if (Result.CrumbComponents.Num() + CrumbByRoot.Num() < 32)
{
FStep2fFragmentMetrics::FCrumbComponent& Crumb =
CrumbByRoot.Add(Index);
Crumb.bAir = false;
Crumb.Samples = ComponentVoxels;
Crumb.Min = FIntVector(Dimension, Dimension, Dimension);
Crumb.Max = FIntVector::ZeroValue;
Crumb.Root = FIntVector(Index % Dimension,
(Index / Dimension) % Dimension, Index / (Dimension * Dimension));
Crumb.DensityAtRoot = Density[Index];
}
}
}
}
if (!CrumbByRoot.IsEmpty())
{
for (int32 Index = 0; Index < Count; ++Index)
{
const int32 Root = FindRoot(Index);
FStep2fFragmentMetrics::FCrumbComponent* Crumb = CrumbByRoot.Find(Root);
if (Crumb == nullptr)
{
continue;
}
const int32 X = Index % Dimension;
const int32 Y = (Index / Dimension) % Dimension;
const int32 Z = Index / (Dimension * Dimension);
Crumb->SignMismatchSamples +=
(Density[Index] > 0.0f) != Crumb->bAir ? 1 : 0;
Crumb->Min.X = FMath::Min(Crumb->Min.X, X);
Crumb->Min.Y = FMath::Min(Crumb->Min.Y, Y);
Crumb->Min.Z = FMath::Min(Crumb->Min.Z, Z);
Crumb->Max.X = FMath::Max(Crumb->Max.X, X);
Crumb->Max.Y = FMath::Max(Crumb->Max.Y, Y);
Crumb->Max.Z = FMath::Max(Crumb->Max.Z, Z);
}
TArray<int32> Roots;
CrumbByRoot.GetKeys(Roots);
Roots.Sort();
for (const int32 Root : Roots)
{
FStep2fFragmentMetrics::FCrumbComponent& Crumb = CrumbByRoot[Root];
const int32 MinIndex = (Crumb.Min.Z * Dimension + Crumb.Min.Y)
* Dimension + Crumb.Min.X;
Crumb.DensityAtMin = Density[MinIndex];
Result.CrumbComponents.Add(Crumb);
}
}
return Result;
}
@@ -5006,10 +5138,44 @@ int32 RunStep2f(const FString& Params)
static_cast<double>(Shape.Fragments.AirCrumbsBelowOneCubicMeter));
Json->SetNumberField(TEXT("solid_crumbs_below_1m3"),
static_cast<double>(Shape.Fragments.SolidCrumbsBelowOneCubicMeter));
Json->SetNumberField(TEXT("air_crumbs_below_1m3_after_boundary_padding"),
static_cast<double>(Shape.Fragments.AirCrumbsAfterBoundaryPadding >= 0
? Shape.Fragments.AirCrumbsAfterBoundaryPadding
: Shape.Fragments.AirCrumbsBelowOneCubicMeter));
Json->SetNumberField(TEXT("solid_crumbs_below_1m3_after_boundary_padding"),
static_cast<double>(Shape.Fragments.SolidCrumbsAfterBoundaryPadding >= 0
? Shape.Fragments.SolidCrumbsAfterBoundaryPadding
: Shape.Fragments.SolidCrumbsBelowOneCubicMeter));
Json->SetNumberField(TEXT("air_crumb_voxel_samples"),
static_cast<double>(Shape.Fragments.AirCrumbVoxelSamples));
Json->SetNumberField(TEXT("solid_crumb_voxel_samples"),
static_cast<double>(Shape.Fragments.SolidCrumbVoxelSamples));
TArray<TSharedPtr<FJsonValue>> CrumbComponents;
for (const FStep2fFragmentMetrics::FCrumbComponent& Crumb
: Shape.Fragments.CrumbComponents)
{
TSharedRef<FJsonObject> CrumbJson = MakeShared<FJsonObject>();
CrumbJson->SetStringField(TEXT("sign"), Crumb.bAir ? TEXT("air") : TEXT("solid"));
CrumbJson->SetNumberField(TEXT("samples"), Crumb.Samples);
CrumbJson->SetNumberField(TEXT("density_at_min"), Crumb.DensityAtMin);
CrumbJson->SetArrayField(TEXT("root_ring_voxel"), {
MakeShared<FJsonValueNumber>(Crumb.Root.X),
MakeShared<FJsonValueNumber>(Crumb.Root.Y),
MakeShared<FJsonValueNumber>(Crumb.Root.Z)});
CrumbJson->SetNumberField(TEXT("density_at_root"), Crumb.DensityAtRoot);
CrumbJson->SetNumberField(TEXT("sign_mismatch_samples"),
Crumb.SignMismatchSamples);
CrumbJson->SetArrayField(TEXT("min_ring_voxel"), {
MakeShared<FJsonValueNumber>(Crumb.Min.X),
MakeShared<FJsonValueNumber>(Crumb.Min.Y),
MakeShared<FJsonValueNumber>(Crumb.Min.Z)});
CrumbJson->SetArrayField(TEXT("max_ring_voxel"), {
MakeShared<FJsonValueNumber>(Crumb.Max.X),
MakeShared<FJsonValueNumber>(Crumb.Max.Y),
MakeShared<FJsonValueNumber>(Crumb.Max.Z)});
CrumbComponents.Add(MakeShared<FJsonValueObject>(CrumbJson));
}
Json->SetArrayField(TEXT("crumb_components_first_32"), CrumbComponents);
Json->SetNumberField(TEXT("largest_air_component_voxels"),
Shape.Fragments.LargestAirComponentVoxels);
Json->SetNumberField(TEXT("largest_solid_component_voxels"),
@@ -5041,6 +5207,35 @@ int32 RunStep2f(const FString& Params)
return Json;
};
constexpr int32 CrumbBoundaryPadding = 64;
const int32 PaddedCrumbDimension = Dimension + 2 * CrumbBoundaryPadding;
const FIntVector PaddedCrumbOrigin = Origin
- FIntVector(CrumbBoundaryPadding, CrumbBoundaryPadding, CrumbBoundaryPadding);
const auto CountBoundaryPaddedCrumbs = [&](bool bLegacyField,
int64& OutAirCrumbs, int64& OutSolidCrumbs,
TArray<FStep2fFragmentMetrics::FCrumbComponent>* OutCrumbComponents = nullptr)
{
VoxelForgeRedefinedDensityField::SetLegacyStep2eAuditMode(bLegacyField);
TArray<float> PaddedDensity;
VoxelForgeRegionEval::FTiming PaddedTiming;
if (!VoxelForgeRegionEval::EvaluateRedefined(
*World.Generator, PaddedCrumbOrigin, PaddedCrumbDimension,
Workers, 1.0f, PaddedDensity, PaddedTiming, false, true))
{
return false;
}
const FStep2fFragmentMetrics PaddedFragments = ComputeStep2fFragmentMetrics(
PaddedDensity, PaddedCrumbDimension,
CrumbBoundaryPadding, Dimension);
OutAirCrumbs = PaddedFragments.AirCrumbsBelowOneCubicMeter;
OutSolidCrumbs = PaddedFragments.SolidCrumbsBelowOneCubicMeter;
if (OutCrumbComponents != nullptr)
{
*OutCrumbComponents = PaddedFragments.CrumbComponents;
}
return true;
};
for (int32 Profile = 0;
Profile < VoxelForgeRedefinedDensityField::GetParameterSetCount(); ++Profile)
{
@@ -5072,12 +5267,20 @@ int32 RunStep2f(const FString& Params)
}
LegacyTimes.Sort();
const double LegacyMedianMs = LegacyTimes[LegacyTimes.Num() / 2];
const FStep2fShapeSnapshot LegacyShape = MeasureShape(
FStep2fShapeSnapshot LegacyShape = MeasureShape(
LegacyDensity, LegacyParameters);
const FStep2eVarietyMetrics LegacyVariety = LegacyShape.Variety;
if (!CountBoundaryPaddedCrumbs(true,
LegacyShape.Fragments.AirCrumbsAfterBoundaryPadding,
LegacyShape.Fragments.SolidCrumbsAfterBoundaryPadding))
{
UE_LOG(LogTemp, Error,
TEXT("[VoxelForgeStep2f] profile %d padded step 2e crumb pass failed."), Profile);
return 2;
}
WorstStep2eMs = FMath::Max(WorstStep2eMs, LegacyMedianMs);
const int64 LegacyCrumbs = LegacyShape.Fragments.AirCrumbsBelowOneCubicMeter
+ LegacyShape.Fragments.SolidCrumbsBelowOneCubicMeter;
const int64 LegacyCrumbs = LegacyShape.Fragments.AirCrumbsAfterBoundaryPadding
+ LegacyShape.Fragments.SolidCrumbsAfterBoundaryPadding;
WorstStep2eCrumbs = FMath::Max(WorstStep2eCrumbs, LegacyCrumbs);
bStep2eCrumbsRejected &= LegacyCrumbs > 0;
WorstStep2eDihedralShare = FMath::Max(
@@ -5092,7 +5295,7 @@ int32 RunStep2f(const FString& Params)
bStep2eBandLimitRejected &= LegacyShape.Detail.LatticeScaleEnergyRatio > 0.20;
WorstStep2eLodDistance = FMath::Max(
WorstStep2eLodDistance, LegacyShape.Lod1P95SurfaceErrorVoxels);
bStep2eLodRejected |= LegacyShape.Lod1P95SurfaceErrorVoxels > 3.5;
bStep2eLodRejected |= LegacyShape.Lod1P95SurfaceErrorVoxels > 0.5;
WorstStep2ePitchCorrelation = FMath::Max(
WorstStep2ePitchCorrelation, LegacyShape.Grid.PitchCorrelationPeak);
WorstStep2ePitchExcess = FMath::Max(
@@ -5136,12 +5339,22 @@ int32 RunStep2f(const FString& Params)
}
NewTimes.Sort();
const double NewMedianMs = NewTimes[NewTimes.Num() / 2];
const FStep2fShapeSnapshot NewShape = MeasureShape(NewDensity, NewParameters);
FStep2fShapeSnapshot NewShape = MeasureShape(NewDensity, NewParameters);
const FStep2eVarietyMetrics NewVariety = NewShape.Variety;
TArray<FStep2fFragmentMetrics::FCrumbComponent> NewPaddedCrumbComponents;
if (!CountBoundaryPaddedCrumbs(false,
NewShape.Fragments.AirCrumbsAfterBoundaryPadding,
NewShape.Fragments.SolidCrumbsAfterBoundaryPadding,
&NewPaddedCrumbComponents))
{
UE_LOG(LogTemp, Error,
TEXT("[VoxelForgeStep2f] profile %d padded step 2f crumb pass failed."), Profile);
return 2;
}
WorstStep2fMs = FMath::Max(WorstStep2fMs, NewMedianMs);
const double NewSolidFraction = 1.0 - NewVariety.OpenFraction;
const int64 NewCrumbs = NewShape.Fragments.AirCrumbsBelowOneCubicMeter
+ NewShape.Fragments.SolidCrumbsBelowOneCubicMeter;
const int64 NewCrumbs = NewShape.Fragments.AirCrumbsAfterBoundaryPadding
+ NewShape.Fragments.SolidCrumbsAfterBoundaryPadding;
WorstStep2fCrumbs = FMath::Max(WorstStep2fCrumbs, NewCrumbs);
WorstStep2fDihedralShare = FMath::Max(
WorstStep2fDihedralShare, NewShape.Mesh.ShareDihedralsOver45Degrees);
@@ -5163,8 +5376,8 @@ int32 RunStep2f(const FString& Params)
WorstStep2fFloorOpenings, NewShape.Structure.FloorOpenings);
WorstStep2fSolidFraction = FMath::Max(WorstStep2fSolidFraction, NewSolidFraction);
BestStep2fSolidFraction = FMath::Min(BestStep2fSolidFraction, NewSolidFraction);
bStep2fCrumbGatePassed &= NewShape.Fragments.AirCrumbsBelowOneCubicMeter == 0
&& NewShape.Fragments.SolidCrumbsBelowOneCubicMeter == 0;
bStep2fCrumbGatePassed &= NewShape.Fragments.AirCrumbsAfterBoundaryPadding == 0
&& NewShape.Fragments.SolidCrumbsAfterBoundaryPadding == 0;
bStep2fFlakeGatePassed &= NewShape.Mesh.TriangleCount > 0
&& NewShape.Mesh.ManifoldEdgeCount > 0
&& NewShape.Mesh.ShareDihedralsOver45Degrees <= 0.25
@@ -5172,7 +5385,7 @@ int32 RunStep2f(const FString& Params)
bStep2fBandLimitPassed &= NewShape.Detail.LatticeScaleEnergyRatio <= 0.20
&& NewShape.Detail.Rms >= 0.40;
bStep2fLodPassed &= NewShape.Lod1VertexCount > 0
&& NewShape.Lod1P95SurfaceErrorVoxels <= 3.5;
&& NewShape.Lod1P95SurfaceErrorVoxels <= 0.5;
bStep2fGridPassed &= NewShape.Grid.PitchCorrelationPeak <= 0.40
&& NewShape.Grid.PitchPeakExcess <= 0.08;
bStep2fStructurePassed &= NewSolidFraction >= 0.25 && NewSolidFraction <= 0.88
@@ -5189,6 +5402,51 @@ int32 RunStep2f(const FString& Params)
LegacyShape, LegacyMedianMs, LegacyVariety));
Row->SetObjectField(TEXT("step2f"), ShapeJson(
NewShape, NewMedianMs, NewVariety));
TArray<TSharedPtr<FJsonValue>> PaddedCrumbDiagnostics;
for (const FStep2fFragmentMetrics::FCrumbComponent& Crumb
: NewPaddedCrumbComponents)
{
// Root is an actual sample in the connected component. The min/max coordinates are
// an axis-aligned bound and their corner may not belong to the component.
const FIntVector SampleVoxel = PaddedCrumbOrigin + Crumb.Root;
const float SampleX = static_cast<float>(SampleVoxel.X);
const float SampleY = static_cast<float>(SampleVoxel.Y);
const float SampleZ = static_cast<float>(SampleVoxel.Z);
TSharedRef<FJsonObject> CrumbJson = MakeShared<FJsonObject>();
CrumbJson->SetStringField(TEXT("sign"), Crumb.bAir ? TEXT("air") : TEXT("solid"));
CrumbJson->SetNumberField(TEXT("samples"), Crumb.Samples);
CrumbJson->SetNumberField(TEXT("density_from_padded_array_at_min"),
Crumb.DensityAtMin);
CrumbJson->SetNumberField(TEXT("density_at_root"), Crumb.DensityAtRoot);
CrumbJson->SetNumberField(TEXT("sign_mismatch_samples"),
Crumb.SignMismatchSamples);
CrumbJson->SetArrayField(TEXT("root_world_voxel"), {
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.X + Crumb.Root.X),
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.Y + Crumb.Root.Y),
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.Z + Crumb.Root.Z)});
CrumbJson->SetArrayField(TEXT("min_world_voxel"), {
MakeShared<FJsonValueNumber>(SampleVoxel.X),
MakeShared<FJsonValueNumber>(SampleVoxel.Y),
MakeShared<FJsonValueNumber>(SampleVoxel.Z)});
CrumbJson->SetArrayField(TEXT("max_world_voxel"), {
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.X + Crumb.Max.X),
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.Y + Crumb.Max.Y),
MakeShared<FJsonValueNumber>(PaddedCrumbOrigin.Z + Crumb.Max.Z)});
CrumbJson->SetNumberField(TEXT("final_density_at_min"),
VoxelForgeRedefinedDensityField::EvaluateParameterized(
*World.Generator, SampleX, SampleY, SampleZ));
CrumbJson->SetNumberField(TEXT("macro_at_min"),
VoxelForgeRedefinedDensityField::EvaluateParameterizedMacroOnly(
*World.Generator, SampleX, SampleY, SampleZ));
CrumbJson->SetNumberField(TEXT("detail_at_min"),
VoxelForgeRedefinedDensityField::EvaluateParameterizedDetail(
*World.Generator, SampleX, SampleY, SampleZ));
CrumbJson->SetStringField(TEXT("macro_description_at_min"),
VoxelForgeRedefinedDensityField::DescribeParameterizedMacroAt(
*World.Generator, SampleX, SampleY, SampleZ));
PaddedCrumbDiagnostics.Add(MakeShared<FJsonValueObject>(CrumbJson));
}
Row->SetArrayField(TEXT("step2f_padded_crumb_diagnostics"), PaddedCrumbDiagnostics);
Row->SetObjectField(TEXT("step2e_parameters"), Step2eParametersJson(LegacyParameters));
Row->SetObjectField(TEXT("step2f_parameters"), Step2eParametersJson(NewParameters));
TArray<TSharedPtr<FJsonValue>> LegacyTrialValues;
@@ -5269,8 +5527,8 @@ int32 RunStep2f(const FString& Params)
"solid=%.3f crumbs=%lld/%lld flakes=%.3f/%.3f grid=%.3f/%.3f "
"detail=%.3f lod95=%.2f roof=%lld floor=%lld"),
Profile, ProfileName, LegacyMedianMs, NewMedianMs, NewSolidFraction,
static_cast<long long>(NewShape.Fragments.AirCrumbsBelowOneCubicMeter),
static_cast<long long>(NewShape.Fragments.SolidCrumbsBelowOneCubicMeter),
static_cast<long long>(NewShape.Fragments.AirCrumbsAfterBoundaryPadding),
static_cast<long long>(NewShape.Fragments.SolidCrumbsAfterBoundaryPadding),
NewShape.Mesh.ShareDihedralsOver45Degrees, NewShape.Detail.LatticeScaleEnergyRatio,
NewShape.Grid.PitchCorrelationPeak, NewShape.Grid.PitchPeakExcess,
NewShape.Detail.Rms, NewShape.Lod1P95SurfaceErrorVoxels,
@@ -5363,7 +5621,7 @@ int32 RunStep2f(const FString& Params)
Step2eCrumbNumbers->SetNumberField(TEXT("crumbs_below_1m3_max"), WorstStep2eCrumbs);
TSharedRef<FJsonObject> Step2fCrumbNumbers = MakeShared<FJsonObject>();
Step2fCrumbNumbers->SetNumberField(TEXT("crumbs_below_1m3_max"), WorstStep2fCrumbs);
AddGate(TEXT("crumbs"), TEXT("zero 25 cm-grid connected components smaller than 64 voxels (about 1 m3)"),
AddGate(TEXT("crumbs"), TEXT("zero 25 cm-grid components smaller than 64 voxels, measured in a 64-sample-padded volume and restricted to components intersecting the 259-cube"),
bStep2eCrumbsRejected, bStep2fCrumbGatePassed, Step2eCrumbNumbers, Step2fCrumbNumbers);
TSharedRef<FJsonObject> Step2eFlakeNumbers = MakeShared<FJsonObject>();
Step2eFlakeNumbers->SetNumberField(TEXT("max_dihedral_share_over_45deg"), WorstStep2eDihedralShare);
@@ -5385,7 +5643,7 @@ int32 RunStep2f(const FString& Params)
Step2eLodNumbers->SetNumberField(TEXT("max_l1_p95_surface_distance_voxels"), WorstStep2eLodDistance);
TSharedRef<FJsonObject> Step2fLodNumbers = MakeShared<FJsonObject>();
Step2fLodNumbers->SetNumberField(TEXT("max_l1_p95_surface_distance_voxels"), WorstStep2fLodDistance);
AddGate(TEXT("lod_stability"), TEXT("L1 mesh p95 estimated distance from the L0 isosurface <= 3.5 lattice samples"),
AddGate(TEXT("lod_stability"), TEXT("L1 mesh p95 estimated distance from the L0 isosurface <= 0.5 lattice samples"),
bStep2eLodRejected, bStep2fLodPassed, Step2eLodNumbers, Step2fLodNumbers);
TSharedRef<FJsonObject> Step2eGridNumbers = MakeShared<FJsonObject>();
Step2eGridNumbers->SetNumberField(TEXT("max_pitch_autocorrelation"), WorstStep2ePitchCorrelation);
@@ -5419,6 +5677,10 @@ int32 RunStep2f(const FString& Params)
Report->SetNumberField(TEXT("step2f_solid_fraction_max"), WorstStep2fSolidFraction);
Report->SetNumberField(TEXT("seed"), Seed);
Report->SetNumberField(TEXT("ring_dimension"), Dimension);
Report->SetArrayField(TEXT("ring_origin_voxels"), {
MakeShared<FJsonValueNumber>(Origin.X),
MakeShared<FJsonValueNumber>(Origin.Y),
MakeShared<FJsonValueNumber>(Origin.Z)});
Report->SetNumberField(TEXT("ring_samples"), static_cast<double>(TotalSamples));
Report->SetNumberField(TEXT("workers_requested"), Workers);
Report->SetNumberField(TEXT("world_prepare_ms_excluded"), WorldPrepareSeconds * 1000.0);
@@ -5427,12 +5689,15 @@ int32 RunStep2f(const FString& Params)
"A conservative nearest-neighbor cap leaves a solid web between chambers; a rooted "
"tree of narrow tunnels and capped shafts joins them. Sparse ledges, pillars, "
"stalactites and large hanging masses remain per-cell rolls. The point and "
"brick detail samplers share three 32/16/8-sample bands with an eight-sample "
"shortest period and a smooth ridge response."));
"brick detail samplers share independently rotated 48/24/12-sample bands with a "
"twelve-sample shortest period and a smooth ridge response; their final-field "
"detail supremum is 3.822 units."));
Report->SetStringField(TEXT("component_method"),
TEXT("26-neighbor connected components are counted on the exact 25 cm sign lattice; "
"components smaller than 64 samples (< 1 m3) are reported separately for air and solid. "
"The existing one-meter downsampled air component count is also reported."));
TEXT("26-neighbor connected components are counted on the exact 25 cm sign lattice. "
"Raw components below 64 samples (< 1 m3) are reported, then a 64-sample pad is "
"evaluated around each 259-cube and only components intersecting the original cube "
"are counted again; this prevents a clipped large component at the ring edge from "
"being called a crumb. The one-meter downsampled air component count is also reported."));
Report->SetStringField(TEXT("mesh_method"),
TEXT("Eight level-0 tiles and one level-1 tile cover the same 64-sample cube selected "
"for maximum coarse-sampled surface crossings. "
@@ -5452,6 +5717,63 @@ int32 RunStep2f(const FString& Params)
static_cast<double>(ProofAudit.CorrectProofSamplesChecked));
Existing->SetNumberField(TEXT("correct_proof_sign_violations"),
static_cast<double>(ProofAudit.CorrectProofViolations));
TSharedRef<FJsonObject> FirstProofViolation = MakeShared<FJsonObject>();
FirstProofViolation->SetBoolField(TEXT("present"), ProofAudit.CorrectProofViolations > 0);
FirstProofViolation->SetArrayField(TEXT("brick_origin_voxels"), {
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickOrigin.X),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickOrigin.Y),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickOrigin.Z)});
FirstProofViolation->SetArrayField(TEXT("brick_size"), {
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickSize.X),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickSize.Y),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationBrickSize.Z)});
FirstProofViolation->SetArrayField(TEXT("sample_voxels"), {
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationSample.X),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationSample.Y),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationSample.Z)});
FirstProofViolation->SetBoolField(TEXT("inside_brick"),
ProofAudit.bFirstViolationWasInsideBrick);
FirstProofViolation->SetBoolField(TEXT("claimed_air"),
ProofAudit.bFirstViolationClaimedAir);
FirstProofViolation->SetNumberField(TEXT("final_density"),
ProofAudit.FirstViolationDensity);
FirstProofViolation->SetNumberField(TEXT("center_macro"),
ProofAudit.FirstViolationCenterMacro);
FirstProofViolation->SetNumberField(TEXT("sample_macro"),
ProofAudit.FirstViolationSampleMacro);
FirstProofViolation->SetNumberField(TEXT("center_room_macro"),
ProofAudit.FirstViolationCenterRoomMacro);
FirstProofViolation->SetNumberField(TEXT("sample_room_macro"),
ProofAudit.FirstViolationSampleRoomMacro);
FirstProofViolation->SetNumberField(TEXT("sample_detail"),
ProofAudit.FirstViolationSampleDetail);
FirstProofViolation->SetNumberField(TEXT("center_to_sample_macro_delta_per_voxel"),
ProofAudit.FirstViolationMacroDeltaPerVoxel);
FirstProofViolation->SetNumberField(TEXT("path_max_macro_gradient"),
ProofAudit.FirstViolationPathMaxGradient);
FirstProofViolation->SetArrayField(TEXT("path_max_from_voxels"), {
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxFrom.X),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxFrom.Y),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxFrom.Z)});
FirstProofViolation->SetArrayField(TEXT("path_max_to_voxels"), {
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxTo.X),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxTo.Y),
MakeShared<FJsonValueNumber>(ProofAudit.FirstViolationPathMaxTo.Z)});
FirstProofViolation->SetNumberField(TEXT("path_max_from_macro"),
ProofAudit.FirstViolationPathMaxFromMacro);
FirstProofViolation->SetNumberField(TEXT("path_max_to_macro"),
ProofAudit.FirstViolationPathMaxToMacro);
FirstProofViolation->SetNumberField(TEXT("path_max_from_room_macro"),
ProofAudit.FirstViolationPathMaxFromRoomMacro);
FirstProofViolation->SetNumberField(TEXT("path_max_to_room_macro"),
ProofAudit.FirstViolationPathMaxToRoomMacro);
FirstProofViolation->SetStringField(TEXT("path_max_from_room_diagnostic"),
ProofAudit.FirstViolationPathMaxFromRoomDiagnostic);
FirstProofViolation->SetStringField(TEXT("path_max_to_room_diagnostic"),
ProofAudit.FirstViolationPathMaxToRoomDiagnostic);
FirstProofViolation->SetNumberField(TEXT("tiny_step_max_macro_gradient"),
ProofAudit.FirstViolationTinyStepMaxGradient);
Existing->SetObjectField(TEXT("first_proof_violation"), FirstProofViolation);
Existing->SetNumberField(TEXT("undersized_bound_claims_checked"),
static_cast<double>(ProofAudit.DeliberatelyUndersizedBoundClaimsChecked));
Existing->SetNumberField(TEXT("wrong_sign_samples_caught_by_undersized_bound"),