wip(assembler): round L33 -- SurfaceWorld can be an upper strate; FloorProfileBlend measures seams

Route planning for an upper SurfaceWorld failed on long candidate chords over steep relief; chords
are now capped to the arrival/departure radii on an 8 m centre grid with an origin-proximity cost
(21.5 m walk, about 4 deg). The departure passage starts at the SW ground and tunnels down through rock.
FI -> SW -> TN fixture: all 4 styles pass every passage audit on both compilers. FloorProfileBlend
now checks endpoint height/tangent seams (step and tangent-step negative controls detected). Owner
world hashes unchanged; 30/30 determinism; cost within noise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-21 22:30:36 +02:00
1 parent d0158c6019
commit b7a47bef95
17 files changed
+1116 -32

No files matched your search

+34
View File
@@ -2076,6 +2076,40 @@ transition one micrometre wider than declared and a band one micrometre below th
[`Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md) [`Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md)
for audit measurements, hashes, timings, captures and run history. for audit measurements, hashes, timings, captures and run history.
### 8.47 Ground-bound SurfaceWorld departure routes — World Assembler M3 Linux L33
An intra-strate SurfaceWorld route follows the resolved terrain ground profile. Its route-point Z
is the ground height plus the player's half-height; the route does not descend to the strate's
bedrock boundary. Bedrock belongs to the separate inter-strate passage, which begins at the
SurfaceWorld departure mouth on the ground and tunnels outward and down through native rock and
the boundary into the next strate.
The old fixed candidate envelope used a 64 m chord and 16 m centre spacing. On the L33 upper-SW
fixture, replaying that envelope sampled ground from −507.767 to −464.857 m; 366/648 candidate paths
exceeded the 15° grade limit. The worst failures clustered near the outer west/northwest terrain
shoulder (up to 79.971°) and the steep approach slopes around the origin. Candidate diagnostics
separate grade failures from endpoints outside the bounded arrival/departure placement disks.
The bounded search now limits its longest chord to the two mouth radii minus a 3 m clearance
margin, checks centres every 8 m, and ranks endpoints near the route anchors. It finds a 21.5 m
route from (−2.75, 0) to (18.75, 0), sampled on ground and accepted by the full capsule/support/
grade audit.
The SurfaceWorld departure passage starts at the ground mouth with a 1.5 m portal, then smoothsteps
to a 3.5 m rock tunnel over 9 m. Its ring is sized and oriented outward from the mouth, so the
approach does not cut back under the walk route. The `FloatingIslands → SurfaceWorld → TunnelNetwork`
fixture passes all four passage styles, including both interfaces, capsule clearance, support,
grade, walkability, naturalness, open-air, column ends, long-bridge and route-binding audits.
`FloorProfileBlend` previously compared each curved floor profile with its straight chord and
applied a 2-voxel limit. That is a curvature measurement, not a seam measurement. It now checks
endpoint height and tangent continuity at 0.01 voxel and 0.001 voxel/m; the 3-voxel step and
0.25 voxel/m tangent-step controls are both detected. SurfaceWorld owner hashes remain identical
to L32 because the route-mouth, expanded column sizing and short-span support changes apply only
when SurfaceWorld is the upper strate. No evaluator or recipe version changed.
[`Standalone/Research/WorldAssemblerM3/Linux33/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux33/REPORT.md)
records the four-style audits, captures, determinism, owner hashes, costs and retries.
## 9. Multiplayer model (listen-server first, dedicated-friendly) ## 9. Multiplayer model (listen-server first, dedicated-friendly)
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a > **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a
+14
View File
@@ -1229,6 +1229,20 @@ The Unreal adapter now forwards the authored transition type and chunk width; th
were not compiled here. See ARCHITECTURE §8.46 and were not compiled here. See ARCHITECTURE §8.46 and
[`Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md). [`Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux29/REPORT.md).
### 3.30 SurfaceWorld as an upper strate and floor-profile joins — World Assembler L33
| Symbol | Canonical file | Role |
|---|---|---|
| `BuildFiniteStrateRoute` | `Standalone/Source/WorldAssemblyPrototype.h` | Samples route heights from the composed terrain ground; bounds candidate chords by the arrival/departure placement radii and records per-segment grade failures. |
| `PlanResolvedLayoutPassagesV1` | `Standalone/Core/src/ResolvedLayoutInternal.h` | Starts an upper-SurfaceWorld departure at its terrain mouth, opens a small portal and smoothsteps to the rock tunnel while orienting the ring outward. |
| `BuildPassageVoidCrossingPlan`, `PassageBridgeSignedDistance` | `Standalone/Core/src/ShapeWorldInternal.h` | Sizes unsupported ranges from the full control-segment window only for upper SurfaceWorld; other upper generators keep the previous bracketing-sample bounds. |
| `--audit-resolved-layout-passages` | `Standalone/Source/StreamBenchmarkPipeline.h` | Uses floor height rather than bore-centre height for naturalness and records failed-only wall probes for column audits. |
| `FloorProfileBlend` | `Standalone/Core/src/ShapeWorldInternal.h` | Measures endpoint height/tangent continuity; chord deviation is informational, with step and tangent-step negative controls. |
The owner SurfaceWorld hashes match L32 and evaluator/recipe versions are unchanged. See
ARCHITECTURE §8.47 and
[`Standalone/Research/WorldAssemblerM3/Linux33/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux33/REPORT.md).
## 4. The density pipeline (most-edited hot path) ## 4. The density pipeline (most-edited hot path)
### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749 ### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749
+72 -6
View File
@@ -788,10 +788,13 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
cfg->distanceMaximumSubvoxels):8*qPerMetre; cfg->distanceMaximumSubvoxels):8*qPerMetre;
const std::int64_t placementRadius=std::max<std::int64_t>(1,outer); const std::int64_t placementRadius=std::max<std::int64_t>(1,outer);
// Leave room for the capsule and bounded wall relief at the floor/wall seam. // Leave room for the capsule and bounded wall relief at the floor/wall seam.
const std::int64_t mouthRadius=std::max<std::int64_t>(static_cast<std::int64_t>(std::llround(1.5*qPerMetre)), const bool upperIsSurfaceWorld=upper.generatorKind=="SurfaceWorld";
const std::int64_t minimumMouthRadius=static_cast<std::int64_t>(std::llround(
(upperIsSurfaceWorld?2.0:1.5)*qPerMetre));
const std::int64_t mouthRadius=std::max<std::int64_t>(minimumMouthRadius,
cfg?cfg->mouthRadiusSubvoxels:0); cfg?cfg->mouthRadiusSubvoxels:0);
const std::int64_t midRadius=std::max<std::int64_t>( const std::int64_t midRadius=std::max<std::int64_t>(
static_cast<std::int64_t>(std::llround(1.5*qPerMetre)), static_cast<std::int64_t>(std::llround((upperIsSurfaceWorld?3.5:1.5)*qPerMetre)),
cfg?cfg->midRadiusSubvoxels:mouthRadius); cfg?cfg->midRadiusSubvoxels:mouthRadius);
const std::int64_t reachMinimum=cfg?std::max<std::int64_t>(0,cfg->reachMinimumSubvoxels):8*qPerMetre; const std::int64_t reachMinimum=cfg?std::max<std::int64_t>(0,cfg->reachMinimumSubvoxels):8*qPerMetre;
const std::int64_t reachMaximum=cfg?std::max<std::int64_t>(reachMinimum,cfg->reachMaximumSubvoxels):24*qPerMetre; const std::int64_t reachMaximum=cfg?std::max<std::int64_t>(reachMinimum,cfg->reachMaximumSubvoxels):24*qPerMetre;
@@ -813,6 +816,7 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::array<std::int64_t,3> upperMouth{},lowerMouth{}; std::array<std::int64_t,3> upperMouth{},lowerMouth{};
const bool hasUpperRoute=connection==0&&routeAnchor(upper,true,upperMouth); const bool hasUpperRoute=connection==0&&routeAnchor(upper,true,upperMouth);
const bool hasLowerRoute=connection==0&&routeAnchor(lower,false,lowerMouth); const bool hasLowerRoute=connection==0&&routeAnchor(lower,false,lowerMouth);
const bool surfaceGroundDeparture=hasUpperRoute&&upperIsSurfaceWorld;
const ResolvedLayoutAnchorV2* passageAnchor=nullptr; const ResolvedLayoutAnchorV2* passageAnchor=nullptr;
if(connection==0) if(connection==0)
for(const auto& anchor:upper.anchors) for(const auto& anchor:upper.anchors)
@@ -870,6 +874,17 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::max<std::int64_t>(0,cfg?cfg->cascadeLedgeSubvoxels:0) std::max<std::int64_t>(0,cfg?cfg->cascadeLedgeSubvoxels:0)
*static_cast<std::int64_t>(cfg?cfg->cascadeSteps:4)), *static_cast<std::int64_t>(cfg?cfg->cascadeSteps:4)),
mouthRadius+2*qPerMetre,outerRingRadius); mouthRadius+2*qPerMetre,outerRingRadius);
if(surfaceGroundDeparture)
{
const double departureRadius=std::hypot(static_cast<double>(upperMouth[0]),
static_cast<double>(upperMouth[1]));
const std::int64_t clearRingRadius=static_cast<std::int64_t>(std::ceil(
departureRadius+mouthRadius+0.5*qPerMetre));
const std::int64_t maximumRingRadius=std::max<std::int64_t>(1,
placementRadius-qPerMetre);
ringRadius=std::min(maximumRingRadius,
std::max(ringRadius,clearRingRadius));
}
if(anchoredIslandPassage) if(anchoredIslandPassage)
ringRadius=std::min(ringRadius,mouthRadius+qPerMetre/2); ringRadius=std::min(ringRadius,mouthRadius+qPerMetre/2);
std::uint32_t phase=static_cast<std::uint32_t>(PassageSeed(seed, std::uint32_t phase=static_cast<std::uint32_t>(PassageSeed(seed,
@@ -890,6 +905,23 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
{bestAlignment=alignment;phase=candidate;} {bestAlignment=alignment;phase=candidate;}
} }
} }
if(hasUpperRoute&&upperIsSurfaceWorld)
{
const auto& directionAtPhase=directions[phase];
const std::int64_t radialAlignment=upperMouth[0]*directionAtPhase[0]
+upperMouth[1]*directionAtPhase[1];
if(radialAlignment<0)
{
std::int64_t bestOutwardAlignment=std::numeric_limits<std::int64_t>::min();
for(std::uint32_t candidate=0;candidate<directions.size();++candidate)
{
const std::int64_t alignment=upperMouth[0]*directions[candidate][0]
+upperMouth[1]*directions[candidate][1];
if(alignment>bestOutwardAlignment)
{bestOutwardAlignment=alignment;phase=candidate;}
}
}
}
bool clockwise=(PassageSeed(seed,upper.strateIndex,lower.strateIndex, bool clockwise=(PassageSeed(seed,upper.strateIndex,lower.strateIndex,
connection,0x44495245u)&1u)!=0; connection,0x44495245u)&1u)!=0;
if(anchoredSpiral&&passageAnchor&&hasUpperTangent) if(anchoredSpiral&&passageAnchor&&hasUpperTangent)
@@ -1159,10 +1191,23 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
if(hasAnchorHelix&&helixHorizontal==0) if(hasAnchorHelix&&helixHorizontal==0)
{error=passage.stableId+" anchor spiral has no horizontal reach";return false;} {error=passage.stableId+" anchor spiral has no horizontal reach";return false;}
passage.controlPoints.reserve(xy.size()); passage.controlPoints.reserve(xy.size());
const std::int64_t surfacePortalRadius=surfaceGroundDeparture
?std::min(mouthRadius,static_cast<std::int64_t>(std::llround(1.5*qPerMetre)))
:mouthRadius;
const std::uint64_t surfaceMouthBlendLength=static_cast<std::uint64_t>(
std::max<std::int64_t>(8*qPerMetre,2*mouthRadius));
for(std::size_t i=0;i<xy.size();++i) for(std::size_t i=0;i<xy.size();++i)
{ {
const std::int64_t radius=(i<=1||i==lowerMouthIndex std::int64_t radius=(i<=1||i==lowerMouthIndex
||i+1>=xy.size()-1)?mouthRadius:midRadius; ||i+1>=xy.size()-1)?mouthRadius:midRadius;
if(surfaceGroundDeparture&&i<lowerMouthIndex)
{
const double t=std::clamp(static_cast<double>(cumulative[i])
/surfaceMouthBlendLength,0.0,1.0);
const double smooth=t*t*(3.0-2.0*t);
radius=surfacePortalRadius+static_cast<std::int64_t>(std::llround(
(midRadius-surfacePortalRadius)*smooth));
}
std::int64_t playerZ=0; std::int64_t playerZ=0;
if(i>lowerMouthIndex) if(i>lowerMouthIndex)
playerZ=lowerLandingPoints[i-lowerMouthIndex-1][2]; playerZ=lowerLandingPoints[i-lowerMouthIndex-1][2];
@@ -1183,9 +1228,30 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
point.positionSubvoxels={xy[i][0],xy[i][1],playerZ+radius-playerCenterAboveFloorQ}; point.positionSubvoxels={xy[i][0],xy[i][1],playerZ+radius-playerCenterAboveFloorQ};
point.radiusSubvoxels=radius;passage.controlPoints.push_back(point); point.radiusSubvoxels=radius;passage.controlPoints.push_back(point);
} }
passage.controlPoints.front().positionSubvoxels[2]=upperMouth[2]+mouthRadius-playerCenterAboveFloorQ; if(surfaceGroundDeparture)
passage.controlPoints[lowerMouthIndex].positionSubvoxels[2]= std::printf("[ResolvedSurfaceWorldDepartureMouth] passage=%s ground_floor_z_m=%.3f portal_radius_m=%.3f tunnel_radius_m=%.3f blend_length_m=%.3f departure_xy_m=(%.3f,%.3f) first_tunnel_xy_m=(%.3f,%.3f) first_tunnel_floor_z_m=%.3f first_tunnel_radius_m=%.3f\n",
lowerMouth[2]+mouthRadius-playerCenterAboveFloorQ; passage.stableId.c_str(),(upperMouth[2]-static_cast<std::int64_t>(std::llround(0.88*qPerMetre)))/static_cast<double>(qPerMetre),
surfacePortalRadius/static_cast<double>(qPerMetre),
midRadius/static_cast<double>(qPerMetre),
surfaceMouthBlendLength/static_cast<double>(qPerMetre),
upperMouth[0]/static_cast<double>(qPerMetre),
upperMouth[1]/static_cast<double>(qPerMetre),
passage.controlPoints.size()>1?passage.controlPoints[1].positionSubvoxels[0]
/static_cast<double>(qPerMetre):0.0,
passage.controlPoints.size()>1?passage.controlPoints[1].positionSubvoxels[1]
/static_cast<double>(qPerMetre):0.0,
passage.controlPoints.size()>1?
(passage.controlPoints[1].positionSubvoxels[2]
-passage.controlPoints[1].radiusSubvoxels+playerCenterAboveFloorQ
-static_cast<std::int64_t>(std::llround(0.88*qPerMetre)))
/static_cast<double>(qPerMetre):0.0,
passage.controlPoints.size()>1?passage.controlPoints[1].radiusSubvoxels
/static_cast<double>(qPerMetre):0.0);
passage.controlPoints.front().positionSubvoxels[2]=upperMouth[2]
+passage.controlPoints.front().radiusSubvoxels-playerCenterAboveFloorQ;
passage.controlPoints[lowerMouthIndex].positionSubvoxels[2]=lowerMouth[2]
+passage.controlPoints[lowerMouthIndex].radiusSubvoxels
-playerCenterAboveFloorQ;
layout.passages.push_back(std::move(passage)); layout.passages.push_back(std::move(passage));
} }
} }
+131 -13
View File
@@ -1309,6 +1309,10 @@ public:
double MaxUnmarkedFloorDirectionSlopeDelta = 0.0; double MaxUnmarkedFloorDirectionSlopeDelta = 0.0;
double MaxMarkedFloorSlopeDelta = 0.0; double MaxMarkedFloorSlopeDelta = 0.0;
double MaxFloorCurveDeviation = 0.0; double MaxFloorCurveDeviation = 0.0;
double MaxFloorProfileEndpointValueError = 0.0;
double MaxFloorProfileEndpointSlopeError = 0.0;
bool FloorProfileEndpointStepControlDetected = false;
bool FloorProfileEndpointSlopeControlDetected = false;
double LocalPrimitiveSeconds = 0.0; double LocalPrimitiveSeconds = 0.0;
double LocalLineBinSeconds = 0.0; double LocalLineBinSeconds = 0.0;
double CandidateMergeSeconds = 0.0; double CandidateMergeSeconds = 0.0;
@@ -1380,6 +1384,8 @@ public:
double FloorCurveStartBlend = 0.0; double FloorCurveStartBlend = 0.0;
double FloorCurveEndBlend = 0.0; double FloorCurveEndBlend = 0.0;
double FloorCurveMaxDeviation = 0.0; double FloorCurveMaxDeviation = 0.0;
double FloorCurveEndpointValueError = 0.0;
double FloorCurveEndpointSlopeError = 0.0;
}; };
struct FInterval { int32 Lo = 0, Hi = -1; }; struct FInterval { int32 Lo = 0, Hi = -1; };
@@ -1517,6 +1523,7 @@ public:
if(NodeCount>160000000ull) if(NodeCount>160000000ull)
{Error="shape interval region exceeds the 160-million-node safety bound";return false;} {Error="shape interval region exceeds the 160-million-node safety bound";return false;}
Stats={};Stats.SignNodes=NodeCount; Stats={};Stats.SignNodes=NodeCount;
AuditFloorProfileBlendNegativeControls();
auto Stage=Clock::now(); auto Stage=Clock::now();
BuildLayerBounds(); BuildLayerBounds();
@@ -1622,13 +1629,19 @@ public:
static_cast<unsigned long long>(Stats.RoomFloorJoinCount)); static_cast<unsigned long long>(Stats.RoomFloorJoinCount));
const double SmoothUnionGrowthBound=JoinBlendRadius/6.0; const double SmoothUnionGrowthBound=JoinBlendRadius/6.0;
const bool bFloorSlopePass=Stats.MaxUnmarkedFloorSlopeDelta<=0.75; const bool bFloorSlopePass=Stats.MaxUnmarkedFloorSlopeDelta<=0.75;
const bool bFloorBlendPass=Stats.MaxFloorCurveDeviation<=2.0; const bool bFloorBlendPass=Stats.MaxFloorProfileEndpointValueError<=0.01
&&Stats.MaxFloorProfileEndpointSlopeError<=0.001
&&Stats.FloorProfileEndpointStepControlDetected
&&Stats.FloorProfileEndpointSlopeControlDetected;
std::printf("[FloorSlopeJoinAudit] raw_unmarked_max_delta=%.5f vox generated_tangent_delta=%.5f vox bend_direction_slope_change=%.5f vox marked_max_delta=%.5f vox marked_joins=%llu threshold=0.750 status=%s\n", std::printf("[FloorSlopeJoinAudit] raw_unmarked_max_delta=%.5f vox generated_tangent_delta=%.5f vox bend_direction_slope_change=%.5f vox marked_max_delta=%.5f vox marked_joins=%llu threshold=0.750 status=%s\n",
Stats.MaxRawUnmarkedFloorSlopeDelta,Stats.MaxUnmarkedFloorSlopeDelta, Stats.MaxRawUnmarkedFloorSlopeDelta,Stats.MaxUnmarkedFloorSlopeDelta,
Stats.MaxUnmarkedFloorDirectionSlopeDelta,Stats.MaxMarkedFloorSlopeDelta, Stats.MaxUnmarkedFloorDirectionSlopeDelta,Stats.MaxMarkedFloorSlopeDelta,
static_cast<unsigned long long>(Stats.MarkedFloorSlopeJoins),bFloorSlopePass?"PASS":"FAIL"); static_cast<unsigned long long>(Stats.MarkedFloorSlopeJoins),bFloorSlopePass?"PASS":"FAIL");
std::printf("[FloorProfileBlend] c1_segments=%llu max_curve_deviation=%.3f vox threshold=2.000 status=%s\n", std::printf("[FloorProfileBlend] c1_segments=%llu max_chord_deviation=%.3f vox informational endpoint_value_residual=%.8f vox endpoint_slope_residual=%.8f vox_per_m thresholds=(0.010,0.001) negative_controls=%s/%s status=%s\n",
static_cast<unsigned long long>(Stats.CurvedFloorSegments),Stats.MaxFloorCurveDeviation, static_cast<unsigned long long>(Stats.CurvedFloorSegments),Stats.MaxFloorCurveDeviation,
Stats.MaxFloorProfileEndpointValueError,Stats.MaxFloorProfileEndpointSlopeError,
Stats.FloorProfileEndpointStepControlDetected?"step_detected":"step_missed",
Stats.FloorProfileEndpointSlopeControlDetected?"slope_detected":"slope_missed",
bFloorBlendPass?"PASS":"FAIL"); bFloorBlendPass?"PASS":"FAIL");
std::printf("[TunnelRadiusAudit] shared_joins=%llu legacy_fixed_segment_max_step=%.4f vox smoothed_profile_max_step=%.4f vox tapered_endpoint_max_delta=%.6f vox radius_slope_join_delta=%.8f floor_endpoint_max_delta=%.6f vox floor_slope_join_delta=%.5f unmarked_floor_slope_delta=%.5f marked_floor_slope_delta=%.5f marked_slope_joins=%llu smooth_union_growth_bound=%.4f vox thresholds=(0.005,0.000001,0.005,0.25) status=%s\n", std::printf("[TunnelRadiusAudit] shared_joins=%llu legacy_fixed_segment_max_step=%.4f vox smoothed_profile_max_step=%.4f vox tapered_endpoint_max_delta=%.6f vox radius_slope_join_delta=%.8f floor_endpoint_max_delta=%.6f vox floor_slope_join_delta=%.5f unmarked_floor_slope_delta=%.5f marked_floor_slope_delta=%.5f marked_slope_joins=%llu smooth_union_growth_bound=%.4f vox thresholds=(0.005,0.000001,0.005,0.25) status=%s\n",
static_cast<unsigned long long>(Stats.CapsuleJoinCount),Stats.LegacySegmentRadiusStep, static_cast<unsigned long long>(Stats.CapsuleJoinCount),Stats.LegacySegmentRadiusStep,
@@ -2751,8 +2764,23 @@ private:
auto& flags= crossing.needsColumn auto& flags= crossing.needsColumn
?PassageColumnSegmentFlags[crossing.passageIndex] ?PassageColumnSegmentFlags[crossing.passageIndex]
:PassageShortSpanSegmentFlags[crossing.passageIndex]; :PassageShortSpanSegmentFlags[crossing.passageIndex];
const std::size_t first=std::min(crossing.firstSegment,flags.size()); bool surfaceWorldUpper=false;
const std::size_t last=std::min(crossing.lastSegment,flags.empty()?0:flags.size()-1); if(crossing.passageIndex<ResolvedLayout->passages.size())
{
const std::int32_t strate=ResolvedLayout->passages[
crossing.passageIndex].upperStrateIndex;
const auto upper=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[strate](const auto& value)
{return value.strateIndex==strate;});
surfaceWorldUpper=upper!=ResolvedLayout->strates.end()
&&upper->generatorKind=="SurfaceWorld";
}
const std::size_t shortSpanPadding=!crossing.needsColumn
&&surfaceWorldUpper&&!flags.empty()?2:0;
const std::size_t first=std::min(crossing.firstSegment>shortSpanPadding
?crossing.firstSegment-shortSpanPadding:0,flags.size());
const std::size_t last=std::min(crossing.lastSegment+shortSpanPadding,
flags.empty()?0:flags.size()-1);
if(!flags.empty()&&first<=last) if(!flags.empty()&&first<=last)
std::fill(flags.begin()+first,flags.begin()+last+1,1); std::fill(flags.begin()+first,flags.begin()+last+1,1);
} }
@@ -3011,6 +3039,11 @@ private:
ResolvedLayout->coreVoxelSizeMicrometres); ResolvedLayout->coreVoxelSizeMicrometres);
const auto& a=passage.controlPoints[SegmentIndex]; const auto& a=passage.controlPoints[SegmentIndex];
const auto& b=passage.controlPoints[SegmentIndex+1]; const auto& b=passage.controlPoints[SegmentIndex+1];
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[&passage](const auto& value)
{return value.strateIndex==passage.upperStrateIndex;});
const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end()
&&upperStratum->generatorKind=="SurfaceWorld";
const double ax=static_cast<double>(a.positionSubvoxels[0]); const double ax=static_cast<double>(a.positionSubvoxels[0]);
const double ay=static_cast<double>(a.positionSubvoxels[1]); const double ay=static_cast<double>(a.positionSubvoxels[1]);
const double dx=static_cast<double>(b.positionSubvoxels[0])-ax; const double dx=static_cast<double>(b.positionSubvoxels[0])-ax;
@@ -3031,7 +3064,8 @@ private:
+PassageBridgeDeckOffsetMetres(PassageIndex,SegmentIndex)*qPerMetre; +PassageBridgeDeckOffsetMetres(PassageIndex,SegmentIndex)*qPerMetre;
const double relief=std::clamp(static_cast<double>(VF_FieldSurfaceRelief(X,Y,Z, const double relief=std::clamp(static_cast<double>(VF_FieldSurfaceRelief(X,Y,Z,
static_cast<std::uint32_t>(Owner?Owner->Seed:0))),-1.0,1.0); static_cast<std::uint32_t>(Owner?Owner->Seed:0))),-1.0,1.0);
const double halfWidth=(3.30+0.20*relief)*qPerMetre; const double halfWidth=(surfaceWorldUpper?3.65+0.10*relief:3.30+0.20*relief)
*qPerMetre;
const double thickness=(4.0+1.0*relief)*qPerMetre; const double thickness=(4.0+1.0*relief)*qPerMetre;
const double horizontalDistance=DeterministicSqrt((qx-centerX)*(qx-centerX) const double horizontalDistance=DeterministicSqrt((qx-centerX)*(qx-centerX)
+(qy-centerY)*(qy-centerY)); +(qy-centerY)*(qy-centerY));
@@ -3214,6 +3248,11 @@ private:
++passageIndex) ++passageIndex)
{ {
const auto& passage=ResolvedLayout->passages[passageIndex]; const auto& passage=ResolvedLayout->passages[passageIndex];
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[&passage](const auto& value)
{return value.strateIndex==passage.upperStrateIndex;});
const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end()
&&upperStratum->generatorKind=="SurfaceWorld";
if(passage.controlPoints.size()<2)continue; if(passage.controlPoints.size()<2)continue;
std::vector<FPathSample> samples; std::vector<FPathSample> samples;
samples.reserve(passage.controlPoints.size()*2); samples.reserve(passage.controlPoints.size()*2);
@@ -3303,14 +3342,32 @@ private:
} }
double maximumOffsetSubvoxels=0.0; double maximumOffsetSubvoxels=0.0;
double maximumBoreSubvoxels=0.0; double maximumBoreSubvoxels=0.0;
for(std::size_t index=startSample;index<=endSample;++index) double minimumCrossingZ=std::min(crossing.startPoint[2],crossing.endPoint[2]);
double maximumCrossingZ=std::max(crossing.startPoint[2],crossing.endPoint[2]);
for(std::size_t sampleIndex=0;sampleIndex<samples.size();++sampleIndex)
{ {
const auto& point=samples[index].point; const auto& sample=samples[sampleIndex];
// The audit and density field use whole control segments, including
// the neighboring segments that extend the column through its caps.
// Size the column from that same segment window instead of only the
// unsupported half-metre samples inside the original gap.
if(surfaceWorldUpper)
{
if(sample.segment<crossing.firstSegment
||sample.segment>crossing.lastSegment)continue;
}
else if(sampleIndex<startSample||sampleIndex>endSample)continue;
const auto& point=sample.point;
const double dx=point[0]-crossing.centerXSubvoxels; const double dx=point[0]-crossing.centerXSubvoxels;
const double dy=point[1]-crossing.centerYSubvoxels; const double dy=point[1]-crossing.centerYSubvoxels;
maximumOffsetSubvoxels=std::max(maximumOffsetSubvoxels, maximumOffsetSubvoxels=std::max(maximumOffsetSubvoxels,
DeterministicSqrt(dx*dx+dy*dy)); DeterministicSqrt(dx*dx+dy*dy));
maximumBoreSubvoxels=std::max(maximumBoreSubvoxels,point[3]); maximumBoreSubvoxels=std::max(maximumBoreSubvoxels,point[3]);
if(surfaceWorldUpper)
{
minimumCrossingZ=std::min(minimumCrossingZ,point[2]);
maximumCrossingZ=std::max(maximumCrossingZ,point[2]);
}
} }
const double maximumOffsetMetres=maximumOffsetSubvoxels/qPerMetre; const double maximumOffsetMetres=maximumOffsetSubvoxels/qPerMetre;
const double maximumBoreMetres=maximumBoreSubvoxels/qPerMetre; const double maximumBoreMetres=maximumBoreSubvoxels/qPerMetre;
@@ -3324,12 +3381,10 @@ private:
nominalRadiusMetres*qPerMetre)); nominalRadiusMetres*qPerMetre));
crossing.maximumRadiusSubvoxels=crossing.minimumRadiusSubvoxels crossing.maximumRadiusSubvoxels=crossing.minimumRadiusSubvoxels
+static_cast<std::int64_t>(std::ceil(11.25*qPerMetre)); +static_cast<std::int64_t>(std::ceil(11.25*qPerMetre));
const double startZ=crossing.startPoint[2];
const double endZ=crossing.endPoint[2];
crossing.topZSubvoxels=static_cast<std::int64_t>(std::llround( crossing.topZSubvoxels=static_cast<std::int64_t>(std::llround(
std::max(startZ,endZ)+5.0*qPerMetre)); maximumCrossingZ+5.0*qPerMetre));
crossing.bottomZSubvoxels=static_cast<std::int64_t>(std::llround( crossing.bottomZSubvoxels=static_cast<std::int64_t>(std::llround(
std::min(startZ,endZ)-6.0*qPerMetre)); minimumCrossingZ-6.0*qPerMetre));
} }
PassageVoidCrossings.push_back(crossing); PassageVoidCrossings.push_back(crossing);
if(crossing.needsColumn) if(crossing.needsColumn)
@@ -3350,7 +3405,7 @@ private:
crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED"); crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED");
} }
else else
std::printf("[PassageShortGroundedSpanPlan] id=%s segments=%zu..%zu span_m=%.3f threshold_m=%.3f connected=%d/%d width_m=6.000 thickness_m=3.000..5.000 status=%s\n", std::printf("[PassageShortGroundedSpanPlan] id=%s segments=%zu..%zu span_m=%.3f threshold_m=%.3f connected=%d/%d width_m=7.300 thickness_m=3.000..5.000 status=%s\n",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment, passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
gapLength,shortSpanMaximumMetres,static_cast<int>(crossing.connectedAtStart), gapLength,shortSpanMaximumMetres,static_cast<int>(crossing.connectedAtStart),
static_cast<int>(crossing.connectedAtEnd), static_cast<int>(crossing.connectedAtEnd),
@@ -4193,7 +4248,10 @@ public:
static_cast<unsigned long long>(S.NearZero),static_cast<unsigned long long>(S.AxisLocked)); static_cast<unsigned long long>(S.NearZero),static_cast<unsigned long long>(S.AxisLocked));
} }
const bool bFloorProfilePass=Stats.MaxUnmarkedFloorSlopeDelta<=0.75 const bool bFloorProfilePass=Stats.MaxUnmarkedFloorSlopeDelta<=0.75
&&Stats.MaxFloorCurveDeviation<=2.0; &&Stats.MaxFloorProfileEndpointValueError<=0.01
&&Stats.MaxFloorProfileEndpointSlopeError<=0.001
&&Stats.FloorProfileEndpointStepControlDetected
&&Stats.FloorProfileEndpointSlopeControlDetected;
return bDetailPass&&bGridPass&&bThinSheetPass&&bFloorProfilePass; return bDetailPass&&bGridPass&&bThinSheetPass&&bFloorProfilePass;
} }
@@ -4949,6 +5007,44 @@ private:
return Result; return Result;
} }
static double EvaluateFloorProfileSlope(double A,double B,double TangentA,double TangentB,
double Length,double StartBlend,double EndBlend,double S)
{
if(S<0.0)return TangentA;
if(S>Length)return TangentB;
const double Secant=(B-A)/Length;
double Result=Secant;
const auto CorrectionSlope=[](double DeltaSlope,double T)
{return DeltaSlope*(1.0-4.0*T+3.0*T*T);};
if(S<StartBlend)
Result+=CorrectionSlope(TangentA-Secant,S/StartBlend);
if(Length-S<EndBlend)
Result+=CorrectionSlope(TangentB-Secant,(Length-S)/EndBlend);
return Result;
}
void AuditFloorProfileBlendNegativeControls()
{
constexpr double A=2.0,B=11.0,TangentA=0.35,TangentB=-0.20;
constexpr double Length=20.0,StartBlend=7.0,EndBlend=7.0;
constexpr double Step=3.0,SlopeStep=0.25;
constexpr double ValueThreshold=0.01,SlopeThreshold=0.001;
const double endValue=EvaluateFloorProfile(A,B,TangentA,TangentB,
Length,StartBlend,EndBlend,Length);
const double startSlope=EvaluateFloorProfileSlope(A,B,TangentA,TangentB,
Length,StartBlend,EndBlend,0.0);
Stats.FloorProfileEndpointStepControlDetected=
std::abs((endValue+Step)-B)>ValueThreshold;
Stats.FloorProfileEndpointSlopeControlDetected=
std::abs((startSlope+SlopeStep)-TangentA)>SlopeThreshold;
std::printf("[FloorProfileBlendNegativeControls] endpoint_step=%.3f_vox tangent_step=%.3f_vox_per_m detected=%s/%s status=%s\n",
Step,SlopeStep,
Stats.FloorProfileEndpointStepControlDetected?"true":"false",
Stats.FloorProfileEndpointSlopeControlDetected?"true":"false",
Stats.FloorProfileEndpointStepControlDetected
&&Stats.FloorProfileEndpointSlopeControlDetected?"PASS":"FAIL");
}
static double FloorSurfaceRelief(double X,double Y,uint32 Seed) static double FloorSurfaceRelief(double X,double Y,uint32 Seed)
{ {
// A shared XY field keeps independently authored floor clips from ending on // A shared XY field keeps independently authored floor clips from ending on
@@ -5014,6 +5110,16 @@ private:
const double Linear=std::lerp(FloorA,FloorB,T); const double Linear=std::lerp(FloorA,FloorB,T);
P.FloorCurveMaxDeviation=std::max(P.FloorCurveMaxDeviation,std::abs(Curve-Linear)); P.FloorCurveMaxDeviation=std::max(P.FloorCurveMaxDeviation,std::abs(Curve-Linear));
} }
P.FloorCurveEndpointValueError=std::max(
std::abs(EvaluateFloorProfile(FloorA,FloorB,TangentA,TangentB,Length,
P.FloorCurveStartBlend,P.FloorCurveEndBlend,0.0)-FloorA),
std::abs(EvaluateFloorProfile(FloorA,FloorB,TangentA,TangentB,Length,
P.FloorCurveStartBlend,P.FloorCurveEndBlend,Length)-FloorB));
P.FloorCurveEndpointSlopeError=std::max(
std::abs(EvaluateFloorProfileSlope(FloorA,FloorB,TangentA,TangentB,Length,
P.FloorCurveStartBlend,P.FloorCurveEndBlend,0.0)-TangentA),
std::abs(EvaluateFloorProfileSlope(FloorA,FloorB,TangentA,TangentB,Length,
P.FloorCurveStartBlend,P.FloorCurveEndBlend,Length)-TangentB));
} }
double FloorAt(const FPrimitive& P,double X,double Y) const double FloorAt(const FPrimitive& P,double X,double Y) const
@@ -5224,6 +5330,12 @@ private:
++Stats.CurvedFloorSegments; ++Stats.CurvedFloorSegments;
Stats.MaxFloorCurveDeviation=std::max(Stats.MaxFloorCurveDeviation, Stats.MaxFloorCurveDeviation=std::max(Stats.MaxFloorCurveDeviation,
Primitives.back().FloorCurveMaxDeviation); Primitives.back().FloorCurveMaxDeviation);
Stats.MaxFloorProfileEndpointValueError=std::max(
Stats.MaxFloorProfileEndpointValueError,
Primitives.back().FloorCurveEndpointValueError);
Stats.MaxFloorProfileEndpointSlopeError=std::max(
Stats.MaxFloorProfileEndpointSlopeError,
Primitives.back().FloorCurveEndpointSlopeError);
} }
FitCapsuleRadiiAtEndpoints(Primitives.back(),Points[I],R0,Points[I+1],R1); FitCapsuleRadiiAtEndpoints(Primitives.back(),Points[I],R0,Points[I+1],R1);
SetCapsuleRadiusProfile(Primitives.back(),Points[I],R0,RadiusSlope0, SetCapsuleRadiusProfile(Primitives.back(),Points[I],R0,RadiusSlope0,
@@ -5348,6 +5460,12 @@ private:
++Stats.CurvedFloorSegments; ++Stats.CurvedFloorSegments;
Stats.MaxFloorCurveDeviation=std::max(Stats.MaxFloorCurveDeviation, Stats.MaxFloorCurveDeviation=std::max(Stats.MaxFloorCurveDeviation,
Primitives.back().FloorCurveMaxDeviation); Primitives.back().FloorCurveMaxDeviation);
Stats.MaxFloorProfileEndpointValueError=std::max(
Stats.MaxFloorProfileEndpointValueError,
Primitives.back().FloorCurveEndpointValueError);
Stats.MaxFloorProfileEndpointSlopeError=std::max(
Stats.MaxFloorProfileEndpointSlopeError,
Primitives.back().FloorCurveEndpointSlopeError);
FitCapsuleRadiiAtEndpoints(Primitives.back(),Points[I],RadiusA,Points[I+1],RadiusB); FitCapsuleRadiiAtEndpoints(Primitives.back(),Points[I],RadiusA,Points[I+1],RadiusB);
SetCapsuleRadiusProfile(Primitives.back(),Points[I],RadiusA,RadiusSlopeA, SetCapsuleRadiusProfile(Primitives.back(),Points[I],RadiusA,RadiusSlopeA,
Points[I+1],RadiusB,RadiusSlopeB); Points[I+1],RadiusB,RadiusSlopeB);
+6
View File
@@ -83,6 +83,12 @@ Costs below are design estimates, not timings. Low means bounded analytic featur
A passage planner must produce a traversable route or pair a non-walkable visual passage with another guaranteed route. A narrow crack or drop cannot be assumed walkable because its centerline is air. A passage planner must produce a traversable route or pair a non-walkable visual passage with another guaranteed route. A narrow crack or drop cannot be assumed walkable because its centerline is air.
For a SurfaceWorld strate, the supported arrival-to-departure route follows the sampled terrain
ground and stays within the mouth placement bounds. The inter-strate departure passage owns the
descent from that ground mouth through rock and bedrock. Treating the bottom of a tall SurfaceWorld
strate as the route's departure height would ask the walk planner to cross open terrain air; it is
the wrong endpoint for the intra-strate route.
| Passage type | Planner output | Bound and likely cost | | Passage type | Planner output | Bound and likely cost |
|---|---|---| |---|---|---|
| SlopedTunnel | Straight-style path with switchbacks as needed, capsule clearance, supported floor, maximum grade and landing geometry. | Swept capsule bounds plus floor envelope; low–medium. | | SlopedTunnel | Straight-style path with switchbacks as needed, capsule clearance, supported floor, maximum grade and landing geometry. | Swept capsule bounds plus floor envelope; low–medium. |
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""Build owner-like FloatingIslands -> SurfaceWorld -> TunnelNetwork fixtures."""
import copy
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
SOURCE = ROOT / "Standalone/data/owner_world.json"
OUT = ROOT / "Saved/Linux/l33/fixtures"
def make_fixture(style: int) -> Path:
world = json.loads(SOURCE.read_text(encoding="utf-8"))
source_tunnel, source_surface = world["strates"]
floating = copy.deepcopy(source_tunnel)
floating.update(index=0, top_chunk_z=0, bottom_chunk_z=-15, height_chunks=16)
floating["asset"]["StrateName"] = "Linux33 Upper FloatingIslands"
floating["asset"]["StrateHeightInChunks"] = 16
floating["asset"]["GeneratorType"] = 6
surface = copy.deepcopy(source_surface)
surface.update(index=1, top_chunk_z=-16, bottom_chunk_z=-79, height_chunks=64)
surface["asset"]["StrateName"] = "Linux33 Middle SurfaceWorld"
surface["asset"]["StrateHeightInChunks"] = 64
surface["asset"]["PassageConfig"]["Style"] = style
surface["passage_config"]["Style"] = style
tunnel = copy.deepcopy(source_tunnel)
tunnel.update(index=2, top_chunk_z=-80, bottom_chunk_z=-143, height_chunks=64)
tunnel["asset"]["StrateName"] = "Linux33 Lower TunnelNetwork"
tunnel["asset"]["StrateHeightInChunks"] = 64
world["strates"] = [floating, surface, tunnel]
world["total_strates"] = 3
world["settings_asset"]["TotalStrates"] = 3
world["settings_asset"]["StratePool"] = [
"/Standalone/Linux33/UpperFloatingIslands",
"/Standalone/Linux33/MiddleSurfaceWorld",
"/Standalone/Linux33/LowerTunnelNetwork",
]
world["passages"] = [] # The L23 legacy coordinates are not part of this resolved stack.
world["source"] = "VoxelForge Linux33 owner-like SurfaceWorld-upper fixture"
OUT.mkdir(parents=True, exist_ok=True)
path = OUT / f"sw-upper-tunnel-network-style{style}.json"
path.write_text(json.dumps(world, separators=(",", ":")), encoding="utf-8")
return path
if __name__ == "__main__":
for style in range(4):
path = make_fixture(style)
print(f"style={style} fixture={path}")
@@ -0,0 +1,100 @@
#!/usr/bin/env python3
"""Export and render two bounded SurfaceWorld departure views."""
import os
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
FIXTURE = OUT / "fixtures/sw-upper-tunnel-network-style0.json"
HEADLESS = OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final"
CAPTURE = OUT / "bin/VoxelForgeOffscreenCapture-clang-l33-final"
PNG_DIR = OUT / "capture-png"
DEST = Path(__file__).resolve().parent / "captures"
PNG_DIR.mkdir(parents=True, exist_ok=True)
DEST.mkdir(parents=True, exist_ok=True)
env = os.environ.copy()
env["LP_NUM_THREADS"] = "12"
env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache")
views = (
{
"name": "sw-departure-mouth",
"export_camera": "18.75,-12,-499,0,-22",
"render_camera": "18.75,0,-490",
"yaw": "0",
"pitch": "-90",
"fov": "38",
"height_center": "-503.166",
"height_range": "4",
"light": "0,-1,0.2",
"headlamp": "off",
"clip": None,
},
{
"name": "sw-departure-rock-entry",
"export_camera": "26,-16,-499,64,-16",
"render_camera": "14,-4,-500",
"yaw": "78",
"pitch": "-16",
"fov": "32",
"height_center": "-503.166",
"height_range": "4",
"light": "0,-1,0.2",
"headlamp": "off",
"clip": "1,0,0,-18.75",
},
)
def run(name, command):
logfile = OUT / f"capture-{name}.log"
wrapped = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1800s", *command,
]
started = time.monotonic()
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(wrapped, cwd=ROOT, env=env, stdout=stream,
stderr=subprocess.STDOUT, timeout=1800, check=False)
print(f"[L33CaptureRun] step={name} elapsed={time.monotonic()-started:.1f}s "
f"exit={result.returncode} log={logfile}", flush=True)
if result.returncode != 0:
raise SystemExit(f"{name} failed; see {logfile}")
for view in views:
name = view["name"]
mesh = OUT / f"{name}.vfmesh"
png = PNG_DIR / f"{name}.png"
jpg = DEST / f"{name}.jpg"
run(f"{name}-export", [
str(HEADLESS), str(FIXTURE), "--workers=12", "--world-assembler-prototype",
"--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=2",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
"--recipe=floating-islands",
f"--camera={view['export_camera']}", f"--mesh-export={mesh}",
])
command = [
str(CAPTURE), str(mesh), str(png), "--size=1600x900", f"--fov-deg={view['fov']}",
f"--camera-m={view['render_camera']}", f"--yaw-deg={view['yaw']}",
f"--pitch-deg={view['pitch']}", "--shade=readable",
f"--headlamp={view['headlamp']}", f"--light-direction={view['light']}",
"--height-tint=on", f"--height-center-m={view['height_center']}",
f"--height-range-m={view['height_range']}", "--tile-edges=off",
]
if view["clip"]:
command.append(f"--clip-plane={view['clip']}")
run(f"{name}-render", command)
run(f"{name}-jpeg", [
"ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error", "-y",
"-i", str(png), "-frames:v", "1", "-q:v", "4", str(jpg),
])
size = jpg.stat().st_size if jpg.exists() else 0
ok = 0 < size <= 300_000
print(f"[L33CaptureJPEG] file={jpg.relative_to(ROOT)} bytes={size} "
f"status={'PASS' if ok else 'FAIL'}", flush=True)
if not ok:
raise SystemExit(f"{jpg.name} is missing or exceeds 300 KB")
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""Check representative owner hashes against L32 before the full matrix."""
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
L32 = ROOT / "Saved/Linux/l32"
BINARIES = {
"clang": OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final",
"gcc": OUT / "bin/VoxelForgeCoreHeadless-gcc-l33-final",
}
HASH_PATTERN = re.compile(
r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
failed = False
for compiler, binary in BINARIES.items():
for recipe in ("surface-world", "floating-islands"):
name = f"owner-hash-preflight-{compiler}-{recipe}-w12"
logfile = OUT / f"{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(binary), str(ROOT / "Standalone/data/owner_world.json"),
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--stream-hash", "--force-generate", "--clip-radius=3", "--max-clip-level=8",
"--far-horizon-lod8-step=0", "--workers=12", f"--recipe={recipe}",
]
started = time.monotonic()
try:
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
timeout=900, check=False)
except subprocess.TimeoutExpired:
result = None
text = logfile.read_text(encoding="utf-8", errors="replace")
hashes = HASH_PATTERN.findall(text)
baseline_path = L32 / f"l25-settled-final-{compiler}-{recipe}-w12.log"
baseline = HASH_PATTERN.findall(baseline_path.read_text(
encoding="utf-8", errors="replace")) if baseline_path.exists() else []
stamps = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M)
same = len(hashes) == 12 and hashes == baseline
ok = (result is not None and result.returncode == 0 and same
and stamps == [(recipe, recipe, "PASS")])
failed |= not ok
print(f"{name} elapsed={time.monotonic()-started:.1f}s hashes={len(hashes)}/12 "
f"same_as_l32={'yes' if same else 'no'} "
f"{'PASS' if ok else 'FAIL'}", flush=True)
raise SystemExit(1 if failed else 0)
@@ -0,0 +1,58 @@
# Linux33 report
## Upper SurfaceWorld route
The old fixed candidate set used 64 m chords, 2 m waypoint spacing and 16 m centre spacing. On the refreshed upper-stack fixture, the legacy replay measured 366/648 candidates above the 15° grade limit; its worst segment was 79.971° at XY (−84,−48) to (−82,−48). These were long paths over steep terrain relief near the outer search area. L23’s earlier fixture reported 648/648 grade rejects; the refreshed fixture gives a different count. The route Z samples are terrain-ground heights (about −503 m at the chosen mouth), not a target at the bottom of the 499 m strate. There was no unit or bedrock-reference error.
The planner now caps chords at 58.5 m for the 24 m arrival and 37.5 m departure radii, searches six lengths and places route centres on an 8 m grid, with a proximity cost favouring the origin. It found a 21.5 m walk from (−2.75,0) to departure (18.75,0), average grade about 4.2°. The SW passage starts at the ground floor (−503.166 m), with a 1.5 m portal blending to a 3.5 m tunnel over 9 m, then descends through SW rock. The first tunnel point is at (32.5,0), floor −505.637 m for style 0.
## Upper-stack fixture audits
Fixture: FloatingIslands → SurfaceWorld → TunnelNetwork; recipe stamp `floating-islands`; layout identity `resolved-layout-v3-fnv64:fc4e73619037f88c`. Clang and GCC passed every row for every style.
| Passage style | Floor chord deviation (voxels) | Passage and route audits | Open air | Naturalness | Bridge / columns | Bindings / walkability |
|---:|---:|---|---|---|---|---|
| 0 | 2.081 | 2/2 each pass | 0 violations | 2/2 pass | pass / 0 failures | 0 failures / pass |
| 1 | 10.901 | 2/2 each pass | 0 violations | 2/2 pass | pass / 0 failures | 0 failures / pass |
| 2 | 14.822 | 2/2 each pass | 0 violations | 2/2 pass | pass / 0 failures | 0 failures / pass |
| 3 | 16.374 | 2/2 each pass | 0 violations | 2/2 pass | pass / 0 failures | 0 failures / pass |
All rows are recipe-stamped and passed on both compilers. Capsule blocking, unsupported samples and grade failures were zero; mouth-content and mouth-radius checks were 2/2. This includes open-air, naturalness, no-long-bridge, rock-column wall/support, route binding and walkability audits.
## FloorProfileBlend
The old 2-voxel check measured maximum curve-to-straight-chord deviation, which grows with valid curvature and does not measure a seam. The check now compares endpoint height and tangent residuals. All styles have 0.00000000 voxel height residual and 0.00000000 voxel/m tangent residual (limits 0.010 and 0.001). Negative controls detected a 3-voxel step and a 0.25 voxel/m tangent step. Verdict: check corrected; no floor geometry change was needed.
## Captures
Both 1600×900 JPEGs are under 300 KB. The first shows the SW ground mouth; the second is a cutaway through the rock entry.
Sizes and SHA-256: mouth 26,939 B, `561d3a1e334ea3a3115fb781a1130ec850d8777b74c1be3704c70b865878640a`; rock entry 37,572 B, `f85d150bf44cd2cdae1ee49de023ad9e4c657b8fa7e8d8f8b93abc86586ad6e5`.
![SurfaceWorld departure mouth](captures/sw-departure-mouth.jpg)
![SurfaceWorld departure rock entry](captures/sw-departure-rock-entry.jpg)
## Hashes, determinism and cost
Owner-world hashes match L32 exactly: all 12 hash lines per run across Clang/GCC and both recipes passed the owner preflight; the L25 and 24 m crossing matrix also passed at W1/W8/W12 (24/24 owner rows). W12 whole-view hashes: SurfaceWorld density `953eb1df1705f277`, mesh `d8006cb43f44aa5b`, payload `9217bff766970de5`, topology `83e3aa6f3a063e60`; FloatingIslands density `806537cdd98f8afb`, mesh `a4b06dd4d260943d`, payload `763a99aa04a73eae`, topology `baa37d80d3620d87`. The upper fixture was stable across W1/W8/W12 on both compilers. Total determinism: 30/30. Invariant audits: 16/16.
Five interleaved W12 cost pairs per recipe against L32: median whole-view ready time changed +0.99% for SurfaceWorld and +0.41% for FloatingIslands; paired medians were +0.57% and +0.41%, within run noise. Recipe/evaluator versions remain 2/20. No Unreal files changed; no Unreal build was run. No version bump was needed because the owner hashes are unchanged.
## Failed and retried runs
- CLI setup rejected `--compiler clang`; the accepted form was `--compiler=clang++-19`. One shell quoting attempt ended at EOF. A FloatingIslands fixture initially had a `surface-world` recipe stamp and was regenerated with `floating-islands`.
- A translated ring centre failed the strict placement disk and was reverted. Fixture audit iterations: r1 had style 1–3 failures (TN capsule pinch, route undercut, naturalness); r2 had 141 open-air violations plus route/naturalness failures; r3 had strict ring-placement and route-support failures; r4 had four edge open-air samples. The broad column-window fix passed passage audits but changed owner hashes. Its first scoped retry dropped supported bracket samples and failed SurfaceWorld hash preflight on both compilers; restoring the original non-SW bracket bounds fixed it.
- An intermediate Clang build failed on `coreVoxelSizeMetres` and `gradeSegments`; both names were corrected. Final Clang 19 and GCC 14 `--fp-contract=off`, `-j12` builds succeeded. An early determinism run on stale binaries was stopped after 21 rows and showed the interim hash mismatch; the final binaries passed all 30 rows.
- The first capture export included the far ring and grew to 2.49 GB; it was stopped before rendering. The LOD0 streamed export reduced the scene to about 2.2 MB. Capture framings r5–r8 rendered successfully but obscured the mouth; r9 is the inspected final framing.
No run exceeded 30 minutes and no step remained stuck for 15 minutes. Logs and exports are in `Saved/Linux/l33/`; no commit, push or stash was made.
## Orchestrator review (Claude)
- Merged: the owner world is unchanged (hashes equal L32); SW-as-upper now plans its route and passes the full audit set
on the FI→SW→TN fixture. The FloorProfileBlend check now measures seams (endpoint height/tangent residuals) with
step/tangent negative controls. Accepted: chord deviation measured curvature, not a defect.
- Captures: `sw-departure-mouth.jpg` is out of focus and unreadable; `sw-departure-rock-entry.jpg` shows a natural opening
but **horizontal step-like ledges inside**, reminiscent of the L23 terraces. L34 checks passage mouths and entries for
stepping across styles and fixes the blurry capture setup.
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
"""Run five interleaved W12 whole-view pairs against the L32 binary."""
import re
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
OUT.mkdir(parents=True, exist_ok=True)
BINARIES = {
"l32": ROOT / "Saved/Linux/l32/bin/VoxelForgeCoreHeadless-l32-clang-v20",
"l33": OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final",
}
ORDERS = (("l32", "l33"), ("l33", "l32"), ("l32", "l33"),
("l33", "l32"), ("l32", "l33"))
READY = re.compile(r"\bwhole_view_ready=([0-9.]+)s")
rows = []
failed = False
for recipe in ("surface-world", "floating-islands"):
for pair, order in enumerate(ORDERS, 1):
for build in order:
name = f"cost-{recipe}-pair{pair}-{build}"
logfile = OUT / f"{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(BINARIES[build]), str(ROOT / "Standalone/data/owner_world.json"),
"--workers=12", "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", "--force-generate", "--clip-radius=3",
"--max-clip-level=8", "--max-level=-1", f"--recipe={recipe}",
]
started = time.monotonic()
try:
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
timeout=900, check=False)
except subprocess.TimeoutExpired:
result = None
elapsed = time.monotonic() - started
text = logfile.read_text(encoding="utf-8", errors="replace")
matches = READY.findall(text)
stamps = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M)
stamp_ok = stamps == [(recipe, recipe, "PASS")]
valid = (result is not None and result.returncode == 0 and len(matches) == 1
and "hash=off" in text and "cache_hits=0" in text and stamp_ok)
ready = float(matches[0]) if len(matches) == 1 else float("nan")
rows.append((recipe, pair, build, ready, elapsed,
result.returncode if result else "TIMEOUT", valid))
print(f"{recipe} pair={pair} build={build} whole_view_ready={ready:.3f}s "
f"process_elapsed={elapsed:.1f}s {'PASS' if valid else 'FAIL'}", flush=True)
failed |= not valid
summary = OUT / "cost-runs.csv"
summary.write_text(
"recipe,pair,build,whole_view_ready_seconds,process_elapsed_seconds,exit_code,status\n" +
"".join(f"{recipe},{pair},{build},{ready:.6f},{elapsed:.3f},{code},"
f"{'PASS' if ok else 'FAIL'}\n"
for recipe, pair, build, ready, elapsed, code, ok in rows), encoding="utf-8")
for recipe in ("surface-world", "floating-islands"):
by_build = {build: [row[3] for row in rows if row[0] == recipe and row[2] == build]
for build in BINARIES}
baseline = statistics.median(by_build["l32"])
current = statistics.median(by_build["l33"])
paired = []
for pair in range(1, 6):
values = {row[2]: row[3] for row in rows if row[0] == recipe and row[1] == pair}
paired.append((values["l33"] - values["l32"]) / values["l32"] * 100.0)
print(f"[L33CostSummary] recipe={recipe} pairs=5 median_l32_s={baseline:.3f} "
f"median_l33_s={current:.3f} median_change_pct={(current/baseline-1)*100.0:+.2f} "
f"paired_change_pct={','.join(f'{value:+.2f}' for value in paired)}", flush=True)
print(f"[L33Cost] runs={len(rows)} status={'FAIL' if failed else 'PASS'} summary={summary}",
flush=True)
raise SystemExit(1 if failed or len(rows) != 20 else 0)
@@ -0,0 +1,131 @@
#!/usr/bin/env python3
"""Run owner L25 hashes, 24 m crossings, and upper-SurfaceWorld fixture determinism."""
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
L32 = ROOT / "Saved/Linux/l32"
FIXTURE = OUT / "fixtures/sw-upper-tunnel-network-style0.json"
BINARIES = {
"clang": OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final",
"gcc": OUT / "bin/VoxelForgeCoreHeadless-gcc-l33-final",
}
HASH_PATTERN = re.compile(
r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
LAYOUT_PATTERN = re.compile(
r"^\[ResolvedLayoutSnapshot\] schema=\d+ stable_identity=([^ ]+) strata=\d+ bytes=\d+ round_trip=PASS$",
re.M)
PLAN_PATTERN = re.compile(
r"^\[WorldAssemblerPlanSerialization\].*canonical_round_trip=true .*"
r"plan_hash=([0-9a-f]+) manifest_hash=([0-9a-f]+) status=PASS$", re.M)
ROUTE_PATTERN = re.compile(
r"^\[WorldAssemblerRouteAccepted\] arrival_xy_m=\([^)]*\) "
r"departure_xy_m=\([^)]*\) endpoint_proximity_cost=\d+ average_grade_q16=\d+$", re.M)
rows = []
failed = False
owner_reference = {}
fixture_reference = None
def run(command, logfile):
started = time.monotonic()
try:
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
timeout=1800, check=False)
except subprocess.TimeoutExpired:
result = None
return result, time.monotonic() - started, logfile.read_text(
encoding="utf-8", errors="replace")
for kind in ("l25", "crossing24"):
for recipe in ("surface-world", "floating-islands"):
for compiler, binary in BINARIES.items():
for workers in (1, 8, 12):
name = f"{kind}-{compiler}-{recipe}-w{workers}"
logfile = OUT / f"determinism-{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(binary), str(ROOT / "Standalone/data/owner_world.json"),
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--stream-hash", "--force-generate", "--clip-radius=3",
"--max-clip-level=8", "--far-horizon-lod8-step=0",
f"--workers={workers}", f"--recipe={recipe}",
]
if kind == "crossing24":
command.extend(("--camera-step=24,0,0", "--region-crossing"))
result, elapsed, text = run(command, logfile)
hashes = HASH_PATTERN.findall(text)
stamps = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M)
ref = L32 / f"{kind}-settled-final-{compiler}-{recipe}-w{workers}.log"
reference_hashes = HASH_PATTERN.findall(ref.read_text(
encoding="utf-8", errors="replace")) if ref.exists() else []
stable_key = (kind, recipe)
stable = stable_key not in owner_reference or hashes == owner_reference[stable_key]
if stable_key not in owner_reference and hashes:
owner_reference[stable_key] = hashes
equal_l32 = len(hashes) == 12 and hashes == reference_hashes
ok = (result is not None and result.returncode == 0
and stamps == [(recipe, recipe, "PASS")]
and "hash=on" in text and len(hashes) == 12 and stable and equal_l32)
rows.append((kind, recipe, compiler, workers, elapsed,
result.returncode if result else "TIMEOUT", ok))
print(f"{name} elapsed={elapsed:.1f}s hashes={len(hashes)}/12 "
f"same_across_matrix={'yes' if stable else 'no'} "
f"same_as_l32={'yes' if equal_l32 else 'no'} {'PASS' if ok else 'FAIL'}",
flush=True)
failed |= not ok
for compiler, binary in BINARIES.items():
for workers in (1, 8, 12):
name = f"upper-fixture-{compiler}-w{workers}"
logfile = OUT / f"determinism-{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(binary), str(FIXTURE), "--workers=" + str(workers),
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", "--clip-radius=3", "--max-clip-level=8",
"--max-level=-1", "--recipe=floating-islands", "--audit-resolved-layout-passages",
]
result, elapsed, text = run(command, logfile)
layouts = LAYOUT_PATTERN.findall(text)
plans = PLAN_PATTERN.findall(text)
routes = ROUTE_PATTERN.findall(text)
stamps = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M)
passage_summary = re.search(r"^\[ResolvedPassageAuditSummary\].*status=PASS$", text, re.M)
signature = (tuple(layouts), tuple(plans), tuple(routes))
stable = fixture_reference is None or signature == fixture_reference
if fixture_reference is None and layouts and plans and routes:
fixture_reference = signature
ok = (result is not None and result.returncode == 0 and len(layouts) == 1
and len(plans) == 1 and len(routes) == 1
and stamps == [("floating-islands", "floating-islands", "PASS")]
and passage_summary is not None and stable)
rows.append(("upper-fixture", "floating-islands", compiler, workers, elapsed,
result.returncode if result else "TIMEOUT", ok))
print(f"{name} elapsed={elapsed:.1f}s layout={layouts[0] if layouts else 'MISSING'} "
f"stable_across_matrix={'yes' if stable else 'no'} {'PASS' if ok else 'FAIL'}",
flush=True)
failed |= not ok
summary = OUT / "determinism-l33.csv"
summary.write_text(
"kind,recipe,compiler,workers,elapsed_seconds,exit_code,status\n" +
"".join(f"{kind},{recipe},{compiler},{workers},{elapsed:.3f},{code},"
f"{'PASS' if ok else 'FAIL'}\n"
for kind, recipe, compiler, workers, elapsed, code, ok in rows),
encoding="utf-8")
print(f"[L33Determinism] runs={len(rows)} pass={sum(row[-1] for row in rows)} "
f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True)
raise SystemExit(1 if failed or len(rows) != 30 else 0)
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
"""Run L33 route/proof and transition invariants with recipe-stamped logs."""
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
BINARIES = {
"clang": OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final",
"gcc": OUT / "bin/VoxelForgeCoreHeadless-gcc-l33-final",
}
rows = []
failed = False
def run(name, binary, data, recipe, extra, checks):
global failed
logfile = OUT / f"{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(binary), str(data), "--workers=12", "--world-assembler-prototype",
"--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=3",
"--max-clip-level=8", "--max-level=-1", f"--recipe={recipe}", *extra,
]
started = time.monotonic()
try:
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
timeout=900, check=False)
except subprocess.TimeoutExpired:
result = None
elapsed = time.monotonic() - started
text = logfile.read_text(encoding="utf-8", errors="replace")
stamps = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M)
stamp_ok = stamps == [(recipe, recipe, "PASS")]
checks_ok = all(check(text) for check in checks)
ok = result is not None and result.returncode == 0 and stamp_ok and checks_ok
rows.append((name, recipe, elapsed, result.returncode if result else "TIMEOUT", ok))
print(f"{name} elapsed={elapsed:.1f}s recipe={stamps[0][1] if stamps else 'MISSING'} "
f"stamp={'PASS' if stamp_ok else 'FAIL'} checks={'PASS' if checks_ok else 'FAIL'} "
f"{'PASS' if ok else 'FAIL'}", flush=True)
failed |= not ok
owner = ROOT / "Standalone/data/owner_world.json"
for recipe in ("surface-world", "floating-islands"):
for compiler, binary in BINARIES.items():
name = f"invariant-route-proof-{recipe}-{compiler}"
run(name, binary, owner, recipe,
["--stream-hash", "--audit-uniform-block-proofs", "--audit-route-parity"],
[lambda text: bool(re.search(
r"^\[RouteParityAudit\].*status=PASS$", text, re.M)),
lambda text: bool(re.search(
r"^\[UniformBlockProofAudit\].*violations=0(?:\s|$)", text, re.M))])
for recipe in ("surface-world", "floating-islands"):
for compiler, binary in BINARIES.items():
for mode in ("hard", "gradient", "interleaved"):
name = f"invariant-transition-{recipe}-{mode}-{compiler}"
run(name, binary, owner, recipe,
[f"--transition-mode={mode}", "--audit-strate-transitions"],
[lambda text: bool(re.search(
r"^\[StrateTransitionAuditSummary\].*hole_columns=0 air_samples=0 .*status=PASS$",
text, re.M)),
lambda text: bool(re.search(
r"^\[StrateTransitionNegativeControls\].*status=PASS$", text, re.M))])
summary = OUT / "invariant-audits.csv"
summary.write_text(
"run,recipe,elapsed_seconds,exit_code,status\n" +
"".join(f"{name},{recipe},{elapsed:.3f},{code},{'PASS' if ok else 'FAIL'}\n"
for name, recipe, elapsed, code, ok in rows),
encoding="utf-8")
print(f"[L33InvariantAudits] runs={len(rows)} pass={sum(row[-1] for row in rows)} "
f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True)
raise SystemExit(1 if failed or len(rows) != 16 else 0)
@@ -0,0 +1,78 @@
#!/usr/bin/env python3
"""Recipe-stamped resolved-passage audits for the L33 upper-SurfaceWorld stack."""
import os
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l33"
TAG = os.environ.get("VOXELFORGE_L33_AUDIT_TAG", "clang").strip() or "clang"
BINARY = Path(os.environ.get("VOXELFORGE_L33_AUDIT_BINARY",
str(OUT / f"bin/VoxelForgeCoreHeadless-{TAG}-l33-final")))
ROWS = []
FAILED = False
for style in range(4):
name = f"upper-sw-three-strata-{TAG}-style{style}"
fixture = OUT / f"fixtures/sw-upper-tunnel-network-style{style}.json"
logfile = OUT / f"{name}.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
str(BINARY), str(fixture), "--workers=12", "--world-assembler-prototype",
"--stream-benchmark", "--stream-pipeline", "--force-generate",
"--clip-radius=3", "--max-clip-level=8", "--max-level=-1",
"--recipe=floating-islands", "--audit-resolved-layout-passages",
]
started = time.monotonic()
try:
with logfile.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
timeout=1800, check=False)
except subprocess.TimeoutExpired:
result = None
elapsed = time.monotonic() - started
text = logfile.read_text(encoding="utf-8", errors="replace")
stamp_ok = re.findall(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
text, re.M) == [("floating-islands", "floating-islands", "PASS")]
summary = re.search(r"^\[ResolvedPassageAuditSummary\].*$", text, re.M)
summary_ok = bool(summary and "interfaces=2 passed=2 natural=2/2" in summary.group()
and "route_walkable=2" in summary.group()
and "route_binding_failures=0" in summary.group()
and "status=PASS" in summary.group())
markers = (
r"^\[PassageOpenAirAuditSummary\].*violations=0.*status=PASS$",
r"^\[PassageNoLongBridgeAudit\].*status=PASS$",
r"^\[PassageRockColumnAuditSummary\].*wall_or_support_failures=0.*status=PASS$",
r"^\[PassageNaturalnessSummary\].*status=PASS$",
)
markers_ok = all(re.search(pattern, text, re.M) for pattern in markers)
passage_rows = re.findall(
r"^\[ResolvedPassageAudit\].*blocked=0 support_samples=\d+ unsupported=0 "
r"grade_failures=0 mouth_content=2/2 mouth_radius=2/2 walkability=PASS$",
text, re.M)
floor_rows = re.findall(r"^\[FloorProfileBlend\].*status=PASS$", text, re.M)
route_rows = re.findall(
r"^\[ResolvedStrateRouteAudit\].*blocked=0 support_samples=\d+ unsupported=0 "
r"grade_failures=0 mouth_binding=PASS status=PASS$", text, re.M)
ok = (result is not None and result.returncode == 0 and stamp_ok and summary_ok
and markers_ok and len(passage_rows) == 2 and len(route_rows) == 2
and len(floor_rows) >= 1 and "[Walkability] PASS" in text)
FAILED |= not ok
ROWS.append((style, elapsed, result.returncode if result else "TIMEOUT", ok))
print(f"{name} elapsed={elapsed:.1f}s exit={result.returncode if result else 'TIMEOUT'} "
f"recipe={'PASS' if stamp_ok else 'FAIL'} passages={len(passage_rows)}/2 "
f"routes={len(route_rows)}/2 floor_blend_rows={len(floor_rows)} "
f"{'PASS' if ok else 'FAIL'}", flush=True)
summary_path = OUT / f"upper-sw-three-strata-{TAG}-audits.csv"
summary_path.write_text(
"style,elapsed_seconds,exit_code,status\n" +
"".join(f"{style},{elapsed:.3f},{code},{'PASS' if ok else 'FAIL'}\n"
for style, elapsed, code, ok in ROWS), encoding="utf-8")
print(f"[L33UpperSurfaceFixtureAudit] compiler={TAG} runs={len(ROWS)} pass={sum(row[-1] for row in ROWS)} "
f"fail={sum(not row[-1] for row in ROWS)} summary={summary_path}", flush=True)
raise SystemExit(1 if FAILED or len(ROWS) != 4 else 0)
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+9 -3
View File
@@ -820,7 +820,9 @@ namespace StandaloneStreamBenchmark
const auto& b=passage.controlPoints[i]; const auto& b=passage.controlPoints[i];
const double dx=qToMetres(b.positionSubvoxels[0]-a.positionSubvoxels[0]); const double dx=qToMetres(b.positionSubvoxels[0]-a.positionSubvoxels[0]);
const double dy=qToMetres(b.positionSubvoxels[1]-a.positionSubvoxels[1]); const double dy=qToMetres(b.positionSubvoxels[1]-a.positionSubvoxels[1]);
const double dz=qToMetres(b.positionSubvoxels[2]-a.positionSubvoxels[2]); const double floorA=qToMetres(a.positionSubvoxels[2]-a.radiusSubvoxels)+1.13;
const double floorB=qToMetres(b.positionSubvoxels[2]-b.radiusSubvoxels)+1.13;
const double dz=floorB-floorA;
const double horizontal=std::hypot(dx,dy); const double horizontal=std::hypot(dx,dy);
if(horizontal>1.0e-6&&std::abs(dz)/horizontal if(horizontal>1.0e-6&&std::abs(dz)/horizontal
<std::tan(0.5*3.14159265358979323846/180.0)) <std::tan(0.5*3.14159265358979323846/180.0))
@@ -1313,6 +1315,9 @@ namespace StandaloneStreamBenchmark
++audit.wallSections; ++audit.wallSections;
audit.wallFailures+=!wallSolid; audit.wallFailures+=!wallSolid;
crossingWallFailures+=!wallSolid; crossingWallFailures+=!wallSolid;
if(!wallSolid&&crossingWallFailures<=8)
std::printf("[PassageRockColumnWallProbe] id=%s segment=%zu xyz_m=(%.3f,%.3f,%.3f) axis_m=(%.3f,%.3f) centerline_radius_m=%.3f bore_radius_m=%.3f wall_probe_radius_m=%.3f\n",
passage.stableId.c_str(),segment,x,y,z,axisX,axisY,radial,radius,wallRadius);
} }
double crossingMinimumSurfaceRadius=std::numeric_limits<double>::infinity(); double crossingMinimumSurfaceRadius=std::numeric_limits<double>::infinity();
double crossingMaximumSurfaceRadius=0.0; double crossingMaximumSurfaceRadius=0.0;
@@ -1378,12 +1383,13 @@ namespace StandaloneStreamBenchmark
&&crossingWallFailures==0&&std::isfinite(measuredWall) &&crossingWallFailures==0&&std::isfinite(measuredWall)
&&measuredWall>=1.50&&crossingSurfaceRelief>=0.20; &&measuredWall>=1.50&&crossingSurfaceRelief>=0.20;
audit.passed&=columnPass; audit.passed&=columnPass;
std::printf("[PassageRockColumnAudit] id=%s segments=%zu..%zu span_m=%.3f axis_m=(%.3f,%.3f) connected=%d/2 route_support=%llu/%llu wall_margin_m=%.3f threshold_m=1.500 radii_m=%.3f..%.3f relief_p2p_m=%.3f nominal_radius_m=%.3f status=%s\n", std::printf("[PassageRockColumnAudit] id=%s segments=%zu..%zu span_m=%.3f axis_m=(%.3f,%.3f) connected=%d/2 route_support=%llu/%llu wall_failures=%llu wall_margin_m=%.3f threshold_m=1.500 radii_m=%.3f..%.3f relief_p2p_m=%.3f nominal_radius_m=%.3f status=%s\n",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment, passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
crossing.unsupportedLengthMetres,axisX,axisY, crossing.unsupportedLengthMetres,axisX,axisY,
static_cast<int>(topCapConnected)+static_cast<int>(bottomCapConnected), static_cast<int>(topCapConnected)+static_cast<int>(bottomCapConnected),
static_cast<unsigned long long>(probeCount-crossingRouteFailures), static_cast<unsigned long long>(probeCount-crossingRouteFailures),
static_cast<unsigned long long>(probeCount),measuredWall, static_cast<unsigned long long>(probeCount),
static_cast<unsigned long long>(crossingWallFailures),measuredWall,
crossingMinimumSurfaceRadius,crossingMaximumSurfaceRadius, crossingMinimumSurfaceRadius,crossingMaximumSurfaceRadius,
crossingSurfaceRelief,qToMetres(crossing.columnNominalRadiusSubvoxels), crossingSurfaceRelief,qToMetres(crossing.columnNominalRadiusSubvoxels),
columnPass?"PASS":"FAIL"); columnPass?"PASS":"FAIL");
+212 -10
View File
@@ -7,6 +7,7 @@
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <cstdlib>
#include <cstdio> #include <cstdio>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
@@ -44,7 +45,8 @@ namespace StandaloneWorldAssemblyPrototype
inline bool BuildFiniteStrateRoute(VoxelForgeCore::WorldAssemblyRecipeV1& recipe, inline bool BuildFiniteStrateRoute(VoxelForgeCore::WorldAssemblyRecipeV1& recipe,
VoxelForgeCore::WorldAssemblyStratumPlanV1& stratum,std::uint64_t& tested, VoxelForgeCore::WorldAssemblyStratumPlanV1& stratum,std::uint64_t& tested,
std::uint64_t& gradeRejected,std::uint64_t& placementRejected, std::uint64_t& gradeRejected,std::uint64_t& placementRejected,
std::uint64_t& sweepRejected,std::int64_t arrivalRadiusSubvoxels, std::uint64_t& sweepRejected,std::uint32_t coreVoxelSizeMicrons,
std::int64_t arrivalRadiusSubvoxels,
std::int64_t departureRadiusSubvoxels,std::string& error) std::int64_t departureRadiusSubvoxels,std::string& error)
{ {
using namespace VoxelForgeCore; using namespace VoxelForgeCore;
@@ -63,9 +65,20 @@ namespace StandaloneWorldAssemblyPrototype
struct Candidate struct Candidate
{ {
std::int64_t score=0; std::int64_t score=0;
std::uint64_t endpointProximityCost=0;
std::int32_t centerX=0,centerY=0,direction=0; std::int32_t centerX=0,centerY=0,direction=0;
std::vector<WorldAssemblyRoutePointV1> points; std::vector<WorldAssemblyRoutePointV1> points;
}; };
struct GradeSegmentAudit
{
std::uint64_t failures=0;
double maximumGrade=0.0;
std::int64_t fromGround=0,toGround=0,fromX=0,fromY=0,toX=0,toY=0;
};
std::array<GradeSegmentAudit,32> placementValidGradeSegments{};
std::uint64_t gradeFailCandidates=0;
double minimumGround=std::numeric_limits<double>::infinity();
double maximumGround=-std::numeric_limits<double>::infinity();
auto& constraints=stratum.routeConstraints; auto& constraints=stratum.routeConstraints;
constraints.version=1; constraints.version=1;
@@ -84,10 +97,112 @@ namespace StandaloneWorldAssemblyPrototype
if(!finalField.isValid()) if(!finalField.isValid())
{error="route planner received an invalid final composed field";return false;} {error="route planner received an invalid final composed field";return false;}
std::vector<Candidate> candidates; std::vector<Candidate> candidates;
constexpr std::int32_t halfLength=128; std::vector<std::int32_t> candidateHalfLengths{128};
constexpr std::int32_t waypointSpacing=8; std::int32_t candidateCenterSpacing=64;
for(std::int32_t centerY=-256;centerY<=256;centerY+=64) if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0)
for(std::int32_t centerX=-256;centerX<=256;centerX+=64) {
// A centered line cannot join two bounded mouths when its chord is
// longer than the sum of their placement radii. Leave 3 m for the
// capsule and terrain-profile repair, then search centers at 8 m
// spacing so asymmetric arrival/departure radii can both be reached.
constexpr std::int64_t placementMarginQ=12*WorldAssemblySubvoxelsPerVoxel;
const std::int64_t availableLengthVoxels=std::max<std::int64_t>(1,
(arrivalRadiusSubvoxels+departureRadiusSubvoxels-placementMarginQ)
/WorldAssemblySubvoxelsPerVoxel);
const std::int32_t maximumHalfLength=static_cast<std::int32_t>(std::min<std::int64_t>(128,
std::max<std::int64_t>(1,availableLengthVoxels/2)));
candidateHalfLengths.clear();
for(const std::int32_t numerator:std::array<std::int32_t,6>{{8,7,6,5,4,3}})
{
const std::int32_t halfLength=std::max(1,maximumHalfLength*numerator/8);
if(std::find(candidateHalfLengths.begin(),candidateHalfLengths.end(),halfLength)
==candidateHalfLengths.end())candidateHalfLengths.push_back(halfLength);
}
candidateCenterSpacing=32;
}
const double coreVoxelMetres=static_cast<double>(coreVoxelSizeMicrons)/1000000.0;
if(std::getenv("VOXELFORGE_AUDIT_LEGACY_ROUTE_GRADE"))
{
constexpr std::int32_t legacyCenterSpacing=64;
constexpr std::int32_t legacyWaypointSpacing=8;
std::array<GradeSegmentAudit,32> legacySegments{};
std::uint64_t legacyGradeFailCandidates=0;
double legacyMinimumGround=std::numeric_limits<double>::infinity();
double legacyMaximumGround=-std::numeric_limits<double>::infinity();
for(std::int32_t centerY=-256;centerY<=256;centerY+=legacyCenterSpacing)
for(std::int32_t centerX=-256;centerX<=256;centerX+=legacyCenterSpacing)
for(const Direction& direction:directions)
{
bool candidateGradeFail=false;
std::int64_t previousGround=0,previousX=0,previousY=0;
for(std::int32_t index=0;index<=32;++index)
{
const std::int64_t along=(index-16)*legacyWaypointSpacing;
const std::int64_t x=centerX+std::llround(
static_cast<double>(along)*direction.x/65536.0);
const std::int64_t y=centerY+std::llround(
static_cast<double>(along)*direction.y/65536.0);
const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)),
WorldAssemblyFixed(static_cast<double>(y)),0);
const double groundMetres=static_cast<double>(column.groundHeightSubvoxels)
*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
legacyMinimumGround=std::min(legacyMinimumGround,groundMetres);
legacyMaximumGround=std::max(legacyMaximumGround,groundMetres);
if(index>0)
{
const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround(
std::hypot(static_cast<double>(x-previousX),
static_cast<double>(y-previousY))*WorldAssemblySubvoxelsPerVoxel));
const std::int64_t riseQ=std::abs(
column.groundHeightSubvoxels-previousGround);
if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16)
{
candidateGradeFail=true;
GradeSegmentAudit& segment=legacySegments[
static_cast<std::size_t>(index-1)];
++segment.failures;
const double grade=horizontalQ>0
?static_cast<double>(riseQ)/static_cast<double>(horizontalQ)
:std::numeric_limits<double>::infinity();
if(grade>segment.maximumGrade)
{
segment.maximumGrade=grade;
segment.fromGround=previousGround;
segment.toGround=column.groundHeightSubvoxels;
segment.fromX=previousX;segment.fromY=previousY;
segment.toX=x;segment.toY=y;
}
}
}
previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y;
}
if(candidateGradeFail)++legacyGradeFailCandidates;
}
std::printf("[WorldAssemblerLegacyRouteGradeProfile] candidates=648 grade_fail_candidates=%llu ground_range_m=%.3f..%.3f grade_limit_deg=15.000 chord_m=%.3f waypoint_step_m=%.3f center_step_m=%.3f\n",
static_cast<unsigned long long>(legacyGradeFailCandidates),
legacyMinimumGround,legacyMaximumGround,256.0*coreVoxelMetres,
legacyWaypointSpacing*coreVoxelMetres,legacyCenterSpacing*coreVoxelMetres);
const double metresPerSubvoxel=coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
for(std::size_t segmentIndex=0;segmentIndex<legacySegments.size();++segmentIndex)
{
const GradeSegmentAudit& segment=legacySegments[segmentIndex];
if(segment.failures==0)continue;
std::printf("[WorldAssemblerLegacyRouteGradeSegment] index=%zu rejected_candidates=%llu max_grade_deg=%.3f ground_m=%.3f->%.3f xy_m=(%.3f,%.3f)->(%.3f,%.3f)\n",
segmentIndex,static_cast<unsigned long long>(segment.failures),
std::atan(segment.maximumGrade)*57.29577951308232,
segment.fromGround*metresPerSubvoxel,segment.toGround*metresPerSubvoxel,
segment.fromX*coreVoxelMetres,segment.fromY*coreVoxelMetres,
segment.toX*coreVoxelMetres,segment.toY*coreVoxelMetres);
}
}
std::printf("[WorldAssemblerRouteCandidateEnvelope] max_chord_m=%.3f length_variants=%zu center_step_m=%.3f arrival_radius_m=%.3f departure_radius_m=%.3f\n",
2.0*candidateHalfLengths.front()*coreVoxelMetres,candidateHalfLengths.size(),
candidateCenterSpacing*coreVoxelMetres,
arrivalRadiusSubvoxels*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel,
departureRadiusSubvoxels*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel);
for(const std::int32_t candidateHalfLength:candidateHalfLengths)
for(std::int32_t centerY=-256;centerY<=256;centerY+=candidateCenterSpacing)
for(std::int32_t centerX=-256;centerX<=256;centerX+=candidateCenterSpacing)
for(std::int32_t directionIndex=0;directionIndex<static_cast<std::int32_t>(directions.size());++directionIndex) for(std::int32_t directionIndex=0;directionIndex<static_cast<std::int32_t>(directions.size());++directionIndex)
{ {
Candidate candidate; Candidate candidate;
@@ -95,22 +210,36 @@ namespace StandaloneWorldAssemblyPrototype
candidate.points.reserve(33); candidate.points.reserve(33);
std::int64_t previousGround=0,previousX=0,previousY=0; std::int64_t previousGround=0,previousX=0,previousY=0;
bool gradePass=true,placementPass=true; bool gradePass=true,placementPass=true;
std::array<GradeSegmentAudit,32> candidateGradeSegments{};
for(std::int32_t index=0;index<=32;++index) for(std::int32_t index=0;index<=32;++index)
{ {
const std::int64_t along=(index-16)*waypointSpacing; const std::int64_t along=(index-16)*candidateHalfLength/16;
const std::int64_t x=centerX+std::llround( const std::int64_t x=centerX+std::llround(
static_cast<double>(along)*directions[directionIndex].x/65536.0); static_cast<double>(along)*directions[directionIndex].x/65536.0);
const std::int64_t y=centerY+std::llround( const std::int64_t y=centerY+std::llround(
static_cast<double>(along)*directions[directionIndex].y/65536.0); static_cast<double>(along)*directions[directionIndex].y/65536.0);
const std::int64_t xQ=WorldAssemblyFixed(static_cast<double>(x)); const std::int64_t xQ=WorldAssemblyFixed(static_cast<double>(x));
const std::int64_t yQ=WorldAssemblyFixed(static_cast<double>(y)); const std::int64_t yQ=WorldAssemblyFixed(static_cast<double>(y));
if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0
&&(index==0||index==32))
{
const std::uint64_t radiusSquared=static_cast<std::uint64_t>(
xQ*xQ+yQ*yQ);
candidate.endpointProximityCost+=radiusSquared*(index==0?16ull:1ull);
}
const auto inRadius=[](std::int64_t xValue,std::int64_t yValue,std::int64_t radius) const auto inRadius=[](std::int64_t xValue,std::int64_t yValue,std::int64_t radius)
{return radius<=0||xValue*xValue+yValue*yValue<=radius*radius;}; {return radius<=0||xValue*xValue+yValue*yValue<=radius*radius;};
if((index==0&&!inRadius(xQ,yQ,arrivalRadiusSubvoxels)) if((index==0&&!inRadius(xQ,yQ,arrivalRadiusSubvoxels))
||(index==32&&!inRadius(xQ,yQ,departureRadiusSubvoxels))) ||(index==32&&!inRadius(xQ,yQ,departureRadiusSubvoxels)))
{placementPass=false;break;} placementPass=false;
const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)), const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)),
WorldAssemblyFixed(static_cast<double>(y)),0); WorldAssemblyFixed(static_cast<double>(y)),0);
const double metresPerSubvoxel=static_cast<double>(coreVoxelSizeMicrons)
/(WorldAssemblySubvoxelsPerVoxel*1000000.0);
const double groundMetres=static_cast<double>(column.groundHeightSubvoxels)
*metresPerSubvoxel;
minimumGround=std::min(minimumGround,groundMetres);
maximumGround=std::max(maximumGround,groundMetres);
const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround( const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround(
std::hypot(static_cast<double>(x-previousX),static_cast<double>(y-previousY)) std::hypot(static_cast<double>(x-previousX),static_cast<double>(y-previousY))
*WorldAssemblySubvoxelsPerVoxel)); *WorldAssemblySubvoxelsPerVoxel));
@@ -118,7 +247,23 @@ namespace StandaloneWorldAssemblyPrototype
{ {
const std::int64_t riseQ=std::abs(column.groundHeightSubvoxels-previousGround); const std::int64_t riseQ=std::abs(column.groundHeightSubvoxels-previousGround);
if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16) if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16)
{gradePass=false;break;} {
gradePass=false;
GradeSegmentAudit& segment=candidateGradeSegments[
static_cast<std::size_t>(index-1)];
++segment.failures;
const double grade=horizontalQ>0
?static_cast<double>(riseQ)/static_cast<double>(horizontalQ)
:std::numeric_limits<double>::infinity();
if(grade>segment.maximumGrade)
{
segment.maximumGrade=grade;
segment.fromGround=previousGround;
segment.toGround=column.groundHeightSubvoxels;
segment.fromX=previousX;segment.fromY=previousY;
segment.toX=x;segment.toY=y;
}
}
candidate.score+=riseQ*65536/std::max<std::int64_t>(1,horizontalQ); candidate.score+=riseQ*65536/std::max<std::int64_t>(1,horizontalQ);
} }
WorldAssemblyRoutePointV1 point; WorldAssemblyRoutePointV1 point;
@@ -131,13 +276,60 @@ namespace StandaloneWorldAssemblyPrototype
candidate.points.push_back(point); candidate.points.push_back(point);
previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y; previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y;
} }
candidate.score/=32;
++tested; ++tested;
if(!gradePass)++gradeFailCandidates;
if(placementPass&&gradePass)candidates.push_back(std::move(candidate)); if(placementPass&&gradePass)candidates.push_back(std::move(candidate));
else if(!placementPass)++placementRejected; else if(!placementPass)++placementRejected;
else ++gradeRejected; else
{
++gradeRejected;
for(std::size_t segmentIndex=0;segmentIndex<candidateGradeSegments.size();
++segmentIndex)
{
const GradeSegmentAudit& rejected=candidateGradeSegments[segmentIndex];
if(rejected.failures==0)continue;
GradeSegmentAudit& aggregate=placementValidGradeSegments[segmentIndex];
aggregate.failures+=rejected.failures;
if(rejected.maximumGrade>aggregate.maximumGrade)
{
aggregate.maximumGrade=rejected.maximumGrade;
aggregate.fromGround=rejected.fromGround;
aggregate.toGround=rejected.toGround;
aggregate.fromX=rejected.fromX;aggregate.fromY=rejected.fromY;
aggregate.toX=rejected.toX;aggregate.toY=rejected.toY;
}
}
}
}
if(gradeRejected>0||placementRejected>0)
{
const double metresPerSubvoxel=static_cast<double>(coreVoxelSizeMicrons)
/(WorldAssemblySubvoxelsPerVoxel*1000000.0);
std::printf("[WorldAssemblerRouteGradeProfile] tested=%llu grade_fail_candidates=%llu grade_rejected_after_placement=%llu placement_rejected=%llu ground_range_m=%.3f..%.3f grade_limit_deg=15.000\n",
static_cast<unsigned long long>(tested),
static_cast<unsigned long long>(gradeFailCandidates),
static_cast<unsigned long long>(gradeRejected),
static_cast<unsigned long long>(placementRejected),minimumGround,maximumGround);
for(std::size_t segmentIndex=0;segmentIndex<placementValidGradeSegments.size();
++segmentIndex)
{
const GradeSegmentAudit& segment=placementValidGradeSegments[segmentIndex];
if(segment.failures==0)continue;
const double gradeDegrees=std::atan(segment.maximumGrade)*57.29577951308232;
std::printf("[WorldAssemblerRouteGradeSegment] index=%zu rejected_candidates=%llu max_grade_deg=%.3f ground_m=%.3f->%.3f xy_m=(%.3f,%.3f)->(%.3f,%.3f)\n",
segmentIndex,static_cast<unsigned long long>(segment.failures),gradeDegrees,
segment.fromGround*metresPerSubvoxel,segment.toGround*metresPerSubvoxel,
segment.fromX*coreVoxelSizeMicrons/1000000.0,
segment.fromY*coreVoxelSizeMicrons/1000000.0,
segment.toX*coreVoxelSizeMicrons/1000000.0,
segment.toY*coreVoxelSizeMicrons/1000000.0);
}
} }
std::stable_sort(candidates.begin(),candidates.end(),[](const Candidate& a,const Candidate& b) std::stable_sort(candidates.begin(),candidates.end(),[](const Candidate& a,const Candidate& b)
{ {
if(a.endpointProximityCost!=b.endpointProximityCost)
return a.endpointProximityCost<b.endpointProximityCost;
if(a.score!=b.score)return a.score<b.score; if(a.score!=b.score)return a.score<b.score;
if(a.centerY!=b.centerY)return a.centerY<b.centerY; if(a.centerY!=b.centerY)return a.centerY<b.centerY;
if(a.centerX!=b.centerX)return a.centerX<b.centerX; if(a.centerX!=b.centerX)return a.centerX<b.centerX;
@@ -165,6 +357,15 @@ namespace StandaloneWorldAssemblyPrototype
if(liftQ>0) if(liftQ>0)
std::printf("[WorldAssemblerRouteRepaired] uniform_lift_q=%lld support_limit_q=%lld\n", std::printf("[WorldAssemblerRouteRepaired] uniform_lift_q=%lld support_limit_q=%lld\n",
static_cast<long long>(liftQ),static_cast<long long>(SupportDepthQ)); static_cast<long long>(liftQ),static_cast<long long>(SupportDepthQ));
const double metresPerSubvoxel=coreVoxelMetres
/WorldAssemblySubvoxelsPerVoxel;
std::printf("[WorldAssemblerRouteAccepted] arrival_xy_m=(%.3f,%.3f) departure_xy_m=(%.3f,%.3f) endpoint_proximity_cost=%llu average_grade_q16=%lld\n",
candidate.points.front().positionSubvoxels[0]*metresPerSubvoxel,
candidate.points.front().positionSubvoxels[1]*metresPerSubvoxel,
candidate.points.back().positionSubvoxels[0]*metresPerSubvoxel,
candidate.points.back().positionSubvoxels[1]*metresPerSubvoxel,
static_cast<unsigned long long>(candidate.endpointProximityCost),
static_cast<long long>(candidate.score));
return true; return true;
} }
if(audit.blockedCapsuleSamples==0||liftQ>=MaximumRepairLiftQ)break; if(audit.blockedCapsuleSamples==0||liftQ>=MaximumRepairLiftQ)break;
@@ -410,7 +611,8 @@ namespace StandaloneWorldAssemblyPrototype
} }
std::uint64_t routeCandidates=0,routeGradeRejected=0,routePlacementRejected=0,routeSweepRejected=0; std::uint64_t routeCandidates=0,routeGradeRejected=0,routePlacementRejected=0,routeSweepRejected=0;
if(!BuildFiniteStrateRoute(recipe,stratum,routeCandidates,routeGradeRejected, if(!BuildFiniteStrateRoute(recipe,stratum,routeCandidates,routeGradeRejected,
routePlacementRejected,routeSweepRejected,arrivalRadiusQ,departureRadiusQ,error))return false; routePlacementRejected,routeSweepRejected,owner.CoreVoxelSizeMicrons,
arrivalRadiusQ,departureRadiusQ,error))return false;
std::printf("[WorldAssemblerRoutePlan] candidates=%llu grade_rejected=%llu placement_rejected=%llu sweep_rejected=%llu accepted_points=%zu capsule_m=0.34x1.76 corridor_radius_vox=4 support_probe_points=5 minimum_support_probes=%u arrival_radius_m=%.3f departure_radius_m=%.3f status=PASS\n", std::printf("[WorldAssemblerRoutePlan] candidates=%llu grade_rejected=%llu placement_rejected=%llu sweep_rejected=%llu accepted_points=%zu capsule_m=0.34x1.76 corridor_radius_vox=4 support_probe_points=5 minimum_support_probes=%u arrival_radius_m=%.3f departure_radius_m=%.3f status=PASS\n",
static_cast<unsigned long long>(routeCandidates), static_cast<unsigned long long>(routeCandidates),
static_cast<unsigned long long>(routeGradeRejected), static_cast<unsigned long long>(routeGradeRejected),