research(step2e): 8 parameter profiles, worst 570 ms -- speed gate met, look NOT yet accepted
Editor-only, default off. Seeded chamber graph (jittered XY grid, spanning tree, optional loops, tunnels, shafts, pillars, ledges, spires, floating masses, basins), 8 profiles, four detail bands at every surface-affecting 25 cm sample, sound brick proofs. 259^3 ring, six workers, medians of 3: 404-570 ms (worst TerracedBasin 570.0 ms). Detail, seam, bound-audit (0 violations, undersized control caught), determinism (1 vs 6 workers) and TraversalSeeds all pass; live tests untouched. Not accepted yet: the profiles are 81-97% open air. In the slices a "TightNetwork" is a large void with scattered solid blobs (rooms of 0.5-0.76 x pitch overlap and merge), and the finest detail band shows as salt-and-pepper speckle with 22-109 separate 1 m components per ring: fast partly because air bricks skip, and the look needs the owner's judgement. Also missing vs live: maze, flat/plain, crystal-chamber, surface-world and underwater grammars; water geometry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
f8a46ecf8d
commit
0a7492ffab
38 files changed
+1761
-186
No files matched your search
@@ -2545,6 +2545,18 @@ struct FStep2dBrickProofAudit
|
||||
uint64 CorrectlySkippedBricksAudited = 0;
|
||||
uint64 CorrectProofSamplesChecked = 0;
|
||||
uint64 CorrectProofViolations = 0;
|
||||
FIntVector FirstViolationBrickOrigin = FIntVector::ZeroValue;
|
||||
FIntVector FirstViolationBrickSize = FIntVector::ZeroValue;
|
||||
FIntVector FirstViolationSample = FIntVector::ZeroValue;
|
||||
float FirstViolationDensity = 0.0f;
|
||||
float FirstViolationCenterMacro = 0.0f;
|
||||
float FirstViolationSampleMacro = 0.0f;
|
||||
float FirstViolationSampleDetail = 0.0f;
|
||||
float FirstViolationMacroDeltaPerVoxel = 0.0f;
|
||||
float FirstViolationPathMaxGradient = 0.0f;
|
||||
float FirstViolationTinyStepMaxGradient = 0.0f;
|
||||
bool bFirstViolationWasInsideBrick = false;
|
||||
bool bFirstViolationClaimedAir = false;
|
||||
uint64 DeliberatelyUndersizedBoundClaimsChecked = 0;
|
||||
uint64 DeliberateBoundDisagreements = 0;
|
||||
};
|
||||
@@ -2608,6 +2620,88 @@ FStep2dBrickProofAudit AuditStep2dBrickProofs(
|
||||
++Result.CorrectProofSamplesChecked;
|
||||
if ((Density > 0.0f) != bProvenAir)
|
||||
{
|
||||
if (Result.CorrectProofViolations == 0)
|
||||
{
|
||||
Result.FirstViolationBrickOrigin = BrickOrigin;
|
||||
Result.FirstViolationBrickSize = Size;
|
||||
Result.FirstViolationSample = BrickOrigin + FIntVector(X, Y, Z);
|
||||
Result.FirstViolationDensity = Density;
|
||||
const FVector ProofMin(
|
||||
static_cast<float>(BrickOrigin.X - 1),
|
||||
static_cast<float>(BrickOrigin.Y - 1),
|
||||
static_cast<float>(BrickOrigin.Z - 1));
|
||||
const FVector ProofMax(
|
||||
static_cast<float>(BrickOrigin.X + Size.X),
|
||||
static_cast<float>(BrickOrigin.Y + Size.Y),
|
||||
static_cast<float>(BrickOrigin.Z + Size.Z));
|
||||
const FVector ProofCentre = (ProofMin + ProofMax) * 0.5f;
|
||||
const FVector SamplePoint(
|
||||
static_cast<float>(BrickOrigin.X + X),
|
||||
static_cast<float>(BrickOrigin.Y + Y),
|
||||
static_cast<float>(BrickOrigin.Z + Z));
|
||||
Result.FirstViolationCenterMacro = bParameterized
|
||||
? VoxelForgeRedefinedDensityField::EvaluateParameterized(
|
||||
Generator, ProofCentre.X, ProofCentre.Y, ProofCentre.Z,
|
||||
nullptr, 0.0f)
|
||||
: VoxelForgeRedefinedDensityField::Evaluate(
|
||||
Generator, ProofCentre.X, ProofCentre.Y, ProofCentre.Z,
|
||||
nullptr, 0.0f);
|
||||
Result.FirstViolationSampleMacro = bParameterized
|
||||
? VoxelForgeRedefinedDensityField::EvaluateParameterized(
|
||||
Generator, SamplePoint.X, SamplePoint.Y, SamplePoint.Z,
|
||||
nullptr, 0.0f)
|
||||
: VoxelForgeRedefinedDensityField::Evaluate(
|
||||
Generator, SamplePoint.X, SamplePoint.Y, SamplePoint.Z,
|
||||
nullptr, 0.0f);
|
||||
Result.FirstViolationSampleDetail = Density
|
||||
- Result.FirstViolationSampleMacro;
|
||||
const float CentreDistance = (SamplePoint - ProofCentre).Size();
|
||||
Result.FirstViolationMacroDeltaPerVoxel = CentreDistance > 1.0e-6f
|
||||
? FMath::Abs(Result.FirstViolationCenterMacro
|
||||
- Result.FirstViolationSampleMacro) / CentreDistance
|
||||
: 0.0f;
|
||||
if (CentreDistance > 1.0e-6f)
|
||||
{
|
||||
constexpr int32 PathSteps = 32;
|
||||
float PreviousMacro = Result.FirstViolationSampleMacro;
|
||||
for (int32 PathStep = 1; PathStep <= PathSteps; ++PathStep)
|
||||
{
|
||||
const float Alpha = static_cast<float>(PathStep) / PathSteps;
|
||||
const FVector Point = FMath::Lerp(
|
||||
SamplePoint, ProofCentre, Alpha);
|
||||
const float PathMacro = bParameterized
|
||||
? VoxelForgeRedefinedDensityField::EvaluateParameterized(
|
||||
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);
|
||||
PreviousMacro = PathMacro;
|
||||
}
|
||||
}
|
||||
constexpr float TinyStep = 0.01f;
|
||||
for (int32 Axis = 0; Axis < 3; ++Axis)
|
||||
for (int32 SignIndex = 0; SignIndex < 2; ++SignIndex)
|
||||
{
|
||||
const int32 Sign = SignIndex == 0 ? -1 : 1;
|
||||
FVector Point = SamplePoint;
|
||||
Point[Axis] += static_cast<float>(Sign) * TinyStep;
|
||||
const float NeighborMacro = bParameterized
|
||||
? VoxelForgeRedefinedDensityField::EvaluateParameterized(
|
||||
Generator, Point.X, Point.Y, Point.Z, nullptr, 0.0f)
|
||||
: VoxelForgeRedefinedDensityField::Evaluate(
|
||||
Generator, Point.X, Point.Y, Point.Z, nullptr, 0.0f);
|
||||
Result.FirstViolationTinyStepMaxGradient = FMath::Max(
|
||||
Result.FirstViolationTinyStepMaxGradient,
|
||||
FMath::Abs(NeighborMacro - Result.FirstViolationSampleMacro)
|
||||
/ TinyStep);
|
||||
}
|
||||
Result.bFirstViolationWasInsideBrick = X >= 0 && X < Size.X
|
||||
&& Y >= 0 && Y < Size.Y && Z >= 0 && Z < Size.Z;
|
||||
Result.bFirstViolationClaimedAir = bProvenAir;
|
||||
}
|
||||
++Result.CorrectProofViolations;
|
||||
}
|
||||
}
|
||||
@@ -2805,6 +2899,17 @@ FStep2dBoundaryStats ComputeStep2dBoundaryStats(
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Step2eBoundaryStatsPass(const FStep2dBoundaryStats& Stats)
|
||||
{
|
||||
return Stats.BrickBoundarySamples > 0
|
||||
&& Stats.InteriorSamples > 0
|
||||
&& Stats.ChunkBoundarySamples > 0
|
||||
&& Stats.FeatureCellBoundarySamples > 0
|
||||
&& Stats.BrickJumpRms <= Stats.InteriorJumpRms * 2.0 + 0.25
|
||||
&& Stats.ChunkBoundaryJumpRms <= Stats.InteriorJumpRms * 2.0 + 0.25
|
||||
&& Stats.FeatureCellJumpRms <= Stats.FeatureCellInteriorJumpRms * 2.0 + 0.25;
|
||||
}
|
||||
|
||||
FColor Step2dDensityColor(float Density)
|
||||
{
|
||||
if (FMath::Abs(Density) < 1.0f)
|
||||
@@ -2868,6 +2973,9 @@ struct FStep2eVarietyMetrics
|
||||
double SurfaceAreaSquareMeters = 0.0;
|
||||
double SurfaceAreaPerVolume = 0.0;
|
||||
double VerticalAdjacencyShare = 0.0;
|
||||
double VerticalAirColumnShare = 0.0;
|
||||
double MeanLongestVerticalAirRunVoxels = 0.0;
|
||||
int32 LongestVerticalAirRunVoxels = 0;
|
||||
double TunnelNeckShare = 0.0;
|
||||
int32 ConnectedComponentsAtOneMeter = 0;
|
||||
int64 LargestComponentCubicMeters = 0;
|
||||
@@ -2886,6 +2994,11 @@ FStep2eVarietyMetrics ComputeStep2eVarietyMetrics(
|
||||
uint64 SurfaceEdgeCount = 0;
|
||||
uint64 HorizontalAdjacencies = 0;
|
||||
uint64 VerticalAdjacencies = 0;
|
||||
const int32 ColumnCount = Dimension * Dimension;
|
||||
TArray<int32> CurrentVerticalRun;
|
||||
CurrentVerticalRun.SetNumZeroed(ColumnCount);
|
||||
TArray<int32> LongestVerticalRun;
|
||||
LongestVerticalRun.SetNumZeroed(ColumnCount);
|
||||
for (int32 Z = 0; Z < Dimension; ++Z)
|
||||
for (int32 Y = 0; Y < Dimension; ++Y)
|
||||
for (int32 X = 0; X < Dimension; ++X)
|
||||
@@ -2893,6 +3006,10 @@ FStep2eVarietyMetrics ComputeStep2eVarietyMetrics(
|
||||
const int32 Index = (Z * Dimension + Y) * Dimension + X;
|
||||
const bool bAir = Density[Index] > 0.0f;
|
||||
AirCount += bAir ? 1 : 0;
|
||||
const int32 ColumnIndex = Y * Dimension + X;
|
||||
CurrentVerticalRun[ColumnIndex] = bAir ? CurrentVerticalRun[ColumnIndex] + 1 : 0;
|
||||
LongestVerticalRun[ColumnIndex] = FMath::Max(
|
||||
LongestVerticalRun[ColumnIndex], CurrentVerticalRun[ColumnIndex]);
|
||||
if (X + 1 < Dimension)
|
||||
{
|
||||
const bool bNextAir = Density[Index + 1] > 0.0f;
|
||||
@@ -2922,6 +3039,22 @@ FStep2eVarietyMetrics ComputeStep2eVarietyMetrics(
|
||||
const uint64 AllAdjacencies = HorizontalAdjacencies + VerticalAdjacencies;
|
||||
Result.VerticalAdjacencyShare = AllAdjacencies > 0
|
||||
? static_cast<double>(VerticalAdjacencies) / AllAdjacencies : 0.0;
|
||||
uint64 ColumnsWithAir = 0;
|
||||
uint64 TotalLongestRunVoxels = 0;
|
||||
for (const int32 LongestRun : LongestVerticalRun)
|
||||
{
|
||||
if (LongestRun > 0)
|
||||
{
|
||||
++ColumnsWithAir;
|
||||
TotalLongestRunVoxels += static_cast<uint64>(LongestRun);
|
||||
Result.LongestVerticalAirRunVoxels = FMath::Max(
|
||||
Result.LongestVerticalAirRunVoxels, LongestRun);
|
||||
}
|
||||
}
|
||||
Result.VerticalAirColumnShare = ColumnCount > 0
|
||||
? static_cast<double>(ColumnsWithAir) / ColumnCount : 0.0;
|
||||
Result.MeanLongestVerticalAirRunVoxels = ColumnsWithAir > 0
|
||||
? static_cast<double>(TotalLongestRunVoxels) / ColumnsWithAir : 0.0;
|
||||
|
||||
constexpr int32 CoarseStep = 4;
|
||||
const int32 CoarseDimension = (Dimension - 1) / CoarseStep + 1;
|
||||
@@ -3056,6 +3189,90 @@ TSharedRef<FJsonObject> Step2eParametersJson(
|
||||
return Json;
|
||||
}
|
||||
|
||||
TSharedRef<FJsonObject> Step2eChamberVolumeQuantilesJson(
|
||||
const VoxelForgeRedefinedDensityField::FGenerationParameters& P)
|
||||
{
|
||||
TSharedRef<FJsonObject> Json = MakeShared<FJsonObject>();
|
||||
constexpr double Pi = 3.14159265358979323846;
|
||||
constexpr double CubicMetersPerVoxel = 0.25 * 0.25 * 0.25;
|
||||
const double Quantiles[] = {0.10, 0.50, 0.90};
|
||||
const TCHAR* Names[] = {TEXT("p10_m3"), TEXT("p50_m3"), TEXT("p90_m3")};
|
||||
for (int32 Index = 0; Index < UE_ARRAY_COUNT(Quantiles); ++Index)
|
||||
{
|
||||
const double RadiusFraction = FMath::Lerp(
|
||||
static_cast<double>(P.MinimumRoomRadiusFraction),
|
||||
static_cast<double>(P.MaximumRoomRadiusFraction), Quantiles[Index]);
|
||||
const double RadiusVoxels = RadiusFraction * P.RoomPitchVoxels;
|
||||
const double VolumeCubicVoxels = Pi * RadiusVoxels * RadiusVoxels
|
||||
* P.RoomHeightVoxels;
|
||||
Json->SetNumberField(Names[Index], VolumeCubicVoxels * CubicMetersPerVoxel);
|
||||
}
|
||||
return Json;
|
||||
}
|
||||
|
||||
TSharedRef<FJsonObject> Step2eParameterRangesJson()
|
||||
{
|
||||
using FParameters = VoxelForgeRedefinedDensityField::FGenerationParameters;
|
||||
struct FParameterRange
|
||||
{
|
||||
const TCHAR* Name;
|
||||
float FParameters::*Value;
|
||||
};
|
||||
static const FParameterRange Fields[] = {
|
||||
{TEXT("room_pitch_voxels"), &FParameters::RoomPitchVoxels},
|
||||
{TEXT("room_radius_fraction_min"), &FParameters::MinimumRoomRadiusFraction},
|
||||
{TEXT("room_radius_fraction_max"), &FParameters::MaximumRoomRadiusFraction},
|
||||
{TEXT("room_height_voxels"), &FParameters::RoomHeightVoxels},
|
||||
{TEXT("floor_relief_voxels"), &FParameters::FloorReliefVoxels},
|
||||
{TEXT("tunnel_radius_voxels"), &FParameters::TunnelRadiusVoxels},
|
||||
{TEXT("tunnel_half_height_voxels"), &FParameters::TunnelHalfHeightVoxels},
|
||||
{TEXT("loop_probability"), &FParameters::LoopProbability},
|
||||
{TEXT("vertical_shaft_probability"), &FParameters::VerticalShaftProbability},
|
||||
{TEXT("shaft_radius_voxels"), &FParameters::ShaftRadiusVoxels},
|
||||
{TEXT("pillar_probability"), &FParameters::PillarProbability},
|
||||
{TEXT("ledge_probability"), &FParameters::LedgeProbability},
|
||||
{TEXT("floating_mass_probability"), &FParameters::FloatingMassProbability},
|
||||
{TEXT("stalactite_stalagmite_probability"), &FParameters::SpireProbability},
|
||||
{TEXT("basin_probability"), &FParameters::BasinProbability},
|
||||
{TEXT("basin_depth_voxels"), &FParameters::BasinDepthVoxels},
|
||||
{TEXT("water_level_fraction"), &FParameters::WaterLevelFraction},
|
||||
};
|
||||
|
||||
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
|
||||
for (const FParameterRange& Field : Fields)
|
||||
{
|
||||
float Minimum = FLT_MAX;
|
||||
float Maximum = -FLT_MAX;
|
||||
for (int32 ProfileIndex = 0;
|
||||
ProfileIndex < VoxelForgeRedefinedDensityField::GetParameterSetCount();
|
||||
++ProfileIndex)
|
||||
{
|
||||
const TCHAR* Name = nullptr;
|
||||
FParameters Parameters;
|
||||
if (!VoxelForgeRedefinedDensityField::GetParameterSetInfo(
|
||||
ProfileIndex, Name, Parameters))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const float Value = Parameters.*(Field.Value);
|
||||
Minimum = FMath::Min(Minimum, Value);
|
||||
Maximum = FMath::Max(Maximum, Value);
|
||||
}
|
||||
TSharedRef<FJsonObject> Bounds = MakeShared<FJsonObject>();
|
||||
Bounds->SetNumberField(TEXT("minimum_across_profiles"), Minimum);
|
||||
Bounds->SetNumberField(TEXT("maximum_across_profiles"), Maximum);
|
||||
Result->SetObjectField(Field.Name, Bounds);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Step2eSameWorkerRun(
|
||||
const VoxelForgeRegionEval::FTiming& A,
|
||||
const VoxelForgeRegionEval::FTiming& B)
|
||||
{
|
||||
return A.QuantizedHash == B.QuantizedHash && A.RawFloatHash == B.RawFloatHash;
|
||||
}
|
||||
|
||||
TSharedRef<FJsonObject> Step2dTimingJson(const VoxelForgeRegionEval::FTiming& Timing)
|
||||
{
|
||||
TSharedRef<FJsonObject> Json = MakeShared<FJsonObject>();
|
||||
@@ -3653,6 +3870,8 @@ int32 RunStep2e(const FString& Params)
|
||||
Row->SetNumberField(TEXT("profile_index"), Profile);
|
||||
Row->SetStringField(TEXT("name"), ProfileName);
|
||||
Row->SetObjectField(TEXT("parameters"), Step2eParametersJson(ProfileParameters));
|
||||
Row->SetObjectField(TEXT("nominal_chamber_volume_quantiles_m3"),
|
||||
Step2eChamberVolumeQuantilesJson(ProfileParameters));
|
||||
Row->SetNumberField(TEXT("six_worker_ring_median_ms"), MedianMs);
|
||||
TArray<TSharedPtr<FJsonValue>> TrialValues;
|
||||
TrialValues.Add(MakeShared<FJsonValueNumber>(Times[0]));
|
||||
@@ -3664,6 +3883,11 @@ int32 RunStep2e(const FString& Params)
|
||||
Row->SetNumberField(TEXT("estimated_surface_area_per_volume_m_inv"),
|
||||
Variety.SurfaceAreaPerVolume);
|
||||
Row->SetNumberField(TEXT("vertical_air_adjacency_share"), Variety.VerticalAdjacencyShare);
|
||||
Row->SetNumberField(TEXT("vertical_air_column_share"), Variety.VerticalAirColumnShare);
|
||||
Row->SetNumberField(TEXT("mean_longest_vertical_air_run_voxels"),
|
||||
Variety.MeanLongestVerticalAirRunVoxels);
|
||||
Row->SetNumberField(TEXT("longest_vertical_air_run_voxels"),
|
||||
Variety.LongestVerticalAirRunVoxels);
|
||||
Row->SetNumberField(TEXT("one_meter_tunnel_neck_share"), Variety.TunnelNeckShare);
|
||||
Row->SetNumberField(TEXT("one_meter_connected_components"),
|
||||
Variety.ConnectedComponentsAtOneMeter);
|
||||
@@ -3675,6 +3899,17 @@ int32 RunStep2e(const FString& Params)
|
||||
Row->SetNumberField(TEXT("skipped_bricks"), static_cast<double>(LastTiming.SkippedBricks));
|
||||
Row->SetNumberField(TEXT("skipped_sample_fraction"), LastTiming.SampleCount > 0
|
||||
? static_cast<double>(LastTiming.SkippedSamples) / LastTiming.SampleCount : 0.0);
|
||||
Row->SetNumberField(TEXT("evaluated_samples"),
|
||||
static_cast<double>(LastTiming.EvaluatedSamples));
|
||||
Row->SetNumberField(TEXT("worker_cpu_seconds"), LastTiming.WorkerCpuSeconds);
|
||||
Row->SetNumberField(TEXT("brick_classification_worker_ms"),
|
||||
LastTiming.BrickClassificationSeconds * 1000.0);
|
||||
Row->SetNumberField(TEXT("density_evaluation_worker_ms"),
|
||||
LastTiming.DensityEvaluationSeconds * 1000.0);
|
||||
Row->SetNumberField(TEXT("uniform_fill_worker_ms"),
|
||||
LastTiming.UniformFillSeconds * 1000.0);
|
||||
Row->SetNumberField(TEXT("longest_worker_ms"),
|
||||
LastTiming.LongestWorkerWallSeconds * 1000.0);
|
||||
|
||||
FString SafeName(ProfileName);
|
||||
SafeName.ToLowerInline();
|
||||
@@ -3778,26 +4013,41 @@ int32 RunStep2e(const FString& Params)
|
||||
const FStep2dBoundaryStats BoundaryStats = ComputeStep2dBoundaryStats(
|
||||
HardestFullDensity, Dimension, Origin,
|
||||
FMath::RoundToInt(HardestParameters.RoomPitchVoxels));
|
||||
TArray<float> SeamFailureDensity = HardestFullDensity;
|
||||
int64 DeliberateSeamSamplesMutated = 0;
|
||||
for (int32 Z = 1; Z < Dimension - 1; ++Z)
|
||||
for (int32 Y = 1; Y < Dimension - 1; ++Y)
|
||||
for (int32 X = 1; X < Dimension - 1; ++X)
|
||||
{
|
||||
const int32 Index = (Z * Dimension + Y) * Dimension + X;
|
||||
if (((Origin.X + X) % 8) == 0 && FMath::Abs(HardestFullDensity[Index]) <= 12.0f)
|
||||
{
|
||||
SeamFailureDensity[Index + 1] += 64.0f;
|
||||
++DeliberateSeamSamplesMutated;
|
||||
}
|
||||
}
|
||||
const FStep2dBoundaryStats SeamFailureStats = ComputeStep2dBoundaryStats(
|
||||
SeamFailureDensity, Dimension, Origin,
|
||||
FMath::RoundToInt(HardestParameters.RoomPitchVoxels));
|
||||
const FStep2dBrickProofAudit ProofAudit = AuditStep2dBrickProofs(
|
||||
*World.Generator, Origin, Dimension, true);
|
||||
const uint64 HardestHash = VoxelForgeRegionEval::HashQuantized(HardestFullDensity);
|
||||
const uint64 RepeatHash = VoxelForgeRegionEval::HashQuantized(RepeatFullDensity);
|
||||
const uint64 OneWorkerHash = VoxelForgeRegionEval::HashQuantized(OneWorkerDensity);
|
||||
const bool bDeterminism = HardestHash == RepeatHash && HardestHash == OneWorkerHash
|
||||
&& HardestFullTiming.RawFloatHash == RepeatTiming.RawFloatHash
|
||||
&& HardestFullTiming.RawFloatHash == OneWorkerTiming.RawFloatHash;
|
||||
&& Step2eSameWorkerRun(HardestFullTiming, RepeatTiming)
|
||||
&& Step2eSameWorkerRun(HardestFullTiming, OneWorkerTiming);
|
||||
VoxelForgeRegionEval::FTiming DeliberateMismatch = HardestFullTiming;
|
||||
DeliberateMismatch.QuantizedHash ^= 1u;
|
||||
const bool bDeliberateDeterminismMismatchCaught =
|
||||
!Step2eSameWorkerRun(HardestFullTiming, DeliberateMismatch);
|
||||
const bool bDetailAtLeastLive = NewSpectrum.RMSLag1 >= OldSpectrum.RMSLag1
|
||||
&& NewSpectrum.RMSLag2 >= OldSpectrum.RMSLag2;
|
||||
const bool bSmoothingControlCaught = SmoothSpectrum.RMSLag1 < NewSpectrum.RMSLag1 * 0.80
|
||||
|| SmoothSpectrum.RMSLag2 < NewSpectrum.RMSLag2 * 0.80;
|
||||
const bool bBoundaryPass = BoundaryStats.BrickBoundarySamples > 0
|
||||
&& BoundaryStats.InteriorSamples > 0
|
||||
&& BoundaryStats.ChunkBoundarySamples > 0
|
||||
&& BoundaryStats.FeatureCellBoundarySamples > 0
|
||||
&& BoundaryStats.BrickJumpRms <= BoundaryStats.InteriorJumpRms * 2.0 + 0.25
|
||||
&& BoundaryStats.ChunkBoundaryJumpRms <= BoundaryStats.InteriorJumpRms * 2.0 + 0.25
|
||||
&& BoundaryStats.FeatureCellJumpRms
|
||||
<= BoundaryStats.FeatureCellInteriorJumpRms * 2.0 + 0.25;
|
||||
const bool bBoundaryPass = Step2eBoundaryStatsPass(BoundaryStats);
|
||||
const bool bDeliberateSeamFailureCaught = DeliberateSeamSamplesMutated > 0
|
||||
&& !Step2eBoundaryStatsPass(SeamFailureStats);
|
||||
const bool bBoundAudit = ProofAudit.CorrectlySkippedBricksAudited > 0
|
||||
&& ProofAudit.CorrectProofSamplesChecked > 0
|
||||
&& ProofAudit.CorrectProofViolations == 0;
|
||||
@@ -3810,6 +4060,7 @@ int32 RunStep2e(const FString& Params)
|
||||
const bool bSpeedPass = Workers == 6 && bProfilePasses && WorstMedianMs <= 600.0;
|
||||
const bool bPassed = bSpeedPass && bDeterminism && bDetailAtLeastLive
|
||||
&& bSmoothingControlCaught && bDetailParity && bBoundaryPass
|
||||
&& bDeliberateSeamFailureCaught && bDeliberateDeterminismMismatchCaught
|
||||
&& bBoundAudit && bUndersizedBoundCaught
|
||||
&& HardestFullTiming.NonFiniteSamples == 0;
|
||||
|
||||
@@ -3832,13 +4083,19 @@ int32 RunStep2e(const FString& Params)
|
||||
"rock masses and a bowl floor with an explicit water level. Passage pads and anchor "
|
||||
"tunnels join the authored inter-strate route to the generated network."));
|
||||
Report->SetStringField(TEXT("parameter_space"),
|
||||
TEXT("Eight named profiles can be assigned per strate from a seed hash (-1 mode), or "
|
||||
"forced for measurement. Each profile rolls cell placement and feature choices from "
|
||||
"the world seed and strate index; see parameters and documented ranges in the report."));
|
||||
TEXT("Eight named profiles can be assigned per strate from a stable seed hash (-1 mode), "
|
||||
"or forced for measurement. Each profile supplies nominal room, tunnel, shaft, "
|
||||
"feature-probability and basin values. Per-cell hashes deterministically roll room "
|
||||
"jitter and feature presence. Profile minima and maxima are recorded below; room "
|
||||
"height is clamped to the strate span, room radii to 0.20-0.72/0.80 of pitch, "
|
||||
"loop probability to 0-0.8, probabilities and water level to 0-1, and basin depth "
|
||||
"to 0-48 voxels."));
|
||||
Report->SetObjectField(TEXT("parameter_ranges_across_eight_profiles"),
|
||||
Step2eParameterRangesJson());
|
||||
Report->SetStringField(TEXT("resolution_contract"),
|
||||
TEXT("One exact field sample per 25 cm lattice point. The four existing 8/4/2/1-sample "
|
||||
"detail bands are evaluated for every potentially surface-affecting point; no coarse "
|
||||
"field is interpolated onto the lattice. 8-cubed skips require the final macro field "
|
||||
"field is interpolated onto the lattice. 4-cubed step 2e skips require the final macro field "
|
||||
"Lipschitz interval plus the full 5.25-unit detail supremum and marching-cubes halo."));
|
||||
Report->SetStringField(TEXT("finer_lattice_scaling"),
|
||||
TEXT("For 12.5 cm voxels, double room pitch, room height, tunnel/feature dimensions and "
|
||||
@@ -3848,9 +4105,11 @@ int32 RunStep2e(const FString& Params)
|
||||
"remain cheap. This scale has not been timed."));
|
||||
Report->SetStringField(TEXT("variety_metric_method"),
|
||||
TEXT("Open fraction uses every ring sample. Surface area estimates sign-changing lattice "
|
||||
"edges times 0.25 m squared. Chamber-size bins, connected components and tunnel-neck "
|
||||
"share use a 1 m downsampled six-neighbor occupancy grid; verticality is the share of "
|
||||
"open 1-cell adjacencies that point vertically."));
|
||||
"edges times 0.25 m squared. Nominal chamber-volume p10/p50/p90 values use the "
|
||||
"uniform per-cell radius roll and room height as circular-cylinder volumes. Tunnel-neck "
|
||||
"share and connected-component sizes use a 1 m downsampled six-neighbor occupancy grid. "
|
||||
"Verticality is the mean longest contiguous open run per XY column, with open-column "
|
||||
"coverage reported separately."));
|
||||
Report->SetStringField(TEXT("water_geometry_limit"),
|
||||
TEXT("Basin profiles generate the bowl floor and water-level parameter; this density field "
|
||||
"does not render or simulate water."));
|
||||
@@ -3884,6 +4143,10 @@ int32 RunStep2e(const FString& Params)
|
||||
Boundary->SetNumberField(TEXT("feature_cell_boundary_gradient_jump_rms"), BoundaryStats.FeatureCellJumpRms);
|
||||
Boundary->SetNumberField(TEXT("feature_cell_interior_gradient_jump_rms"), BoundaryStats.FeatureCellInteriorJumpRms);
|
||||
Boundary->SetBoolField(TEXT("boundary_artifact_check_pass"), bBoundaryPass);
|
||||
Boundary->SetNumberField(TEXT("deliberate_seam_samples_mutated"),
|
||||
static_cast<double>(DeliberateSeamSamplesMutated));
|
||||
Boundary->SetBoolField(TEXT("deliberate_seam_failure_caught"),
|
||||
bDeliberateSeamFailureCaught);
|
||||
Report->SetObjectField(TEXT("boundary_artifact_check"), Boundary);
|
||||
|
||||
TSharedRef<FJsonObject> Proofs = MakeShared<FJsonObject>();
|
||||
@@ -3893,6 +4156,32 @@ int32 RunStep2e(const FString& Params)
|
||||
static_cast<double>(ProofAudit.CorrectProofSamplesChecked));
|
||||
Proofs->SetNumberField(TEXT("correct_proof_sign_violations"),
|
||||
static_cast<double>(ProofAudit.CorrectProofViolations));
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_x"), ProofAudit.FirstViolationBrickOrigin.X);
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_y"), ProofAudit.FirstViolationBrickOrigin.Y);
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_z"), ProofAudit.FirstViolationBrickOrigin.Z);
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_size_x"), ProofAudit.FirstViolationBrickSize.X);
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_size_y"), ProofAudit.FirstViolationBrickSize.Y);
|
||||
Proofs->SetNumberField(TEXT("first_violation_brick_size_z"), ProofAudit.FirstViolationBrickSize.Z);
|
||||
Proofs->SetNumberField(TEXT("first_violation_sample_x"), ProofAudit.FirstViolationSample.X);
|
||||
Proofs->SetNumberField(TEXT("first_violation_sample_y"), ProofAudit.FirstViolationSample.Y);
|
||||
Proofs->SetNumberField(TEXT("first_violation_sample_z"), ProofAudit.FirstViolationSample.Z);
|
||||
Proofs->SetNumberField(TEXT("first_violation_density"), ProofAudit.FirstViolationDensity);
|
||||
Proofs->SetNumberField(TEXT("first_violation_center_macro"),
|
||||
ProofAudit.FirstViolationCenterMacro);
|
||||
Proofs->SetNumberField(TEXT("first_violation_sample_macro"),
|
||||
ProofAudit.FirstViolationSampleMacro);
|
||||
Proofs->SetNumberField(TEXT("first_violation_sample_detail"),
|
||||
ProofAudit.FirstViolationSampleDetail);
|
||||
Proofs->SetNumberField(TEXT("first_violation_macro_delta_per_voxel"),
|
||||
ProofAudit.FirstViolationMacroDeltaPerVoxel);
|
||||
Proofs->SetNumberField(TEXT("first_violation_path_max_gradient"),
|
||||
ProofAudit.FirstViolationPathMaxGradient);
|
||||
Proofs->SetNumberField(TEXT("first_violation_tiny_step_max_gradient"),
|
||||
ProofAudit.FirstViolationTinyStepMaxGradient);
|
||||
Proofs->SetBoolField(TEXT("first_violation_inside_proven_brick"),
|
||||
ProofAudit.bFirstViolationWasInsideBrick);
|
||||
Proofs->SetBoolField(TEXT("first_violation_claimed_air"),
|
||||
ProofAudit.bFirstViolationClaimedAir);
|
||||
Proofs->SetNumberField(TEXT("undersized_bound_claims_checked"),
|
||||
static_cast<double>(ProofAudit.DeliberatelyUndersizedBoundClaimsChecked));
|
||||
Proofs->SetNumberField(TEXT("wrong_sign_samples_caught_by_undersized_bound"),
|
||||
@@ -3915,6 +4204,8 @@ int32 RunStep2e(const FString& Params)
|
||||
Determinism->SetStringField(TEXT("one_worker_raw_float"), FString::Printf(
|
||||
TEXT("%016llx"), static_cast<unsigned long long>(OneWorkerTiming.RawFloatHash)));
|
||||
Determinism->SetBoolField(TEXT("same_across_two_runs_and_1_vs_6_workers"), bDeterminism);
|
||||
Determinism->SetBoolField(TEXT("deliberate_quantized_hash_mismatch_rejected"),
|
||||
bDeliberateDeterminismMismatchCaught);
|
||||
Report->SetObjectField(TEXT("determinism"), Determinism);
|
||||
Report->SetBoolField(TEXT("entrance_exit_walkability_test_added"), true);
|
||||
Report->SetBoolField(TEXT("inter_strate_passage_open_space_test_added"), true);
|
||||
|
||||
@@ -181,27 +181,30 @@ namespace VoxelForgeRegionEval
|
||||
TArray<FResearchBrick> Bricks;
|
||||
const FIntVector Last = OriginVoxels
|
||||
+ FIntVector(Dimension - 1, Dimension - 1, Dimension - 1);
|
||||
const FIntVector ProofBrickSize = bParameterized
|
||||
? FIntVector(4, 4, 4) : FIntVector(8, 8, 8);
|
||||
const FIntVector FirstBrick(
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.X) / 8.0f),
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.Y) / 8.0f),
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.Z) / 8.0f));
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.X) / ProofBrickSize.X),
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.Y) / ProofBrickSize.Y),
|
||||
FMath::FloorToInt(static_cast<float>(OriginVoxels.Z) / ProofBrickSize.Z));
|
||||
const FIntVector LastBrick(
|
||||
FMath::FloorToInt(static_cast<float>(Last.X) / 8.0f),
|
||||
FMath::FloorToInt(static_cast<float>(Last.Y) / 8.0f),
|
||||
FMath::FloorToInt(static_cast<float>(Last.Z) / 8.0f));
|
||||
FMath::FloorToInt(static_cast<float>(Last.X) / ProofBrickSize.X),
|
||||
FMath::FloorToInt(static_cast<float>(Last.Y) / ProofBrickSize.Y),
|
||||
FMath::FloorToInt(static_cast<float>(Last.Z) / ProofBrickSize.Z));
|
||||
Bricks.Reserve((LastBrick.X - FirstBrick.X + 1)
|
||||
* (LastBrick.Y - FirstBrick.Y + 1) * (LastBrick.Z - FirstBrick.Z + 1));
|
||||
for (int32 BZ = FirstBrick.Z; BZ <= LastBrick.Z; ++BZ)
|
||||
for (int32 BY = FirstBrick.Y; BY <= LastBrick.Y; ++BY)
|
||||
for (int32 BX = FirstBrick.X; BX <= LastBrick.X; ++BX)
|
||||
{
|
||||
const FIntVector BrickWorldMin(BX * 8, BY * 8, BZ * 8);
|
||||
const FIntVector BrickWorldMin(
|
||||
BX * ProofBrickSize.X, BY * ProofBrickSize.Y, BZ * ProofBrickSize.Z);
|
||||
FResearchBrick& Brick = Bricks.AddDefaulted_GetRef();
|
||||
Brick.Origin = FIntVector(
|
||||
FMath::Max(OriginVoxels.X, BrickWorldMin.X),
|
||||
FMath::Max(OriginVoxels.Y, BrickWorldMin.Y),
|
||||
FMath::Max(OriginVoxels.Z, BrickWorldMin.Z));
|
||||
const FIntVector BrickEnd = BrickWorldMin + FIntVector(8, 8, 8);
|
||||
const FIntVector BrickEnd = BrickWorldMin + ProofBrickSize;
|
||||
const FIntVector RingEnd = OriginVoxels
|
||||
+ FIntVector(Dimension, Dimension, Dimension);
|
||||
const FIntVector End(
|
||||
@@ -315,28 +318,62 @@ namespace VoxelForgeRegionEval
|
||||
VoxelForgeRedefinedDensityField::BuildParameterizedBrickContext(
|
||||
Generator, Brick.Origin, Brick.Size, ParameterizedBrickContext);
|
||||
}
|
||||
for (int32 Z = 0; Z < Brick.Size.Z; ++Z)
|
||||
for (int32 Y = 0; Y < Brick.Size.Y; ++Y)
|
||||
for (int32 X = 0; X < Brick.Size.X; ++X)
|
||||
if (bParameterized)
|
||||
{
|
||||
const int32 WorldX = Brick.Origin.X + X;
|
||||
const int32 WorldY = Brick.Origin.Y + Y;
|
||||
const int32 WorldZ = Brick.Origin.Z + Z;
|
||||
const int64 LatticeIndex = LinearIndex(
|
||||
Brick.Lattice.X + X, Brick.Lattice.Y + Y,
|
||||
Brick.Lattice.Z + Z, Dimension);
|
||||
const float DetailValue = BrickDetail[
|
||||
(Z * Brick.Size.Y + Y) * Brick.Size.X + X];
|
||||
OutDensities[static_cast<int32>(LatticeIndex)] = bParameterized
|
||||
? VoxelForgeRedefinedDensityField::EvaluateParameterizedWithDetailValue(
|
||||
Generator, static_cast<float>(WorldX), static_cast<float>(WorldY),
|
||||
static_cast<float>(WorldZ), DetailValue, nullptr, DetailScale,
|
||||
&ParameterizedBrickContext)
|
||||
: VoxelForgeRedefinedDensityField::EvaluateWithDetailValue(
|
||||
Generator, static_cast<float>(WorldX), static_cast<float>(WorldY),
|
||||
static_cast<float>(WorldZ), DetailValue,
|
||||
nullptr, DetailScale, &BrickContext);
|
||||
++WorkerEvaluated[WorkerIndex];
|
||||
const int32 DetailStride = Brick.Size.X * Brick.Size.Y;
|
||||
float ColumnValues[8] = {};
|
||||
float ParameterizedBrickValues[8 * 8 * 8];
|
||||
for (int32 Y = 0; Y < Brick.Size.Y; ++Y)
|
||||
for (int32 X = 0; X < Brick.Size.X; ++X)
|
||||
{
|
||||
const int32 DetailBase = Y * Brick.Size.X + X;
|
||||
VoxelForgeRedefinedDensityField::EvaluateParameterizedColumnWithDetailValues(
|
||||
Generator, static_cast<float>(Brick.Origin.X + X),
|
||||
static_cast<float>(Brick.Origin.Y + Y),
|
||||
static_cast<float>(Brick.Origin.Z),
|
||||
BrickDetail.GetData() + DetailBase, DetailStride,
|
||||
Brick.Size.Z, ColumnValues,
|
||||
&ParameterizedBrickContext, DetailScale);
|
||||
for (int32 Z = 0; Z < Brick.Size.Z; ++Z)
|
||||
{
|
||||
ParameterizedBrickValues[(Z * Brick.Size.Y + Y)
|
||||
* Brick.Size.X + X] = ColumnValues[Z];
|
||||
}
|
||||
}
|
||||
for (int32 Z = 0; Z < Brick.Size.Z; ++Z)
|
||||
for (int32 Y = 0; Y < Brick.Size.Y; ++Y)
|
||||
{
|
||||
const int64 LatticeIndex = LinearIndex(
|
||||
Brick.Lattice.X, Brick.Lattice.Y + Y,
|
||||
Brick.Lattice.Z + Z, Dimension);
|
||||
const int32 LocalIndex = (Z * Brick.Size.Y + Y) * Brick.Size.X;
|
||||
FMemory::Memcpy(OutDensities.GetData() + LatticeIndex,
|
||||
ParameterizedBrickValues + LocalIndex,
|
||||
static_cast<SIZE_T>(Brick.Size.X) * sizeof(float));
|
||||
}
|
||||
WorkerEvaluated[WorkerIndex] += static_cast<uint64>(Brick.SampleCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int32 Z = 0; Z < Brick.Size.Z; ++Z)
|
||||
for (int32 Y = 0; Y < Brick.Size.Y; ++Y)
|
||||
for (int32 X = 0; X < Brick.Size.X; ++X)
|
||||
{
|
||||
const int32 WorldX = Brick.Origin.X + X;
|
||||
const int32 WorldY = Brick.Origin.Y + Y;
|
||||
const int32 WorldZ = Brick.Origin.Z + Z;
|
||||
const int64 LatticeIndex = LinearIndex(
|
||||
Brick.Lattice.X + X, Brick.Lattice.Y + Y,
|
||||
Brick.Lattice.Z + Z, Dimension);
|
||||
const float DetailValue = BrickDetail[
|
||||
(Z * Brick.Size.Y + Y) * Brick.Size.X + X];
|
||||
OutDensities[static_cast<int32>(LatticeIndex)] =
|
||||
VoxelForgeRedefinedDensityField::EvaluateWithDetailValue(
|
||||
Generator, static_cast<float>(WorldX), static_cast<float>(WorldY),
|
||||
static_cast<float>(WorldZ), DetailValue,
|
||||
nullptr, DetailScale, &BrickContext);
|
||||
++WorkerEvaluated[WorkerIndex];
|
||||
}
|
||||
}
|
||||
WorkerEvaluate[WorkerIndex] += FPlatformTime::Seconds() - EvaluationStart;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user