Stopped by low memory (another app held 12.5 GB; processes failed with 0xC0000142). Editor-only, default off: a seeded connected room graph (varied chambers on a spanning network, optional loops, shafts, rock features, ledges, basin floors), eight parameter profiles, the step-2d brick driver and detail bands, a new test VoxelForge.ParameterizedGeneration.TraversalSeeds (PASS in step2e_functional_01, which also proves the tree compiles). Existing live tests untouched. Not yet run: the eight-profile ring benchmark, variety metrics, slices, detail/artefact/determinism checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
152 lines
6.9 KiB
C++
152 lines
6.9 KiB
C++
#if WITH_DEV_AUTOMATION_TESTS
|
|
|
|
#include "Misc/AutomationTest.h"
|
|
|
|
#include "VoxelForgeTestFixture.h"
|
|
#include "VoxelRedefinedDensityField.h"
|
|
#include "VoxelStrateMeasure.h"
|
|
|
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
|
FVoxelForgeParameterizedGenerationTraversalSeedsTest,
|
|
"VoxelForge.ParameterizedGeneration.TraversalSeeds",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
|
|
|
|
bool FVoxelForgeParameterizedGenerationTraversalSeedsTest::RunTest(const FString& Parameters)
|
|
{
|
|
(void)Parameters;
|
|
struct FRestoreResearchFields
|
|
{
|
|
bool bWasParameterizedEnabled = VoxelForgeRedefinedDensityField::IsParameterizedEnabled();
|
|
bool bWasRedefinedEnabled = VoxelForgeRedefinedDensityField::IsEnabled();
|
|
int32 PreviousSet = VoxelForgeRedefinedDensityField::GetParameterSet();
|
|
float PreviousScale = VoxelForgeRedefinedDensityField::GetDetailScale();
|
|
~FRestoreResearchFields()
|
|
{
|
|
VoxelForgeRedefinedDensityField::SetDetailScale(PreviousScale);
|
|
VoxelForgeRedefinedDensityField::SetParameterSet(PreviousSet);
|
|
VoxelForgeRedefinedDensityField::SetEnabled(bWasRedefinedEnabled);
|
|
VoxelForgeRedefinedDensityField::SetParameterizedEnabled(bWasParameterizedEnabled);
|
|
}
|
|
} Restore;
|
|
VoxelForgeRedefinedDensityField::SetEnabled(false);
|
|
VoxelForgeRedefinedDensityField::SetParameterizedEnabled(true);
|
|
VoxelForgeRedefinedDensityField::SetParameterSet(-1);
|
|
VoxelForgeRedefinedDensityField::SetDetailScale(1.0f);
|
|
|
|
constexpr int32 Seeds[] = {1337, 12345, 20260930};
|
|
int32 CheckedLandings = 0;
|
|
int32 CheckedRoutes = 0;
|
|
int32 RoutesWithResolvedEndpoints = 0;
|
|
for (const int32 Seed : Seeds)
|
|
{
|
|
VoxelForgeTest::FTestWorld World;
|
|
World.Build(Seed, /*InGapChunks=*/2, /*InStrateHeightInChunks=*/4);
|
|
if (!World.IsValid())
|
|
{
|
|
AddError(FString::Printf(
|
|
TEXT("Seed %d: test world did not build: %s"), Seed, *World.WhyInvalid()));
|
|
return false;
|
|
}
|
|
|
|
const TArray<FStrateSlot>& Layout = World.StrateManager->GetLayout();
|
|
const TArray<FVoxelPassage>& Passages = World.StrateManager->GetPassages();
|
|
for (const FVoxelPassage& Passage : Passages)
|
|
{
|
|
if (Passage.UpperStrateIndex == Passage.LowerStrateIndex)
|
|
{
|
|
continue;
|
|
}
|
|
const FVector UpperAir = Passage.UpperLanding.StandingPoint;
|
|
const FVector LowerAir = Passage.LowerLanding.StandingPoint;
|
|
const float UpperDensity = World.Generator->GetDensityAt(
|
|
UpperAir.X, UpperAir.Y, UpperAir.Z);
|
|
const float UpperFooting = World.Generator->GetDensityAt(
|
|
UpperAir.X, UpperAir.Y, Passage.UpperLanding.FloorZ - 0.75f);
|
|
const float LowerDensity = World.Generator->GetDensityAt(
|
|
LowerAir.X, LowerAir.Y, LowerAir.Z);
|
|
const float LowerFooting = World.Generator->GetDensityAt(
|
|
LowerAir.X, LowerAir.Y, Passage.LowerLanding.FloorZ - 0.75f);
|
|
++CheckedLandings;
|
|
if (!FMath::IsFinite(UpperDensity) || !FMath::IsFinite(UpperFooting)
|
|
|| !FMath::IsFinite(LowerDensity) || !FMath::IsFinite(LowerFooting)
|
|
|| UpperDensity <= 0.0f || LowerDensity <= 0.0f
|
|
|| UpperFooting >= 0.0f || LowerFooting >= 0.0f)
|
|
{
|
|
AddError(FString::Printf(
|
|
TEXT("Parameterized model seed %d: passage %d landing failed the final-field "
|
|
"air/floor bracket (upper %.4f/%.4f, lower %.4f/%.4f)."),
|
|
Seed, CheckedLandings - 1, UpperDensity, UpperFooting,
|
|
LowerDensity, LowerFooting));
|
|
}
|
|
}
|
|
|
|
for (int32 StrateIndex = 0; StrateIndex < Layout.Num(); ++StrateIndex)
|
|
{
|
|
FVector Arrival = FVector::ZeroVector;
|
|
FVector Departure = FVector::ZeroVector;
|
|
bool bHasArrival = false;
|
|
bool bHasDeparture = false;
|
|
for (const FVoxelPassage& Passage : Passages)
|
|
{
|
|
if (Passage.UpperStrateIndex == Passage.LowerStrateIndex)
|
|
{
|
|
continue;
|
|
}
|
|
if (Passage.LowerStrateIndex == StrateIndex && !bHasArrival)
|
|
{
|
|
Arrival = Passage.LowerLanding.StandingPoint;
|
|
bHasArrival = true;
|
|
}
|
|
if (Passage.UpperStrateIndex == StrateIndex && !bHasDeparture)
|
|
{
|
|
Departure = Passage.UpperLanding.StandingPoint;
|
|
bHasDeparture = true;
|
|
}
|
|
}
|
|
if (!bHasArrival || !bHasDeparture)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FVoxelStrateMeasureSettings Settings;
|
|
Settings.SampleStep = 4;
|
|
Settings.RadiusInVoxels = 192;
|
|
Settings.CenterXY = FVector2D(
|
|
(Arrival.X + Departure.X) * 0.5f,
|
|
(Arrival.Y + Departure.Y) * 0.5f);
|
|
Settings.MaxCells = 4000000;
|
|
Settings.HeadroomCells = 2;
|
|
const FVoxelConnectivityDiagnostics Route = VF_DiagnoseConnectivity(
|
|
*World.Generator, *World.StrateManager, StrateIndex,
|
|
Arrival, Departure, Settings);
|
|
++CheckedRoutes;
|
|
RoutesWithResolvedEndpoints += Route.bStartSnapped || Route.bGoalSnapped;
|
|
if (!Route.bValid || Route.Result != EVoxelConnectivityResult::Connected)
|
|
{
|
|
AddError(FString::Printf(
|
|
TEXT("Parameterized model seed %d strate %d (%s): arrival-to-exit walking "
|
|
"route was not connected (result=%d, valid=%s, start resolved=%s, "
|
|
"goal resolved=%s)."),
|
|
Seed, StrateIndex,
|
|
Layout[StrateIndex].Definition
|
|
? *Layout[StrateIndex].Definition->GetName() : TEXT("no definition"),
|
|
static_cast<int32>(Route.Result),
|
|
Route.bValid ? TEXT("yes") : TEXT("no"),
|
|
Route.bStartSnapped ? TEXT("yes") : TEXT("no"),
|
|
Route.bGoalSnapped ? TEXT("yes") : TEXT("no")));
|
|
}
|
|
}
|
|
}
|
|
|
|
TestTrue(TEXT("Several seeds exercised parameterized passage landings"), CheckedLandings >= 6);
|
|
TestTrue(TEXT("Several seeds exercised parameterized arrival-to-exit walking"), CheckedRoutes >= 6);
|
|
AddInfo(FString::Printf(
|
|
TEXT("Parameterized generation functional sweep: %d inter-strate passage landings "
|
|
"bracketed open air over %d seeds; %d arrival-to-exit walking routes checked; "
|
|
"%d used a resolved coarse endpoint after the full-density segment check."),
|
|
CheckedLandings, UE_ARRAY_COUNT(Seeds), CheckedRoutes, RoutesWithResolvedEndpoints));
|
|
return CheckedLandings >= 6 && CheckedRoutes >= 6;
|
|
}
|
|
|
|
#endif // WITH_DEV_AUTOMATION_TESTS
|