wip(L27, side branch): passages cross open voids inside shared natural rock columns

Unsupported passage runs > 12.5 m become a solid relief-bearing column (ceiling/island to
ground, flared base) with the helix inside, for every recipe; FI anchor uses the same path.
All 4 styles x both recipes: 0/0/0, 0 open-air, naturalness pass; no-long-bridge audit (L26
fails it). Deterministic, Clang = GCC. Look approved; cost +35% SW / +19% FI blocks merge (L28).

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 04:14:14 +02:00
1 parent 37a223046c
commit 07b3fe2852
14 files changed
+772 -201

No files matched your search

@@ -249,8 +249,8 @@ namespace VoxelForgeCore
// L'assembleur v1 encode coordonnees et scalaires en 1/256 de voxel, independamment des tuiles.
inline constexpr std::int64_t WorldAssemblySubvoxelsPerVoxel = 256;
inline constexpr std::uint32_t WorldAssemblySchemaVersion = 2;
// Version 13 adds connected relief-bearing rock spans across native open-air passage gaps.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 13;
// Version 14 adds shared passage columns for long native open-air crossings.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 14;
enum class FieldChannel : std::uint32_t
{
@@ -666,7 +666,7 @@ namespace VoxelForgeCore
std::vector<ResolvedLayoutPassagePointV1> controlPoints;
};
struct PassageBridgeRangeAuditV1
struct PassageVoidCrossingAuditV1
{
std::size_t passageIndex = 0;
std::size_t firstSegment = 0;
@@ -675,6 +675,17 @@ namespace VoxelForgeCore
double unsupportedLengthMetres = 0.0;
std::array<double, 4> startPointSubvoxels{};
std::array<double, 4> endPointSubvoxels{};
bool needsColumn = false;
bool connectedAtStart = false;
bool connectedAtEnd = false;
std::array<std::int64_t, 2> columnAxisSubvoxels{};
std::int64_t columnTopZSubvoxels = 0;
std::int64_t columnBottomZSubvoxels = 0;
std::int64_t columnMinimumRadiusSubvoxels = 0;
std::int64_t columnNominalRadiusSubvoxels = 0;
std::int64_t columnMaximumRadiusSubvoxels = 0;
double maximumRouteOffsetMetres = 0.0;
double maximumBoreRadiusMetres = 0.0;
};
struct ResolvedLayoutPassageConfigV1
@@ -1325,10 +1336,12 @@ namespace VoxelForgeCore
ShapeBuildStats buildStats() const;
float densityAt(Vec3d voxelPosition) const;
// Audit-only view of connected rock spans planned for passage support.
std::vector<PassageBridgeRangeAuditV1> passageBridgeRanges() const;
bool isPassageBridgeSample(std::size_t passageIndex, std::size_t segmentIndex,
Vec3d voxelPosition) const;
// Audit-only view of density-field columns and short spans supporting passage voids.
std::vector<PassageVoidCrossingAuditV1> passageVoidCrossings() const;
bool isPassageColumnSample(std::size_t passageIndex, std::size_t segmentIndex,
Vec3d voxelPosition) const;
bool isPassageShortSpanSample(std::size_t passageIndex, std::size_t segmentIndex,
Vec3d voxelPosition) const;
// Audit-only selector provenance for the same point evaluator; never used by meshing.
std::string densityDispatchPathAt(Vec3d voxelPosition) const;
// Analytic source distance without the occupancy-preserving near-zero clamp or packed proxy.
@@ -281,7 +281,7 @@ namespace floating_island_detail
? recipe.ownerVoxelSizeMicrons / ScaleGcd : 0;
const std::uint32_t ExpectedDenominator = ScaleGcd > 0
? recipe.coreVoxelSizeMicrons / ScaleGcd : 0;
if (recipe.schemaVersion != 1 || recipe.geometryVersion < 1 || recipe.geometryVersion > 7
if (recipe.schemaVersion != 1 || recipe.geometryVersion < 1 || recipe.geometryVersion > 8
|| (recipe.geometryVersion == 1
&& (recipe.crustDepthBonusQ16 != 0 || recipe.rootDepthRatioQ16 != 0))
|| recipe.unitsPerVoxel != Q
@@ -753,7 +753,8 @@ namespace floating_island_detail
const double rootBlend = std::clamp(radius * 0.12, 2.0 * Q, 5.0 * Q);
for (std::int32_t root = 0; root < rootCount; ++root)
sdf = SmoothMin(sdf, RootLobeDensity(recipe, island, root, x, y, z), rootBlend);
if (recipe.geometryVersion >= 5 && island.ordinal == recipe.anchorIslandOrdinal
if (recipe.geometryVersion >= 5 && recipe.geometryVersion < 8
&& island.ordinal == recipe.anchorIslandOrdinal
&& recipe.anchorRootBottomZSubvoxels < island.bottomZSubvoxels)
{
// The central buttress must meet the island crust underside. IslandBottom
@@ -944,14 +945,14 @@ namespace floating_island_detail
FloatingIslandAnchorV1& island)
{
const std::int64_t pad = IslandBlendMargin(recipe) + recipe.roughnessSubvoxels;
const bool isAnchor=recipe.geometryVersion>=5
const bool isAnchorRoot=recipe.geometryVersion>=5&&recipe.geometryVersion<8
&&island.ordinal==recipe.anchorIslandOrdinal;
const std::int64_t reach = std::max(island.radiusSubvoxels,
isAnchor?recipe.anchorRootRadiusSubvoxels:std::int64_t{0})
isAnchorRoot?recipe.anchorRootRadiusSubvoxels:std::int64_t{0})
+ recipe.contourWarpSubvoxels + pad;
island.influenceMinimumSubvoxels = {island.centerSubvoxels[0] - reach,
island.centerSubvoxels[1] - reach,
(isAnchor?std::min(island.bottomZSubvoxels,recipe.anchorRootBottomZSubvoxels)
(isAnchorRoot?std::min(island.bottomZSubvoxels,recipe.anchorRootBottomZSubvoxels)
:island.bottomZSubvoxels)-pad};
island.influenceMaximumSubvoxels = {island.centerSubvoxels[0] + reach,
island.centerSubvoxels[1] + reach, island.topZSubvoxels + pad};
@@ -1026,14 +1027,15 @@ namespace floating_island_detail
{ error = "floating-island anchor has invalid coordinates or an inverted bound"; return false; }
}
const std::int64_t pad = IslandBlendMargin(recipe) + recipe.roughnessSubvoxels;
const bool hasAnchorRoot=recipe.geometryVersion>=5&&recipe.geometryVersion<8&&isAnchor;
const std::int64_t reach = std::max(island.radiusSubvoxels,
isAnchor?recipe.anchorRootRadiusSubvoxels:std::int64_t{0})
hasAnchorRoot?recipe.anchorRootRadiusSubvoxels:std::int64_t{0})
+ recipe.contourWarpSubvoxels + pad;
if (island.influenceMinimumSubvoxels[0] > island.centerSubvoxels[0] - reach
|| island.influenceMaximumSubvoxels[0] < island.centerSubvoxels[0] + reach
|| island.influenceMinimumSubvoxels[1] > island.centerSubvoxels[1] - reach
|| island.influenceMaximumSubvoxels[1] < island.centerSubvoxels[1] + reach
|| island.influenceMinimumSubvoxels[2] > (isAnchor
|| island.influenceMinimumSubvoxels[2] > (hasAnchorRoot
?std::min(island.bottomZSubvoxels,recipe.anchorRootBottomZSubvoxels)
:island.bottomZSubvoxels) - pad
|| island.influenceMaximumSubvoxels[2] < island.topZSubvoxels + pad
+282 -76
View File
@@ -41,27 +41,31 @@ public:
double SealThickness=0.0;
};
const std::vector<FStandalonePassageBridgeRange>& GetPassageBridgeRanges() const
{return PassageBridgeRanges;}
const std::vector<FStandalonePassageVoidCrossing>& GetPassageVoidCrossings() const
{return PassageVoidCrossings;}
bool IsResolvedPassageBridgeSample(std::size_t PassageIndex,std::size_t SegmentIndex,
bool IsResolvedPassageColumnSample(std::size_t PassageIndex,std::size_t SegmentIndex,
const VoxelForgeCore::Vec3d& Position) const
{
if(IsPassageBridgeSegment(PassageIndex,SegmentIndex)
&&PassageBridgeSignedDistance(PassageIndex,SegmentIndex,
static_cast<float>(Position.x),static_cast<float>(Position.y),
static_cast<float>(Position.z))<=0.0)return true;
for(const auto& range:PassageBridgeRanges)
(void)SegmentIndex;
for(const auto& range:PassageVoidCrossings)
{
if(range.passageIndex!=PassageIndex)continue;
for(std::size_t segment=range.firstSegment;segment<=range.lastSegment;++segment)
if(segment!=SegmentIndex&&PassageBridgeSignedDistance(PassageIndex,segment,
static_cast<float>(Position.x),static_cast<float>(Position.y),
static_cast<float>(Position.z))<=0.0)return true;
if(!range.needsColumn||range.passageIndex!=PassageIndex)continue;
if(PassageColumnSignedDistance(range,static_cast<float>(Position.x),
static_cast<float>(Position.y),static_cast<float>(Position.z))<=0.0)return true;
}
return false;
}
bool IsResolvedPassageShortSpanSample(std::size_t PassageIndex,std::size_t SegmentIndex,
const VoxelForgeCore::Vec3d& Position) const
{
return IsPassageShortSpanSegment(PassageIndex,SegmentIndex)
&&PassageBridgeSignedDistance(PassageIndex,SegmentIndex,
static_cast<float>(Position.x),static_cast<float>(Position.y),
static_cast<float>(Position.z))<=0.0;
}
double GetCoreVoxelSizeCm() const
{
return Owner == nullptr || Owner->CoreVoxelSizeMicrons == 0
@@ -197,6 +201,13 @@ public:
-passage.controlPoints.front().radiusSubvoxels+playerCenterAboveFloorQ;
const double lastFloorQ=passage.controlPoints.back().positionSubvoxels[2]
-passage.controlPoints.back().radiusSubvoxels+playerCenterAboveFloorQ;
for(const auto& crossing:PassageVoidCrossings)
{
if(!crossing.needsColumn||crossing.passageIndex!=passageIndex
||qz>crossing.topZSubvoxels||qz<crossing.bottomZSubvoxels)continue;
const double columnDistance=PassageColumnSignedDistance(crossing,X,Y,Z);
composed=std::min(composed,static_cast<float>(columnDistance/Q));
}
if(qz>firstFloorQ+2.0*passage.mouthRadiusSubvoxels
||qz<lastFloorQ-2.0*passage.mouthRadiusSubvoxels)
{
@@ -297,7 +308,7 @@ public:
const double wallReliefWeight=1.0-0.80*verticalWallAlignment;
const double roughSignedDistance=bestSignedDistance
+static_cast<double>(std::clamp(relief,-1.0f,1.0f))*0.24*qPerMetre*wallReliefWeight;
if(IsPassageBridgeSegment(passageIndex,static_cast<std::size_t>(bestIndex)))
if(IsPassageShortSpanSegment(passageIndex,static_cast<std::size_t>(bestIndex)))
{
const double bridgeDistance=PassageBridgeSignedDistance(passageIndex,
static_cast<std::size_t>(bestIndex),X,Y,Z);
@@ -317,8 +328,9 @@ public:
const double radiusB=segmentB.radiusSubvoxels;
// Keep the tread within the probe band and below the capsule's
// lowest sampled point.
const double floorOffset=IsPassageBridgeSegment(passageIndex,
const double floorOffset=IsPassageShortSpanSegment(passageIndex,
static_cast<std::size_t>(index))
||IsPassageColumnSegment(passageIndex,static_cast<std::size_t>(index))
?PassageBridgeDeckOffsetMetres(passageIndex,static_cast<std::size_t>(index))
:0.20;
const double horizontalLengthSq=dx*dx+dy*dy;
@@ -387,11 +399,14 @@ public:
considerSupportSegment(index);
// Keep route treads inside the native rock envelope. Carving may reopen the
// floor above this point, but a support cannot create a new surface in air.
const bool bridgeFloorSupport=hasSupportFloor
&&IsPassageBridgeSegment(passageIndex,
const bool passageColumnFloorSupport=hasSupportFloor
&&IsPassageColumnSegment(passageIndex,
static_cast<std::size_t>(bestSupportSegmentIndex));
const bool shortSpanFloorSupport=hasSupportFloor
&&IsPassageShortSpanSegment(passageIndex,
static_cast<std::size_t>(bestSupportSegmentIndex));
if(hasSupportFloor&&bestPlayerCapsuleSignedDistance>=0.05*qPerMetre
&&(density<0.0f||bridgeFloorSupport))
&&(density<0.0f||passageColumnFloorSupport||shortSpanFloorSupport))
composed=std::min(composed,static_cast<float>(bestSupportDensity));
}
return composed;
@@ -416,9 +431,8 @@ public:
const double radius=static_cast<double>(std::max(a.radiusSubvoxels,b.radiusSubvoxels))/Q;
const double floorThicknessVoxels=Owner&&Owner->CoreVoxelSizeMicrons>0
?1000000.0/Owner->CoreVoxelSizeMicrons:4.0;
// A resolved passage bridge extends to a 3.5 m half-width and almost 5 m
// below the bore floor. Keep those cells shape-dependent for classification
// and streaming even before its bridge ranges have been compiled.
// Short support spans can extend to a 3.5 m half-width and almost 5 m
// below the bore floor. Keep those cells shape-dependent for classification.
const double horizontalExtent=std::max(radius,bridgeHalfWidthVoxels);
const double footDepth=std::max(floorThicknessVoxels,bridgeFootDepthVoxels);
const double low[3]={
@@ -435,6 +449,19 @@ public:
if(overlap)return true;
}
}
for(const auto& crossing:PassageVoidCrossings)
{
if(!crossing.needsColumn)continue;
const double radius=static_cast<double>(crossing.maximumRadiusSubvoxels)/Q;
const double low[3]={crossing.centerXSubvoxels/Q-radius,
crossing.centerYSubvoxels/Q-radius,crossing.bottomZSubvoxels/Q};
const double high[3]={crossing.centerXSubvoxels/Q+radius,
crossing.centerYSubvoxels/Q+radius,crossing.topZSubvoxels/Q};
bool overlap=true;
for(int axis=0;axis<3;++axis)
overlap&=high[axis]>=minimum[axis]&&low[axis]<=maximum[axis];
if(overlap)return true;
}
return false;
}
@@ -785,8 +812,10 @@ public:
if(RoundTunnelsEnabled)
BuildRoundTunnelPrimitives();
BuildSpatialBins(LineBinSize);
BuildPassageBridgePlan();
Stats.LocalLineBinSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
const auto SharedStage=Clock::now();
RebuildSharedFieldPrimitives();
Stats.SharedFieldSeconds=std::chrono::duration<double>(Clock::now()-SharedStage).count();
Stats.ShapeSeconds=std::chrono::duration<double>(Clock::now()-Stage).count();
Stats.PrimitiveCount=Primitives.size();
if(Primitives.empty())
@@ -797,6 +826,10 @@ public:
RockWords.assign(static_cast<size_t>(Size[0])*Size[1]*WordsPerZ,0);
SurfaceDistanceQ=std::make_unique_for_overwrite<int16[]>(static_cast<size_t>(NodeCount));
BuildPackedRockIntervals(Stats.RockIntervalLines);
// Native density queries for non-heightfield strates use the exact interval
// evaluator. Build those native intervals before scanning passage support;
// the scan itself still completes before any resolved column is composed.
BuildPassageVoidCrossingPlan();
BuildCandidateBands(Stats.CandidateAxisLines,Stats.CandidateMergeLines,
Stats.CandidateMergeSeconds);
if(!BuildGpuVisualDetailNodeSets(InGpuVisualDetailTiles,InCpuVisualDetailTiles,Error))
@@ -820,9 +853,6 @@ public:
return false;
}
Stats.PassageValidationSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
Substage=Clock::now();
RebuildSharedFieldPrimitives();
Stats.SharedFieldSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
Built=true;
if(bIncludeFarWorld)BuildFarWorld();
const uint64 WordBytes=static_cast<uint64>(RockWords.size()+CandidateWords.size())*sizeof(uint64);
@@ -1693,23 +1723,27 @@ public:
}
private:
bool IsPassageBridgeSegment(std::size_t PassageIndex,std::size_t SegmentIndex) const
bool IsPassageColumnSegment(std::size_t PassageIndex,std::size_t SegmentIndex) const
{
return std::any_of(PassageBridgeRanges.begin(),PassageBridgeRanges.end(),
[PassageIndex,SegmentIndex](const auto& range)
{return range.passageIndex==PassageIndex
&&SegmentIndex>=range.firstSegment&&SegmentIndex<=range.lastSegment;});
return std::any_of(PassageVoidCrossings.begin(),PassageVoidCrossings.end(),
[PassageIndex,SegmentIndex](const auto& crossing)
{return crossing.needsColumn&&crossing.passageIndex==PassageIndex
&&SegmentIndex>=crossing.firstSegment&&SegmentIndex<=crossing.lastSegment;});
}
bool IsPassageShortSpanSegment(std::size_t PassageIndex,std::size_t SegmentIndex) const
{
return std::any_of(PassageVoidCrossings.begin(),PassageVoidCrossings.end(),
[PassageIndex,SegmentIndex](const auto& crossing)
{return !crossing.needsColumn&&crossing.passageIndex==PassageIndex
&&SegmentIndex>=crossing.firstSegment&&SegmentIndex<=crossing.lastSegment;});
}
double PassageBridgeDeckOffsetMetres(std::size_t PassageIndex,
std::size_t SegmentIndex) const
{
for(const auto& range:PassageBridgeRanges)
{
if(range.passageIndex!=PassageIndex||SegmentIndex>range.lastSegment)continue;
if(SegmentIndex>=range.firstSegment)return 0.13;
}
return 0.20;
(void)PassageIndex;(void)SegmentIndex;
return 0.13;
}
double PassageBridgeSignedDistance(std::size_t PassageIndex,std::size_t SegmentIndex,
@@ -1760,6 +1794,109 @@ private:
return outside+inside;
}
double PassageColumnSignedDistance(const FStandalonePassageVoidCrossing& crossing,
float X,float Y,float Z) const
{
if(crossing.maximumRadiusSubvoxels<=0||crossing.topZSubvoxels
<=crossing.bottomZSubvoxels)return std::numeric_limits<double>::infinity();
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
const double qPerMetre=Q*1000000.0/std::max<std::uint32_t>(1,
ResolvedLayout?ResolvedLayout->coreVoxelSizeMicrometres:250000u);
const double qx=static_cast<double>(X)*Q,qy=static_cast<double>(Y)*Q,
qz=static_cast<double>(Z)*Q;
const double dx=qx-crossing.centerXSubvoxels;
const double dy=qy-crossing.centerYSubvoxels;
const double maximumRadius=static_cast<double>(crossing.maximumRadiusSubvoxels);
const double horizontalSquared=dx*dx+dy*dy;
if(horizontalSquared>maximumRadius*maximumRadius)
return DeterministicSqrt(horizontalSquared)-maximumRadius;
if(qz>crossing.topZSubvoxels)
return qz-crossing.topZSubvoxels;
if(qz<crossing.bottomZSubvoxels)
return crossing.bottomZSubvoxels-qz;
// The lower-strate route is already walkable in its native field and binds
// directly to the passage mouth. Preserve that player capsule as the column
// flares into the ground, so the pillar joins the route instead of sealing it.
if(ResolvedLayout&&crossing.passageIndex<ResolvedLayout->passages.size()
&&qz<crossing.bottomZSubvoxels+18.0*qPerMetre)
{
const auto& passage=ResolvedLayout->passages[crossing.passageIndex];
const auto lower=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[&](const auto& value)
{return value.strateIndex==passage.lowerStrateIndex;});
if(lower!=ResolvedLayout->strates.end())
{
const double capsuleRadius=0.37*qPerMetre;
const double capsuleHalfHeight=0.86*qPerMetre;
const double capsuleRadiusSquared=capsuleRadius*capsuleRadius;
const VoxelForgeCore::ResolvedLayoutAnchorV2* previous=nullptr;
for(const auto& anchor:lower->anchors)
{
if(anchor.kind!="route_point"||anchor.values.size()<3)continue;
if(previous)
{
const double ax=previous->values[0],ay=previous->values[1];
const double dx=static_cast<double>(anchor.values[0])-ax;
const double dy=static_cast<double>(anchor.values[1])-ay;
const double lengthSquared=dx*dx+dy*dy;
const double t=lengthSquared>0.0?std::clamp(
((qx-ax)*dx+(qy-ay)*dy)/lengthSquared,0.0,1.0):0.0;
const double routeX=ax+t*dx,routeY=ay+t*dy;
const double routeZ=previous->values[2]+t*(
static_cast<double>(anchor.values[2])-previous->values[2]);
const double routeDx=qx-routeX,routeDy=qy-routeY;
if(routeDx*routeDx+routeDy*routeDy<=capsuleRadiusSquared
&&std::abs(qz-routeZ)<=capsuleHalfHeight)
return maximumRadius+qPerMetre;
}
previous=&anchor;
}
}
}
const double height=static_cast<double>(crossing.topZSubvoxels
-crossing.bottomZSubvoxels);
const double t=std::clamp((crossing.topZSubvoxels-qz)/height,0.0,1.0);
const auto smoothStep=[](double value)
{
value=std::clamp(value,0.0,1.0);
return value*value*(3.0-2.0*value);
};
const float z=static_cast<float>(Z);
const float scaledZ=z*0.12f;
const float driftX=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ,
static_cast<std::uint32_t>(Owner?Owner->Seed:0)^0x434f4c58u);
const float driftY=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ,
static_cast<std::uint32_t>(Owner?Owner->Seed:0)^0x434f4c59u);
const double axisX=crossing.centerXSubvoxels
+std::clamp(static_cast<double>(driftX),-1.0,1.0)*0.35*qPerMetre;
const double axisY=crossing.centerYSubvoxels
+std::clamp(static_cast<double>(driftY),-1.0,1.0)*0.35*qPerMetre;
const double centerDx=qx-axisX,centerDy=qy-axisY;
const double radialDistance=DeterministicSqrt(centerDx*centerDx+centerDy*centerDy);
const float broadRelief=VF_FieldSurfaceRelief(X*0.12f,Y*0.12f,Z*0.12f,
static_cast<std::uint32_t>(Owner?Owner->Seed:0)^0x434f4c52u);
const float surfaceRelief=VF_FieldSurfaceRelief(X,Y,Z,
static_cast<std::uint32_t>(Owner?Owner->Seed:0)^0x434f4c53u);
const double baseFlare=6.0*qPerMetre*smoothStep((t-0.82)/0.18);
const double ceilingFlare=2.0*qPerMetre*(1.0-smoothStep(t/0.075));
const double irregularity=1.25*qPerMetre
+std::clamp(static_cast<double>(broadRelief),-1.0,1.0)*1.10*qPerMetre
+std::clamp(static_cast<double>(surfaceRelief),-1.0,1.0)*0.35*qPerMetre;
const double radius=static_cast<double>(crossing.minimumRadiusSubvoxels)
+std::max(0.15*qPerMetre,irregularity)+baseFlare+ceilingFlare;
const double radialDistanceField=radialDistance-radius;
const double topDistance=qz-crossing.topZSubvoxels;
const double bottomDistance=crossing.bottomZSubvoxels-qz;
const double verticalDistance=std::max(topDistance,bottomDistance);
const double outside=DeterministicSqrt(
std::max(radialDistanceField,0.0)*std::max(radialDistanceField,0.0)
+std::max(verticalDistance,0.0)*std::max(verticalDistance,0.0));
const double inside=std::min(std::max(radialDistanceField,verticalDistance),0.0);
return outside+inside;
}
float NativePassageDensityAt(float X,float Y,float Z) const
{
float density=0.0f;
@@ -1775,33 +1912,25 @@ private:
return ApplyResolvedStrateBoundaryBand(density,X,Y,Z);
}
void BuildPassageBridgePlan()
void BuildPassageVoidCrossingPlan()
{
PassageBridgeRanges.clear();
PassageVoidCrossings.clear();
if(!Owner||!ResolvedLayout||ResolvedLayout->passages.empty()
||!Owner->PassageBridgeCache)return;
auto& cache=*Owner->PassageBridgeCache;
||!Owner->PassageVoidCrossingCache)return;
auto& cache=*Owner->PassageVoidCrossingCache;
std::lock_guard<std::mutex> lock(cache.mutex);
const auto cached=cache.byLayout.find(ResolvedLayout->stableIdentity);
const std::string cacheKey=ResolvedLayout->stableIdentity+"/passage-void-columns-v1";
const auto cached=cache.byLayout.find(cacheKey);
if(cached!=cache.byLayout.end())
{PassageBridgeRanges=cached->second;return;}
{PassageVoidCrossings=cached->second;return;}
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
const double qPerMetre=Q*1000000.0/std::max<std::uint32_t>(1,
ResolvedLayout->coreVoxelSizeMicrometres);
const auto inSurfaceWorldStratum=[&](double zSubvoxels)
{
const double zMicrometres=zSubvoxels
*ResolvedLayout->coreVoxelSizeMicrometres/Q;
return std::any_of(ResolvedLayout->strates.begin(),ResolvedLayout->strates.end(),
[zMicrometres](const auto& stratum)
{return stratum.generatorKind=="SurfaceWorld"
&&zMicrometres>=stratum.interiorBottomMicrometres
&&zMicrometres<stratum.interiorTopMicrometres;});
};
constexpr std::array<std::array<double,2>,5> supportOffsets{{
{{0.0,0.0}},{{0.45,0.0}},{{-0.45,0.0}},{{0.0,0.45}},{{0.0,-0.45}}}};
constexpr std::array<double,2> supportDepthsMetres{{0.125,0.25}};
constexpr double shortSpanMaximumMetres=12.5; // 2.5 x the 5 m legacy support thickness.
struct FPathSample
{
std::size_t segment=0;
@@ -1818,14 +1947,10 @@ private:
for(const double depth:supportDepthsMetres)
{
const double sampleZ=floorQ-depth*qPerMetre;
// Bridge spans address the measured SurfaceWorld void. Other native
// strata retain their own route/cave composition and are excluded here.
if(!inSurfaceWorldStratum(sampleZ)){hasSolid=true;break;}
float density=1.0f;
if(!NativeSurfaceDensityAt(
const float density=NativePassageDensityAt(
static_cast<float>((point[0]+offset[0]*qPerMetre)/Q),
static_cast<float>((point[1]+offset[1]*qPerMetre)/Q),
static_cast<float>(sampleZ/Q),density))continue;
static_cast<float>(sampleZ/Q));
if(density<0.0f){hasSolid=true;break;}
}
supported+=hasSolid;
@@ -1874,9 +1999,10 @@ private:
const std::size_t gapBegin=cursor;
while(cursor<samples.size()&&!samples[cursor].nativeSupported)++cursor;
const std::size_t gapEnd=cursor-1;
if(gapBegin==0||cursor>=samples.size())continue;
const std::size_t startSample=gapBegin>0?gapBegin-1:gapBegin;
const std::size_t endSample=cursor<samples.size()?cursor:samples.size()-1;
double gapLength=0.0;
for(std::size_t index=gapBegin;index<=gapEnd;++index)
for(std::size_t index=startSample+1;index<=endSample;++index)
{
const auto& a=samples[index-1].point;
const auto& b=samples[index].point;
@@ -1884,25 +2010,105 @@ private:
gapLength+=DeterministicSqrt(dx*dx+dy*dy+dz*dz)/qPerMetre;
}
if(gapLength<1.0)continue;
FStandalonePassageBridgeRange range;
range.passageIndex=passageIndex;
range.firstSegment=samples[gapBegin-1].segment;
range.lastSegment=samples[cursor].segment;
range.unsupportedSamples=gapEnd-gapBegin+1;
range.unsupportedLengthMetres=gapLength;
range.startPoint=samples[gapBegin-1].point;
range.endPoint=samples[cursor].point;
PassageBridgeRanges.push_back(range);
std::printf("[PassageRockBridgePlan] id=%s first_segment=%zu last_segment=%zu unsupported_samples=%llu gap_length_m=%.3f connected_start=1 connected_end=1 width_m=6.000 thickness_m=3.000..5.000 status=PLANNED\n",
passage.stableId.c_str(),range.firstSegment,range.lastSegment,
static_cast<unsigned long long>(range.unsupportedSamples),gapLength);
FStandalonePassageVoidCrossing crossing;
crossing.passageIndex=passageIndex;
crossing.firstSegment=samples[startSample].segment;
crossing.lastSegment=samples[endSample].segment;
crossing.unsupportedSamples=gapEnd-gapBegin+1;
crossing.unsupportedLengthMetres=gapLength;
crossing.startPoint=samples[startSample].point;
crossing.endPoint=samples[endSample].point;
crossing.connectedAtStart=gapBegin>0&&samples[startSample].nativeSupported;
crossing.connectedAtEnd=cursor<samples.size()&&samples[endSample].nativeSupported;
crossing.needsColumn=gapLength>shortSpanMaximumMetres;
if(crossing.needsColumn&&passage.controlPoints.size()>1)
crossing.lastSegment=std::min(crossing.lastSegment+1,
passage.controlPoints.size()-2);
if(crossing.needsColumn)
{
std::int64_t sumX=0,sumY=0;
std::uint64_t centerSamples=0;
for(std::size_t index=gapBegin;index<=gapEnd;++index)
{
sumX+=static_cast<std::int64_t>(std::llround(samples[index].point[0]));
sumY+=static_cast<std::int64_t>(std::llround(samples[index].point[1]));
++centerSamples;
}
crossing.centerXSubvoxels=centerSamples>0
?static_cast<std::int64_t>(std::llround(static_cast<double>(sumX)/centerSamples)):0;
crossing.centerYSubvoxels=centerSamples>0
?static_cast<std::int64_t>(std::llround(static_cast<double>(sumY)/centerSamples)):0;
for(const auto& stratum:ResolvedLayout->strates)
if(stratum.strateIndex==passage.upperStrateIndex
&&stratum.generatorKind=="FloatingIslands")
for(const auto& anchor:stratum.anchors)
if(anchor.kind=="passage_anchor"&&anchor.values.size()>=2)
{
crossing.centerXSubvoxels=anchor.values[0];
crossing.centerYSubvoxels=anchor.values[1];
break;
}
double maximumOffsetSubvoxels=0.0;
double maximumBoreSubvoxels=0.0;
for(std::size_t index=startSample;index<=endSample;++index)
{
const auto& point=samples[index].point;
const double dx=point[0]-crossing.centerXSubvoxels;
const double dy=point[1]-crossing.centerYSubvoxels;
maximumOffsetSubvoxels=std::max(maximumOffsetSubvoxels,
DeterministicSqrt(dx*dx+dy*dy));
maximumBoreSubvoxels=std::max(maximumBoreSubvoxels,point[3]);
}
const double maximumOffsetMetres=maximumOffsetSubvoxels/qPerMetre;
const double maximumBoreMetres=maximumBoreSubvoxels/qPerMetre;
const double minimumRadiusMetres=maximumOffsetMetres+maximumBoreMetres+2.0;
const double nominalRadiusMetres=minimumRadiusMetres+1.25;
crossing.maximumRouteOffsetMetres=maximumOffsetMetres;
crossing.maximumBoreRadiusMetres=maximumBoreMetres;
crossing.minimumRadiusSubvoxels=static_cast<std::int64_t>(std::ceil(
minimumRadiusMetres*qPerMetre));
crossing.nominalRadiusSubvoxels=static_cast<std::int64_t>(std::llround(
nominalRadiusMetres*qPerMetre));
crossing.maximumRadiusSubvoxels=crossing.minimumRadiusSubvoxels
+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(
std::max(startZ,endZ)+5.0*qPerMetre));
crossing.bottomZSubvoxels=static_cast<std::int64_t>(std::llround(
std::min(startZ,endZ)-6.0*qPerMetre));
}
PassageVoidCrossings.push_back(crossing);
if(crossing.needsColumn)
{
const double coreRadius=crossing.nominalRadiusSubvoxels/qPerMetre;
const double minimumWall=coreRadius-crossing.maximumRouteOffsetMetres
-crossing.maximumBoreRadiusMetres;
std::printf("[PassageVoidColumnPlan] id=%s segments=%zu..%zu unsupported_samples=%llu span_m=%.3f threshold_m=%.3f connected=%d/%d axis_m=(%.3f,%.3f) z_m=%.3f..%.3f route_radius_m=%.3f bore_radius_m=%.3f min_radius_m=%.3f nominal_radius_m=%.3f max_radius_m=%.3f nominal_wall_m=%.3f flare_m=6.000 status=%s\n",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
static_cast<unsigned long long>(crossing.unsupportedSamples),gapLength,
shortSpanMaximumMetres,static_cast<int>(crossing.connectedAtStart),
static_cast<int>(crossing.connectedAtEnd),
crossing.centerXSubvoxels/qPerMetre,crossing.centerYSubvoxels/qPerMetre,
crossing.topZSubvoxels/qPerMetre,crossing.bottomZSubvoxels/qPerMetre,
crossing.maximumRouteOffsetMetres,crossing.maximumBoreRadiusMetres,
crossing.minimumRadiusSubvoxels/qPerMetre,coreRadius,
crossing.maximumRadiusSubvoxels/qPerMetre,minimumWall,
crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED");
}
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",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
gapLength,shortSpanMaximumMetres,static_cast<int>(crossing.connectedAtStart),
static_cast<int>(crossing.connectedAtEnd),
crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED");
}
if(std::none_of(PassageBridgeRanges.begin(),PassageBridgeRanges.end(),
if(std::none_of(PassageVoidCrossings.begin(),PassageVoidCrossings.end(),
[passageIndex](const auto& range){return range.passageIndex==passageIndex;}))
std::printf("[PassageRockBridgePlan] id=%s spans=0 status=NOT_REQUIRED\n",
std::printf("[PassageVoidColumnPlan] id=%s crossings=0 status=NOT_REQUIRED\n",
passage.stableId.c_str());
}
cache.byLayout.emplace(ResolvedLayout->stableIdentity,PassageBridgeRanges);
cache.byLayout.emplace(cacheKey,PassageVoidCrossings);
}
static uint64 PackLatticeKey(int32 X,int32 Y,int32 Z)
@@ -6151,7 +6357,7 @@ private:
std::vector<FFarConnectorSegment> FarConnectorSegments;
std::unordered_map<FBinKey,std::vector<uint32>,FBinHash> FarConnectorSpatialBins;
std::vector<FEditBrush> EditBrushes;
std::vector<FStandalonePassageBridgeRange> PassageBridgeRanges;
std::vector<FStandalonePassageVoidCrossing> PassageVoidCrossings;
std::array<FAxisBins,3> AxisBins;
std::unordered_map<FBinKey,FBinItems,FBinHash> SpatialBins;
std::unordered_map<FBinKey,FBinItems,FBinHash> CriticalAirBins;
+28 -12
View File
@@ -1542,27 +1542,43 @@ namespace VoxelForgeCore
float World::densityAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->DensityAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):0.0f; }
std::vector<PassageBridgeRangeAuditV1> World::passageBridgeRanges() const
std::vector<PassageVoidCrossingAuditV1> World::passageVoidCrossings() const
{
std::vector<PassageBridgeRangeAuditV1> result;
std::vector<PassageVoidCrossingAuditV1> result;
if(!impl_||!impl_->shapeReady.load(std::memory_order_acquire)||!impl_->shape)return result;
const auto& ranges=impl_->shape->GetPassageBridgeRanges();
result.reserve(ranges.size());
for(const auto& range:ranges)
const auto& crossings=impl_->shape->GetPassageVoidCrossings();
result.reserve(crossings.size());
for(const auto& crossing:crossings)
{
PassageBridgeRangeAuditV1 value;
value.passageIndex=range.passageIndex;value.firstSegment=range.firstSegment;
value.lastSegment=range.lastSegment;value.unsupportedSamples=range.unsupportedSamples;
value.unsupportedLengthMetres=range.unsupportedLengthMetres;
value.startPointSubvoxels=range.startPoint;value.endPointSubvoxels=range.endPoint;
PassageVoidCrossingAuditV1 value;
value.passageIndex=crossing.passageIndex;value.firstSegment=crossing.firstSegment;
value.lastSegment=crossing.lastSegment;value.unsupportedSamples=crossing.unsupportedSamples;
value.unsupportedLengthMetres=crossing.unsupportedLengthMetres;
value.startPointSubvoxels=crossing.startPoint;value.endPointSubvoxels=crossing.endPoint;
value.needsColumn=crossing.needsColumn;
value.connectedAtStart=crossing.connectedAtStart;
value.connectedAtEnd=crossing.connectedAtEnd;
value.columnAxisSubvoxels={crossing.centerXSubvoxels,crossing.centerYSubvoxels};
value.columnTopZSubvoxels=crossing.topZSubvoxels;
value.columnBottomZSubvoxels=crossing.bottomZSubvoxels;
value.columnMinimumRadiusSubvoxels=crossing.minimumRadiusSubvoxels;
value.columnNominalRadiusSubvoxels=crossing.nominalRadiusSubvoxels;
value.columnMaximumRadiusSubvoxels=crossing.maximumRadiusSubvoxels;
value.maximumRouteOffsetMetres=crossing.maximumRouteOffsetMetres;
value.maximumBoreRadiusMetres=crossing.maximumBoreRadiusMetres;
result.push_back(value);
}
return result;
}
bool World::isPassageBridgeSample(std::size_t passageIndex,std::size_t segmentIndex,
bool World::isPassageColumnSample(std::size_t passageIndex,std::size_t segmentIndex,
Vec3d position) const
{return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape
&&impl_->shape->IsResolvedPassageBridgeSample(passageIndex,segmentIndex,
&&impl_->shape->IsResolvedPassageColumnSample(passageIndex,segmentIndex,
{position.x,position.y,position.z});}
bool World::isPassageShortSpanSample(std::size_t passageIndex,std::size_t segmentIndex,
Vec3d position) const
{return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape
&&impl_->shape->IsResolvedPassageShortSpanSample(passageIndex,segmentIndex,
{position.x,position.y,position.z});}
std::string World::densityDispatchPathAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape
@@ -0,0 +1,179 @@
# VoxelForge L27 — passage voids inside rock columns
## Owner summary
The SurfaceWorld passage now drops from the ceiling (about −138 to −143 m) to terrain near
−505 m inside one continuous, relief-bearing rock column. Its helix is cut inside the column; the
~2 km route no longer crosses the open sky as a bridge. FloatingIslands uses the same field and
planner path: the passage descends inside a column from its island to the bedrock floor. Styles 1
and 3 have a second, smaller cap crossing, so they get a second column. The FI style-0 anchor stays
at the L25 axis and remains connected. Its shared column is slimmer (11.25 m nominal radius vs
L25's 13.25 m) with a larger measured wall margin (3.25 m vs 1.938 m), visible in the new
exterior capture.
All four styles in both recipes pass on Clang and GCC: 0 blocked, 0 unsupported, 0 grade failures,
0 open-air violations, and naturalness passes. The new no-long-bridge audit detects the L26
SurfaceWorld bridge as its negative control.
## Column rule and size
The shared planner samples native support every 0.5 m. A contiguous unsupported route run longer
than **12.5 m** becomes one column; this is 2.5 times the former 5 m support-thickness limit. A
shorter span is allowed only while grounded. The column is a solid signed-distance union in the
shared composition field, so terrain queries, collision and meshes all see the same rock. The
recipe still chooses passage style; the helix applies inside a column and that style continues
outside it.
The minimum planned outer radius is maximum route offset + bore radius + 2 m; the nominal profile
adds 1.25 m. The base flares by up to 6 m and the ceiling end by up to 2 m; bounds extend 6 m
below and 5 m above the unsupported run to overlap the native rock. Measured wall margin is 1.75 m
minimum in SW and 3.0 m minimum in FI, above the 1.5 m requirement. SW columns span about
363–368 m vertically and have nominal radii 19.744–27.027 m. FI main columns span about 53–57 m
with nominal radii 9.251–12.746 m; styles 1 and 3 also have ~14 m cap columns.
| Recipe / style | Unsupported route run(s) | Column nominal radius; audited profile radius | Minimum wall |
|---|---:|---:|---:|
| SW 0 Straight | 2,004.815 m; z −142.687 to −505.109 m | 27.027 m; 25.527–27.777 m | 1.75 m |
| SW 1 Worm | 1,946.355 m; z −138.668 to −505.109 m | 24.187 m; 22.687–24.937 m | 1.75 m |
| SW 2 Spiral | 1,957.892 m; z −137.967 to −505.138 m | 19.744 m; 18.244–20.744 m | 1.75 m |
| SW 3 Cascading | 1,981.103 m; z −137.484 to −505.112 m | 22.791 m; 21.291–23.541 m | 1.75 m |
| FI 0 Straight | 249.982 m; z −65.846 to −122.390 m | 11.250 m; 11.250–12.500 m | 3.25 m |
| FI 1 Worm | 17.042 m and 249.965 m; z −61.574 to −122.416 m | 12.719 m and 12.746 m; 12.968–16.468 m and 12.746–13.996 m | 3.25 m |
| FI 2 Spiral | 244.479 m; z −68.891 to −122.382 m | 9.251 m; 9.000–10.500 m | 3.00 m |
| FI 3 Cascading | 17.955 m and 231.814 m; z −65.805 to −122.436 m | 11.250 m each; 11.250–14.000 m and 11.250–12.500 m | 3.25 m |
The helix path measurements are length / turns / mean path radius / vertical pitch. SW styles 0–3
measure **2,015.1 m / 16.88 / 18.96 m / 21.00 m**, **1,956.1 / 20.69 / 14.99 / 17.32 m**,
**1,963.0 / 61.62 / 5.02 / 5.81 m**, and **1,987.2 / 21.63 / 14.50 / 16.59 m**. FI styles 0–3
measure **254.0 m / 8.00 / 5.00 m / 5.78 m**, **254.0 / 7.99 / 4.97 / 5.72 m**,
**246.9 / 12.95 / 3.00 / 3.31 m**, and **235.5 / 7.94 / 4.50 / 5.37 m**. FI styles 1 and 3
also have short cap descents: respectively 22.1 m / 0.59 turns / 5.70 m radius / 6.71 m pitch,
and 22.2 m / 0.75 turns / 4.54 m radius / 5.37 m pitch. Main helix grades are about 10.0–10.5°;
the walkability audit reports zero grade failures.
## Audits
Clang and GCC each ran all eight recipe/style combinations. Every row has 0 blocked capsule
samples, 0 unsupported samples, 0 grade failures, 0 open-air violations, connected column ends
(2/2), 128/128 route-support samples for each main crossing, and passing walkability. The naturalness wall-relief audit measured 0.509–0.806 m against
the 0.200 m minimum; flat runs were 0 m against the 8 m limit. The strict V3 layout validator
accepted with zero issues and rejected its malformed controls 9/9.
The no-long-bridge threshold is 12.5 m. SW has 0 m uncolumned span in all styles. FI's longest
short grounded span is 4.464 m (style 0); every other span is shorter. The L26 SW bridge control
(1,946–2,005 m unsupported) was detected in all four SW styles. The L24 ungated-support and L23
smooth-wall naturalness controls were detected in all eight recipe/style rows. The 16 final matrix logs are
`Saved/Linux/linux27-final-audit-{surface-world,floating-islands}-style{0,1,2,3}-{clang,gcc}.log`.
## Captures
All five JPEGs are 16:9 and below 300 KB in `captures/`.
| Capture | View | Size | SHA-256 |
|---|---|---:|---|
| [sw-column-wide.jpg](captures/sw-column-wide.jpg) | Wide side section: ceiling, full column and local ground; 1280×720 | 27 KB | `63e621794a48747c5892b74d3313da1df93e95bc1fb5e23c511211f992023acf` |
| [sw-column-base.jpg](captures/sw-column-base.jpg) | Close base flare into terrain; 1280×720 | 27 KB | `c4dbf7bcbd4962cf0e2c4f567cceec798deac8686a85cd02716ebd3c21db43bf` |
| [sw-column-top.jpg](captures/sw-column-top.jpg) | Close ceiling blend and upper helix; 1280×720 | 30 KB | `fe83fbb0bf90ea51696f9f63129738eb55812c01bbbec65e7430b8a7e6b512ed` |
| [sw-column-cutaway.jpg](captures/sw-column-cutaway.jpg) | Full-height cutaway through the helix; 1920×1080 | 60 KB | `8233e80035aac69dec7fd6d2e77a46e5798f627aefe216671d884bf84b339c40` |
| [fi-anchor-pillar.jpg](captures/fi-anchor-pillar.jpg) | L27 FI anchor pillar from outside; 1280×720 | 21 KB | `5bb8ad6a0729818577764596d3fa9ccff9621b31217ee9d8e34401098e6b4ef6` |
## Cost, determinism and compatibility
The whole-view timing comparison alternated two L24 and two L27 Clang W12 runs per recipe. No
prebuilt L24 executable was present, so I rebuilt it from local commit `cb9236c` with Clang 19 and
FP contraction off under `Saved/Linux/l24-source/bin/linux/`.
| Recipe | L24 whole-view seconds, two runs (mean) | L27 whole-view seconds, two runs (mean) | Change | Tiles, both versions |
|---|---:|---:|---:|---:|
| SurfaceWorld | 1.644 / 1.663 (1.654) | 2.207 / 2.252 (2.230) | +0.576 s (+34.8%) | 2,370 total; 960 full detail |
| Floating Islands | 15.907 / 16.848 (16.378) | 19.403 / 19.649 (19.526) | +3.149 s (+19.2%) | 2,370 total; 960 full detail |
No tiles were added. The L24 and L27 per-run logs are `Saved/Linux/linux27-cost-interleaved-*.log`.
The L25 whole-view command produced identical hashes across Clang/GCC and W1/W8/W12. Hash order
is density / mesh / payload / topology:
| Recipe | L27 whole-view hash |
|---|---|
| SurfaceWorld | `117547e5e18c6847 / db5fa276315ff2d4 / b4e9d01d70413fea / 03caf881fa047f1c` |
| Floating Islands | `70ab5bc87dd174d2 / 6f357f9085a496f0 / 08ce7d4e036da65a / eb5eef04a5cb85d9` |
Full-detail hashes also match across the matrix: SW `ace56c8f205238ad / a9c603a1248de6b8 /
ea55f1f4fcc6a894 / 5ea7bc78a1b678ae`; FI `ed550e0c8b182695 / 0e410a8e80a3e7f7 /
0751926f0c67d8a4 / f01208bc2f7841ec`. Exact-query hashes (density / unclamped / detail / collision)
are SW `c949c4df2ce6f9d9 / c949c4df2ce6f9d9 / 114c501e2d830d94 / e6011d3a248d4849` and FI
`7b7c50ac24ccadcc / 7b7c50ac24ccadcc / efcba20c0c70c415 / e604823a249029bf`.
The 24 m crossing processed 314 moving tiles and matched across both compilers:
| Recipe | Moving-tile hash: density / mesh / payload / topology |
|---|---|
| SurfaceWorld | `fe83368d746bf44d / d4379e0f86fa5780 / 0d1d6659a251dcaf / 73940f21b0fdaf14` |
| Floating Islands | `e3d0ea833bca4215 / f4b27f4bd1adbb07 / 8aedcdc86e5f21a2 / 323f880d952306e9` |
L13 parity passed for both compilers and recipes: 8 page pairs, 14 higher-LOD pairs, one edit pair,
782,026 exact-query samples, zero mismatches. At a 10 km off-route view, L9 proofs checked 6,896
blocks / 9,178,576 samples with zero violations on both compilers. SW had 1,296 fallbacks and no
unknown blocks; FI had 18,704 fallbacks, 17,408 unknown blocks and zero violations.
At a 100 km SW view, L26 and L27 were bit-identical on Clang and GCC: full-detail hash
`3148a6af10901e4d / 7025b8fc8d4636cd / ca0a8081022340bf / 1c49e72a6636ae99`, whole-view hash
`a212129dc5f2bfcf / e9b3980b69c789bf / 785a394605885d1f / 8f7e3a55bf429175`, exact-query hash
`482500abbe835b11 / c4948c7179963784 / efcba20c0c70c415 / 137e8f6c0b03a624`; LOD0–8 also match.
At 10 km, the whole-view hash changes because the new column enters LOD8; full detail, exact queries
and LOD0–7 remain identical.
Headless binary SHA-256: Clang `81ae5a03765eb3937f53c10e8f8b82cf1b38d3e3b6240511a57e5d66d99a9755`,
GCC `30c8927eee3c8c2ec0e7ff72228872435d19527719bedbb2399e6dcaff4819a4`. Rebuilt L24 Clang
binary: `29bb68ed425b4770b1b4ddcc68996c5d680665014e7ab7ffb3c307523015cf0b`.
## Changes and invariants
The deterministic crossing planner and field composition are shared in
`Standalone/Core/src/ShapeWorldInternal.h`. `VoxelForgeCore.h/.cpp` expose the void-crossing audit;
`StreamBenchmarkPipeline.h` adds column, open-air and no-long-bridge audits with the L26 negative
control. `FloatingIslandsInternal.h` retires the old special-case root for geometry 8, while
`OwnerWorldLoader.h` and `WorldAssemblyPrototype.h` use the shared crossing plan and version.
Geometry/evaluator versions are now 8/14; resolved-layout schema V3 is unchanged. The only Unreal
edit is the matching geometry-version bump in `Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp`;
Unreal was not available to compile here.
L4 lazy caches, L7 shared cache, L9/L12 proofs, L11 readiness handling, L13 route parity, L18/L19
ceilings and L21/L22 layout behavior remain unchanged. No async path was added.
## Failed and retried runs
- Two temporary Clang backtrace builds failed on `signal` namespace qualification; corrected before
the instrumentation was removed. The first SW style-0 audit segfaulted because the planner read
shared-field intervals before they were built; build order was corrected. An early SW style-1
iteration had 3,816 open-air violations and 869 blocked samples at the lower mouth; the carve
guard fixed it.
- Early FI audit revisions mis-tagged segments and reported false open-air spans; corrected to use
the actual route ranges and physical field. FI style 2 briefly had two unsupported samples; the
seam extension fixed them. A 3 m cap left 13 FI style-0 open-air samples; the 5 m cap cleared
them. A relaxed tread guard introduced one SW style-1 blocked sample and was reverted.
- A layout-only invocation without the required streaming flags exited 2. During capture setup,
`--hash` and `--data=` were rejected; the correct switches are `--stream-hash` and a positional
data path. Those were corrected. A helix-metrics helper first failed while formatting a list and
was rerun successfully.
- The first close SW export at max clip level 1 hit the 160-million-node interval safety bound.
Two finer endpoint exports then grew past 1.2 GB without a final pipeline summary and were
stopped; the already-complete full-column cutaway mesh supplied the final base/top views. The
first wide camera hid the base; a cut-plane side view fixed it. The first FI close camera cropped
the endpoints and was moved back.
- The first FI max-clip-level-3 export grew past 1.6 GB without a summary and was stopped. The
max-clip-level-8 retry completed in 21.7 s with a 104 MB mesh. The final capture is from that
L27 mesh. All rejected, stopped and successful export logs are in `Saved/Linux/`.
No run exceeded 30 minutes or remained stuck for 15 minutes. Only the requested small JPEGs and
this report were written under `Standalone/Research/WorldAssemblerM3/Linux27/`; exports and logs
remain in `Saved/Linux/`. The pre-existing untracked `Linux18/exports/` directory was left alone.
No commit, push or stash was made.
## Orchestrator review (Claude) — side branch
- Look approved by me: `sw-column-wide.jpg` and `sw-column-cutaway.jpg` show one slender ceiling-to-ground
column with the helix inside; `sw-column-base.jpg` shows the base meeting the terrain with a natural crack
exit; `fi-anchor-pillar.jpg` shows a textured pillar with a flared base under the island.
- **Blocking merge: cost.** Whole view +34.8% SW (1.654 → 2.230 s) and +19.2% FI with no new tiles. A local
feature must cost locally. L28: bound column/helix evaluation spatially (feature lists / AABB culling), then
merge `wip/l25-helix` into `assembler/world`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+17 -5
View File
@@ -24,7 +24,7 @@ struct FStandaloneParitySample
int32 StrateIndex = INDEX_NONE;
};
struct FStandalonePassageBridgeRange
struct FStandalonePassageVoidCrossing
{
std::size_t passageIndex=0;
std::size_t firstSegment=0;
@@ -33,12 +33,24 @@ struct FStandalonePassageBridgeRange
double unsupportedLengthMetres=0.0;
std::array<double,4> startPoint{};
std::array<double,4> endPoint{};
bool needsColumn=false;
bool connectedAtStart=false;
bool connectedAtEnd=false;
std::int64_t centerXSubvoxels=0;
std::int64_t centerYSubvoxels=0;
std::int64_t topZSubvoxels=0;
std::int64_t bottomZSubvoxels=0;
std::int64_t minimumRadiusSubvoxels=0;
std::int64_t nominalRadiusSubvoxels=0;
std::int64_t maximumRadiusSubvoxels=0;
double maximumRouteOffsetMetres=0.0;
double maximumBoreRadiusMetres=0.0;
};
struct FStandalonePassageBridgeCache
struct FStandalonePassageVoidCrossingCache
{
std::mutex mutex;
std::unordered_map<std::string,std::vector<FStandalonePassageBridgeRange>> byLayout;
std::unordered_map<std::string,std::vector<FStandalonePassageVoidCrossing>> byLayout;
};
struct FStandaloneOwnerWorld
@@ -66,8 +78,8 @@ struct FStandaloneOwnerWorld
std::uint32_t CoreVoxelSizeMicrons = 250000;
std::uint32_t StrateLayoutChunkSizeMicrometres = 8000000;
std::int64_t StrateLayoutChunkWidthSubvoxels = 8192;
std::shared_ptr<FStandalonePassageBridgeCache> PassageBridgeCache =
std::make_shared<FStandalonePassageBridgeCache>();
std::shared_ptr<FStandalonePassageVoidCrossingCache> PassageVoidCrossingCache =
std::make_shared<FStandalonePassageVoidCrossingCache>();
};
namespace StandaloneOwnerLoader
+235 -92
View File
@@ -726,7 +726,8 @@ namespace StandaloneStreamBenchmark
}
struct FPassageOpenAirAudit
{
std::uint64_t supportSamples=0,violations=0,legacyViolations=0,bridgeSamples=0;
std::uint64_t supportSamples=0,violations=0,legacyViolations=0;
std::uint64_t columnSamples=0,shortSpanSamples=0;
std::uint64_t routeSupportSamples=0,routeSupportViolations=0;
std::array<std::array<double,4>,8> firstViolations{};
std::size_t firstViolationCount=0;
@@ -773,10 +774,14 @@ namespace StandaloneStreamBenchmark
++audit.legacyViolations;
if(nativeDensity>=0.0f&&passageDensity<0.0f)
{
const bool connectedBridge=!routeSupport
const bool connectedColumn=!routeSupport
&&passageSegment!=std::numeric_limits<std::size_t>::max()
&&Field.isPassageBridgeSample(passageIndex,passageSegment,sample);
if(connectedBridge){++audit.bridgeSamples;return;}
&&Field.isPassageColumnSample(passageIndex,passageSegment,sample);
if(connectedColumn){++audit.columnSamples;return;}
const bool groundedShortSpan=!routeSupport
&&passageSegment!=std::numeric_limits<std::size_t>::max()
&&Field.isPassageShortSpanSample(passageIndex,passageSegment,sample);
if(groundedShortSpan){++audit.shortSpanSamples;return;}
audit.routeSupportViolations+=routeSupport;
if(audit.firstViolationCount<audit.firstViolations.size())
audit.firstViolations[audit.firstViolationCount++]={xMetres,yMetres,
@@ -894,20 +899,23 @@ namespace StandaloneStreamBenchmark
}
return audit;
};
struct FPassageBridgeAudit
struct FPassageColumnAudit
{
std::uint64_t spans=0,connectedEnds=0,crossSections=0,crossSectionFailures=0;
double minimumThicknessMetres=std::numeric_limits<double>::infinity();
double maximumThicknessMetres=0.0;
double thicknessReliefPeakToPeakMetres=0.0;
std::uint64_t columns=0,shortSpans=0,connectedEnds=0,routeSections=0;
std::uint64_t routeSectionFailures=0,wallSections=0,wallFailures=0;
double minimumWallMetres=std::numeric_limits<double>::infinity();
double minimumSurfaceRadiusMetres=std::numeric_limits<double>::infinity();
double maximumSurfaceRadiusMetres=0.0;
double surfaceRadiusReliefMetres=0.0;
double longestShortSpanMetres=0.0;
bool passed=true;
};
const auto auditPassageBridges=[&](const VoxelForgeCore::World& Field,
const auto auditPassageColumns=[&](const VoxelForgeCore::World& Field,
const VoxelForgeCore::World& Native,
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
std::size_t passageIndex)
{
FPassageBridgeAudit audit;
FPassageColumnAudit audit;
const double qMetres=coreMetres
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
constexpr std::array<std::array<double,2>,5> supportOffsets{{
@@ -928,37 +936,67 @@ namespace StandaloneStreamBenchmark
}
return supported>=3;
};
const auto bridgeSolidAt=[&](std::size_t segment,double x,double y,double z)
const auto columnSolidAt=[&](std::size_t segment,double x,double y,double z)
{
return Field.isPassageBridgeSample(passageIndex,segment,
return Field.isPassageColumnSample(passageIndex,segment,
{x/coreMetres,y/coreMetres,z/coreMetres});
};
const auto thicknessAt=[&](std::size_t segment,double x,double y,double floor)
const auto shortSpanSolidAt=[&](std::size_t segment,double x,double y,double z)
{
double thickness=0.0;
for(double depth=0.125;depth<=6.0+1.0e-6;depth+=0.125)
{
if(!bridgeSolidAt(segment,x,y,floor-depth))break;
thickness=depth;
}
return thickness;
return Field.isPassageShortSpanSample(passageIndex,segment,
{x/coreMetres,y/coreMetres,z/coreMetres});
};
for(const auto& range:Field.passageBridgeRanges())
const auto crossings=Field.passageVoidCrossings();
for(const auto& crossing:crossings)
{
if(range.passageIndex!=passageIndex
||range.lastSegment+1>=passage.controlPoints.size())continue;
++audit.spans;
const bool connectedStart=endpointConnected(range.startPointSubvoxels);
const bool connectedEnd=endpointConnected(range.endPointSubvoxels);
if(crossing.passageIndex!=passageIndex)continue;
const bool connectedStart=endpointConnected(crossing.startPointSubvoxels);
const bool connectedEnd=endpointConnected(crossing.endPointSubvoxels);
if(!crossing.needsColumn)
{
++audit.shortSpans;
audit.longestShortSpanMetres=std::max(audit.longestShortSpanMetres,
crossing.unsupportedLengthMetres);
const bool shortSpanPass=connectedStart&&connectedEnd
&&crossing.unsupportedLengthMetres<=12.5
&&crossing.lastSegment+1<passage.controlPoints.size();
audit.passed&=shortSpanPass;
std::printf("[PassageGroundedShortSpanAudit] id=%s segments=%zu..%zu length_m=%.3f threshold_m=12.500 connected=%d/2 status=%s\n",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
crossing.unsupportedLengthMetres,
static_cast<int>(connectedStart)+static_cast<int>(connectedEnd),
shortSpanPass?"PASS":"FAIL");
const std::size_t segment=std::min(crossing.firstSegment,
passage.controlPoints.size()-2);
const auto& a=passage.controlPoints[segment];
const auto& b=passage.controlPoints[segment+1];
const double x=(qToMetres(a.positionSubvoxels[0])
+qToMetres(b.positionSubvoxels[0]))*0.5;
const double y=(qToMetres(a.positionSubvoxels[1])
+qToMetres(b.positionSubvoxels[1]))*0.5;
const double z=(qToMetres(a.positionSubvoxels[2])
+qToMetres(b.positionSubvoxels[2]))*0.5
-qToMetres(a.radiusSubvoxels+b.radiusSubvoxels)*0.5+0.13;
audit.passed&=shortSpanSolidAt(segment,x,y,z-0.25);
continue;
}
if(crossing.lastSegment+1>=passage.controlPoints.size())
{audit.passed=false;continue;}
++audit.columns;
audit.connectedEnds+=connectedStart+connectedEnd;
const std::size_t segmentCount=range.lastSegment-range.firstSegment+1;
const std::size_t probeCount=std::min<std::size_t>(256,segmentCount);
double spanMinimumThickness=std::numeric_limits<double>::infinity();
double spanMaximumThickness=0.0;
std::uint64_t spanCrossSections=0,spanCrossSectionFailures=0;
const double axisX=qToMetres(crossing.columnAxisSubvoxels[0]);
const double axisY=qToMetres(crossing.columnAxisSubvoxels[1]);
const double minimumRadius=qToMetres(crossing.columnMinimumRadiusSubvoxels);
const double maximumRadius=qToMetres(crossing.columnMaximumRadiusSubvoxels);
const double minimumWall=minimumRadius-crossing.maximumRouteOffsetMetres
-crossing.maximumBoreRadiusMetres-0.50;
audit.minimumWallMetres=std::min(audit.minimumWallMetres,minimumWall);
const std::size_t segmentCount=crossing.lastSegment-crossing.firstSegment+1;
const std::size_t probeCount=std::min<std::size_t>(128,segmentCount);
std::uint64_t crossingRouteFailures=0,crossingWallFailures=0;
for(std::size_t probe=0;probe<probeCount;++probe)
{
const std::size_t segment=range.firstSegment
const std::size_t segment=crossing.firstSegment
+std::min(segmentCount-1,(probe*segmentCount)/probeCount);
const auto& a=passage.controlPoints[segment];
const auto& b=passage.controlPoints[segment+1];
@@ -973,42 +1011,96 @@ namespace StandaloneStreamBenchmark
const double radius=(qToMetres(a.radiusSubvoxels)
+qToMetres(b.radiusSubvoxels))*0.5;
const double floor=z-radius+0.13;
const double thickness=thicknessAt(segment,x,y,floor);
spanMinimumThickness=std::min(spanMinimumThickness,thickness);
spanMaximumThickness=std::max(spanMaximumThickness,thickness);
audit.minimumThicknessMetres=std::min(audit.minimumThicknessMetres,thickness);
audit.maximumThicknessMetres=std::max(audit.maximumThicknessMetres,thickness);
const double dx=bx-ax,dy=by-ay,horizontal=std::hypot(dx,dy);
if(horizontal<=1.0e-6)continue;
const double nx=dy/horizontal,ny=-dx/horizontal;
bool crossSectionSolid=true;
for(const double offset:{-2.5,0.0,2.5})
crossSectionSolid&=bridgeSolidAt(segment,x+nx*offset,
y+ny*offset,floor-2.0);
++audit.crossSections;
++spanCrossSections;
spanCrossSectionFailures+=!crossSectionSolid;
audit.crossSectionFailures+=!crossSectionSolid;
const VoxelForgeCore::Vec3d supportPoint{
x/coreMetres,y/coreMetres,(floor-2.0)/coreMetres};
const bool solidUnderRoute=columnSolidAt(segment,x,y,floor-2.0)
||Native.densityAt(supportPoint)<0.0f;
++audit.routeSections;
audit.routeSectionFailures+=!solidUnderRoute;
crossingRouteFailures+=!solidUnderRoute;
const double radial=std::hypot(x-axisX,y-axisY);
const double wallRadius=radial+radius+1.5;
const double outwardX=radial>1.0e-6?(x-axisX)/radial:1.0;
const double outwardY=radial>1.0e-6?(y-axisY)/radial:0.0;
const bool wallSolid=columnSolidAt(segment,
axisX+outwardX*wallRadius,axisY+outwardY*wallRadius,z);
++audit.wallSections;
audit.wallFailures+=!wallSolid;
crossingWallFailures+=!wallSolid;
}
const double relief=std::isfinite(spanMinimumThickness)
?spanMaximumThickness-spanMinimumThickness:0.0;
audit.thicknessReliefPeakToPeakMetres=std::max(
audit.thicknessReliefPeakToPeakMetres,relief);
const bool spanPass=connectedStart&&connectedEnd
&&spanCrossSections>=3&&spanCrossSectionFailures==0
&&spanMinimumThickness>=2.75
&&spanMaximumThickness<=6.5
&&audit.thicknessReliefPeakToPeakMetres>=0.20;
audit.passed&=spanPass;
std::printf("[PassageRockBridgeAudit] id=%s segments=%zu..%zu gap_m=%.3f connected_ends=%d/2 width_at_least_m=5.000 cross_sections=%llu/%llu thickness_m=%.3f..%.3f relief_p2p_m=%.3f status=%s\n",
passage.stableId.c_str(),range.firstSegment,range.lastSegment,
range.unsupportedLengthMetres,static_cast<int>(connectedStart)
+static_cast<int>(connectedEnd),
static_cast<unsigned long long>(spanCrossSections-spanCrossSectionFailures),
static_cast<unsigned long long>(spanCrossSections),
std::isfinite(spanMinimumThickness)?spanMinimumThickness:0.0,
spanMaximumThickness,relief,
spanPass?"PASS":"FAIL");
double crossingMinimumSurfaceRadius=std::numeric_limits<double>::infinity();
double crossingMaximumSurfaceRadius=0.0;
std::array<double,6> meanRadiusByHeight{};
std::size_t heightSamples=0;
constexpr double RayStepMetres=0.25;
constexpr std::array<double,6> HeightFractions{{0.25,0.35,0.45,0.55,0.65,0.75}};
constexpr std::size_t DirectionCount=16;
const double topMetres=qToMetres(crossing.columnTopZSubvoxels);
const double bottomMetres=qToMetres(crossing.columnBottomZSubvoxels);
const double rayStart=crossing.maximumRouteOffsetMetres
+crossing.maximumBoreRadiusMetres+0.75;
for(const double heightFraction:HeightFractions)
{
const double z=topMetres+(bottomMetres-topMetres)*heightFraction;
double heightMeanRadius=0.0;
std::uint64_t heightRayCount=0;
for(std::size_t direction=0;direction<DirectionCount;++direction)
{
const double angle=2.0*3.14159265358979323846
*direction/DirectionCount;
double lastSolidRadius=0.0;
bool enteredColumn=false;
const std::size_t raySteps=static_cast<std::size_t>(std::ceil(
(maximumRadius+2.0-rayStart)/RayStepMetres));
for(std::size_t step=0;step<=raySteps;++step)
{
const double rayRadius=rayStart+step*RayStepMetres;
const VoxelForgeCore::Vec3d point{
(axisX+rayRadius*std::cos(angle))/coreMetres,
(axisY+rayRadius*std::sin(angle))/coreMetres,
z/coreMetres};
if(Field.densityAt(point)<0.0f)
{enteredColumn=true;lastSolidRadius=rayRadius;}
else if(enteredColumn)break;
}
if(!enteredColumn)continue;
heightMeanRadius+=lastSolidRadius;
++heightRayCount;
crossingMinimumSurfaceRadius=std::min(crossingMinimumSurfaceRadius,
lastSolidRadius);
crossingMaximumSurfaceRadius=std::max(crossingMaximumSurfaceRadius,
lastSolidRadius);
}
if(heightRayCount==0)continue;
meanRadiusByHeight[heightSamples++]=heightMeanRadius/heightRayCount;
}
const double crossingSurfaceRelief=heightSamples>=2
?*std::max_element(meanRadiusByHeight.begin(),
meanRadiusByHeight.begin()+heightSamples)
-*std::min_element(meanRadiusByHeight.begin(),
meanRadiusByHeight.begin()+heightSamples):0.0;
audit.minimumSurfaceRadiusMetres=std::min(audit.minimumSurfaceRadiusMetres,
crossingMinimumSurfaceRadius);
audit.maximumSurfaceRadiusMetres=std::max(audit.maximumSurfaceRadiusMetres,
crossingMaximumSurfaceRadius);
audit.surfaceRadiusReliefMetres=std::max(audit.surfaceRadiusReliefMetres,
crossingSurfaceRelief);
const double measuredWall=crossingMinimumSurfaceRadius
-crossing.maximumRouteOffsetMetres-crossing.maximumBoreRadiusMetres;
const bool columnPass=connectedStart&&connectedEnd
&&minimumWall>=1.50&&crossingRouteFailures==0
&&crossingWallFailures==0&&std::isfinite(measuredWall)
&&measuredWall>=1.50&&crossingSurfaceRelief>=0.20;
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",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
crossing.unsupportedLengthMetres,axisX,axisY,
static_cast<int>(connectedStart)+static_cast<int>(connectedEnd),
static_cast<unsigned long long>(probeCount-crossingRouteFailures),
static_cast<unsigned long long>(probeCount),measuredWall,
crossingMinimumSurfaceRadius,crossingMaximumSurfaceRadius,
crossingSurfaceRelief,qToMetres(crossing.columnNominalRadiusSubvoxels),
columnPass?"PASS":"FAIL");
}
return audit;
};
@@ -1022,6 +1114,7 @@ namespace StandaloneStreamBenchmark
Assembly->floatingIslands.end(),[&](const auto& value)
{return value.strateIndex==stratum.strateIndex;});
if(anchor==stratum.anchors.end()||islandPlan==Assembly->floatingIslands.end())continue;
if(islandPlan->manifest.recipe.geometryVersion>=8)continue;
const auto ordinal=islandPlan->manifest.recipe.anchorIslandOrdinal;
if(ordinal>=islandPlan->manifest.plan.islands.size())continue;
const auto& anchorIsland=islandPlan->manifest.plan.islands[ordinal];
@@ -1110,9 +1203,34 @@ namespace StandaloneStreamBenchmark
};
std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0;
std::uint64_t openAirViolations=0,openAirLegacyViolations=0,openAirSamples=0;
std::uint64_t openAirAudits=0,openAirBridgeSamples=0,bridgeSpans=0,
bridgeConnectedEnds=0;
bool bridgeAuditsPassed=true;
std::uint64_t openAirAudits=0,openAirColumnSamples=0,openAirShortSpanSamples=0;
std::uint64_t columnCrossings=0,shortGroundedSpans=0,columnConnectedEnds=0;
std::uint64_t columnRouteFailures=0,columnWallFailures=0;
double longestUncolumnedSpanMetres=0.0,longestShortSpanMetres=0.0;
double l26LegacyBridgeSpanMetres=0.0;
bool columnAuditsPassed=true,noLongBridgeAuditPassed=true;
bool l26NegativeControlApplicable=false;
const auto plannedVoidCrossings=Shape.passageVoidCrossings();
for(const auto& crossing:plannedVoidCrossings)
{
if(crossing.needsColumn)continue;
longestUncolumnedSpanMetres=std::max(longestUncolumnedSpanMetres,
crossing.unsupportedLengthMetres);
}
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
++passageIndex)
{
const auto& passage=ResolvedLayout->passages[passageIndex];
const auto* upper=findStratum(passage.upperStrateIndex);
const auto* lower=findStratum(passage.lowerStrateIndex);
if(!upper||!lower||lower->generatorKind!="SurfaceWorld"
||upper->generatorKind=="FloatingIslands")continue;
l26NegativeControlApplicable=true;
for(const auto& crossing:plannedVoidCrossings)
if(crossing.passageIndex==passageIndex)
l26LegacyBridgeSpanMetres=std::max(l26LegacyBridgeSpanMetres,
crossing.unsupportedLengthMetres);
}
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();++passageIndex)
{
const auto& passage=ResolvedLayout->passages[passageIndex];
@@ -1131,15 +1249,21 @@ namespace StandaloneStreamBenchmark
const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage);
const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld,
passage,passageIndex);
const FPassageBridgeAudit bridgeAudit=auditPassageBridges(Shape,blockedWorld,
const FPassageColumnAudit columnAudit=auditPassageColumns(Shape,blockedWorld,
passage,passageIndex);
openAirSamples+=openAirAudit.supportSamples;
openAirViolations+=openAirAudit.violations;
openAirLegacyViolations+=openAirAudit.legacyViolations;
openAirBridgeSamples+=openAirAudit.bridgeSamples;
bridgeSpans+=bridgeAudit.spans;
bridgeConnectedEnds+=bridgeAudit.connectedEnds;
bridgeAuditsPassed&=bridgeAudit.passed;
openAirColumnSamples+=openAirAudit.columnSamples;
openAirShortSpanSamples+=openAirAudit.shortSpanSamples;
columnCrossings+=columnAudit.columns;
shortGroundedSpans+=columnAudit.shortSpans;
columnConnectedEnds+=columnAudit.connectedEnds;
columnRouteFailures+=columnAudit.routeSectionFailures;
columnWallFailures+=columnAudit.wallFailures;
longestShortSpanMetres=std::max(longestShortSpanMetres,
columnAudit.longestShortSpanMetres);
columnAuditsPassed&=columnAudit.passed;
++openAirAudits;
const auto radialSquared=[](const std::array<std::int64_t,3>& p)
{return p[0]*p[0]+p[1]*p[1];};
@@ -1167,10 +1291,11 @@ namespace StandaloneStreamBenchmark
static_cast<unsigned long long>(naturalAudit.wallSamples),
static_cast<unsigned long long>(naturalAudit.missingWallSamples),
naturalAudit.passed?"PASS":"FAIL");
std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu bridge_samples=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n",
std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu column_samples=%llu short_span_samples=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n",
passage.stableId.c_str(),static_cast<unsigned long long>(openAirAudit.supportSamples),
static_cast<unsigned long long>(openAirAudit.violations),
static_cast<unsigned long long>(openAirAudit.bridgeSamples),
static_cast<unsigned long long>(openAirAudit.columnSamples),
static_cast<unsigned long long>(openAirAudit.shortSpanSamples),
static_cast<unsigned long long>(openAirAudit.legacyViolations),
static_cast<unsigned long long>(openAirAudit.routeSupportSamples),
static_cast<unsigned long long>(openAirAudit.routeSupportViolations),
@@ -1229,12 +1354,12 @@ namespace StandaloneStreamBenchmark
const VoxelForgeCore::Vec3d nativePosition{sample[0]/coreMetres,
sample[1]/coreMetres,sample[2]/coreMetres};
const float nativeDensity=blockedWorld.densityAt(nativePosition);
const bool bridgeVolume=Shape.isPassageBridgeSample(passageIndex,
const bool passageColumn=Shape.isPassageColumnSample(passageIndex,
nearestSegment,nativePosition);
std::printf("[ResolvedPassageAuditSample] id=%s kind=blocked xyz_m=(%.3f,%.3f,%.3f) density=%.6f native_density=%.6f segment=%zu t=%.3f passage_segment=%zu passage_sdf_m=%.3f bridge_volume=%d native_path=%s\n",
std::printf("[ResolvedPassageAuditSample] id=%s kind=blocked xyz_m=(%.3f,%.3f,%.3f) density=%.6f native_density=%.6f segment=%zu t=%.3f passage_segment=%zu passage_sdf_m=%.3f passage_column=%d native_path=%s\n",
passage.stableId.c_str(),sample[0],sample[1],sample[2],sample[3],
nativeDensity,nearestSegment,nearestT,nearestPassageSegment,
nearestPassageSdf,bridgeVolume?1:0,
nearestPassageSdf,passageColumn?1:0,
blockedWorld.densityDispatchPathAt(nativePosition).c_str());
}
for(std::size_t i=0;i<passageAudit.firstUnsupportedCount;++i)
@@ -1255,15 +1380,15 @@ namespace StandaloneStreamBenchmark
const double firstZ=(sample[2]-0.125)/coreMetres;
const VoxelForgeCore::Vec3d bridgeProbe{sample[0]/coreMetres,
sample[1]/coreMetres,(sample[2]-0.25)/coreMetres};
const bool bridgeAtSupport=Shape.isPassageBridgeSample(passageIndex,
const bool columnAtSupport=Shape.isPassageColumnSample(passageIndex,
segment,bridgeProbe);
std::printf("[ResolvedPassageSupportSegment] id=%s segment=%zu route_z_m=%.3f..%.3f centers=%llu unsupported=%llu native_unsupported=%llu first_foot_m=(%.3f,%.3f,%.3f) bridge_at_d025=%d native_support_probes=%u/5 native_density_d0125_d1_d2_d4=(%.6f,%.6f,%.6f,%.6f) native_path=%s\n",
std::printf("[ResolvedPassageSupportSegment] id=%s segment=%zu route_z_m=%.3f..%.3f centers=%llu unsupported=%llu native_unsupported=%llu first_foot_m=(%.3f,%.3f,%.3f) column_at_d025=%d native_support_probes=%u/5 native_density_d0125_d1_d2_d4=(%.6f,%.6f,%.6f,%.6f) native_path=%s\n",
passage.stableId.c_str(),segment,
std::min(a[2],b[2])*coreMetres,std::max(a[2],b[2])*coreMetres,
static_cast<unsigned long long>(item.centers),
static_cast<unsigned long long>(item.unsupported),
static_cast<unsigned long long>(item.nativeUnsupported),
sample[0],sample[1],sample[2],bridgeAtSupport?1:0,
sample[0],sample[1],sample[2],columnAtSupport?1:0,
item.firstNativeSupportedProbes,item.firstNativeDensities[0],item.firstNativeDensities[1],
item.firstNativeDensities[2],item.firstNativeDensities[3],
blockedWorld.densityDispatchPathAt({firstX,firstY,firstZ}).c_str());
@@ -1429,19 +1554,37 @@ namespace StandaloneStreamBenchmark
std::printf("[PassageOpenAirNegativeControl] source=L24_ungated_support unsupported_samples=%llu detected=%s\n",
static_cast<unsigned long long>(openAirLegacyViolations),
l24OpenAirControlDetected?"true":"false");
std::printf("[PassageOpenAirAuditSummary] interfaces=%llu samples=%llu violations=%llu bridge_samples=%llu l24_negative_control=%s status=%s\n",
std::printf("[PassageOpenAirAuditSummary] interfaces=%llu samples=%llu violations=%llu column_samples=%llu short_span_samples=%llu l24_negative_control=%s status=%s\n",
static_cast<unsigned long long>(openAirAudits),
static_cast<unsigned long long>(openAirSamples),
static_cast<unsigned long long>(openAirViolations),
static_cast<unsigned long long>(openAirBridgeSamples),
static_cast<unsigned long long>(openAirColumnSamples),
static_cast<unsigned long long>(openAirShortSpanSamples),
l24OpenAirControlDetected?"DETECTED":"MISSED",
openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
?"PASS":"FAIL");
std::printf("[PassageRockBridgeAuditSummary] spans=%llu connected_ends=%llu/%llu status=%s\n",
static_cast<unsigned long long>(bridgeSpans),
static_cast<unsigned long long>(bridgeConnectedEnds),
static_cast<unsigned long long>(bridgeSpans*2),
bridgeAuditsPassed?"PASS":"FAIL");
const bool l26NoLongBridgeControlDetected=l26NegativeControlApplicable
&&l26LegacyBridgeSpanMetres>12.5;
const bool l26NoLongBridgeControlPass=!l26NegativeControlApplicable
||l26NoLongBridgeControlDetected;
noLongBridgeAuditPassed=longestUncolumnedSpanMetres<=12.5
&&l26NoLongBridgeControlPass;
std::printf("[PassageNoLongBridgeNegativeControl] source=L26_SurfaceWorld_bridge applicable=%s longest_uncolumned_m=%.3f threshold_m=12.500 detected=%s\n",
l26NegativeControlApplicable?"true":"false",l26LegacyBridgeSpanMetres,
l26NoLongBridgeControlDetected?"true":"false");
std::printf("[PassageNoLongBridgeAudit] columns=%llu short_grounded_spans=%llu longest_uncolumned_m=%.3f threshold_m=12.500 longest_short_span_m=%.3f l26_negative_control=%s status=%s\n",
static_cast<unsigned long long>(columnCrossings),
static_cast<unsigned long long>(shortGroundedSpans),longestUncolumnedSpanMetres,
longestShortSpanMetres,l26NegativeControlApplicable
?(l26NoLongBridgeControlDetected?"DETECTED":"MISSED"):"NOT_APPLICABLE",
noLongBridgeAuditPassed?"PASS":"FAIL");
std::printf("[PassageRockColumnAuditSummary] columns=%llu connected_ends=%llu/%llu short_spans=%llu wall_or_support_failures=%llu status=%s\n",
static_cast<unsigned long long>(columnCrossings),
static_cast<unsigned long long>(columnConnectedEnds),
static_cast<unsigned long long>(columnCrossings*2),
static_cast<unsigned long long>(shortGroundedSpans),
static_cast<unsigned long long>(columnRouteFailures+columnWallFailures),
columnAuditsPassed?"PASS":"FAIL");
const bool l23SmoothWallDetected=!looksNatural(0.0,0.0);
std::printf("[PassageNaturalnessNegativeControl] source=L23_smooth_unrelieved_wall relief_p2p_m=0.000 threshold_m=%.3f detected=%s\n",
MinimumWallReliefMetres,l23SmoothWallDetected?"true":"false");
@@ -1452,7 +1595,7 @@ namespace StandaloneStreamBenchmark
const bool auditPassed=passageCount>0&&passagePasses==passageCount
&&naturalPasses==passageCount&&l23SmoothWallDetected
&&openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
&&bridgeAuditsPassed
&&columnAuditsPassed&&noLongBridgeAuditPassed
&&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings
&&routeBindingFailures==0
&&blockedCompiled&&blockedControls==passageCount;
+1 -1
View File
@@ -540,7 +540,7 @@ namespace StandaloneWorldAssemblyPrototype
FIntVector(0,0,islandSlot->TopChunkZ));
const FStratePassageConfig& passage=islandSlot->Definition->PassageConfig;
recipe.seed=static_cast<std::uint32_t>(owner.Seed);
recipe.geometryVersion=7;
recipe.geometryVersion=8;
recipe.ownerVoxelSizeMicrons=owner.OwnerVoxelSizeMicrons;
recipe.coreVoxelSizeMicrons=owner.CoreVoxelSizeMicrons;
recipe.ownerToCoreScaleNumerator=owner.OwnerVoxelSizeMicrons/static_cast<std::uint32_t>(divisor);