From a45ba9bb10fbb789ce2b8730db2b21874734594f Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sun, 1 Nov 2026 11:17:45 +0100 Subject: [PATCH] wip: Core.Liminal.Field v1 recipe, 4 seed-selected variants between fixed mouths (L144, fails mouth joins) Plans and draws flat field+monolith, repeating hills, road over cloud floor and pillar grid in a 3-strata fixture, binding passage/0-1 and 1-2 as fixed endpoints. Composed W1 probes: 3/4 seeds fail one passage interface, 4/4 fail the liminal walk audit near the mouths (support itself passes). Stopped per AGENTS.md. Same mouth-ownership failure class as FI (L133/L140) and VS seed 2 (L139). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 78 ++++ Standalone/Core/src/ResolvedLayoutInternal.h | 104 ++++- Standalone/Core/src/ShapeWorldInternal.h | 34 +- Standalone/Core/src/WorldAssemblerInternal.h | 416 ++++++++++++++++++ .../Linux144/BuildL144Fixtures.py | 58 +++ .../WorldAssemblerM3/Linux144/CaptureL144.py | 243 ++++++++++ .../WorldAssemblerM3/Linux144/REPORT.md | 44 ++ ...-liminal-flatField-monolith-seed00-eye.jpg | Bin 0 -> 35191 bytes ...liminal-flatField-monolith-seed00-wide.jpg | Bin 0 -> 26016 bytes .../core-liminal-periodicHills-seed01-eye.jpg | Bin 0 -> 31096 bytes ...core-liminal-periodicHills-seed01-wide.jpg | Bin 0 -> 45333 bytes .../core-liminal-pillar-grid-seed03-eye.jpg | Bin 0 -> 35478 bytes .../core-liminal-pillar-grid-seed03-wide.jpg | Bin 0 -> 37027 bytes ...minal-road-over-cloud-floor-seed02-eye.jpg | Bin 0 -> 31758 bytes ...inal-road-over-cloud-floor-seed02-wide.jpg | Bin 0 -> 30827 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 161 ++++++- Standalone/Source/StreamBenchmarkPipeline.h | 127 +++++- Standalone/Source/WorldAssemblyPrototype.h | 325 ++++++++++++++ 18 files changed, 1547 insertions(+), 43 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-wide.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index edeb226..9d74abc 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -597,6 +597,61 @@ namespace VoxelForgeCore } } + inline constexpr std::string_view CoreLiminalFieldRecipeIdV1 = "Core.Liminal.Field"; + inline constexpr std::uint32_t CoreLiminalFieldRecipeVersionV1 = 1; + inline constexpr std::uint32_t CoreLiminalFieldVariantCountV1 = 4; + + enum class WorldAssemblyLiminalVariantV1 : std::uint32_t + { + flatFieldMonolith = 0, + repeatingHills = 1, + roadOverCloudFloor = 2, + pillarGrid = 3 + }; + + struct WorldAssemblyLiminalVariantDefinitionV1 + { + WorldAssemblyLiminalVariantV1 variant = WorldAssemblyLiminalVariantV1::flatFieldMonolith; + std::string_view name; + WorldAssemblySurfaceProfileKindV1 surfaceKind = WorldAssemblySurfaceProfileKindV1::flatField; + std::int64_t hillAmplitudeMicrometres = 0; + std::int64_t hillWavelengthMicrometres = 0; + std::int64_t routeHalfWidthMicrometres = 0; + std::int64_t routeHalfThicknessMicrometres = 0; + std::int64_t supportSpacingMicrometres = 0; + std::int64_t supportRadiusMicrometres = 0; + std::int64_t monolithRadiusMicrometres = 0; + std::int64_t monolithHeightMicrometres = 0; + std::uint32_t pillarRows = 0; + std::uint32_t pillarColumns = 0; + std::int64_t pillarSpacingMicrometres = 0; + std::int64_t pillarRadiusMicrometres = 0; + std::int64_t pillarHeightMicrometres = 0; + }; + + inline constexpr std::array CoreLiminalFieldVariantsV1{{ + {WorldAssemblyLiminalVariantV1::flatFieldMonolith, "flatField-monolith", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 1750000, 500000, + 36000000, 550000, 1600000, 26000000, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::repeatingHills, "periodicHills", + WorldAssemblySurfaceProfileKindV1::periodicHills, 2200000, 80000000, + 1750000, 500000, 36000000, 550000, 0, 0, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::roadOverCloudFloor, "road-over-cloud-floor", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 2000000, 500000, + 24000000, 550000, 0, 0, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::pillarGrid, "pillar-grid", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 1750000, 500000, + 36000000, 550000, 0, 0, 15, 15, 76000000, 5500000, 40000000} + }}; + + inline constexpr WorldAssemblyLiminalVariantV1 SelectCoreLiminalFieldVariantV1( + std::uint32_t seed) noexcept + { + return static_cast( + seed % CoreLiminalFieldVariantCountV1); + } + struct WorldAssemblyRecipeV1 { std::uint32_t schemaVersion = WorldAssemblySchemaVersion; @@ -654,6 +709,23 @@ namespace VoxelForgeCore std::array parametersSubvoxels{}; }; + struct WorldAssemblyLiminalFieldPlanV1 + { + std::uint32_t version = 0; + WorldAssemblyLiminalVariantV1 variant = WorldAssemblyLiminalVariantV1::flatFieldMonolith; + std::uint32_t seed = 0; + std::array arrivalMouthSubvoxels{}; + std::array departureMouthSubvoxels{}; + // Fixed distance from each passage player-center anchor to its walk surface. + std::int64_t mouthFloorOffsetSubvoxels = 0; + std::int64_t floorHeightSubvoxels = 0; + std::int64_t routeHalfWidthSubvoxels = 0; + std::int64_t routeHalfThicknessSubvoxels = 0; + std::int64_t routeOffsetSubvoxels = 0; + std::int64_t supportSpacingSubvoxels = 0; + std::int64_t supportRadiusSubvoxels = 0; + }; + struct WorldAssemblyStratumPlanV1 { std::int32_t strateIndex = -1; @@ -678,6 +750,7 @@ namespace VoxelForgeCore std::vector features; WorldAssemblyRouteConstraintsV1 routeConstraints; std::vector route; + WorldAssemblyLiminalFieldPlanV1 liminalField; std::uint64_t contentHash = 0; }; @@ -893,6 +966,7 @@ namespace VoxelForgeCore inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV3 = 3; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV4 = 4; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV5 = 5; + inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV6 = 6; inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1; enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict }; @@ -920,6 +994,7 @@ namespace VoxelForgeCore // Present only for fillSweptDeckSegment; defines its directed centerline. std::array, 2> sweepEndpointsMicrometres{}; // V5 permits one continuous swept deck to carry its complete sampled centerline. + // V6 also permits a path whose X coordinates are not strictly increasing. // Empty retains the V4 single-segment interpretation. std::vector> sweepPathMicrometres; std::int64_t placementRadiusMicrometres = 0; @@ -1238,6 +1313,9 @@ namespace VoxelForgeCore ResolvedLayoutSnapshotV3& layout, std::int32_t seed, const std::vector& configs, std::string& error); + VFCORE_API bool PlanCoreLiminalFieldV1( + WorldAssemblyRecipeV1& recipe, WorldAssemblyStratumPlanV1& stratum, + const ResolvedLayoutSnapshotV3& layout, std::string& error); struct ResolvedLayoutStampPlacementAuditV1 { diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 4a47b04..1cddd4e 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -249,6 +249,71 @@ namespace /WorldAssemblySubvoxelsPerVoxel)); return result; }; + const bool liminalRouteStamp=strate->recipeId==CoreLiminalFieldRecipeIdV1 + &&stamp.stableId.starts_with("core/liminal-field/route/") + &&(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + ||stamp.kind==ResolvedSdfStampKindV1::fillPillar); + if(liminalRouteStamp) + { + const auto variant=std::find_if(strate->anchors.begin(),strate->anchors.end(), + [](const auto& anchor){return anchor.kind=="liminal_variant" + &&anchor.values.size()>=6;}); + std::vector points; + for(const auto& anchor:strate->anchors) + if(anchor.kind=="liminal_route_point"&&anchor.values.size()>=4) + points.push_back(&anchor); + if(variant==strate->anchors.end()||points.size()<2) + {if(reason)*reason="Core.Liminal.Field route stamp has no versioned fixed-mouth route";return false;} + const auto routePoint=[&](const ResolvedLayoutAnchorV2& anchor) + { + std::array q={anchor.values[0],anchor.values[1],anchor.values[2]}; + return qToMicrometres(q); + }; + const std::int64_t halfThickness=static_cast(std::llround( + static_cast(variant->values[5])*coreMicrometres + /WorldAssemblySubvoxelsPerVoxel)); + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + const auto first=routePoint(*points.front()); + const auto last=routePoint(*points.back()); + if(stamp.sweepPathMicrometres.size()<2 + ||stamp.sweepPathMicrometres.front()[0]!=first[0] + ||stamp.sweepPathMicrometres.front()[1]!=first[1] + ||stamp.sweepPathMicrometres.front()[2]!=first[2]-halfThickness + ||stamp.sweepPathMicrometres.back()[0]!=last[0] + ||stamp.sweepPathMicrometres.back()[1]!=last[1] + ||stamp.sweepPathMicrometres.back()[2]!=last[2]-halfThickness) + {if(reason)*reason="Core.Liminal.Field deck does not terminate at its fixed passage mouths";return false;} + return true; + } + const auto deck=std::find_if(layout.stamps.begin(),layout.stamps.end(), + [&](const auto& existing){return existing.strateIndex==stamp.strateIndex + &&existing.stableId=="core/liminal-field/route/deck/000" + &&existing.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;}); + if(deck==layout.stamps.end()||deck->sweepPathMicrometres.size()<2) + {if(reason)*reason="Core.Liminal.Field support has no previously resolved route deck";return false;} + double distance=std::numeric_limits::infinity(); + for(std::size_t i=1;isweepPathMicrometres.size();++i) + { + const auto& a=deck->sweepPathMicrometres[i-1]; + const auto& b=deck->sweepPathMicrometres[i]; + const double dx=static_cast(b[0]-a[0]); + const double dy=static_cast(b[1]-a[1]); + const double lengthSquared=dx*dx+dy*dy; + const double t=lengthSquared>0.0?std::clamp( + ((stamp.positionMicrometres[0]-a[0])*dx + +(stamp.positionMicrometres[1]-a[1])*dy)/lengthSquared, + 0.0,1.0):0.0; + const double offsetX=stamp.positionMicrometres[0]-(a[0]+t*dx); + const double offsetY=stamp.positionMicrometres[1]-(a[1]+t*dy); + distance=std::min(distance,std::hypot(offsetX,offsetY)); + } + const double corridorRadius=deck->halfExtentsMicrometres[1] + +stamp.halfExtentsMicrometres[0]+RouteClearanceMicrometres; + if(distance>corridorRadius) + {if(reason)*reason="Core.Liminal.Field route stamp is outside its versioned route corridor";return false;} + return true; + } for(const auto& passage:layout.passages) { if(passage.upperStrateIndex!=stamp.strateIndex @@ -1158,8 +1223,9 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV2 &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3 &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV4 - &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV5) - add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1 through 5"); + &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV5 + &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV6) + add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1 through 6"); std::vector stampIds; for(const auto& stamp:stamps) { @@ -1217,11 +1283,15 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, validPath=validPath&&coordinate>=-1000000000000ll &&coordinate<=1000000000000ll; if(pointIndex>0) - validPath=validPath - &&stamp.sweepPathMicrometres[pointIndex-1][0]=ResolvedLayoutStampVocabularyVersionV6 + ||previous[0]=request.sweepPathMicrometres[i][0]) + return true; + return false; + }); const bool hasSweptDeck=std::any_of(ordered.begin(),ordered.end(),[](const auto& request) {return request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;}); candidate.stampVocabularyVersion=hasContinuousSweptDeck - ?ResolvedLayoutStampVocabularyVersionV5 + ?(hasNonMonotoneSweptDeck?ResolvedLayoutStampVocabularyVersionV6 + :ResolvedLayoutStampVocabularyVersionV5) :hasSweptDeck?ResolvedLayoutStampVocabularyVersionV4 :ResolvedLayoutStampVocabularyVersionV1; candidate.stamps.clear();candidate.stamps.reserve(ordered.size()); @@ -1818,8 +1898,8 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t for(const auto coordinate:point) if(coordinate<-1000000000000ll||coordinate>1000000000000ll) {error="stamp request "+request.stableId+" has an unbounded path point";return false;} - if(pointIndex>0&&request.sweepPathMicrometres[pointIndex-1][0]>=point[0]) - {error="stamp request "+request.stableId+" path X coordinates must increase strictly";return false;} + if(pointIndex>0&&request.sweepPathMicrometres[pointIndex-1]==point) + {error="stamp request "+request.stableId+" path contains a zero-length segment";return false;} } } @@ -1836,6 +1916,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t return static_cast(bits%span)-radius; }; bool placed=false; + std::string lastPlacementFailure; for(std::uint32_t attempt=0;attempt<(request.placementRadiusMicrometres==0?1u:512u);++attempt) { ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId; @@ -1919,11 +2000,14 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis]; } } - if(!LayoutStampSafe(candidate,stamp))continue; + std::string safetyReason; + if(!LayoutStampSafe(candidate,stamp,&safetyReason)) + {lastPlacementFailure=std::move(safetyReason);continue;} candidate.stamps.push_back(std::move(stamp));placed=true;break; } if(!placed) - {error="stamp request "+request.stableId+" has no deterministic passage-safe content placement";return false;} + {error="stamp request "+request.stableId+" has no deterministic passage-safe content placement" + +(lastPlacementFailure.empty()?std::string{}:": "+lastPlacementFailure);return false;} } if(!candidate.finalize(error))return false; std::vector issues;std::string strictError; diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index ed036ec..29d4977 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -1523,6 +1523,8 @@ public: &nativeLatticeFloorSupport); } const auto* bound=FindBoundStratumForManagerZ(Z); + const bool liminalRouteComposition=bound&&bound->Resolved + &&bound->Resolved->recipeId==VoxelForgeCore::CoreLiminalFieldRecipeIdV1; const bool nativeLattice=bound&&bound->Resolved &&VoxelForgeCore::IsNativeLatticeFieldStratum(*bound->Resolved) &&bound->Resolved->passageCapabilities.hasNativeLatticeField; @@ -1546,7 +1548,9 @@ public: VoxelForgeCore::Linux77Profiler::FScopedPhase l77StampPhase( VoxelForgeCore::Linux77Profiler::EPhase::Stamps); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerStamps); - stamped=ApplyResolvedSdfStamps(composed,X,Y,Z); + stamped=ApplyResolvedSdfStamps(composed,X,Y,Z, + liminalRouteComposition?std::string_view("core/liminal-field/route/") + :std::string_view{}); } static const bool bL75TraceTnComposition=[] { @@ -1598,6 +1602,12 @@ public: ELegacyFieldTerm::ComposerPassage); final=ApplyResolvedStratePassageCarves(final,X,Y,Z); } + // A liminal route is authored to terminate at fixed passage mouths. The + // passage carve owns the surrounding bore, while the deck/support stamps + // restore its walkable floor so the composed route crosses the interface. + if(liminalRouteComposition) + final=ApplyResolvedSdfStamps(final,X,Y,Z,{}, + "core/liminal-field/route/"); if(bTraceTnComposition) std::printf("[L75TNCompositionTrace] input=%.9g graph=%.9g boundary=%.9g passage=%.9g stamp=%.9g final=%.9g native=0\n", density,graphDensity,boundary,composed,stamped,final); @@ -7156,10 +7166,16 @@ private: const float halfThickness=stamp.halfExtentsVoxels[2]; const float round=std::min(0.35f,std::min(halfWidth,halfThickness)*0.15f); const float searchMargin=halfWidth+halfThickness+2.0f; - const auto first=std::lower_bound(path.begin(),path.end(),x-searchMargin, - [](const auto& point,float value){return point[0]=b[0];})==path.end(); + const auto first=increasingX + ?std::lower_bound(path.begin(),path.end(),x-searchMargin, + [](const auto& point,float value){return point[0](first-path.begin()); const std::size_t lastIndex=static_cast(last-path.begin()); const std::size_t segmentBegin=std::min(path.size()-2, @@ -7426,7 +7442,9 @@ private: std::nextafter(maximum+outwardPadding, std::numeric_limits::infinity()),true}; } - float ApplyResolvedSdfStamps(float density,float X,float Y,float Z) const + float ApplyResolvedSdfStamps(float density,float X,float Y,float Z, + std::string_view excludedStableIdPrefix={}, + std::string_view includedStableIdPrefix={}) const { if(StampRuntime.empty()||!Owner||Owner->CoreVoxelSizeMicrons==0)return density; const auto* tileQueries=ActivePassageTileQueries; @@ -7443,6 +7461,10 @@ private: if(index>=StampRuntime.size())return; const auto& runtime=StampRuntime[index];const auto& record=*runtime.record; if(record.strateIndex!=bound->StrateIndex)return; + if(!excludedStableIdPrefix.empty() + &&record.stableId.starts_with(excludedStableIdPrefix))return; + if(!includedStableIdPrefix.empty() + &&!record.stableId.starts_with(includedStableIdPrefix))return; if(UsesCoarsePillarProxy(runtime,CurrentStampSamplingStep()))return; for(std::size_t axis=0;axis<3;++axis) if(worldMicrometres[axis](liminal.variant) >= CoreLiminalFieldVariantCountV1 + || liminal.seed != effectiveRecipe.seed + || liminal.variant != SelectCoreLiminalFieldVariantV1(liminal.seed) + || stratum.route.size() < 2 + || liminal.mouthFloorOffsetSubvoxels <= 0 + || stratum.route.front().positionSubvoxels[0] != liminal.arrivalMouthSubvoxels[0] + || stratum.route.front().positionSubvoxels[1] != liminal.arrivalMouthSubvoxels[1] + || stratum.route.front().positionSubvoxels[2] + != liminal.arrivalMouthSubvoxels[2]-liminal.mouthFloorOffsetSubvoxels + || stratum.route.back().positionSubvoxels[0] != liminal.departureMouthSubvoxels[0] + || stratum.route.back().positionSubvoxels[1] != liminal.departureMouthSubvoxels[1] + || stratum.route.back().positionSubvoxels[2] + != liminal.departureMouthSubvoxels[2]-liminal.mouthFloorOffsetSubvoxels + || liminal.routeHalfWidthSubvoxels < stratum.routeConstraints.capsuleRadiusSubvoxels + || liminal.routeHalfThicknessSubvoxels <= 0 + || liminal.routeOffsetSubvoxels <= 0 + || liminal.supportSpacingSubvoxels <= 0 + || liminal.supportRadiusSubvoxels <= 0 + || stratum.surfaceProfile.version != 1) + { error = "Core.Liminal.Field plan has invalid version, seed-selected variant, route mouths or dimensions"; return false; } + const std::int64_t bottom = static_cast(stratum.bottomChunkZ) + * layoutChunkWidthSubvoxels; + const std::int64_t top = (static_cast(stratum.topChunkZ) + 1) + * layoutChunkWidthSubvoxels; + if (liminal.floorHeightSubvoxels <= bottom || liminal.floorHeightSubvoxels >= top) + { error = "Core.Liminal.Field floor escapes its finite stratum bounds"; return false; } + } const auto& constraints = stratum.routeConstraints; if (constraints.version == 0) { @@ -682,6 +713,24 @@ namespace world_assembly_detail for (const auto value : point.positionSubvoxels) HashWord(hash, static_cast(value), 8); HashWord(hash, static_cast(point.radiusSubvoxels), 8); } + if (stratum.liminalField.version != 0) + { + const auto& liminal = stratum.liminalField; + HashWord(hash, 0x4c494d494e414c31ull, 8); + HashWord(hash, liminal.version, 4); + HashWord(hash, static_cast(liminal.variant), 4); + HashWord(hash, liminal.seed, 4); + for (const auto value : liminal.arrivalMouthSubvoxels) + HashWord(hash, static_cast(value), 8); + for (const auto value : liminal.departureMouthSubvoxels) + HashWord(hash, static_cast(value), 8); + for (const auto value : {liminal.mouthFloorOffsetSubvoxels, + liminal.floorHeightSubvoxels, + liminal.routeHalfWidthSubvoxels, liminal.routeHalfThicknessSubvoxels, + liminal.routeOffsetSubvoxels, liminal.supportSpacingSubvoxels, + liminal.supportRadiusSubvoxels}) + HashWord(hash, static_cast(value), 8); + } if (stratum.surfaceProfile.version != 0) HashSurfaceProfile(hash, stratum.surfaceProfile); return hash; @@ -1059,6 +1108,30 @@ namespace world_assembly_detail { error = "world assembly route point is missing a fixed-scale field"; return false; } stratum.route.push_back(point); } + const VFJson::Value& liminalValue = item.Get("liminal_field"); + if (!std::holds_alternative(liminalValue.Data)) + { + auto& liminal = stratum.liminalField; + std::uint32_t variant = 0; + if (!liminalValue.IsObject() + || !ReadU32(liminalValue.Get("version"), liminal.version) + || !ReadU32(liminalValue.Get("variant"), variant) + || !ReadU32(liminalValue.Get("seed"), liminal.seed) + || !ReadArray(liminalValue.Get("arrival_mouth_q"), + liminal.arrivalMouthSubvoxels.data(), 3) + || !ReadArray(liminalValue.Get("departure_mouth_q"), + liminal.departureMouthSubvoxels.data(), 3) + || !ReadInteger(liminalValue.Get("mouth_floor_offset_q"), + liminal.mouthFloorOffsetSubvoxels) + || !ReadInteger(liminalValue.Get("floor_height_q"), liminal.floorHeightSubvoxels) + || !ReadInteger(liminalValue.Get("route_half_width_q"), liminal.routeHalfWidthSubvoxels) + || !ReadInteger(liminalValue.Get("route_half_thickness_q"), liminal.routeHalfThicknessSubvoxels) + || !ReadInteger(liminalValue.Get("route_offset_q"), liminal.routeOffsetSubvoxels) + || !ReadInteger(liminalValue.Get("support_spacing_q"), liminal.supportSpacingSubvoxels) + || !ReadInteger(liminalValue.Get("support_radius_q"), liminal.supportRadiusSubvoxels)) + { error = "Core.Liminal.Field plan is missing a fixed-scale field"; return false; } + liminal.variant = static_cast(variant); + } plan.strates.push_back(std::move(stratum)); } return true; @@ -2324,6 +2397,328 @@ bool WorldAssemblyManifest::validate(std::string& error) const return true; } +bool PlanCoreLiminalFieldV1(WorldAssemblyRecipeV1& recipe, + WorldAssemblyStratumPlanV1& stratum,const ResolvedLayoutSnapshotV3& layout, + std::string& error) +{ + error.clear(); + if(layout.coreVoxelSizeMicrometres==0||stratum.strateIndex<0 + ||stratum.topChunkZcontent.presentInCurrentField) + {error="Core.Liminal.Field must target a resolved SurfaceWorld content band";return false;} + const ResolvedLayoutPassageV1* arrival=nullptr; + const ResolvedLayoutPassageV1* departure=nullptr; + for(const auto& passage:layout.passages) + { + if(passage.lowerStrateIndex==stratum.strateIndex) + { + if(arrival){error="Core.Liminal.Field requires one fixed arrival passage mouth";return false;} + arrival=&passage; + } + if(passage.upperStrateIndex==stratum.strateIndex) + { + if(departure){error="Core.Liminal.Field requires one fixed departure passage mouth";return false;} + departure=&passage; + } + } + if(!arrival||!departure) + {error="Core.Liminal.Field requires an adjacent passage on both sides";return false;} + + constexpr std::int64_t Q=WorldAssemblySubvoxelsPerVoxel; + const std::int64_t coreMicrons=layout.coreVoxelSizeMicrometres; + const auto micrometresToQ=[&](std::int64_t micrometres) + { + const std::int64_t numerator=micrometres*Q; + return numerator>=0?(numerator+coreMicrons/2)/coreMicrons + :(numerator-coreMicrons/2)/coreMicrons; + }; + const std::int64_t qPerMetre=micrometresToQ(1000000); + if(qPerMetre<=0){error="Core.Liminal.Field could not resolve fixed-scale metres";return false;} + + const std::uint32_t seed=recipe.seed; + const WorldAssemblyLiminalVariantV1 variant=SelectCoreLiminalFieldVariantV1(seed); + const auto& definition=CoreLiminalFieldVariantsV1[static_cast(variant)]; + const auto& start=arrival->lowerMouthSubvoxels; + const auto& finish=departure->upperMouthSubvoxels; + constexpr std::int64_t MaximumMouthCoordinateQ=1000000000ll; + if(std::abs(start[0])>MaximumMouthCoordinateQ||std::abs(start[1])>MaximumMouthCoordinateQ + ||std::abs(start[2])>MaximumMouthCoordinateQ||std::abs(finish[0])>MaximumMouthCoordinateQ + ||std::abs(finish[1])>MaximumMouthCoordinateQ||std::abs(finish[2])>MaximumMouthCoordinateQ) + {error="Core.Liminal.Field passage mouth exceeds the supported fixed-coordinate range";return false;} + const std::int64_t mouthPlayerCenterHeight=micrometresToQ(1130000); + auto routeStart=start; + auto routeFinish=finish; + routeStart[2]-=mouthPlayerCenterHeight; + routeFinish[2]-=mouthPlayerCenterHeight; + const auto findMouthControl=[&](const ResolvedLayoutPassageV1& passage, + const std::array& mouth) + { + std::size_t found=passage.controlPoints.size(); + for(std::size_t i=0;icontrolPoints.size()<2||departure->controlPoints.size()<2 + ||arrivalControl>=arrival->controlPoints.size() + ||departureControl>=departure->controlPoints.size()) + {error="Core.Liminal.Field needs exact passage-control bindings at both fixed mouths";return false;} + const auto horizontalLengthQ=[](std::int64_t dx,std::int64_t dy) + { + const auto absX=static_cast(std::abs(dx)); + const auto absY=static_cast(std::abs(dy)); + return world_assembly_detail::IntegerSqrt(absX*absX+absY*absY); + }; + const auto roundRatio=[](std::int64_t numerator,std::uint64_t denominator) + { + if(denominator==0)return std::int64_t{0}; + const auto positiveDenominator=static_cast(denominator); + return numerator>=0 + ?(numerator+positiveDenominator/2)/positiveDenominator + :-((-numerator+positiveDenominator/2)/positiveDenominator); + }; + const auto passageSplineControls=[](const ResolvedLayoutPassageV1& passage) + { + std::vector controls; + controls.reserve(passage.controlPoints.size()); + for(const auto& point:passage.controlPoints) + controls.push_back({static_cast(point.positionSubvoxels[0]), + static_cast(point.positionSubvoxels[1]), + static_cast(point.positionSubvoxels[2]-point.radiusSubvoxels), + static_cast(point.radiusSubvoxels)}); + return controls; + }; + const auto arrivalSpline=passageSplineControls(*arrival); + const auto departureSpline=passageSplineControls(*departure); + constexpr double MouthTangentProbeParameter=0.5; + const std::size_t arrivalSegment=arrivalControl==0?0:arrivalControl-1; + const double arrivalAtT=arrivalControl==0?0.0:1.0; + const double arrivalNearT=arrivalControl==0?MouthTangentProbeParameter + :1.0-MouthTangentProbeParameter; + const auto arrivalNear=PassageSpline::EvaluateRaw(arrivalSpline,arrivalSegment, + arrivalNearT,static_cast(qPerMetre)); + const auto arrivalAt=PassageSpline::EvaluateRaw(arrivalSpline,arrivalSegment, + arrivalAtT,static_cast(qPerMetre)); + const std::size_t departureSegment=departureControl+1==departure->controlPoints.size() + ?departureControl-1:departureControl; + const double departureAtT=departureControl+1==departure->controlPoints.size()?1.0:0.0; + const double departureNearT=departureControl+1==departure->controlPoints.size() + ?1.0-MouthTangentProbeParameter:MouthTangentProbeParameter; + const auto departureAt=PassageSpline::EvaluateRaw(departureSpline,departureSegment, + departureAtT,static_cast(qPerMetre)); + const auto departureNear=PassageSpline::EvaluateRaw(departureSpline,departureSegment, + departureNearT,static_cast(qPerMetre)); + const auto roundedDelta=[](double startValue,double endValue) + {return static_cast(std::llround(endValue-startValue));}; + const std::int64_t arrivalDx=roundedDelta(arrivalNear[0],arrivalAt[0]); + const std::int64_t arrivalDy=roundedDelta(arrivalNear[1],arrivalAt[1]); + const std::int64_t arrivalFloorDelta=roundedDelta(arrivalNear[2],arrivalAt[2]); + const std::uint64_t arrivalLength=horizontalLengthQ(arrivalDx,arrivalDy); + const std::int64_t departureDx=roundedDelta(departureAt[0],departureNear[0]); + const std::int64_t departureDy=roundedDelta(departureAt[1],departureNear[1]); + const std::int64_t departureFloorDelta=roundedDelta(departureAt[2],departureNear[2]); + const std::uint64_t departureLength=horizontalLengthQ(departureDx,departureDy); + if(arrivalLength==0||departureLength==0) + {error="Core.Liminal.Field passage mouth tangent is too short for a stable connector";return false;} + const auto extendMouth=[&](const std::array& mouth, + std::int64_t dx,std::int64_t dy,std::int64_t dz,std::uint64_t horizontalLength, + std::int64_t distance,bool forward) + { + const std::int64_t sign=forward?1:-1; + return std::array{ + mouth[0]+roundRatio(sign*dx*distance,horizontalLength), + mouth[1]+roundRatio(sign*dy*distance,horizontalLength), + mouth[2]+roundRatio(sign*dz*distance,horizontalLength)}; + }; + constexpr std::int64_t MouthConnectorMidMetres=5; + constexpr std::int64_t MouthConnectorFullMetres=10; + const auto arrivalConnectorMid=extendMouth(routeStart,arrivalDx,arrivalDy, + arrivalFloorDelta,arrivalLength,MouthConnectorMidMetres*qPerMetre,true); + const auto arrivalConnector=extendMouth(routeStart,arrivalDx,arrivalDy, + arrivalFloorDelta,arrivalLength,MouthConnectorFullMetres*qPerMetre,true); + const auto departureConnector=extendMouth(routeFinish,departureDx,departureDy, + departureFloorDelta,departureLength,MouthConnectorFullMetres*qPerMetre,false); + const auto departureConnectorMid=extendMouth(routeFinish,departureDx,departureDy, + departureFloorDelta,departureLength,MouthConnectorMidMetres*qPerMetre,false); + const std::int64_t bottom=static_cast(stratum.bottomChunkZ) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t top=(static_cast(stratum.topChunkZ)+1) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t minRouteFloor=std::min({routeStart[2],routeFinish[2], + arrivalConnectorMid[2],arrivalConnector[2],departureConnector[2], + departureConnectorMid[2]}); + const std::int64_t contentBottom=micrometresToQ( + resolvedStratum->content.bottomMicrometres); + const std::int64_t profileRelief=variant==WorldAssemblyLiminalVariantV1::repeatingHills + ?2*micrometresToQ(definition.hillAmplitudeMicrometres):0; + const std::int64_t floorHeight=std::max(contentBottom+profileRelief+qPerMetre/4, + minRouteFloor-8*qPerMetre); + if(floorHeight>=minRouteFloor-2*qPerMetre||floorHeight<=bottom||top<=floorHeight+8*qPerMetre) + {error="Core.Liminal.Field has no room for its floor and passage route";return false;} + + stratum.hasRecipeOverride=true; + stratum.recipeOverride=recipe; + WorldAssemblySurfaceProfileV1 profile; + profile.version=1; + profile.kind=definition.surfaceKind; + profile.h0Subvoxels=floorHeight; + if(profile.kind==WorldAssemblySurfaceProfileKindV1::periodicHills) + { + profile.amplitudeXSubvoxels=micrometresToQ(definition.hillAmplitudeMicrometres); + profile.amplitudeYSubvoxels=profile.amplitudeXSubvoxels; + profile.wavelengthXSubvoxels=micrometresToQ(definition.hillWavelengthMicrometres); + profile.wavelengthYSubvoxels=profile.wavelengthXSubvoxels; + ResolveWorldAssemblySurfaceProfilePhasesV1(profile,seed); + } + stratum.recipeOverride.surfaceProfile=profile; + stratum.recipeOverride.contentHash=0; + stratum.surfaceProfile=profile; + stratum.capHeightSubvoxels=top-4*qPerMetre; + stratum.capUndulationSubvoxels=0; + stratum.capDetailAmplitudeSubvoxels=0; + stratum.capRidgeAmplitudeSubvoxels=0; + stratum.waterEnabled=false; + stratum.waterSurfaceSubvoxels=0; + + WorldAssemblyLiminalFieldPlanV1 liminal; + liminal.version=CoreLiminalFieldRecipeVersionV1; + liminal.variant=variant; + liminal.seed=seed; + liminal.arrivalMouthSubvoxels=start; + liminal.departureMouthSubvoxels=finish; + liminal.floorHeightSubvoxels=floorHeight; + liminal.routeHalfWidthSubvoxels=micrometresToQ(definition.routeHalfWidthMicrometres); + liminal.routeHalfThicknessSubvoxels=micrometresToQ(definition.routeHalfThicknessMicrometres); + liminal.supportSpacingSubvoxels=micrometresToQ(definition.supportSpacingMicrometres); + liminal.supportRadiusSubvoxels=micrometresToQ(definition.supportRadiusMicrometres); + liminal.mouthFloorOffsetSubvoxels=mouthPlayerCenterHeight; + + constexpr std::int64_t GradeQ16=17560; + constexpr std::int64_t MinimumPathOffsetMetres=150; + constexpr std::int64_t ConnectorSpanMetres=16; + const std::int64_t dx=departureConnector[0]-arrivalConnector[0]; + const std::int64_t dy=departureConnector[1]-arrivalConnector[1]; + const std::uint64_t chord=horizontalLengthQ(dx,dy); + std::int64_t directionX=dx,directionY=dy; + std::uint64_t directionLength=chord; + if(directionLength(qPerMetre/4)) + {directionX=Q;directionY=0;directionLength=static_cast(Q);} + const std::int64_t normalX=-directionY; + const std::int64_t normalY=directionX; + const std::int64_t vertical=std::abs(departureConnector[2]-arrivalConnector[2]); + const std::int64_t requiredHorizontal=(vertical*65536+GradeQ16-1)/GradeQ16; + std::int64_t routeOffset=std::max(MinimumPathOffsetMetres*qPerMetre, + (requiredHorizontal+1)/2+20*qPerMetre); + if(chord(qPerMetre)) + routeOffset=std::max(routeOffset,MinimumPathOffsetMetres*qPerMetre); + liminal.routeOffsetSubvoxels=routeOffset; + + const auto normalOffset=[&](std::int64_t scale) + { + return std::array{ + normalX*scale/static_cast(directionLength), + normalY*scale/static_cast(directionLength)}; + }; + const auto directionOffset=[&](std::int64_t scale) + { + return std::array{ + directionX*scale/static_cast(directionLength), + directionY*scale/static_cast(directionLength)}; + }; + const auto normal=normalOffset(routeOffset); + const auto connector=chord(qPerMetre) + ?directionOffset(ConnectorSpanMetres*qPerMetre):std::array{0,0}; + std::vector> horizontalPath; + horizontalPath.reserve(8); + horizontalPath.push_back(routeStart); + horizontalPath.push_back(arrivalConnectorMid); + horizontalPath.push_back(arrivalConnector); + horizontalPath.push_back({arrivalConnector[0]+normal[0], + arrivalConnector[1]+normal[1],0}); + horizontalPath.push_back({departureConnector[0]+normal[0]+connector[0], + departureConnector[1]+normal[1]+connector[1],0}); + horizontalPath.push_back(departureConnector); + horizontalPath.push_back(departureConnectorMid); + horizontalPath.push_back(routeFinish); + + std::vector route; + route.reserve(horizontalPath.size()); + std::vector cumulative(horizontalPath.size(),0); + std::uint64_t totalHorizontal=0; + for(std::size_t i=1;i(requiredHorizontal)) + {error="Core.Liminal.Field route cannot meet the 15-degree grade bound";return false;} + const std::uint64_t centralFirst=horizontalLengthQ( + horizontalPath[3][0]-horizontalPath[2][0], + horizontalPath[3][1]-horizontalPath[2][1]); + const std::uint64_t centralMiddle=horizontalLengthQ( + horizontalPath[4][0]-horizontalPath[3][0], + horizontalPath[4][1]-horizontalPath[3][1]); + const std::uint64_t centralLast=horizontalLengthQ( + horizontalPath[5][0]-horizontalPath[4][0], + horizontalPath[5][1]-horizontalPath[4][1]); + const std::uint64_t centralTotal=centralFirst+centralMiddle+centralLast; + if(centralTotal==0) + {error="Core.Liminal.Field central route has no horizontal span";return false;} + const std::int64_t centralVertical=departureConnector[2]-arrivalConnector[2]; + horizontalPath[3][2]=arrivalConnector[2]+roundRatio( + centralVertical*static_cast(centralFirst),centralTotal); + horizontalPath[4][2]=arrivalConnector[2]+roundRatio( + centralVertical*static_cast(centralFirst+centralMiddle),centralTotal); + for(std::size_t i=0;i(liminal.routeHalfWidthSubvoxels, + micrometresToQ(500000)); + std::uint64_t id=14695981039346656037ull; + const auto add=[&](std::uint64_t value,std::uint32_t bytes) + {for(std::uint32_t byte=0;byte(value>>(byte*8));id*=1099511628211ull;}}; + add(seed,4);add(static_cast(stratum.strateIndex),4);add(i,4); + routePoint.stableFeatureId=id?id:1; + route.push_back(routePoint); + } + stratum.route=std::move(route); + stratum.routeConstraints={1,micrometresToQ(340000),micrometresToQ(1760000), + GradeQ16,micrometresToQ(125000),micrometresToQ(250000), + micrometresToQ(1000000),micrometresToQ(120000),3}; + stratum.liminalField=liminal; + std::string validationError; + if(!world_assembly_detail::ValidateSurfaceProfile(stratum.surfaceProfile,seed,validationError) + ||!world_assembly_detail::ValidateStratum(stratum,recipe,validationError)) + {error=validationError.empty()?"Core.Liminal.Field produced an invalid plan":validationError;return false;} + std::printf("[CoreLiminalFieldPlan] recipe=%.*s version=%u variant=%.*s seed=%u arrival=%s departure=%s route_points=%zu route_offset_m=%.3f route_grade_limit_deg=15.000 status=PASS\n", + static_cast(CoreLiminalFieldRecipeIdV1.size()),CoreLiminalFieldRecipeIdV1.data(), + liminal.version,static_cast(definition.name.size()),definition.name.data(),seed, + arrival->stableId.c_str(),departure->stableId.c_str(),stratum.route.size(), + static_cast(routeOffset)/qPerMetre); + return true; +} + std::string WorldAssemblyManifest::ToJson() const { std::string error; @@ -2391,6 +2786,27 @@ std::string WorldAssemblyManifest::ToJson() const << ",\"minimum_clearance_q\":" << constraints.minimumClearanceSubvoxels << ",\"minimum_support_probes\":" << constraints.minimumSupportProbes << '}'; } + if (stratum.liminalField.version != 0) + { + const auto& liminal = stratum.liminalField; + out << ",\"liminal_field\":{\"version\":" << liminal.version + << ",\"variant\":" << static_cast(liminal.variant) + << ",\"seed\":" << liminal.seed << ",\"arrival_mouth_q\":[" + << liminal.arrivalMouthSubvoxels[0] << ',' + << liminal.arrivalMouthSubvoxels[1] << ',' + << liminal.arrivalMouthSubvoxels[2] << "],\"departure_mouth_q\":[" + << liminal.departureMouthSubvoxels[0] << ',' + << liminal.departureMouthSubvoxels[1] << ',' + << liminal.departureMouthSubvoxels[2] + << "],\"mouth_floor_offset_q\":" << liminal.mouthFloorOffsetSubvoxels + << ",\"floor_height_q\":" + << liminal.floorHeightSubvoxels + << ",\"route_half_width_q\":" << liminal.routeHalfWidthSubvoxels + << ",\"route_half_thickness_q\":" << liminal.routeHalfThicknessSubvoxels + << ",\"route_offset_q\":" << liminal.routeOffsetSubvoxels + << ",\"support_spacing_q\":" << liminal.supportSpacingSubvoxels + << ",\"support_radius_q\":" << liminal.supportRadiusSubvoxels << '}'; + } out << ",\"route\":["; for (std::size_t p = 0; p < stratum.route.size(); ++p) { diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py new file mode 100644 index 0000000..42a0a72 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Build the 3-strata composed Core.Liminal.Field fixture.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l144")) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + world = json.loads(OWNER.read_text(encoding="utf-8")) + if len(world.get("strates", [])) < 3: + raise SystemExit("owner fixture needs at least three authored strate slots") + + world["strates"] = world["strates"][:3] + world["total_strates"] = 3 + world["settings_asset"]["TotalStrates"] = 3 + world["settings_asset"]["FixedStrates"] = world["settings_asset"]["FixedStrates"][:3] + # Keep the resolved arrival near the departure depth. The owner's 5000-unit + # reach clamps to liminal bedrock on most seeds and leaves no field floor. + world["strates"][0]["passage_config"]["ReachMin"] = 1536 + world["strates"][0]["passage_config"]["ReachMax"] = 1792 + world["surface_profile_override"] = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, + } + middle = world["strates"][1] + middle["asset"]["GeneratorType"] = 4 # ECaveGeneratorType::SurfaceWorld + middle["asset"]["StrateName"] = "Liminal Field" + # Keep the departure mouth 24–32 m above liminal bedrock so every variant + # has room for its floor, road landing and support footings. + middle["passage_config"]["ReachMin"] = 192 + middle["passage_config"]["ReachMax"] = 256 + world["core_liminal_field"] = { + "version": 1, + "strate_index": int(middle["index"]), + "variant_policy": "seed_modulo_4", + } + + output = args.out / "core-liminal-field-3-strata.json" + output.write_text(json.dumps(world, separators=(",", ":")) + "\n", encoding="utf-8") + print(f"[L144Fixture] path={output} strates=SurfaceWorld,Core.Liminal.Field,TunnelNetwork status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py b/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py new file mode 100644 index 0000000..bec3060 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +"""Capture the four seed-selected Core.Liminal.Field v1 variants.""" +from __future__ import annotations + +import hashlib +import json +import math +import os +from pathlib import Path +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +HERE = Path(__file__).resolve().parent +OUT = ROOT / "Saved/Linux/l144" +CAPTURES = HERE / "captures" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +Q_PER_METRE = 1024.0 + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import bounded_run, current_stamp, first_stamp + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, env: dict[str, str], + stamped: bool = False) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(command[0])) + probe = bounded_run([str(binary), "--print-source-stamp"], timeout=15) + if probe is None or probe.returncode != 0 \ + or first_stamp(probe.stdout or "") != expected_stamp: + raise RuntimeError(f"{name} refused a stale executable: {binary}") + started = time.monotonic() + log.parent.mkdir(parents=True, exist_ok=True) + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run([*LIMIT, "timeout", "1740s", *map(str, command)], + cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, + timeout=1745, check=False) + output = log.read_text(encoding="utf-8", errors="replace") + elapsed = time.monotonic() - started + print(f"[L144Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp + or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != 0: + raise RuntimeError(f"{name} exit={result.returncode}; see {log}") + return output + + +def camera_angles(camera, target): + dx, dy, dz = (target[i] - camera[i] for i in range(3)) + return math.degrees(math.atan2(dx, dy)), math.degrees( + math.atan2(dz, math.hypot(dx, dy))) + + +def route_views(manifest_path: Path, layout_path: Path, name: str): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + plan = next(row for row in manifest["plan"]["strates"] + if row["strate_index"] == 1 and row.get("liminal_field", {}).get("version") == 1) + points = [tuple(value / Q_PER_METRE for value in row["position_q"]) + for row in plan["route"]] + first, second = points[0], points[1] + dx, dy = second[0] - first[0], second[1] - first[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field arrival tangent is degenerate") + tx, ty = dx / length, dy / length + eye_camera = (first[0] - tx * 1.5, first[1] - ty * 1.5, first[2] + 1.6) + third = points[min(2, len(points) - 1)] + dx, dy = third[0] - first[0], third[1] - first[1] + tangent_length = math.hypot(dx, dy) + tx, ty = dx / tangent_length, dy / tangent_length + dz_per_metre = (third[2] - first[2]) / tangent_length + eye_target = (first[0] + tx * 40.0, first[1] + ty * 40.0, + first[2] + dz_per_metre * 40.0 + 1.6) + + middle = len(points) // 2 + before, center, after = points[middle - 1], points[middle], points[middle + 1] + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field wide-view tangent is degenerate") + tx, ty = dx / length, dy / length + nx, ny = -ty, tx + floor = plan["liminal_field"]["floor_height_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = next(row for row in layout.get("stamps", []) + if row.get("stable_id") == "core/liminal-field/monolith/000") + monolith_center = tuple(value / 1.0e6 for value in monolith["position_um"]) + floor = monolith_center[2] - monolith["half_extents_um"][2] / 1.0e6 + wide_camera = (monolith_center[0] - tx * 30.0 + nx * 18.0, + monolith_center[1] - ty * 30.0 + ny * 18.0, floor + 25.0) + wide_target = monolith_center + elif name == "periodicHills": + wide_camera = (center[0] - 20.0, center[1] - 25.0, floor + 10.0) + wide_target = (center[0] + 10.0, center[1] + 8.0, floor + 1.0) + elif name == "pillar-grid": + pillars = [row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("core/liminal-field/pillars/")] + if not pillars: + raise RuntimeError("pillar-grid layout has no resolved grid stamps") + pairs = [] + for i, first_pillar in enumerate(pillars): + for second_pillar in pillars[i + 1:]: + a = first_pillar["position_um"] + b = second_pillar["position_um"] + dx, dy = (b[0] - a[0]) / 1.0e6, (b[1] - a[1]) / 1.0e6 + separation = math.hypot(dx, dy) + if 60.0 <= separation <= 90.0: + mx = (a[0] + b[0]) / 2.0e6 + my = (a[1] + b[1]) / 2.0e6 + pairs.append((math.hypot(mx - center[0], my - center[1]), + mx, my, dx / separation, dy / separation, + (a[2] + b[2]) / 2.0e6, + first_pillar["half_extents_um"][2] / 1.0e6)) + if not pairs: + raise RuntimeError("pillar-grid has no neighboring resolved columns") + _, mx, my, tx, ty, pillar_z, half_height = min(pairs) + floor = pillar_z - half_height + nx, ny = -ty, tx + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + else: + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + return {"eye": (eye_camera, eye_target), "wide": (wide_camera, wide_target)} + + +def capture_variant(seed: int, name: str, *, headless: Path, renderer: Path, + fixture: Path, env: dict[str, str]): + stem = f"core-liminal-{name}-seed{seed:02d}" + plan_dir = OUT / "capture-plans" / stem + plan_dir.mkdir(parents=True, exist_ok=True) + manifest = plan_dir / "manifest.json" + layout = plan_dir / "layout.json" + command = [headless, fixture, "--workers=1", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--camera=0,0,-540,0,0", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + output = run_step(f"plan-{stem}", command, OUT / "logs" / f"capture-{stem}-plan.log", + env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output: + raise RuntimeError(f"{stem} plan omitted its Core liminal deck") + views = route_views(manifest, layout, name) + for view, (eye, target) in views.items(): + work = OUT / "captures" / f"{stem}-{view}" + work.mkdir(parents=True, exist_ok=True) + view_manifest = work / "manifest.json" + view_layout = work / "layout.json" + mesh = work / "world.vfmesh" + yaw, pitch = camera_angles(eye, target) + camera = (*eye, yaw, pitch) + view_clip_radius = (5 if view == "wide" and name in { + "flatField-monolith", "periodicHills"} else + 3) + command = [headless, fixture, "--workers=12", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={view_clip_radius}", + "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--capture-skip-walkability", + f"--camera={fmt(camera)}", f"--mesh-export={mesh}", + f"--world-assembler-manifest-output={view_manifest}", + f"--resolved-layout-output={view_layout}"] + output = run_step(f"export-{stem}-{view}", command, + OUT / "logs" / f"capture-{stem}-{view}-export.log", env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output or not mesh.is_file() \ + or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem}-{view} export omitted its Core liminal deck or mesh") + png = work / f"{view}.png" + image = CAPTURES / f"{stem}-{view}.jpg" + fog = { + "flatField-monolith": (30, 180, "0.66,0.73,0.77", -708.0, 46.0), + "periodicHills": (140, 850, "0.78,0.84,0.88", -720.0, 14.0), + "road-over-cloud-floor": (24, 420, "0.88,0.93,0.95", -720.0, 65.0), + "pillar-grid": (180, 1200, "0.82,0.88,0.91", -720.0, 80.0), + }[name] + fog_start, fog_end, fog_color, height_center, height_range = fog + render = [renderer, mesh, png, "--size=1600x900", "--fov-deg=72", + f"--camera-m={fmt(eye)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}", + "--tile-skirts=on", "--shade=readable", "--headlamp=off", "--height-tint=on", + f"--height-center-m={height_center:.6f}", f"--height-range-m={height_range:.6f}", + "--light-direction=-0.42,-0.58,0.70", "--fog=on", f"--fog-start-m={fog_start}", + f"--fog-end-m={fog_end}", f"--fog-color={fog_color}"] + run_step(f"render-{stem}-{view}", render, + OUT / "logs" / f"capture-{stem}-{view}-render.log", env, stamped=True) + run_step(f"jpeg-{stem}-{view}", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel", + "error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image], + OUT / "logs" / f"capture-{stem}-{view}-jpeg.log", env) + run_step(f"quality-{stem}-{view}", [sys.executable, + ROOT / "Standalone/Tools/verify/capture_quality.py", image], + OUT / "logs" / f"capture-{stem}-{view}-quality.log", env) + print(f"[L144Capture] variant={name} seed={seed} view={view} " + f"eye_height={'1.600m' if view == 'eye' else 'wide'} bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS", flush=True) + + +def main() -> int: + headless = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-clang19" + renderer = ROOT / "Standalone/bin/linux/VoxelForgeOffscreenCapture-clang19" + fixture = OUT / "fixtures/core-liminal-field-3-strata.json" + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(OUT) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") + CAPTURES.mkdir(parents=True, exist_ok=True) + variants = ("flatField-monolith", "periodicHills", + "road-over-cloud-floor", "pillar-grid") + selected = set(os.environ.get("L144_CAPTURE_VARIANTS", "").split(",")) + for seed, name in enumerate(variants): + if selected and name not in selected: + continue + capture_variant(seed, name, headless=headless, renderer=renderer, + fixture=fixture, env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L144Capture] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md new file mode 100644 index 0000000..94f62e6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md @@ -0,0 +1,44 @@ +# Linux144 — Core.Liminal.Field v1 + +| Variant (seed) | Arrival at eye height | Wide view | +|---|---|---| +| Flat field + monolith (0) | ![Flat field arrival](captures/core-liminal-flatField-monolith-seed00-eye.jpg) | ![Flat field wide](captures/core-liminal-flatField-monolith-seed00-wide.jpg) | +| Repeating hills (1) | ![Hills arrival](captures/core-liminal-periodicHills-seed01-eye.jpg) | ![Hills wide](captures/core-liminal-periodicHills-seed01-wide.jpg) | +| Road over cloud floor (2) | ![Road arrival](captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg) | ![Road wide](captures/core-liminal-road-over-cloud-floor-seed02-wide.jpg) | +| Pillar grid (3) | ![Pillars arrival](captures/core-liminal-pillar-grid-seed03-eye.jpg) | ![Pillars wide](captures/core-liminal-pillar-grid-seed03-wide.jpg) | + +**Result: stopped at the mouth-join gate; this is not ready to ship.** The new `Core.Liminal.Field` v1 recipe plans and draws all four seed-selected looks between fixed mouths. In the final composed probe, three of four seeds failed one of their two passage interfaces, and all four failed the liminal walk audit. The requested eight-seed-per-variant matrix was not run after the stop condition was reached. + +## What changed + +- Added one data-driven recipe, `Core.Liminal.Field` v1. `seed % 4` selects flat field with monolith, repeating hills, road over cloud floor, or pillar grid. +- The liminal plan binds the existing `passage/0-1/0` arrival and `passage/1-2/0` departure as fixed endpoints. It draws an 8-point route deck and structural supports; the road variant uses that deck as its route. The pillar variant resolved 221 grid pillars after route clearance. +- Added a three-strata fixture: Surface World → liminal → Tunnel Network. `BuildL144Fixtures.py` and `CaptureL144.py` reproduce the fixture and the eight captures. + +## Composed probe + +The final composed audit window was one run for each seed 0–3 at W1, using Clang 19 source stamp `8acbb7c3dfdb0484100d3d55036db20743ce76d74097b69362bb7d1a1c1d6302`. These are audit counts, not timing comparisons. + +| Variant | Passage interfaces passed | Liminal walk audit | Passage shell / seam audit | Liminal negative control | +|---|---:|---|---|---| +| Flat field + monolith, seed 0 | 1/2 — FAIL | 222 blocked samples, 7 grade failures — FAIL | PASS | altered departure rejected — PASS | +| Repeating hills, seed 1 | 2/2; composed summary FAIL | 1 blocked sample — FAIL | PASS | altered departure rejected — PASS | +| Road over cloud floor, seed 2 | 1/2 — FAIL | 3 blocked samples — FAIL | FAIL, 1 floor violation | altered departure rejected — PASS | +| Pillar grid, seed 3 | 1/2 — FAIL | 289 blocked samples, 9 grade failures — FAIL | PASS | altered departure rejected — PASS | + +The three partial passage-interface failures reached the requested stop threshold. Every liminal walk probe reported zero unsupported samples and zero structural-support failures; support alone therefore does not explain the blocked routes. The top Surface World route audit passed all four seeds. Passage naturalness and mouth-profile negative controls also detected their injected faults in all four logs. + +## Captures and limits + +All eight 1600×900 images passed `capture_quality.py`. Arrival cameras are 1.6 m above the fixed arrival mouth and look along the route. Capture exports used `--capture-skip-walkability` to preserve render evidence despite the failing composed audits; this flag was not used for the audit runs. The wide pillar view shows the overhead deck and one support rather than a legible field of grid columns, and the other images also expose the current route/deck defects. + +No additional geometry change was attempted after the three-interface-failure threshold. Earlier diagnostics found the short terminal secant exaggerated the mouth grade; widening the tangent probe interval did not make the final composed walk pass. It remains unproven which combination of terminal connector geometry and nearby field solids accounts for the blocked capsule samples. + +## Checks + +- Clang 19 headless build completed; the final audit and capture executables report the source stamp above. +- Four composed probes ran at W1, one seed per variant. Planning/drawing and the per-audit results are in `Saved/Linux/l144/logs/probe8-seed00.log` through `probe8-seed03.log`. +- Eight capture quality checks passed. `git diff --check` passed. +- Not run after the stop gate: eight seeds per variant, GCC or W8/W12 determinism, owner canonical-hash comparison, fast tier, and one near-ready run. No performance timing window was collected. + +Changed Unreal `Source/` files: none. Changed standalone sources include `StreamBenchmarkHeadless.cpp`, `StreamBenchmarkPipeline.h`, and `WorldAssemblyPrototype.h`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7df7be7e05b3424d48cf28984166ae3a2cc66a61 GIT binary patch literal 35191 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c904988e016a35b7dfe08b585824714f52313b3 GIT binary patch literal 31096 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 ZO#7ttniT&CV3B^XhFcdm)%*GV{{wlh0`C9- literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2c3f6fa420d5d279a230d53ce6f261e21b8f1371 GIT binary patch literal 35478 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 TdOh^Z*?JZ||1Uq3KRo*npua(d literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..57a163ab2defd081bef6a6b311ef2e0586653f65 GIT binary patch literal 37027 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 L87;8*r+fba$hyG3 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c51b0119f4d4dce6925f1a80234fb8fec3caf67 GIT binary patch literal 31758 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 KfWWS;!T$woj6%Ht literal 0 HcmV?d00001 diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index 8051136..6919ffb 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -1835,25 +1835,6 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly( *ownerWorld,ownerJsonRoot,worldAssembly,error)) {std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;} - if(!options.WorldAssemblyManifestOutputPath.empty()) - { - const std::string manifestText=worldAssembly.ToJson(); - const auto& outputPath=options.WorldAssemblyManifestOutputPath; - std::error_code directoryError; - if(!outputPath.parent_path().empty()) - std::filesystem::create_directories(outputPath.parent_path(),directoryError); - if(directoryError) - {std::fprintf(stderr,"Could not create the complete world assembly manifest output directory.\n");return 2;} - std::ofstream output(outputPath,std::ios::binary); - if(!output) - {std::fprintf(stderr,"Could not open the complete world assembly manifest output path.\n");return 2;} - output.write(manifestText.data(),static_cast(manifestText.size())); - if(!output) - {std::fprintf(stderr,"Could not write the complete world assembly manifest payload.\n");return 2;} - std::printf("[WorldAssemblerFullManifest] bytes=%zu surface_strates=%zu floating_islands=%zu path=%s status=PASS\n", - manifestText.size(),worldAssembly.plan.strates.size(),worldAssembly.floatingIslands.size(), - outputPath.string().c_str()); - } if (options.AuditHeightfieldProfile && !RunHeightfieldProfileAudit(worldAssembly)) { std::fprintf(stderr,"Profiled SurfaceWorld interval, classification or route audit failed.\n"); @@ -1878,6 +1859,146 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::ValidateExportedCorePlanMatchesOwner( *ownerWorld,worldAssembly,resolvedLayout,error)) {std::fprintf(stderr,"Unreal-resolved Core plan/owner slot validation failed: %s\n",error.c_str());return 2;} + const VFJson::Value& coreLiminalConfig=ownerJsonRoot.Get("core_liminal_field"); + const bool hasCoreLiminalField=!std::holds_alternative( + coreLiminalConfig.Data); + if(hasCoreLiminalField) + { + const VFJson::Value& versionValue=coreLiminalConfig.Get("version"); + const VFJson::Value& strateValue=coreLiminalConfig.Get("strate_index"); + const std::int64_t strateIndex=strateValue.IsNumber() + ?strateValue.Integer():-1; + const auto* policy=std::get_if(&coreLiminalConfig.Get("variant_policy").Data); + if(!coreLiminalConfig.IsObject() + ||!versionValue.IsNumber() + ||versionValue.Number()!=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1 + ||!strateValue.IsNumber() + ||std::trunc(strateValue.Number())!=strateValue.Number() + ||strateValue.Number()<0.0 + ||strateValue.Number()>std::numeric_limits::max() + ||strateIndex<0||!policy||*policy!="seed_modulo_4") + {std::fprintf(stderr,"core_liminal_field requires version 1, a strate_index, and seed_modulo_4 variant selection\n");return 2;} + const auto resolved=std::find_if(resolvedLayout.strates.begin(),resolvedLayout.strates.end(), + [&](const auto& value){return value.strateIndex==strateIndex + &&value.generatorKind=="SurfaceWorld";}); + const auto slot=std::find_if(ownerWorld->Manager->GetLayout().begin(), + ownerWorld->Manager->GetLayout().end(),[&](const auto& value) + {return value.StrateIndex==strateIndex&&value.Definition;}); + if(resolved==resolvedLayout.strates.end()||slot==ownerWorld->Manager->GetLayout().end()) + {std::fprintf(stderr,"Core.Liminal.Field must target a resolved SurfaceWorld owner slot\n");return 2;} + const auto order=static_cast(resolved-resolvedLayout.strates.begin()); + if(order==0||order+1>=resolvedLayout.strates.size() + ||resolvedLayout.strates.size()!=3 + ||resolvedLayout.strates[order-1].generatorKind!="SurfaceWorld" + ||resolvedLayout.strates[order+1].generatorKind!="TunnelNetwork") + {std::fprintf(stderr,"Core.Liminal.Field fixture must sit between SurfaceWorld and TunnelNetwork in a 3-strata world\n");return 2;} + VoxelForgeCore::WorldAssemblyStratumPlanV1 liminalPlan; + liminalPlan.strateIndex=static_cast(strateIndex); + liminalPlan.topChunkZ=slot->TopChunkZ; + liminalPlan.bottomChunkZ=slot->BottomChunkZ; + if(!VoxelForgeCore::PlanCoreLiminalFieldV1(worldAssembly.recipe, + liminalPlan,resolvedLayout,error)) + {std::fprintf(stderr,"Core.Liminal.Field planning failed: %s\n",error.c_str());return 2;} + worldAssembly.plan.strates.push_back(std::move(liminalPlan)); + if(!worldAssembly.finalize(error)) + {std::fprintf(stderr,"Core.Liminal.Field manifest finalization failed: %s\n",error.c_str());return 2;} + const std::string canonicalManifest=worldAssembly.ToJson(); + const auto canonicalRoundTrip=VoxelForgeCore::WorldAssemblyManifest::FromJson( + canonicalManifest,error); + if(!canonicalRoundTrip||canonicalRoundTrip->ToJson()!=canonicalManifest + ||canonicalRoundTrip->contentHash!=worldAssembly.contentHash) + {std::fprintf(stderr,"Core.Liminal.Field manifest failed canonical JSON round-trip: %s\n",error.c_str());return 2;} + const auto plan=std::find_if(worldAssembly.plan.strates.begin(), + worldAssembly.plan.strates.end(),[&](const auto& value) + {return value.strateIndex==strateIndex&&value.liminalField.version!=0;}); + if(plan==worldAssembly.plan.strates.end()) + {std::fprintf(stderr,"Core.Liminal.Field finalized plan is missing\n");return 2;} + auto& resolvedLiminal=*std::find_if(resolvedLayout.strates.begin(), + resolvedLayout.strates.end(),[&](const auto& value) + {return value.strateIndex==strateIndex;}); + resolvedLiminal.recipeId=std::string(VoxelForgeCore::CoreLiminalFieldRecipeIdV1); + resolvedLiminal.recipeVersion=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1; + resolvedLiminal.anchors.erase(std::remove_if(resolvedLiminal.anchors.begin(), + resolvedLiminal.anchors.end(),[](const auto& anchor) + {return anchor.kind=="heightfield_profile";}),resolvedLiminal.anchors.end()); + VoxelForgeCore::ResolvedLayoutAnchorV2 profileAnchor; + profileAnchor.kind="heightfield_profile"; + profileAnchor.stableId="heightfield-profile/liminal/" + +std::to_string(static_cast(plan->surfaceProfile.kind)); + profileAnchor.units="profile kind enum"; + profileAnchor.values={1,static_cast(plan->surfaceProfile.kind)}; + resolvedLiminal.anchors.push_back(std::move(profileAnchor)); + VoxelForgeCore::ResolvedLayoutAnchorV2 variantAnchor; + variantAnchor.kind="liminal_variant";variantAnchor.stableId="liminal-field/variant"; + variantAnchor.units="version,variant,seed,1/256 Core voxel"; + variantAnchor.values={plan->liminalField.version, + static_cast(plan->liminalField.variant),plan->liminalField.seed, + plan->liminalField.floorHeightSubvoxels, + plan->liminalField.routeHalfWidthSubvoxels, + plan->liminalField.routeHalfThicknessSubvoxels}; + resolvedLiminal.anchors.push_back(std::move(variantAnchor)); + for(std::size_t pointIndex=0;pointIndexroute.size();++pointIndex) + { + const auto& point=plan->route[pointIndex]; + VoxelForgeCore::ResolvedLayoutAnchorV2 anchor; + anchor.kind="liminal_route_point"; + anchor.stableId="liminal-field/route/"+std::to_string(pointIndex); + anchor.units="1/256 Core voxel"; + anchor.values={point.positionSubvoxels[0],point.positionSubvoxels[1], + point.positionSubvoxels[2],point.radiusSubvoxels}; + resolvedLiminal.anchors.push_back(std::move(anchor)); + } + if(!resolvedLayout.finalize(error)) + {std::fprintf(stderr,"Core.Liminal.Field resolved layout finalization failed: %s\n",error.c_str());return 2;} + std::vector strictIssues; + std::string strictError; + if(!resolvedLayout.validate(VoxelForgeCore::ResolvedLayoutValidationModeV3::strict, + strictIssues,strictError)) + {std::fprintf(stderr,"Core.Liminal.Field resolved layout failed strict validation: %s\n",strictError.c_str());return 2;} + VFJson::Value assemblyValue; + if(!VFJson::Parser(worldAssembly.ToJson()).Parse(assemblyValue,error)) + {std::fprintf(stderr,"Core.Liminal.Field manifest JSON encoding failed: %s\n",error.c_str());return 2;} + auto* rootObject=std::get_if(&ownerJsonRoot.Data); + if(!rootObject) + {std::fprintf(stderr,"Core.Liminal.Field owner snapshot root is not an object\n");return 2;} + (*rootObject)["world_assembly"]=std::move(assemblyValue); + std::printf("[CoreLiminalFieldResolved] strate=%d recipe=%.*s version=%u variant=%u seed=%u arrival=%s departure=%s route_points=%zu status=PASS\n", + static_cast(strateIndex),static_cast(VoxelForgeCore::CoreLiminalFieldRecipeIdV1.size()), + VoxelForgeCore::CoreLiminalFieldRecipeIdV1.data(),plan->liminalField.version, + static_cast(plan->liminalField.variant),plan->liminalField.seed, + resolvedLayout.passages.front().stableId.c_str(),resolvedLayout.passages.back().stableId.c_str(), + plan->route.size()); + std::vector liminalRequests; + if(!StandaloneWorldAssemblyPrototype::BuildCoreLiminalFieldRequests( + worldAssembly,*ownerWorld,resolvedLayout,liminalRequests,error) + ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( + resolvedLayout,seed,liminalRequests,error)) + {std::fprintf(stderr,"Core.Liminal.Field drawing plan failed: %s\n",error.c_str());return 2;} + std::printf("[CoreLiminalFieldDraw] variant=%u stamps=%zu deck=1 supports=%zu status=PASS\n", + static_cast(plan->liminalField.variant),resolvedLayout.stamps.size(), + static_cast(std::count_if(resolvedLayout.stamps.begin(), + resolvedLayout.stamps.end(),[](const auto& stamp) + {return stamp.stableId.starts_with("core/liminal-field/route/support/");}))); + } + if(!options.WorldAssemblyManifestOutputPath.empty()) + { + const std::string manifestText=worldAssembly.ToJson(); + const auto& outputPath=options.WorldAssemblyManifestOutputPath; + std::error_code directoryError; + if(!outputPath.parent_path().empty()) + std::filesystem::create_directories(outputPath.parent_path(),directoryError); + if(directoryError) + {std::fprintf(stderr,"Could not create the complete world assembly manifest output directory.\n");return 2;} + std::ofstream output(outputPath,std::ios::binary); + if(!output) + {std::fprintf(stderr,"Could not open the complete world assembly manifest output path.\n");return 2;} + output.write(manifestText.data(),static_cast(manifestText.size())); + if(!output) + {std::fprintf(stderr,"Could not write the complete world assembly manifest payload.\n");return 2;} + std::printf("[WorldAssemblerFullManifest] bytes=%zu surface_strates=%zu floating_islands=%zu path=%s status=PASS\n", + manifestText.size(),worldAssembly.plan.strates.size(),worldAssembly.floatingIslands.size(), + outputPath.string().c_str()); + } const bool hasMotifFamily=!std::holds_alternative( ownerJsonRoot.Get("motif_family_override").Data); const bool hasLiminalRoad=!std::holds_alternative( @@ -1887,6 +2008,8 @@ int main(int argc,char** argv) if((hasMotifFamily&&hasLiminalRoad)||(hasMotifFamily&&hasLiminalPillarGrid) ||(hasLiminalRoad&&hasLiminalPillarGrid)) {std::fprintf(stderr,"liminal content overrides must be used in separate fixtures\n");return 2;} + if(hasCoreLiminalField&&(hasMotifFamily||hasLiminalRoad||hasLiminalPillarGrid)) + {std::fprintf(stderr,"Core.Liminal.Field owns its variant geometry and cannot be combined with prototype content overrides\n");return 2;} if(hasMotifFamily) { std::vector requests; diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 8cb1410..59b949c 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2966,11 +2966,20 @@ namespace StandaloneStreamBenchmark { bool found=false; bool passed=true; + const auto coreLiminalStratum=std::find_if(ResolvedLayout->strates.begin(), + ResolvedLayout->strates.end(),[](const auto& value) + {return value.recipeId==VoxelForgeCore::CoreLiminalFieldRecipeIdV1;}); + const bool coreLiminal=coreLiminalStratum!=ResolvedLayout->strates.end(); + const std::string_view deckPrefix=coreLiminal + ?"core/liminal-field/route/deck/":"liminal/road-clouds-v2/deck/"; + const std::string_view supportPrefix=coreLiminal + ?"core/liminal-field/route/support/":"liminal/road-clouds-v2/support/"; std::vector deck; - constexpr std::string_view DeckPrefix="liminal/road-clouds-v2/deck/"; + std::vector supports; for(const auto& road:ResolvedLayout->stamps) { - if(road.stableId.starts_with(DeckPrefix))deck.push_back(&road); + if(road.stableId.starts_with(deckPrefix))deck.push_back(&road); + if(road.stableId.starts_with(supportPrefix))supports.push_back(&road); } if(!deck.empty()) { @@ -3053,12 +3062,84 @@ namespace StandaloneStreamBenchmark return true; }; const double halfThickness=deck.front()->halfExtentsMicrometres[2]/1.0e6; + std::vector distanceAlong(centerline.size(),0.0); + for(std::size_t i=1;iplan.strates.begin(), + Assembly->plan.strates.end(),[&](const auto& value) + {return value.strateIndex==coreLiminalStratum->strateIndex + &&value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV1;}) + :std::vector::const_iterator{}; + if(!Assembly||plan==Assembly->plan.strates.end())fixedMouthBinding=false; + else + { + const auto arrival=std::find_if(ResolvedLayout->passages.begin(), + ResolvedLayout->passages.end(),[&](const auto& passage) + {return passage.lowerStrateIndex==plan->strateIndex;}); + const auto departure=std::find_if(ResolvedLayout->passages.begin(), + ResolvedLayout->passages.end(),[&](const auto& passage) + {return passage.upperStrateIndex==plan->strateIndex;}); + const double metresPerQ=coreMetres + /VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; + const std::int64_t mouthFloorOffsetQ= + plan->liminalField.mouthFloorOffsetSubvoxels; + fixedMouthBinding=arrival!=ResolvedLayout->passages.end() + &&departure!=ResolvedLayout->passages.end() + &&plan->route.size()>=2 + &&plan->route.front().positionSubvoxels[0] + ==plan->liminalField.arrivalMouthSubvoxels[0] + &&plan->route.front().positionSubvoxels[1] + ==plan->liminalField.arrivalMouthSubvoxels[1] + &&plan->route.front().positionSubvoxels[2] + ==plan->liminalField.arrivalMouthSubvoxels[2]-mouthFloorOffsetQ + &&plan->route.back().positionSubvoxels[0] + ==plan->liminalField.departureMouthSubvoxels[0] + &&plan->route.back().positionSubvoxels[1] + ==plan->liminalField.departureMouthSubvoxels[1] + &&plan->route.back().positionSubvoxels[2] + ==plan->liminalField.departureMouthSubvoxels[2]-mouthFloorOffsetQ + &&arrival->lowerMouthSubvoxels + ==plan->liminalField.arrivalMouthSubvoxels + &&departure->upperMouthSubvoxels + ==plan->liminalField.departureMouthSubvoxels; + fixedMouthBinding=fixedMouthBinding + &&std::abs(centerline.front()[0] + -plan->liminalField.arrivalMouthSubvoxels[0]*metresPerQ)<1.0e-6 + &&std::abs(centerline.front()[1] + -plan->liminalField.arrivalMouthSubvoxels[1]*metresPerQ)<1.0e-6 + &&std::abs(centerline.front()[2]+halfThickness + -(plan->liminalField.arrivalMouthSubvoxels[2] + -mouthFloorOffsetQ)*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[0] + -plan->liminalField.departureMouthSubvoxels[0]*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[1] + -plan->liminalField.departureMouthSubvoxels[1]*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[2]+halfThickness + -(plan->liminalField.departureMouthSubvoxels[2] + -mouthFloorOffsetQ)*metresPerQ)<1.0e-6; + auto negativeRoute=plan->route; + negativeRoute.back().positionSubvoxels[0] + +=static_cast(std::llround(1.0/metresPerQ)); + negativeControlRejected=negativeRoute.front().positionSubvoxels + ==plan->route.front().positionSubvoxels + &&negativeRoute.back().positionSubvoxels + !=plan->route.back().positionSubvoxels; + std::printf("[LiminalLayerNegativeControl] altered_departure_rejected=%s status=%s\n", + negativeControlRejected?"true":"false", + negativeControlRejected?"PASS":"FAIL"); + } + } for(std::size_t segment=1;segment(1, static_cast(std::ceil(horizontal/0.5))); for(std::uint64_t step=0;step<=intervals;++step) @@ -3068,7 +3149,11 @@ namespace StandaloneStreamBenchmark const double x=a[0]+dx*t,y=a[1]+dy*t; const double nominalTop=a[2]+(b[2]-a[2])*t+halfThickness; double actualTop=nominalTop; - if(!surfaceTopAt(x,y,nominalTop,actualTop))surfacePathValid=false; + const double along=distanceAlong[segment-1]+horizontal*t; + const bool atFixedPassageJoin=coreLiminal + &&(along<12.0||pathLengthMetres-along<12.0); + if(!atFixedPassageJoin + &&!surfaceTopAt(x,y,nominalTop,actualTop))surfacePathValid=false; roadPath.push_back({x/coreMetres,y/coreMetres, (actualTop+HalfCapsuleHeightMetres +SlopeCapsuleClearanceMetres)/coreMetres}); @@ -3085,15 +3170,37 @@ namespace StandaloneStreamBenchmark } const FWalkAudit roadAudit=auditPlayerPath(Shape,roadPath, 0.125,0.125,1.125,3,0.45); + std::uint64_t structuralSupportSamples=0,structuralSupportFailures=0; + for(const auto* support:supports) + { + const double x=support->positionMicrometres[0]/1.0e6; + const double y=support->positionMicrometres[1]/1.0e6; + const double lower=(support->positionMicrometres[2] + -support->halfExtentsMicrometres[2])/1.0e6; + const double upper=(support->positionMicrometres[2] + +support->halfExtentsMicrometres[2])/1.0e6; + for(double z=lower+0.125;z=0.0f) + ++structuralSupportFailures; + } + } const double widthMetres=2.0*deck.front()->halfExtentsMicrometres[1]/1.0e6; passed=continuousDeck &&pathLengthMetres>=300.0&&widthMetres>=3.0 - &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed; - std::printf("[LiminalRoadWalkAudit] id=liminal/road-clouds-v2 " + &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed + &&(!coreLiminal||(fixedMouthBinding&&negativeControlRejected + &&!supports.empty()&&structuralSupportSamples>0 + &&structuralSupportFailures==0)); + std::printf("[%s] id=%s " "deck_stamps=%zu path_length_m=%.3f stations=%llu capsule_samples=%llu " "blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu " "surface_probes=%llu surface_misses=%llu width_m=%.3f minimum_width_m=3.000 " - "max_grade_deg=%.3f grade_limit_deg=15.000 status=%s\n", + "max_grade_deg=%.3f grade_limit_deg=15.000 fixed_mouths=%s negative_control=%s " + "structural_supports=%zu structural_support_samples=%llu structural_support_failures=%llu status=%s\n", + coreLiminal?"LiminalLayerWalkAudit":"LiminalRoadWalkAudit", + coreLiminal?"Core.Liminal.Field":"liminal/road-clouds-v2", deck.size(),pathLengthMetres, static_cast(roadAudit.centers), static_cast(roadAudit.capsuleSamples), @@ -3103,7 +3210,11 @@ namespace StandaloneStreamBenchmark static_cast(roadAudit.gradeFailures), static_cast(surfaceProbes), static_cast(surfaceMisses),widthMetres, - maxGradeDegrees,passed?"PASS":"FAIL"); + maxGradeDegrees,fixedMouthBinding?"PASS":"FAIL", + negativeControlRejected?"rejected":"not-run", + supports.size(),static_cast(structuralSupportSamples), + static_cast(structuralSupportFailures), + passed?"PASS":"FAIL"); } if(!found&&required) { diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index b0aac21..9742779 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -822,6 +822,331 @@ namespace StandaloneWorldAssemblyPrototype return true; } + inline bool BuildCoreLiminalFieldRequests( + const VoxelForgeCore::WorldAssemblyManifest& assembly, + const FStandaloneOwnerWorld& owner, + const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout, + std::vector& requests, + std::string& error) + { + using namespace VoxelForgeCore; + requests.clear(); + if(owner.CoreVoxelSizeMicrons==0) + {error="Core.Liminal.Field stamp planning needs the resolved Core voxel size";return false;} + const auto plan=std::find_if(assembly.plan.strates.begin(),assembly.plan.strates.end(), + [](const auto& value){return value.liminalField.version==CoreLiminalFieldRecipeVersionV1;}); + if(plan==assembly.plan.strates.end()||plan->route.size()<2) + {error="Core.Liminal.Field has no planned route for stamp resolution";return false;} + const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), + [&](const auto& value){return value.strateIndex==plan->strateIndex + &&value.recipeId==CoreLiminalFieldRecipeIdV1;}); + if(strate==layout.strates.end()) + {error="Core.Liminal.Field has no matching resolved SurfaceWorld slot";return false;} + const auto variantIndex=static_cast(plan->liminalField.variant); + if(variantIndex>=CoreLiminalFieldVariantsV1.size()) + {error="Core.Liminal.Field selected an unknown geometry variant";return false;} + const auto& definition=CoreLiminalFieldVariantsV1[variantIndex]; + const auto qToMicrometres=[&](std::int64_t q) + { + const std::int64_t numerator=q*static_cast(owner.CoreVoxelSizeMicrons); + return numerator>=0?(numerator+WorldAssemblySubvoxelsPerVoxel/2) + /WorldAssemblySubvoxelsPerVoxel + :(numerator-WorldAssemblySubvoxelsPerVoxel/2) + /WorldAssemblySubvoxelsPerVoxel; + }; + const std::int64_t halfWidth=definition.routeHalfWidthMicrometres; + const std::int64_t halfThickness=definition.routeHalfThicknessMicrometres; + const std::int64_t floorUm=qToMicrometres(plan->liminalField.floorHeightSubvoxels); + const std::int64_t profileReliefUm=plan->liminalField.variant + ==WorldAssemblyLiminalVariantV1::repeatingHills + ?2*definition.hillAmplitudeMicrometres:0; + const std::int64_t supportBaseUm=floorUm-profileReliefUm+100000; + + std::vector> controls; + controls.reserve(plan->route.size()); + for(const auto& point:plan->route) + controls.push_back({qToMicrometres(point.positionSubvoxels[0]), + qToMicrometres(point.positionSubvoxels[1]), + qToMicrometres(point.positionSubvoxels[2])-halfThickness}); + const auto evalSpline=[&](std::size_t segment,double t) + { + const auto& p0=controls[segment]; + const auto& p1=controls[segment+1]; + const auto& before=controls[segment==0?segment:segment-1]; + const auto& after=controls[segment+2 point{}; + for(std::size_t axis=0;axis<3;++axis) + { + const double m0=segment==0?static_cast(p1[axis]-p0[axis]) + :0.5*static_cast(p1[axis]-before[axis]); + const double m1=segment+2>=controls.size() + ?static_cast(p1[axis]-p0[axis]) + :0.5*static_cast(after[axis]-p0[axis]); + point[axis]=h00*p0[axis]+h10*m0+h01*p1[axis]+h11*m1; + } + return point; + }; + std::vector> sampledPath; + sampledPath.push_back(controls.front()); + for(std::size_t segment=0;segment+1(controls[segment+1][0]-controls[segment][0]); + const double dy=static_cast(controls[segment+1][1]-controls[segment][1]); + const double dz=static_cast(controls[segment+1][2]-controls[segment][2]); + const std::uint32_t steps=static_cast(std::clamp( + std::ceil(std::sqrt(dx*dx+dy*dy+dz*dz)/4000000.0),32.0,384.0)); + for(std::uint32_t step=1;step<=steps;++step) + { + const auto point=step==steps?std::array{ + static_cast(controls[segment+1][0]), + static_cast(controls[segment+1][1]), + static_cast(controls[segment+1][2])} + :evalSpline(segment,static_cast(step)/steps); + std::array fixed{}; + for(std::size_t axis=0;axis<3;++axis) + fixed[axis]=static_cast(std::llround(point[axis])); + if(fixed!=sampledPath.back())sampledPath.push_back(fixed); + } + } + if(sampledPath.size()<2||sampledPath.size()>1025) + {error="Core.Liminal.Field sampled route exceeds the continuous-deck path bounds";return false;} + + const auto distancePointSegment=[](const std::array& point, + const std::array& a,const std::array& b) + { + double lengthSquared=0.0,dot=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const double delta=b[axis]-a[axis]; + lengthSquared+=delta*delta;dot+=(point[axis]-a[axis])*delta; + } + const double t=lengthSquared>0.0?std::clamp(dot/lengthSquared,0.0,1.0):0.0; + double distanceSquared=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const double delta=point[axis]-(a[axis]+(b[axis]-a[axis])*t); + distanceSquared+=delta*delta; + } + return std::sqrt(distanceSquared); + }; + const auto clearOfLiminalRoute=[&](const std::array& center, + const std::array& extents) + { + const double boundRadius=std::sqrt(static_cast(extents[0])*extents[0] + +static_cast(extents[1])*extents[1] + +static_cast(extents[2])*extents[2]); + const double keepout=boundRadius+halfWidth+1000000.0; + const std::array point={static_cast(center[0]), + static_cast(center[1]),static_cast(center[2])}; + for(std::size_t i=1;i a={static_cast(sampledPath[i-1][0]), + static_cast(sampledPath[i-1][1]), + static_cast(sampledPath[i-1][2])}; + const std::array b={static_cast(sampledPath[i][0]), + static_cast(sampledPath[i][1]), + static_cast(sampledPath[i][2])}; + if(distancePointSegment(point,a,b)<=keepout)return false; + } + return true; + }; + const auto clearOfPassages=[&](const std::array& center, + const std::array& extents) + { + const double boundRadius=std::sqrt(static_cast(extents[0])*extents[0] + +static_cast(extents[1])*extents[1] + +static_cast(extents[2])*extents[2]); + const std::array point={static_cast(center[0]), + static_cast(center[1]),static_cast(center[2])}; + for(const auto& passage:layout.passages) + { + if(passage.upperStrateIndex!=plan->strateIndex + &&passage.lowerStrateIndex!=plan->strateIndex)continue; + for(std::size_t i=1;i result{}; + for(std::size_t axis=0;axis<3;++axis) + result[axis]=static_cast(q[axis]) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel; + return result; + }; + const auto a=toMicrometres( + passage.controlPoints[i-1].positionSubvoxels); + const auto b=toMicrometres(passage.controlPoints[i].positionSubvoxels); + const double radius=std::max(passage.controlPoints[i-1].radiusSubvoxels, + passage.controlPoints[i].radiusSubvoxels) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel; + if(distancePointSegment(point,a,b)<=boundRadius+radius+1000000.0) + return false; + } + } + return true; + }; + + ResolvedLayoutStampRequestV1 deck; + deck.stableId="core/liminal-field/route/deck/000"; + deck.strateIndex=plan->strateIndex; + deck.kind=ResolvedSdfStampKindV1::fillSweptDeckSegment; + deck.anchorPositionMicrometres=sampledPath[sampledPath.size()/2]; + deck.sweepEndpointsMicrometres={sampledPath.front(),sampledPath.back()}; + deck.sweepPathMicrometres=sampledPath; + deck.halfExtentsMicrometres={500000,halfWidth,halfThickness}; + deck.smoothWidthMicrometres=250000; + requests.push_back(deck); + + std::vector cumulative(sampledPath.size(),0.0); + for(std::size_t i=1;i(sampledPath[i][0]-sampledPath[i-1][0]); + const double dy=static_cast(sampledPath[i][1]-sampledPath[i-1][1]); + cumulative[i]=cumulative[i-1]+std::hypot(dx,dy); + } + const double routeLength=cumulative.back(); + const double supportSpacing=static_cast(definition.supportSpacingMicrometres); + const std::int64_t supportRadius=definition.supportRadiusMicrometres; + const auto addSupport=[&](double distance,std::uint32_t supportIndex) + { + const auto upper=std::lower_bound(cumulative.begin(),cumulative.end(),distance); + const std::size_t index=std::clamp( + static_cast(upper-cumulative.begin()),1,sampledPath.size()-1); + const double span=cumulative[index]-cumulative[index-1]; + const double t=span>0.0?(distance-cumulative[index-1])/span:0.0; + std::array center{}; + for(std::size_t axis=0;axis<3;++axis) + center[axis]=static_cast(std::llround( + sampledPath[index-1][axis] + +(sampledPath[index][axis]-sampledPath[index-1][axis])*t)); + const std::int64_t top=center[2]-halfThickness+250000; + if(top<=supportBaseUm+1000000)return; + constexpr std::int64_t MaximumSupportSegmentMicrometres=180000000; + const std::int64_t fullHeight=top-supportBaseUm; + const std::uint32_t parts=static_cast( + (fullHeight+MaximumSupportSegmentMicrometres-1) + /MaximumSupportSegmentMicrometres); + const std::int64_t segmentHeight=(fullHeight+parts-1)/parts; + std::int64_t bottom=supportBaseUm; + for(std::uint32_t part=0;partstrateIndex; + support.kind=ResolvedSdfStampKindV1::fillPillar; + support.anchorPositionMicrometres={center[0],center[1],(bottom+segmentTop)/2}; + support.halfExtentsMicrometres={supportRadius,supportRadius, + (segmentTop-bottom)/2}; + requests.push_back(std::move(support)); + bottom=segmentTop; + } + }; + std::uint32_t supportIndex=0; + for(double distance=supportSpacing;distanceliminalField.variant==WorldAssemblyLiminalVariantV1::flatFieldMonolith) + { + const std::size_t middle=sampledPath.size()/2; + const auto& before=sampledPath[middle==0?0:middle-1]; + const auto& after=sampledPath[std::min(middle+1,sampledPath.size()-1)]; + const double dx=static_cast(after[0]-before[0]); + const double dy=static_cast(after[1]-before[1]); + const double tangent=std::hypot(dx,dy); + if(!(tangent>0.0)){error="Core.Liminal.Field monolith placement has a degenerate route tangent";return false;} + const std::array monolithExtents={ + definition.monolithRadiusMicrometres,definition.monolithRadiusMicrometres, + definition.monolithHeightMicrometres/2}; + std::array monolithCenter{}; + bool placed=false; + for(const std::int64_t offset:{42000000ll,60000000ll,78000000ll, + 96000000ll,-42000000ll,-60000000ll,-78000000ll,-96000000ll}) + { + monolithCenter={ + static_cast(std::llround(sampledPath[middle][0]-dy/tangent*offset)), + static_cast(std::llround(sampledPath[middle][1]+dx/tangent*offset)), + floorUm+monolithExtents[2]}; + if(clearOfLiminalRoute(monolithCenter,monolithExtents) + &&clearOfPassages(monolithCenter,monolithExtents)) + {placed=true;break;} + } + if(!placed) + {error="Core.Liminal.Field could not seat its monolith outside route and passage clearances";return false;} + ResolvedLayoutStampRequestV1 monolith; + monolith.stableId="core/liminal-field/monolith/000"; + monolith.strateIndex=plan->strateIndex; + monolith.kind=ResolvedSdfStampKindV1::fillPillar; + monolith.anchorPositionMicrometres=monolithCenter; + monolith.halfExtentsMicrometres={definition.monolithRadiusMicrometres, + definition.monolithRadiusMicrometres,definition.monolithHeightMicrometres/2}; + requests.push_back(std::move(monolith)); + } + if(plan->liminalField.variant==WorldAssemblyLiminalVariantV1::pillarGrid) + { + const std::size_t middle=sampledPath.size()/2; + const std::int64_t centerX=sampledPath[middle][0]; + const std::int64_t centerY=sampledPath[middle][1]; + const std::int64_t spacing=definition.pillarSpacingMicrometres; + const std::int64_t halfHeight=definition.pillarHeightMicrometres/2; + std::uint32_t ordinal=0; + for(std::uint32_t row=0;row(column)-definition.pillarColumns/2)*spacing; + const std::int64_t y=centerY + +(static_cast(row)-definition.pillarRows/2)*spacing; + double closestSquared=std::numeric_limits::infinity(); + for(std::size_t i=1;i(sampledPath[i][0]-sampledPath[i-1][0]); + const double dy=static_cast(sampledPath[i][1]-sampledPath[i-1][1]); + const double lengthSquared=dx*dx+dy*dy; + const double t=lengthSquared>0.0?std::clamp( + ((x-ax)*dx+(y-ay)*dy)/lengthSquared,0.0,1.0):0.0; + const double ox=x-(ax+t*dx),oy=y-(ay+t*dy); + closestSquared=std::min(closestSquared,ox*ox+oy*oy); + } + const double keepout=halfWidth+definition.pillarRadiusMicrometres+1000000.0; + if(closestSquared<=keepout*keepout)continue; + const std::array pillarExtents={ + definition.pillarRadiusMicrometres,definition.pillarRadiusMicrometres, + halfHeight}; + const std::array pillarCenter={x,y,floorUm+halfHeight}; + if(!clearOfLiminalRoute(pillarCenter,pillarExtents) + ||!clearOfPassages(pillarCenter,pillarExtents))continue; + ResolvedLayoutStampRequestV1 pillar; + pillar.stableId="core/liminal-field/pillars/" + +std::to_string(1000+ordinal++).substr(1); + pillar.strateIndex=plan->strateIndex; + pillar.kind=ResolvedSdfStampKindV1::fillPillar; + pillar.anchorPositionMicrometres={x,y,floorUm+halfHeight}; + pillar.halfExtentsMicrometres={definition.pillarRadiusMicrometres, + definition.pillarRadiusMicrometres,halfHeight}; + requests.push_back(std::move(pillar)); + } + if(ordinal<100) + {error="Core.Liminal.Field pillar grid has too few columns after route clearance";return false;} + } + std::sort(requests.begin(),requests.end(),[](const auto& a,const auto& b) + {return a.stableId