wip: L174 Design50 steps 0-2 in progress (interrupted for a power cut)

Audits collect gates and run seams (landing discs + end runs, LOD0/1), tagged uncapped failures, separate exempt
counts, self-overlap census; level end runs; overlap/turn constraints. Partial sweep: end runs pass 3/3 per seed;
1-2 end-turn violations per seed; 50-110k tagged seam mismatches per seed (real vs audit artefact not yet decided).
Not verified; resume L174.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-11-03 13:11:26 +01:00
1 parent b09728354d
commit dee53c8d2a
9 files changed
+2155 -257

No files matched your search

@@ -327,6 +327,9 @@ namespace VoxelForgeCore
// boundary-face bit mask (bit order: -X,+X,-Y,+Y,-Z,+Z).
std::vector<std::uint8_t> skirtFaceMasks;
std::vector<float> debugDensitySamples;
std::array<std::int32_t,3> debugDensityOriginVoxels{};
std::array<std::int32_t,3> debugDensityDimensions{};
std::int32_t debugDensityStepVoxels = 0;
MeshGroups groups;
TileGenerationStats diagnostics;
std::uint64_t densitySampleCount = 0;
@@ -512,7 +515,8 @@ namespace VoxelForgeCore
// boundary-blended host rock from widening the authored passage wall.
// v238 plans one resolved passage spline with explicit landing chambers.
// v239 plans their floor planes as the passage's continuous floor profile.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 239;
// v240 adds level end runs and rejects passage tube overlaps and hairpins.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 240;
enum class FieldChannel : std::uint32_t
{
@@ -1336,6 +1340,69 @@ namespace VoxelForgeCore
std::int64_t clearHeightSubvoxels = 0;
};
inline std::int64_t ResolvedLayoutPassageLandingDiscRadiusSubvoxels(
std::int64_t mouthRadiusSubvoxels,
std::uint32_t coreVoxelSizeMicrometres) noexcept
{
if(coreVoxelSizeMicrometres==0)return 0;
const std::int64_t qPerMetre=static_cast<std::int64_t>(std::llround(
static_cast<double>(WorldAssemblySubvoxelsPerVoxel)*1000000.0
/coreVoxelSizeMicrometres));
return std::max<std::int64_t>(3*qPerMetre,
mouthRadiusSubvoxels+qPerMetre);
}
inline bool IsInsideResolvedLayoutPassageLandingDiscV1(
const std::array<std::int64_t,2>& centerSubvoxels,
std::int64_t radiusSubvoxels,double xSubvoxels,double ySubvoxels) noexcept
{
if(radiusSubvoxels<=0)return false;
const double dx=xSubvoxels-static_cast<double>(centerSubvoxels[0]);
const double dy=ySubvoxels-static_cast<double>(centerSubvoxels[1]);
const double radius=static_cast<double>(radiusSubvoxels);
return dx*dx+dy*dy<=radius*radius;
}
inline bool IsInsideResolvedLayoutPassageLandingRimV1(
const std::array<std::int64_t,2>& centerSubvoxels,
std::int64_t radiusSubvoxels,std::int64_t halfWidthSubvoxels,
double xSubvoxels,double ySubvoxels) noexcept
{
if(radiusSubvoxels<=0||halfWidthSubvoxels<0)return false;
const double dx=xSubvoxels-static_cast<double>(centerSubvoxels[0]);
const double dy=ySubvoxels-static_cast<double>(centerSubvoxels[1]);
return std::abs(std::hypot(dx,dy)-static_cast<double>(radiusSubvoxels))
<=static_cast<double>(halfWidthSubvoxels);
}
// Shared landing-volume predicate for planners, the passage composer, and audits.
// Query coordinates use the same world subvoxel units as the resolved passage.
inline double ResolvedLayoutPassageLandingFloorAtXYSubvoxels(
const ResolvedLayoutPassageLandingChamberV1& chamber,
double xSubvoxels,double ySubvoxels) noexcept
{
return static_cast<double>(chamber.floorCenterSubvoxels[2])
+static_cast<double>(chamber.floorGradientQ16[0])/65536.0
*(xSubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[0]))
+static_cast<double>(chamber.floorGradientQ16[1])/65536.0
*(ySubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[1]));
}
inline bool IsInsideResolvedLayoutPassageLandingChamberV1(
const ResolvedLayoutPassageLandingChamberV1& chamber,
double xSubvoxels,double ySubvoxels,double zSubvoxels) noexcept
{
if(chamber.radiusSubvoxels<=0||chamber.clearHeightSubvoxels<=0)return false;
const double dx=xSubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[0]);
const double dy=ySubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[1]);
const double radius=static_cast<double>(chamber.radiusSubvoxels);
const double floor=ResolvedLayoutPassageLandingFloorAtXYSubvoxels(
chamber,xSubvoxels,ySubvoxels);
return dx*dx+dy*dy<=radius*radius
&&zSubvoxels>=floor
&&zSubvoxels<=floor+static_cast<double>(chamber.clearHeightSubvoxels);
}
struct ResolvedLayoutPassageV1
{
std::string stableId;
@@ -1348,6 +1415,8 @@ namespace VoxelForgeCore
std::array<std::int64_t, 3> lowerMouthSubvoxels{};
std::int64_t mouthRadiusSubvoxels = 0;
std::int64_t midRadiusSubvoxels = 0;
// Planned flat distance from each landing, at least R+1 m.
std::int64_t endRunSubvoxels = 0;
// Derived from the mouth binding; the main descent is monotone through this point.
std::size_t lowerMouthControlIndex = 0;
ResolvedLayoutPassageLandingChamberV1 upperLandingChamber;
@@ -1380,6 +1449,47 @@ namespace VoxelForgeCore
std::int64_t cascadeLedgeSubvoxels = 0;
};
struct ResolvedLayoutPassageSelfOverlapAuditV1
{
std::uint64_t segmentPairs = 0;
std::uint64_t measuredSegmentPairs = 0;
std::uint64_t localExemptSegmentPairs = 0;
std::uint64_t overlappingSegmentPairs = 0;
std::uint64_t firstOverlapSegmentA = 0;
std::uint64_t firstOverlapSegmentB = 0;
std::uint64_t firstLandingColumnSegment = 0;
bool firstLandingColumnIsLower = false;
std::uint64_t landingColumnViolations = 0;
double maximumEndTurnDegrees = 0.0;
std::uint32_t endTurnViolations = 0;
double minimumClearanceMetres = 0.0;
bool hasOverlapLocation = false;
bool hasMeasuredCoverage = false;
bool passed = false;
};
VFCORE_API ResolvedLayoutPassageSelfOverlapAuditV1
AuditResolvedLayoutPassageSelfOverlapV1(
const ResolvedLayoutPassageV1& passage,
std::uint32_t coreVoxelSizeMicrometres);
struct ResolvedLayoutPassageEndRunAuditV1
{
double requiredEndRunMetres = 0.0;
double measuredStartMetres = 0.0;
double measuredEndMetres = 0.0;
double startMaximumFloorDeviationMetres = 0.0;
double endMaximumFloorDeviationMetres = 0.0;
double startMaximumGradeDegrees = 0.0;
double endMaximumGradeDegrees = 0.0;
bool hasMeasuredCoverage = false;
bool passed = false;
};
VFCORE_API ResolvedLayoutPassageEndRunAuditV1
AuditResolvedLayoutPassageEndRunsV1(
const ResolvedLayoutPassageV1& passage,
std::uint32_t coreVoxelSizeMicrometres,
std::int64_t endRunSubvoxels = 0);
struct VFCORE_API ResolvedLayoutSnapshotV3
{
std::uint32_t schemaVersion = ResolvedLayoutSchemaVersionV3;
File diff suppressed because it is too large. Load diff
+13 -2
View File
@@ -2890,6 +2890,7 @@ namespace VoxelForgeCore
const auto MarchingCubesStart=std::chrono::steady_clock::now();
FVoxelUniformBlockProofAuditStats BlockProofAudit;
FVoxelMeshData mesh;
FIntVector DebugDensityOrigin,DebugDensityDimensions;
{
FStandaloneShapeWorld::FScopedStampSamplingStep stampSamplingStep(MeshStep);
mesh=mesher.GenerateMesh(origin,MeshStep,MeshCells,nullptr,
@@ -2897,7 +2898,9 @@ namespace VoxelForgeCore
(options.hashDensity||options.captureDensitySamples)?&densityValues:nullptr,
options.profileMesherStages?&McStageTimings:nullptr,
options.auditUniformBlockProofs?&BlockProofAudit:nullptr,
options.forceFullDensityCapture);
options.forceFullDensityCapture,
options.captureDensitySamples?&DebugDensityOrigin:nullptr,
options.captureDensitySamples?&DebugDensityDimensions:nullptr);
}
passageFeatureScope.copySweptTubeRuntimeCounts();
if(options.auditUniformBlockProofs)
@@ -3222,7 +3225,15 @@ namespace VoxelForgeCore
std::chrono::steady_clock::now()-materialQueryStart).count():0.0;
out.indices.reserve(static_cast<std::size_t>(mesh.Triangles.Num()));
for(const int32 index:mesh.Triangles)out.indices.push_back(static_cast<std::uint32_t>(index));
if(options.captureDensitySamples)out.debugDensitySamples=std::move(densityValues);
if(options.captureDensitySamples)
{
out.debugDensitySamples=std::move(densityValues);
out.debugDensityOriginVoxels={DebugDensityOrigin.X,DebugDensityOrigin.Y,
DebugDensityOrigin.Z};
out.debugDensityDimensions={DebugDensityDimensions.X,
DebugDensityDimensions.Y,DebugDensityDimensions.Z};
out.debugDensityStepVoxels=MeshStep;
}
if(options.hashDensity)
{
std::uint64_t densityHash=14695981039346656037ull;