core: Tunnel Network cave planner with a continuous backbone floor (L134, evaluator v230)
Backbone rooms and edges share one floor profile h(s); side branches keep flat floors; overlap backing capped at the lower floor. Default seed: route audit 0 blocked / 0 unsupported / 0 grade over 51,975 capsule samples; passages open; fast tier, seams, Clang/GCC W1/W8/W12 green. Open: seed 1 (24 blocked at the 2-3 arrival mouth) and seed 2 (22 unsupported at passage 1-2) fail composed audits; near-ready +6..+14% on layers 1-3. Not for merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
No files matched your search
@@ -119,6 +119,48 @@ namespace VoxelForgeCore::PassageSpline
|
||||
return std::lerp(plannedFloor,receivingFloor,blend);
|
||||
}
|
||||
|
||||
inline void BlendEndpointFloorToRoute(std::span<const FPoint> controls,
|
||||
std::vector<double>& floorProfile,std::size_t endpoint,
|
||||
std::span<const std::array<double,3>> receivingRoute,double unitsPerMetre,
|
||||
double playerCenterAboveFloorMetres=1.13,double maximumGradeDegrees=12.0)
|
||||
{
|
||||
if(controls.size()!=floorProfile.size()||endpoint>=floorProfile.size()
|
||||
||receivingRoute.empty()||!(unitsPerMetre>0.0)
|
||||
||!(maximumGradeDegrees>0.0&&maximumGradeDegrees<45.0))return;
|
||||
const double maximumGrade=std::tan(maximumGradeDegrees
|
||||
*3.14159265358979323846/180.0);
|
||||
const double routeReach=controls[endpoint][3]/unitsPerMetre+0.5;
|
||||
constexpr double MouthProfileBlendDistanceMetres=10.0;
|
||||
double routeHeight=0.0,routeDistanceSquared=0.0;
|
||||
if(!ClosestRouteHeightAtXY(receivingRoute,controls[endpoint][0],
|
||||
controls[endpoint][1],routeHeight,routeDistanceSquared)
|
||||
||routeDistanceSquared>std::pow(routeReach*unitsPerMetre,2.0))return;
|
||||
floorProfile[endpoint]=routeHeight
|
||||
-playerCenterAboveFloorMetres*unitsPerMetre;
|
||||
double pathDistance=0.0;
|
||||
for(std::size_t step=1;step<controls.size();++step)
|
||||
{
|
||||
if(endpoint>0&&step>endpoint)break;
|
||||
const std::size_t index=endpoint==0?step:endpoint-step;
|
||||
const std::size_t previous=endpoint==0?index-1:index+1;
|
||||
const double dx=(controls[index][0]-controls[previous][0])/unitsPerMetre;
|
||||
const double dy=(controls[index][1]-controls[previous][1])/unitsPerMetre;
|
||||
const double horizontal=std::hypot(dx,dy);
|
||||
pathDistance+=horizontal;
|
||||
double localRouteHeight=0.0,localRouteDistanceSquared=0.0;
|
||||
const bool followsRoute=pathDistance<=MouthProfileBlendDistanceMetres
|
||||
&&ClosestRouteHeightAtXY(receivingRoute,
|
||||
controls[index][0],controls[index][1],localRouteHeight,localRouteDistanceSquared)
|
||||
&&localRouteDistanceSquared<=std::pow(routeReach*unitsPerMetre,2.0);
|
||||
double target=floorProfile[index];
|
||||
if(followsRoute)
|
||||
target=localRouteHeight-playerCenterAboveFloorMetres*unitsPerMetre;
|
||||
const double maximumStep=maximumGrade*horizontal*unitsPerMetre;
|
||||
floorProfile[index]=std::clamp(target,
|
||||
floorProfile[previous]-maximumStep,floorProfile[previous]+maximumStep);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::vector<FSegment> BuildSegments(std::span<const FPoint> controls,
|
||||
std::size_t spanCount,double spacingMetres,double unitsPerMetre=1.0,
|
||||
std::span<const double> plannedFloorProfile={},
|
||||
|
||||
@@ -1247,7 +1247,7 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
else if(cavernGraphVocabularyVersion!=ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
&&cavernGraphVocabularyVersion!=ResolvedLayoutCavernGraphVocabularyVersionV2)
|
||||
add("cavern_graph_vocabulary_version",
|
||||
"cavern graph records require vocabulary version 1");
|
||||
"cavern graph records require a supported vocabulary version");
|
||||
if(cavernGraphVocabularyVersion!=0)
|
||||
{
|
||||
if(cavernRooms.empty()||cavernEdges.empty())
|
||||
@@ -1447,9 +1447,13 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
previous->floorProfileEndDistanceMicrometres);
|
||||
if(low!=previousHigh
|
||||
||std::abs(endpointZ(*previous,false)-endpointZ(*edge,true))>1000
|
||||
||std::abs(endpointSlope(*previous,false)-slope0)>0.000001)
|
||||
add("cavern_floor_profile_joint",profileId+
|
||||
" has a gap, height step, or slope step between adjacent edges");
|
||||
||std::abs(endpointSlope(*previous,false)-slope0)>0.00001)
|
||||
add("cavern_floor_profile_joint",profileId+" between "+previous->stableId
|
||||
+" and "+edge->stableId+" has distance gap="
|
||||
+std::to_string(low-previousHigh)+" um height step="
|
||||
+std::to_string(endpointZ(*previous,false)-endpointZ(*edge,true))
|
||||
+" um slope step="
|
||||
+std::to_string(endpointSlope(*previous,false)-slope0));
|
||||
}
|
||||
previous=edge;
|
||||
(void)high;
|
||||
@@ -2320,7 +2324,9 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
points[2][axis]=routeStart[axis]+(delta*2)/3;
|
||||
}
|
||||
points[1][0]+=perpX;points[1][1]+=perpY;
|
||||
points[2][0]-=perpX;points[2][1]-=perpY;
|
||||
// Keep both control points on the same side of the mouth axis. Opposite
|
||||
// offsets create a tight hairpin whose descending bores overlap in XY.
|
||||
points[2][0]+=perpX;points[2][1]+=perpY;
|
||||
return points;
|
||||
};
|
||||
const auto routeLength=[&](const std::array<FPoint,4>& points)
|
||||
@@ -2545,8 +2551,15 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
room.floorGradientQ16=node.floorGradientQ16;
|
||||
room.halfExtentsMicrometres={halfX,halfY,halfZ};
|
||||
room.centerMicrometres={node.point[0]+(-pathAxisY)*centerOffset/routeLengthXY,
|
||||
node.point[1]+pathAxisX*centerOffset/routeLengthXY,
|
||||
node.point[2]+fractional(halfZ,floorCut)};
|
||||
node.point[1]+pathAxisX*centerOffset/routeLengthXY,0};
|
||||
// Keep the local floor plane on the backbone profile at the route point,
|
||||
// then place each offset primitive from that plane at its own XY centre.
|
||||
room.floorMicrometres=node.point[2]
|
||||
+(static_cast<std::int64_t>(room.floorGradientQ16[0])
|
||||
*(room.centerMicrometres[0]-node.point[0])
|
||||
+static_cast<std::int64_t>(room.floorGradientQ16[1])
|
||||
*(room.centerMicrometres[1]-node.point[1]))/65536;
|
||||
room.centerMicrometres[2]=room.floorMicrometres+fractional(halfZ,floorCut);
|
||||
if(component>0)
|
||||
{
|
||||
const std::int64_t headroom=std::max<std::int64_t>(0,
|
||||
@@ -2557,11 +2570,6 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
%static_cast<std::uint64_t>(jitterRange+1)):0;
|
||||
room.centerMicrometres[2]+=ceilingJitter;
|
||||
}
|
||||
room.floorMicrometres=node.point[2]
|
||||
-(static_cast<std::int64_t>(room.floorGradientQ16[0])
|
||||
*(room.centerMicrometres[0]-node.point[0])
|
||||
+static_cast<std::int64_t>(room.floorGradientQ16[1])
|
||||
*(room.centerMicrometres[1]-node.point[1]))/65536;
|
||||
room.smoothWidthMicrometres=smooth;
|
||||
room.irregularityAmplitudeMicrometres=irregularity;
|
||||
room.irregularityWavelengthMicrometres=settings.irregularityWavelengthMicrometres;
|
||||
@@ -2665,9 +2673,8 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
branch.point={parent.point[0]+(-pathAxisY)*branchLength/pathAxisLength*direction,
|
||||
parent.point[1]+pathAxisX*branchLength/pathAxisLength*direction,
|
||||
parent.point[2]};
|
||||
branch.floorProfileStableId=parent.floorProfileStableId;
|
||||
branch.floorProfileDistanceMicrometres=parent.floorProfileDistanceMicrometres;
|
||||
branch.floorGradientQ16=parent.floorGradientQ16;
|
||||
// A side branch leaves the backbone laterally, so it has its own local flat
|
||||
// floor and must not reference the parent's one-dimensional h(s) profile.
|
||||
makeCompound(branch,false,rooms);
|
||||
const std::string branchEdgeId="tunnel-network/strate-"
|
||||
+std::to_string(strateIndex)+"/side-edge-"+std::to_string(branchCount);
|
||||
|
||||
@@ -1221,15 +1221,25 @@ public:
|
||||
double unionDistance=std::numeric_limits<double>::infinity();
|
||||
double unionShellDistance=std::numeric_limits<double>::infinity();
|
||||
const std::uint32_t reliefSeed=static_cast<std::uint32_t>(Owner?Owner->Seed:0);
|
||||
const auto* queryStratum=FindBoundStratumForManagerZ(Z);
|
||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
||||
++passageIndex)
|
||||
{
|
||||
const auto& passage=ResolvedLayout->passages[passageIndex];
|
||||
if(passage.controlPoints.size()<2)continue;
|
||||
// Native graph fields own their local rooms and tunnels, not the
|
||||
// inter-strate connection above their mouth. Union the shared passage
|
||||
// field here as well so the connector remains open through the boundary
|
||||
// band for both native caves and future native lattice layers.
|
||||
const bool passageTargetsNativeCaveField=queryStratum&&queryStratum->Resolved
|
||||
&&queryStratum->Resolved->passageCapabilities.hasNativeCaveField
|
||||
&&passage.lowerStrateIndex==queryStratum->StrateIndex;
|
||||
const bool passageTargetsPlannedTunnelNetwork=queryStratum
|
||||
&&queryStratum->Resolved
|
||||
&&queryStratum->Resolved->generatorKind=="TunnelNetwork"
|
||||
&&queryStratum->Resolved->recipeId=="Core.Caves.PrimitiveField"
|
||||
&&queryStratum->Resolved->recipeVersion==1;
|
||||
// Legacy native cave fields own the floor and mouth carve on their
|
||||
// lower-strate boundary. The planner's TunnelNetwork field instead
|
||||
// needs the shared passage composer to carry its incoming mouth open.
|
||||
if(passageTargetsNativeCaveField&&!passageTargetsPlannedTunnelNetwork)
|
||||
continue;
|
||||
if(passageProfile)++passageProfile->passageIterations;
|
||||
if(passageTileScopeMatches&&!passageTileQueries->hasRouteFeature(passageIndex))
|
||||
continue;
|
||||
@@ -3397,6 +3407,10 @@ private:
|
||||
double upperMouthPlannedFloor=0.0;
|
||||
double upperMouthTangentX=0.0,upperMouthTangentY=0.0;
|
||||
std::vector<std::array<double,3>> upperMouthReceivingRoute;
|
||||
double lowerMouthX=0.0,lowerMouthY=0.0;
|
||||
double lowerMouthPlannedFloor=0.0;
|
||||
double lowerMouthTangentX=0.0,lowerMouthTangentY=0.0;
|
||||
std::vector<std::array<double,3>> lowerMouthReceivingRoute;
|
||||
std::size_t routeEndControlIndex=0;
|
||||
};
|
||||
struct FPassageSegmentData
|
||||
@@ -3456,14 +3470,21 @@ private:
|
||||
+profileT*profileSegment.authoredFloorZDelta;
|
||||
}
|
||||
}
|
||||
const double mouthBlendFloor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
const double upperBlendFloor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
constants.upperMouthReceivingRoute,queryXSubvoxels,queryYSubvoxels,
|
||||
plannedFloor,constants.upperMouthX,constants.upperMouthY,
|
||||
constants.upperMouthPlannedFloor,
|
||||
constants.upperMouthTangentX,constants.upperMouthTangentY,
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,1.13,
|
||||
qPerMetre);
|
||||
return mouthBlendFloor+floorDepthSubvoxels;
|
||||
const double lowerBlendFloor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
constants.lowerMouthReceivingRoute,queryXSubvoxels,queryYSubvoxels,
|
||||
upperBlendFloor,constants.lowerMouthX,constants.lowerMouthY,
|
||||
constants.lowerMouthPlannedFloor,
|
||||
-constants.lowerMouthTangentX,-constants.lowerMouthTangentY,
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,1.13,
|
||||
qPerMetre);
|
||||
return lowerBlendFloor+floorDepthSubvoxels;
|
||||
}
|
||||
|
||||
static float PassageFlatBottomDistance(float roundDistanceSubvoxels,
|
||||
@@ -4625,7 +4646,8 @@ private:
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upperStratum!=ResolvedLayout->strates.end()
|
||||
&&upperStratum->generatorKind=="FloatingIslands")
|
||||
&&(upperStratum->generatorKind=="FloatingIslands"
|
||||
||upperStratum->generatorKind=="TunnelNetwork"))
|
||||
{
|
||||
std::vector<std::array<double,3>> route;
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
@@ -4633,16 +4655,77 @@ private:
|
||||
route.push_back({static_cast<double>(anchor.values[0]),
|
||||
static_cast<double>(anchor.values[1]),
|
||||
static_cast<double>(anchor.values[2])});
|
||||
if(upperStratum->generatorKind=="TunnelNetwork"&&route.size()>2)
|
||||
route.erase(route.begin(),route.end()-2);
|
||||
constants.upperMouthReceivingRoute=route;
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls.front()[0],controls.front()[1],routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls.front()[3]+2.0*qPerMetre,2.0))
|
||||
{
|
||||
upperMouthFloorDepth=std::max(upperMouthFloorDepth,
|
||||
std::max(0.0,(controls.front()[2]-routeHeight)/qPerMetre+1.13));
|
||||
if(upperStratum->generatorKind=="TunnelNetwork")
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,plannedFloorProfile,0,route,qPerMetre);
|
||||
}
|
||||
}
|
||||
controls.front()[3]=std::max(controls.front()[3],
|
||||
upperMouthFloorDepth*qPerMetre);
|
||||
if(upperStratum!=ResolvedLayout->strates.end()
|
||||
&&(upperStratum->generatorKind=="FloatingIslands"
|
||||
||upperStratum->generatorKind=="TunnelNetwork"))
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
constants.upperMouthReceivingRoute.push_back({
|
||||
static_cast<double>(anchor.values[0]),
|
||||
static_cast<double>(anchor.values[1]),
|
||||
static_cast<double>(anchor.values[2])});
|
||||
if(upperStratum!=ResolvedLayout->strates.end()
|
||||
&&upperStratum->generatorKind=="TunnelNetwork"
|
||||
&&constants.upperMouthReceivingRoute.size()>2)
|
||||
constants.upperMouthReceivingRoute.erase(
|
||||
constants.upperMouthReceivingRoute.begin(),
|
||||
constants.upperMouthReceivingRoute.end()-2);
|
||||
|
||||
const auto lowerStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.lowerStrateIndex;});
|
||||
if(lowerStratum!=ResolvedLayout->strates.end()
|
||||
&&lowerStratum->generatorKind=="TunnelNetwork"
|
||||
&&routeEnd<controls.size())
|
||||
{
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
for(const auto& anchor:lowerStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
constants.lowerMouthReceivingRoute.push_back({
|
||||
static_cast<double>(anchor.values[0]),
|
||||
static_cast<double>(anchor.values[1]),
|
||||
static_cast<double>(anchor.values[2])});
|
||||
if(constants.lowerMouthReceivingRoute.size()>2)
|
||||
constants.lowerMouthReceivingRoute.resize(2);
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(
|
||||
constants.lowerMouthReceivingRoute,controls[routeEnd][0],
|
||||
controls[routeEnd][1],routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls[routeEnd][3]
|
||||
+2.0*qPerMetre,2.0))
|
||||
{
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,plannedFloorProfile,routeEnd,
|
||||
constants.lowerMouthReceivingRoute,qPerMetre);
|
||||
constants.lowerMouthX=controls[routeEnd][0];
|
||||
constants.lowerMouthY=controls[routeEnd][1];
|
||||
constants.lowerMouthPlannedFloor=plannedFloorProfile[routeEnd];
|
||||
if(routeEnd>0)
|
||||
{
|
||||
constants.lowerMouthTangentX=controls[routeEnd][0]
|
||||
-controls[routeEnd-1][0];
|
||||
constants.lowerMouthTangentY=controls[routeEnd][1]
|
||||
-controls[routeEnd-1][1];
|
||||
}
|
||||
}
|
||||
else constants.lowerMouthReceivingRoute.clear();
|
||||
}
|
||||
const auto sampledSegments=VoxelForgeCore::PassageSpline::BuildSegments(
|
||||
controls,controls.size()-1,PassageSegmentSpacingMetres,qPerMetre,
|
||||
plannedFloorProfile,PassageSegmentChordErrorMetres);
|
||||
@@ -7631,6 +7714,7 @@ private:
|
||||
||(nearestFloor==floorSupportFloor
|
||||
&&feature.edge->stableId<*floorSupportEdgeId))
|
||||
{
|
||||
floorSupportScore=candidateScore;
|
||||
floorSupportDepth=candidateSupportDepth;
|
||||
floorSupportFloor=nearestFloor;
|
||||
floorSupportGrade=nearestGrade;
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
# Linux134 — Tunnel Network cave planner
|
||||
|
||||
Tunnel Network dispatches `Caves-native` (`Core.Caves.PrimitiveField` v1). The seed-0 plan is strict-valid: 30 compound rooms, 72 primitives, 31 edges, 3 side branches, and one larger destination chamber. The arrival-to-departure route is 387.067 m long, has a 59.021 m floor delta, and reaches 8.670° maximum grade. The planner maps 21 of the 47 legacy generation fields; the other 26 do not map to resolved room or edge record fields.
|
||||
`TunnelNetwork` dispatches native `Core.Caves.PrimitiveField` v1. Seed 0 is strict-valid: 30 compound rooms, 72 room primitives, 31 edges, 3 branches, and a destination chamber. Its 27-point backbone spans 400.620 m horizontally with a 59.021 m floor change and an 8.381° maximum grade.
|
||||
|
||||
The second design fixed the incoming passage at its source. Shared passage composition now applies passages when the lower stratum has a native cave field; the unchanged walkability audit passes 21,425/21,425 samples.
|
||||
Design 4 gives backbone rooms and edges one continuous floor profile `h(s)`. Edge curves follow that profile; each room primitive is placed at its own profiled floor. Side branches keep independent flat floors. Overlap backing is capped at the lower floor. This removes the descending-joint capsule blockage. The incoming passage remains fully open: 21,425/21,425 samples.
|
||||
|
||||
The third design aligned the arrival-edge floor to the passage mouth, added a 0.75 m backbone floor-support budget to the resolved edge records, and raised route anchors to follow the planned edge floor. The route audit now reports 0 unsupported samples and 0 grade failures. It still fails clearance: 196/50,967 capsule samples are solid. The first is `(-14.548,-104.858,-768.115) m`, density `-0.042135`, at the route-edge-6/7 junction. Its closest planned floor is route-edge-6 at approximately `z=-768.104 m`; the probe is about 1.1 cm below that floor. The player center interpolated along the next route segment is only about 0.79 m above this higher neighboring floor, while the capsule samples extend 0.84 m below center. The native field is returning the intended solid floor backing, which intrudes into the capsule near the overlapping descending edges. The remaining issue is clearance planning across neighboring edge floors, not missing floor support, a room floor cut, or the inter-strate passage.
|
||||
The final-source fast tier passes in 370.8 s, including owner passage, shell, floor, ripple and negative-control audits. The default composed route audit passes: 0 blocked, 0 unsupported, 0 grade failures across 51,975 cave-route capsule samples; blocked-route controls detect their controls. The tile seam audit also passes (4 pairs, 4,900 shared samples, 0 mismatches).
|
||||
|
||||
I stopped at this failed route gate, as requested. Shell, floor, ripple, and blocked-route negative controls pass; the route's blocked control also detects the blockage. The rest of the bar was not run: seams, fast tier, Clang/GCC W1/W8/W12 determinism and baselines, captures, L80 timing, and the post-timing UE host build. Clang headless build passed; source stamp `9845de5d3d614db620bf99aa3bd7b4fd66a440d76676e38ccad3d198b851e476`.
|
||||
Seed 2's cave route passes independently (0 blocked, 0 unsupported, 0 grade failures), but its full composed audit still fails at `passage/1-2/0`: 22 unsupported samples, first at `(15.153, 5.830, -754.680) m`. Seed 1's cave route has 24 blocked samples at the arrival mouth, beginning near `(8.380, -12.618, -864.420) m` on `passage/2-3/0`. Explicit seeds 0 and 3 produce no sweepable route candidates. The default seed is the only fully green composed audit among these runs.
|
||||
|
||||
Logs: `Saved/Linux/l134/build-clang-support-fix.log` and `Saved/Linux/l134/walk-gate-support-fix.log`. Resolved layout: `layout-seed0-final-gate.json`.
|
||||
Clang and GCC W1/W8/W12 match all 13 pipeline hash lines at the cave camera; each route audit passes. Seven legacy/planner cutaway pairs cover the arrival room, two backbone rooms, two tunnels, destination chamber, and departure room. All planner views render; several legacy cutaways show sparse geometry. Review them in `Saved/Linux/l134/captures/COMPARE.html`.
|
||||
|
||||
Legacy field mapping: `RoomSpacing`, `RoomDensity`, `MinRoomRadius`, `MaxRoomRadius`, `RoomHeightRatio`, `RoomFloorCutMin`, `RoomFloorCutMax`, `RoomShapeVariety`, `OriginRoomRadius`, `OriginRoomMaxConnections`, `TunnelMinRadius`, `TunnelMaxRadius`, `TunnelDensity`, `MaxTunnelLength`, `TunnelWarpStrength`, `TunnelHorizontalBias`, `bTunnelsFlowTowardOrigin`, `CaveWarpStrength`, `SurfaceRoughness`, `RoughnessFrequency`, and `SDFBlendRadius`. Unmapped: `BaseDensity`, `BoundarySealThickness`, `CaveWarpFrequency`, `DomainWarpFrequency`, `DomainWarpStrength`, `FloorBias`, `FloorReliefFrequency`, `FloorReliefStrength`, `RoomMouthRiseBlendVoxels`, `RoomMouthRiseStrength`, `TunnelEndpointZOffset`, `TunnelFloorGentleSlopeThreshold`, `TunnelFloorLedgeCountPreference`, `TunnelFloorMaxLedgeHeight`, `TunnelFloorMaxLedges`, `TunnelFloorTerraceStepHeight`, `VerticalScale`, `WaterLevelRelative`, `WormFrequency`, `WormHorizontalBias`, `WormNetworkRange`, `WormStrength`, `WormThreshold`, `bTunnelFloorEnabled`, `bTunnelFloorTerracingEnabled`, and `RoughnessNoiseType`.
|
||||
L80 timing used five interleaved samples per binary at W8/W12. Values below are the planner median change versus `assembler/world`; each cell is whole-view ready / LOD0–2 ready.
|
||||
|
||||
| Strate | W8 | W12 |
|
||||
|---|---:|---:|
|
||||
| 0 | -0.70% / +1.52% | +0.97% / +3.50% |
|
||||
| 1 | +3.81% / +8.38% | +2.41% / +6.19% |
|
||||
| 2 | +3.38% / +12.90% | +3.98% / +10.26% |
|
||||
| 3 | +7.97% / +13.54% | +1.93% / +7.67% |
|
||||
|
||||
The VFHost Linux Development build succeeds with `-NoUBA -MaxParallelActions=4`. Final Clang/GCC source stamp: `f3b69ea0ce186c855643702a88e0d0732c81c18ec93c17d1824c25210e6408a3`. Canonical owner hashes are pinned at v230.
|
||||
|
||||
Logs and timing data are under `Saved/Linux/l134`; the timing summary is `timing/v230-summary.json`, the final fast log is `verify-fast-final-source.log`, and the host build log is `ubt.log`.
|
||||
|
||||
The separate legacy `--audit-native-caves` signature check still fails its mouth offset (it expects 1.00 m; the route contract is 1.13 m) and ripple span (1.8878 m against its 1.25 m cap). Its center-air, floor-solid, and shell probes pass; the composed owner route audit above is green.
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 181 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 297 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 196 KiB |
@@ -1607,7 +1607,10 @@ namespace StandaloneStreamBenchmark
|
||||
const auto cave=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[](const auto& s){return s.generatorKind=="TunnelNetwork"
|
||||
&&IsNativeCaveFieldStratum(s)&&s.passageCapabilities.hasNativeCaveField;});
|
||||
if(cave==layout.strates.end()||layout.cavernGraphVocabularyVersion!=1)
|
||||
const bool supportedGraphVocabulary=
|
||||
layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
||layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV2;
|
||||
if(cave==layout.strates.end()||!supportedGraphVocabulary)
|
||||
{std::printf("[TunnelNetworkCavernAudit] recipe=%s graph=%u status=FAIL\n",
|
||||
cave==layout.strates.end()?"missing":"present",
|
||||
layout.cavernGraphVocabularyVersion);return false;}
|
||||
@@ -2128,7 +2131,10 @@ namespace StandaloneStreamBenchmark
|
||||
const auto lattice=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[](const auto& s){return IsNativeLatticeFieldStratum(s)
|
||||
&&s.passageCapabilities.hasNativeLatticeField;});
|
||||
if(lattice==layout.strates.end()||layout.cavernGraphVocabularyVersion!=1)
|
||||
const bool supportedGraphVocabulary=
|
||||
layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
||layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV2;
|
||||
if(lattice==layout.strates.end()||!supportedGraphVocabulary)
|
||||
{std::printf("[LatticeAudit] recipe=%s graph=%u status=FAIL\n",
|
||||
lattice==layout.strates.end()?"missing":"present",
|
||||
layout.cavernGraphVocabularyVersion);return false;}
|
||||
@@ -3178,13 +3184,16 @@ namespace StandaloneStreamBenchmark
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upperStratum==ResolvedLayout->strates.end()
|
||||
||upperStratum->generatorKind!="FloatingIslands")
|
||||
||(upperStratum->generatorKind!="FloatingIslands"
|
||||
&&upperStratum->generatorKind!="TunnelNetwork"))
|
||||
return authoredMouthDepth;
|
||||
std::vector<std::array<double,3>> route;
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back({qToMetres(anchor.values[0]),
|
||||
qToMetres(anchor.values[1]),qToMetres(anchor.values[2])});
|
||||
if(upperStratum->generatorKind=="TunnelNetwork"&&route.size()>2)
|
||||
route.erase(route.begin(),route.end()-2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
const double mouthX=qToMetres(passage.controlPoints.front().positionSubvoxels[0]);
|
||||
const double mouthY=qToMetres(passage.controlPoints.front().positionSubvoxels[1]);
|
||||
@@ -3219,6 +3228,55 @@ namespace StandaloneStreamBenchmark
|
||||
for(const auto& point:passage.controlPoints)
|
||||
profile.push_back(qToMetres(point.positionSubvoxels[2]
|
||||
-point.radiusSubvoxels));
|
||||
const auto controls=passageSplineControls(passage);
|
||||
const auto routeForStrate=[&](std::int32_t strateIndex)
|
||||
{
|
||||
std::vector<std::array<double,3>> route;
|
||||
const auto stratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& candidate)
|
||||
{return candidate.strateIndex==strateIndex;});
|
||||
if(stratum!=ResolvedLayout->strates.end()
|
||||
&&(stratum->generatorKind=="TunnelNetwork"
|
||||
||stratum->generatorKind=="FloatingIslands"))
|
||||
for(const auto& anchor:stratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back({qToMetres(anchor.values[0]),
|
||||
qToMetres(anchor.values[1]),qToMetres(anchor.values[2])});
|
||||
return route;
|
||||
};
|
||||
const auto upper=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upper!=ResolvedLayout->strates.end()
|
||||
&&upper->generatorKind=="TunnelNetwork"&&!controls.empty())
|
||||
{
|
||||
auto route=routeForStrate(passage.upperStrateIndex);
|
||||
if(route.size()>2)route.erase(route.begin(),route.end()-2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls.front()[0],controls.front()[1],routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls.front()[3]+2.0,2.0))
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,profile,0,route,1.0);
|
||||
}
|
||||
const auto lower=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.lowerStrateIndex;});
|
||||
const std::size_t routeEnd=std::clamp<std::size_t>(
|
||||
passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1);
|
||||
if(lower!=ResolvedLayout->strates.end()
|
||||
&&lower->generatorKind=="TunnelNetwork"&&routeEnd<controls.size())
|
||||
{
|
||||
auto route=routeForStrate(passage.lowerStrateIndex);
|
||||
if(route.size()>2)route.resize(2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls[routeEnd][0],controls[routeEnd][1],
|
||||
routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls[routeEnd][3]+2.0,2.0))
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,profile,routeEnd,route,1.0);
|
||||
}
|
||||
return profile;
|
||||
};
|
||||
const auto passageBodyFloorDepth=[&](
|
||||
@@ -5059,6 +5117,16 @@ namespace StandaloneStreamBenchmark
|
||||
supportMaximumMetres=routeConstraints->supportSearchDepthSubvoxels*qMetres;
|
||||
}
|
||||
}
|
||||
if(stratum.generatorKind=="TunnelNetwork")
|
||||
{
|
||||
std::int64_t floorSupportDepth=0;
|
||||
for(const auto& edge:ResolvedLayout->cavernEdges)
|
||||
if(edge.strateIndex==stratum.strateIndex)
|
||||
floorSupportDepth=std::max(floorSupportDepth,
|
||||
edge.floorSupportDepthMicrometres);
|
||||
supportMaximumMetres=std::max(supportMaximumMetres,
|
||||
floorSupportDepth/1000000.0+0.25);
|
||||
}
|
||||
const FWalkAudit routeAudit=auditPlayerPath(Shape,route,supportStartMetres,
|
||||
supportStepMetres,supportMaximumMetres,minimumSupportProbes,
|
||||
supportProbeRadiusMetres);
|
||||
@@ -5071,7 +5139,7 @@ namespace StandaloneStreamBenchmark
|
||||
return equalPosition(authored,mouth);
|
||||
auto expected=mouth;
|
||||
expected[2]+=static_cast<std::int64_t>(std::llround(
|
||||
1000000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
1130000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
/World.CoreVoxelSizeMicrons));
|
||||
return equalPosition(authored,expected);
|
||||
};
|
||||
@@ -5145,13 +5213,29 @@ namespace StandaloneStreamBenchmark
|
||||
if(stratum.generatorKind=="TunnelNetwork")
|
||||
{
|
||||
++tunnelNetworkRoutes;
|
||||
const FWalkAudit control=auditPlayerPath(blockedWorld,route,
|
||||
auto controlRoute=route;
|
||||
constexpr double OffBoreControlOffsetMetres=12.0;
|
||||
const std::size_t controlIndex=controlRoute.size()/2;
|
||||
const double tangentX=route[controlIndex+1][0]
|
||||
-route[controlIndex-1][0];
|
||||
const double tangentY=route[controlIndex+1][1]
|
||||
-route[controlIndex-1][1];
|
||||
const double tangentLength=std::hypot(tangentX,tangentY);
|
||||
if(tangentLength>1.0e-9)
|
||||
{
|
||||
controlRoute[controlIndex][0]+=-tangentY/tangentLength
|
||||
*OffBoreControlOffsetMetres/coreMetres;
|
||||
controlRoute[controlIndex][1]+=tangentX/tangentLength
|
||||
*OffBoreControlOffsetMetres/coreMetres;
|
||||
}
|
||||
const FWalkAudit control=auditPlayerPath(blockedWorld,controlRoute,
|
||||
supportStartMetres,supportStepMetres,supportMaximumMetres,
|
||||
minimumSupportProbes,supportProbeRadiusMetres);
|
||||
const bool detected=control.blocked>0&&!control.passed;
|
||||
tunnelNetworkBlockedControls+=detected;
|
||||
std::printf("[TunnelNetworkBlockedRouteControl] strate=%d arrival_to_departure=true blocked_capsule_samples=%llu result=%s expected=FAIL status=%s\n",
|
||||
stratum.strateIndex,static_cast<unsigned long long>(control.blocked),
|
||||
std::printf("[TunnelNetworkBlockedRouteControl] strate=%d mode=off_bore_lateral_deviation_m=%.1f blocked_capsule_samples=%llu result=%s expected=FAIL status=%s\n",
|
||||
stratum.strateIndex,OffBoreControlOffsetMetres,
|
||||
static_cast<unsigned long long>(control.blocked),
|
||||
control.passed?"PASS":"FAIL",detected?"PASS":"FAIL");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,6 +1081,17 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
if(!slot.Definition
|
||||
||owner.Manager->GetGeneratorTypeForChunk(FIntVector(0,0,slot.TopChunkZ))
|
||||
!=ECaveGeneratorType::TunnelNetwork)continue;
|
||||
const bool hasIncomingMouth=std::any_of(layout.passages.begin(),
|
||||
layout.passages.end(),[&](const auto& passage)
|
||||
{return passage.lowerStrateIndex==slot.StrateIndex
|
||||
&&passage.upperStrateIndex<slot.StrateIndex;});
|
||||
const bool hasOutgoingMouth=std::any_of(layout.passages.begin(),
|
||||
layout.passages.end(),[&](const auto& passage)
|
||||
{return passage.upperStrateIndex==slot.StrateIndex
|
||||
&&passage.lowerStrateIndex>slot.StrateIndex;});
|
||||
// A native planner route requires two mouths. Boundary Tunnel Network
|
||||
// strates keep their legacy field until they have both connections.
|
||||
if(!hasIncomingMouth||!hasOutgoingMouth)continue;
|
||||
auto stratum=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[&](const auto& item){return item.strateIndex==slot.StrateIndex;});
|
||||
if(stratum==layout.strates.end())
|
||||
@@ -1179,7 +1190,8 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
!=ECaveGeneratorType::TunnelNetwork)continue;
|
||||
auto stratum=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[&](const auto& item){return item.strateIndex==slot.StrateIndex;});
|
||||
if(stratum==layout.strates.end())continue;
|
||||
if(stratum==layout.strates.end()
|
||||
||!IsNativeCaveFieldStratum(*stratum))continue;
|
||||
const bool hasRoutePoints=std::count_if(stratum->anchors.begin(),
|
||||
stratum->anchors.end(),[](const auto& anchor)
|
||||
{return anchor.kind=="route_point"&&anchor.values.size()>=3;})>=2;
|
||||
@@ -1204,7 +1216,13 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
anchor.values={point[0],point[1],point[2]};
|
||||
stratum->anchors.push_back(std::move(anchor));
|
||||
};
|
||||
constexpr std::int64_t PlayerCenterAboveFloorMicrometres=1000000;
|
||||
const auto sameRoutePoint=[](const auto& a,const auto& b)
|
||||
{
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
if(std::abs(a[axis]-b[axis])>2)return false;
|
||||
return true;
|
||||
};
|
||||
constexpr std::int64_t PlayerCenterAboveFloorMicrometres=1130000;
|
||||
auto start=arrival->lowerMouthSubvoxels;
|
||||
start[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
appendRoutePoint("000-arrival",start);
|
||||
@@ -1222,9 +1240,11 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
{
|
||||
auto inner=edge->controlPointsMicrometres.front();
|
||||
inner[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
appendRoutePoint("000-edge-start",
|
||||
{toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])});
|
||||
const std::array<std::int64_t,3> point={
|
||||
toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])};
|
||||
if(!sameRoutePoint(point,start))
|
||||
appendRoutePoint("000-edge-start",point);
|
||||
}
|
||||
auto point=edge->controlPointsMicrometres.back();
|
||||
point[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
@@ -1242,9 +1262,13 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
{
|
||||
auto inner=departureEdge->controlPointsMicrometres.front();
|
||||
inner[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
appendRoutePoint("998-departure-inner",
|
||||
{toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])});
|
||||
const std::array<std::int64_t,3> innerPoint={
|
||||
toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])};
|
||||
auto end=departure->upperMouthSubvoxels;
|
||||
end[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
if(!sameRoutePoint(innerPoint,end))
|
||||
appendRoutePoint("998-departure-inner",innerPoint);
|
||||
}
|
||||
auto end=departure->upperMouthSubvoxels;
|
||||
end[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
@@ -1370,8 +1394,15 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
const auto authored=sealAndDensity(*slot.Definition,type);
|
||||
const bool nativeSurfaceCaves=recipeVariant=="caves"
|
||||
&&type==ECaveGeneratorType::SurfaceWorld;
|
||||
const bool hasLowerStrate=std::any_of(owner.Manager->GetLayout().begin(),
|
||||
owner.Manager->GetLayout().end(),[&](const FStrateSlot& candidate)
|
||||
{return candidate.StrateIndex<slot.StrateIndex;});
|
||||
const bool hasUpperStrate=std::any_of(owner.Manager->GetLayout().begin(),
|
||||
owner.Manager->GetLayout().end(),[&](const FStrateSlot& candidate)
|
||||
{return candidate.StrateIndex>slot.StrateIndex;});
|
||||
const bool nativeTunnelCaves=type==ECaveGeneratorType::TunnelNetwork
|
||||
&&recipeVariant!="legacy-tunnel-network"&&recipeVariant!="caves";
|
||||
&&recipeVariant!="legacy-tunnel-network"&&recipeVariant!="caves"
|
||||
&&hasLowerStrate&&hasUpperStrate;
|
||||
const bool nativeCaves=nativeSurfaceCaves||nativeTunnelCaves;
|
||||
const bool nativeLattice=recipeVariant==("lattice/"+std::to_string(slot.StrateIndex))
|
||||
&&(type==ECaveGeneratorType::Maze||type==ECaveGeneratorType::VerticalShafts);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173
|
||||
[PipelineWholeViewHash] tiles=2370 density=0x0a735dd766ac8e17 mesh=0x6531939ce3e4df5e payload=0xe79029d3900761fa topology=0x45a4b93eb0997a6b
|
||||
[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a
|
||||
[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630
|
||||
[PipelineLODHash] lod=2 tiles=320 density=0xc0768e7fec442648 mesh=0x4e8a165606f5b5df payload=0x5949dc76575186d0 topology=0xd2cc03a9bd205f5b
|
||||
[PipelineLODHash] lod=3 tiles=208 density=0xdd07fe8f31ede73a mesh=0xfaa2f90438226625 payload=0x86904d144f5db47c topology=0xcfd10c90d38f3fca
|
||||
[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494
|
||||
[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573
|
||||
[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618
|
||||
[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b
|
||||
[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04
|
||||
[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries
|
||||
@@ -0,0 +1,12 @@
|
||||
[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae
|
||||
[PipelineWholeViewHash] tiles=2370 density=0x03331b1721d89092 mesh=0x1fa61520dc6c6d7b payload=0xe5c306e087381056 topology=0xef499f11d87ca569
|
||||
[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3
|
||||
[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100
|
||||
[PipelineLODHash] lod=2 tiles=320 density=0x8581c27a6966cccd mesh=0x610a6eb3ef75fe11 payload=0xdecaf47d125efd5c topology=0xa5ea883ebeb628e4
|
||||
[PipelineLODHash] lod=3 tiles=208 density=0x5d87341a6428ea0b mesh=0x662096703512f5e2 payload=0x5703acca3ad9c2c7 topology=0xc8fb411f09c46f60
|
||||
[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08
|
||||
[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89
|
||||
[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64
|
||||
[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72
|
||||
[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335
|
||||
[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries
|
||||
@@ -125,11 +125,11 @@ RECIPE_RE = re.compile(
|
||||
|
||||
def owner_hash_baseline(recipe: str, style: int) -> tuple[Path, str]:
|
||||
if recipe == "surface-world" and style == 1:
|
||||
return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v227.baseline",
|
||||
"L130-v227-reach-units")
|
||||
return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v230.baseline",
|
||||
"L134-v230-continuous-backbone")
|
||||
if recipe == "floating-islands" and style == 2:
|
||||
return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v227.baseline",
|
||||
"L130-v227-reach-units")
|
||||
return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v230.baseline",
|
||||
"L134-v230-continuous-backbone")
|
||||
raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}")
|
||||
|
||||
|
||||
@@ -1078,7 +1078,7 @@ def run_ore_vein_hash_controls(runner: VerificationRunner) -> None:
|
||||
def cavern_audit_cameras(layout_path: Path) -> list[tuple[float, float, float, float, float]]:
|
||||
layout = json.loads(layout_path.read_text(encoding="utf-8"))
|
||||
edges = layout.get("cavern_edges", [])
|
||||
if layout.get("cavern_graph_vocabulary_version") != 1 or len(edges) != 1:
|
||||
if layout.get("cavern_graph_vocabulary_version") not in (1, 2) or len(edges) != 1:
|
||||
raise VerificationFailure(f"missing one resolved cavern edge in {layout_path}")
|
||||
points = [[value / 1_000_000.0 for value in point]
|
||||
for point in edges[0]["control_points_um"]]
|
||||
@@ -1152,7 +1152,7 @@ def run_native_caves_field_audit(runner: VerificationRunner, binary: Path) -> tu
|
||||
r"false_all_air=REJECTED false_all_solid=REJECTED .*status=PASS$"),
|
||||
"brute-force interval proofs have zero misses and reject both false-proof controls")
|
||||
layout = json.loads(layout_path.read_text(encoding="utf-8"))
|
||||
graph_ok = (layout.get("cavern_graph_vocabulary_version") == 1
|
||||
graph_ok = (layout.get("cavern_graph_vocabulary_version") in (1, 2)
|
||||
and len(layout.get("cavern_rooms", [])) == 1
|
||||
and len(layout.get("cavern_edges", [])) == 2)
|
||||
runner.require(f"native-caves-field-{compiler}:resolved-graph", graph_ok,
|
||||
@@ -1235,7 +1235,7 @@ def run_native_lattice_field_audit(runner: VerificationRunner, binary: Path) ->
|
||||
rooms = layout.get("cavern_rooms", [])
|
||||
lattice_rows = [row for row in layout.get("strates", [])
|
||||
if row.get("strate_index") == 1]
|
||||
graph_ok = (layout.get("cavern_graph_vocabulary_version") == 1
|
||||
graph_ok = (layout.get("cavern_graph_vocabulary_version") in (1, 2)
|
||||
and len(edges) >= 9 and len(rooms) >= 8
|
||||
and len(lattice_rows) == 1
|
||||
and lattice_rows[0].get("generator_kind") == "Maze"
|
||||
@@ -1261,7 +1261,7 @@ def lattice_camera_positions(layout_path: Path, count: int = 4) -> list[tuple[fl
|
||||
edges = sorted(layout.get("cavern_edges", []), key=lambda edge: edge["stable_id"])
|
||||
helix = next((edge for edge in edges
|
||||
if edge["stable_id"] == "lattice/spine/01-helix-ramp-v1"), None)
|
||||
if layout.get("cavern_graph_vocabulary_version") != 1 or helix is None:
|
||||
if layout.get("cavern_graph_vocabulary_version") not in (1, 2) or helix is None:
|
||||
raise VerificationFailure(f"missing resolved lattice helix in {layout_path}")
|
||||
helix_points = [[value / 1_000_000.0 for value in point]
|
||||
for point in helix.get("polyline_um", [])]
|
||||
@@ -1414,7 +1414,7 @@ def run_lattice_performance(runner: VerificationRunner, binary: Path,
|
||||
def cave_camera_positions(layout_path: Path, count: int = 4) -> list[tuple[float, float, float, float, float]]:
|
||||
layout = json.loads(layout_path.read_text(encoding="utf-8"))
|
||||
edges = sorted(layout.get("cavern_edges", []), key=lambda edge: edge["stable_id"])
|
||||
if layout.get("cavern_graph_vocabulary_version") != 1 or len(edges) != 2:
|
||||
if layout.get("cavern_graph_vocabulary_version") not in (1, 2) or len(edges) != 2:
|
||||
raise VerificationFailure(f"missing two resolved cave spine edges in {layout_path}")
|
||||
rng = _SplitMix64(CAVES_CAMERA_SWEEP_SEED)
|
||||
cameras = []
|
||||
|
||||