Author SHA1 Message Date
Fr0zkaandClaude Opus 5.5 f23ab7b9fa wip(L28): passage columns/routes culled per tile (BVH); cost back near L24, bit-identical to L27
GenerateMesh scopes passage queries to the tile's sample bounds with a feature AABB BVH plus
per-passage segment BVHs; L9 proof boxes use a passage-bound BVH. Whole view vs L24: FI ~0%, SW
+3.7% (reviewer interleaved). All hashes equal L27; all passage/route/proof audits pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
2026-10-21 07:42:16 +02:00
Fr0zkaandClaude Opus 5.5 07b3fe2852 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
2026-10-21 04:14:14 +02:00
Fr0zkaandClaude Opus 5.5 37a223046c wip(L26, side branch): every passage style walkable in both recipes (0/0/0); SW bridges look wrong
All 4 styles x both recipes pass capsule, open-air and naturalness audits, and full-view hashes are
deterministic. But the SW passage crosses 355 m of open SurfaceWorld sky as a ~2 km fragmented rock
ramp, which is not natural. L27 replaces long bridges with a shared ceiling-to-ground rock column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
2026-10-21 02:39:44 +02:00
Fr0zkaandClaude Opus 5.5 ef789aaa00 wip(L25, side branch): FI helix enclosed in a 13 m rock root; support never created in open air
Fixes the L24 ribbon (owner request). NOT merged: the open-air support gate leaves ~4,000 unsupported
samples on every SurfaceWorld-recipe passage style (TN -> SW), a walkability regression. L26 fixes that
on this branch. See Linux25/REPORT.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
2026-10-21 00:38:57 +02:00
29 changed files with 2975 additions and 126 deletions

No files matched your search

+68
View File
@@ -1983,6 +1983,74 @@ cutaway views. Both affect captures only, not generated geometry.
[`Standalone/Research/WorldAssemblerM3/Linux24/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux24/REPORT.md)
records the evidence and owner-facing caveats.
### 8.43 Enclosed FloatingIslands helix and native-solid passage support — World Assembler L25
L24's support tread was composited into the passage field without requiring native solid terrain at
the support sample. A 6 m root could not contain the resolved helix either: the centreline reaches
5.562 m from the anchor axis and the mouth bore is 4.5 m. With the old root radius, the tread could
therefore read as a free-floating spiral outside the rock. This was not a unit conversion error.
The shared passage composer now emits route-mouth support, tread, and fallback support only where
the pre-passage native density is solid. The open-air audit samples each support footprint at 0.25 m
spacing and two depths, including route-mouth shelves; its L24 ungated-support control must report a
violation. The FI anchor root is now a relief-bearing 13.25 m nominal rock column. Across five
heights its measured radius is 12.0–13.375 m. Taking the maximum 5.562 m centreline radius and the
full 4.5 m mouth bore at every height gives a conservative minimum wall of 1.938 m, exceeding the
previous 1.5 m reserve. The authored mid-bore remains 3 m. The helix is selected from its route-bound
root point and joins the lower route before the tunnel hands off through the shared SW ceiling.
The configured FI Spiral passes the capsule/support/grade audit with zero blocked, unsupported, or
grade-failure samples; the L23 smooth-wall control fails naturalness and the L24 ungated-support
control fails the open-air audit. The other style overrides also pass the open-air audit, but their
capsule results are recorded individually in the L25 report because some overrides are not
walkable after floating support is suppressed. Evaluator version is 12, FI geometry version is 7,
and resolved-layout schema V3 remains unchanged. The L25 report records measurements, hashes,
captures, style results, and the single Unreal adapter version edit.
[`Standalone/Research/WorldAssemblerM3/Linux25/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux25/REPORT.md)
records the evidence and caveats.
### 8.44 Walkable passages as tunnels in rock — World Assembler L26
L25 correctly stopped support from appearing in native air, but its SurfaceWorld-recipe passages
still crossed a long open volume in the SurfaceWorld arrival strata. The segment map places that gap
inside SurfaceWorld (about `-146` to `-497 m`), after the TunnelNetwork transition; it is not TunnelNetwork
cave air. Both ends meet native rock. The shared Core planner now finds contiguous unsupported ranges
from the native field sign and caches them by resolved-layout identity. It adds a deterministic,
relief-bearing rock span only across those ranges. The span is at least 5 m wide, several metres thick,
and joins native rock at both ends. The passage carve then opens the bore through the added density,
leaving a grounded floor and rock walls/ceiling. SurfaceWorld away from the passage remains unchanged.
Native route support remains gated on pre-passage solid density. Before adding any support density, the
composer also checks the resolved player capsule, so neighboring floor segments cannot restore rock
inside the avatar path. This keeps all four style overrides walkable in both recipes. The bridge audit
measures its authored density field at 256 route sections, checks the 5 m width and connected ends, and
records a relief-bearing thickness range; the open-air audit still runs the L24 negative control.
The shared evaluator is version 13; FloatingIslands geometry remains version 7 and resolved-layout
schema V3 is unchanged. These changes are in Core and the standalone audit/capture path; no Unreal
adapter edit is required. The L26 report contains the eight-style table, hashes, captures and run history.
[`Standalone/Research/WorldAssemblerM3/Linux26/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux26/REPORT.md)
records the final evidence.
### 8.45 Tile-bounded passage evaluation — World Assembler M3 Linux L28
Each mesh tile scopes passage composition to the inclusive density-sample AABB, including the
mesher's normal halo. A conservative feature AABB BVH selects route segments, columns and mouth
support for that tile. A per-passage nearest-segment BVH bounds the long helix search; a separate
passage-bound BVH rejects far L9 proof boxes. An unindexed native-only proof object uses a conservative
linear fallback. No field, union order, serialized layout or recipe version changes.
The column's exact complex SDF is evaluated only in XY/Z feature candidates. A cheap density-aware
radial guard remains for samples sharing the column's Z slab: a positive column distance can still
lower positive base density, so skipping that guard needs an exact bound on the base field. This is
the remaining SurfaceWorld cost noted in the Linux L28 report. The passage candidate lists and
proof bounds preserve the L27 output.
[Linux28 report](Standalone/Research/WorldAssemblerM3/Linux28/REPORT.md)
records counts, parity, costs and audit caveats.
## 9. Multiplayer model (listen-server first, dedicated-friendly)
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a
+36
View File
@@ -1181,6 +1181,42 @@ The shared evaluator is version 10, the FI recipe geometry is version 5, and res
V3 is unchanged. See ARCHITECTURE §8.42 and
[`Standalone/Research/WorldAssemblerM3/Linux24/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux24/REPORT.md).
### 3.26 Enclosed FloatingIslands helix and open-air support gate — World Assembler L25
| Symbol | Canonical file | Role |
|---|---|---|
| `ApplyResolvedStratePassageCarves` | `Standalone/Core/src/ShapeWorldInternal.h` | Emits route-mouth support, tread and fallback support only over pre-passage native solid density, shared by every passage style. |
| `auditPassageOpenAir` / `--audit-resolved-layout-passages` | `Standalone/Source/StreamBenchmarkPipeline.h` | Samples the support footprint at 0.25 m spacing and two depths; compares against L24 ungated support as a required negative control. |
| Anchor root dimensions and relief | `Standalone/Core/src/FloatingIslandsInternal.h` | Raises the FI anchor root from a 6 m cylinder to a nominal 13.25 m relief-bearing rock column sized around the 3 m helix and 4.5 m mouth. |
| Passage route and root measures | `Standalone/Core/src/ResolvedLayoutInternal.h`, `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h` | Binds the Spiral to the root and reports measured centreline/root clearance. |
The shared evaluator is version 12 and FI geometry version is 7; resolved-layout schema V3 is
unchanged. See ARCHITECTURE §8.43 and
[`Standalone/Research/WorldAssemblerM3/Linux25/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux25/REPORT.md).
### 3.27 Tunnels in native rock with grounded passage bridges — World Assembler L26
| Symbol | Canonical file | Role |
|---|---|---|
| `BuildPassageBridgePlan` / `PassageBridgeSignedDistance` | `Standalone/Core/src/ShapeWorldInternal.h` | Uses native density sign to plan cached, connected rock spans only across unsupported route ranges; shared by both recipes and all passage styles. |
| `PassageBridgeCache` | `Standalone/Source/OwnerWorldLoader.h` | Shares deterministic ranges by resolved-layout identity across shape instances. |
| `ApplyResolvedStratePassageCarves` | `Standalone/Core/src/ShapeWorldInternal.h` | Adds bridge density before carving the bore; gates native floor support on solid input and player-capsule clearance. |
| `auditPassageBridges` / `auditPassageOpenAir` / `--audit-resolved-layout-passages` | `Standalone/Source/StreamBenchmarkPipeline.h` | Measures bridge width, thickness, relief and connected ends; checks capsule support, open air, naturalness, route binding and the L24 negative control. |
| `PassageBridgeRangeAuditV1` / `passageBridgeRanges()` / `isPassageBridgeSample()` | `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`, `Standalone/Core/src/VoxelForgeCore.cpp` | Exposes audit-only bridge ranges and density queries to the standalone validator. |
The shared evaluator is version 13; FloatingIslands geometry remains version 7 and resolved-layout
schema V3 is unchanged. See ARCHITECTURE §8.44 and
[`Standalone/Research/WorldAssemblerM3/Linux26/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux26/REPORT.md).
### 3.28 Tile-bounded passage evaluation — World Assembler M3 Linux L28
| Symbol | Canonical file | Role |
|---|---|---|
| FScopedPassageTileQueries / BuildPassageFeatureTileList / ResolvedPassageIntersectsBox | Standalone/Core/src/ShapeWorldInternal.h; scope entered by GenerateMesh in Standalone/Core/src/VoxelForgeCore.cpp | Builds conservative per-tile route, column and mouth-support candidates from an AABB BVH; long paths use a nearest-segment BVH and L9 box checks use a separate passage-bound BVH. Empty native-only proof indexes fall back conservatively. The density arithmetic and serialized versions stay unchanged. |
See ARCHITECTURE §8.45 and
[Linux28 report](Standalone/Research/WorldAssemblerM3/Linux28/REPORT.md).
## 4. The density pipeline (most-edited hot path)
### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749
@@ -485,7 +485,7 @@ bool BuildFloatingIslandStratumPlan(const UVoxelStrateManager* StrateManager,
IslandPlan.topChunkZ = Slot.TopChunkZ;
IslandPlan.bottomChunkZ = Slot.BottomChunkZ;
auto& Recipe = IslandPlan.manifest.recipe;
Recipe.geometryVersion = 5;
Recipe.geometryVersion = 8;
Recipe.layoutChunkWidthSubvoxels = LayoutChunkWidthSubvoxels;
Recipe.seed = static_cast<std::uint32_t>(StrateManager->GetWorldSeed());
Recipe.ownerVoxelSizeMicrons = static_cast<std::uint32_t>(std::llround(OwnerVoxelSizeCm * 10000.0));
+3 -2
View File
@@ -36,8 +36,9 @@ command -v ar >/dev/null || { printf 'ar not found\n' >&2; exit 2; }
command -v pkg-config >/dev/null || { printf 'pkg-config not found\n' >&2; exit 2; }
pkg-config --exists egl glesv2 libpng || { printf 'EGL, GLESv2, and libpng development files are required\n' >&2; exit 2; }
BUILD_DIR="$ROOT/Build/linux-$VARIANT"
BIN_DIR="$ROOT/bin/linux"
BUILD_ROOT="${VOXELFORGE_BUILD_ROOT:-$ROOT/Build}"
BIN_DIR="${VOXELFORGE_BIN_DIR:-$ROOT/bin/linux}"
BUILD_DIR="$BUILD_ROOT/linux-$VARIANT"
mkdir -p "$BUILD_DIR/wrappers" "$BUILD_DIR/objects" "$BIN_DIR"
INCLUDES=(
@@ -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 10 adds per-strate passage styles and rough wall relief to resolved passages.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 10;
// 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,6 +666,28 @@ namespace VoxelForgeCore
std::vector<ResolvedLayoutPassagePointV1> controlPoints;
};
struct PassageVoidCrossingAuditV1
{
std::size_t passageIndex = 0;
std::size_t firstSegment = 0;
std::size_t lastSegment = 0;
std::uint64_t unsupportedSamples = 0;
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
{
std::int32_t upperStrateIndex = -1;
@@ -1314,6 +1336,12 @@ namespace VoxelForgeCore
ShapeBuildStats buildStats() const;
float densityAt(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.
+13 -9
View File
@@ -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 > 5
if (recipe.schemaVersion != 1 || recipe.geometryVersion < 1 || recipe.geometryVersion > 8
|| (recipe.geometryVersion == 1
&& (recipe.crustDepthBonusQ16 != 0 || recipe.rootDepthRatioQ16 != 0))
|| recipe.unitsPerVoxel != Q
@@ -753,10 +753,13 @@ 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)
{
const double rootTop = static_cast<double>(island.bottomZSubvoxels);
// The central buttress must meet the island crust underside. IslandBottom
// also includes the four shorter root lobes and sits below that surface.
const double rootTop = static_cast<double>(IslandCrustBottom(recipe, island));
const double rootBottom = static_cast<double>(recipe.anchorRootBottomZSubvoxels);
const double depth = std::max(1.0, rootTop - rootBottom);
const double blend = std::clamp(static_cast<double>(recipe.anchorRootRadiusSubvoxels)
@@ -942,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};
@@ -1024,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
@@ -1330,7 +1334,7 @@ std::optional<FloatingIslandManifestV1> FloatingIslandManifestV1::FromJson(
manifest.recipe.anchorRootBottomZSubvoxels)
||!floating_island_detail::ReadInteger(recipeValue.Get("anchor_mouth_offset_q"),
manifest.recipe.anchorMouthOffsetSubvoxels))
{error="floating-island geometry version 5 is missing a passage-rooted anchor field";return std::nullopt;}
{error="floating-island geometry version 7 is missing a passage-rooted anchor field";return std::nullopt;}
}
if (!floating_island_detail::ReadU32(root.Get("schema_version"), schema)
|| !floating_island_detail::ReadHash(root.Get("content_hash"), manifestHash)
+42 -9
View File
@@ -550,6 +550,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const auto routeAnchor=[](const ResolvedLayoutStratumV2& s,bool departure,
std::array<std::int64_t,3>& out)
{
if(departure)
for(const auto& a:s.anchors)
if(a.kind=="passage_anchor"&&a.values.size()>=10)
{out={a.values[7],a.values[8],a.values[9]};return true;}
if(!departure)
for(const auto& a:s.anchors)
if(a.kind=="passage_arrival"&&a.values.size()>=3)
{out={a.values[0],a.values[1],a.values[2]};return true;}
const ResolvedLayoutAnchorV2* selected=nullptr;
for(const auto& a:s.anchors)
if(a.kind=="route_point"&&a.values.size()>=3)
@@ -597,8 +605,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
// 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)),
cfg?cfg->mouthRadiusSubvoxels:0);
const std::int64_t midRadius=std::max<std::int64_t>(mouthRadius,
cfg?cfg->midRadiusSubvoxels:0);
const std::int64_t midRadius=std::max<std::int64_t>(
static_cast<std::int64_t>(std::llround(1.5*qPerMetre)),
cfg?cfg->midRadiusSubvoxels:mouthRadius);
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::uint32_t style=cfg?std::min<std::uint32_t>(cfg->style,3u):1u;
@@ -624,7 +633,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
for(const auto& anchor:upper.anchors)
if(anchor.kind=="passage_anchor"&&anchor.values.size()>=7)
{passageAnchor=&anchor;break;}
const bool anchoredSpiral=style==2&&passageAnchor!=nullptr;
const bool anchoredIslandPassage=passageAnchor!=nullptr
&&upper.generatorKind=="FloatingIslands";
const bool anchoredSpiral=style==2&&anchoredIslandPassage;
if(!hasUpperRoute||!hasLowerRoute)
{
const auto xy=PassageRandomXY(PassageSeed(seed,upper.strateIndex,lower.strateIndex,
@@ -652,7 +663,10 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::array<std::int64_t,2> upperTangent{},lowerTangent{};
const bool hasUpperTangent=hasUpperRoute
&&routeTangent(upper,true,upperTangent);
const bool hasLowerTangent=hasLowerRoute
const bool hasPassageArrival=std::any_of(lower.anchors.begin(),lower.anchors.end(),
[](const auto& anchor){return anchor.kind=="passage_arrival"
&&anchor.values.size()>=3;});
const bool hasLowerTangent=hasLowerRoute&&!hasPassageArrival
&&routeTangent(lower,false,lowerTangent);
const std::int64_t outerRingRadius=std::max<std::int64_t>(1,
@@ -671,6 +685,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::max<std::int64_t>(0,cfg?cfg->cascadeLedgeSubvoxels:0)
*static_cast<std::int64_t>(cfg?cfg->cascadeSteps:4)),
mouthRadius+2*qPerMetre,outerRingRadius);
if(anchoredIslandPassage)
ringRadius=std::min(ringRadius,mouthRadius+qPerMetre/2);
std::uint32_t phase=static_cast<std::uint32_t>(PassageSeed(seed,
upper.strateIndex,lower.strateIndex,connection,0x50484153u)%16);
if(hasUpperRoute)
@@ -700,7 +716,7 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
+clockwiseTangentY*upperTangent[1]>=0.0;
}
const int direction=clockwise?1:-1;
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree contract.
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree helix contract.
const std::int64_t wormRadialWobble=std::min<std::int64_t>(
std::max<std::int64_t>(0,wander/3),2*qPerMetre);
const std::int64_t wormCenterWobble=std::min<std::int64_t>(
@@ -716,10 +732,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const double loop=static_cast<double>(loopIndex);
const double phaseA=loop*0.6180339887498948+0.37;
const double phaseB=loop*0.4142135623730950+1.11;
const double jitterX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
const double jitterY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
radius+=static_cast<double>(wormRadialWobble)
*std::sin(angle+phaseA);
centerX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
centerY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
centerX=jitterX+(anchoredIslandPassage&&passageAnchor
?static_cast<double>(passageAnchor->values[0]):0.0);
centerY=jitterY+(anchoredIslandPassage&&passageAnchor
?static_cast<double>(passageAnchor->values[1]):0.0);
}
else if(pathStyle==3u)
{
@@ -730,6 +750,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
cfg->cascadeLedgeSubvoxels):0));
radius-=ledge*(0.5-0.5*std::cos(angle*steps));
}
if(pathStyle!=1u&&anchoredIslandPassage&&passageAnchor)
{
centerX=static_cast<double>(passageAnchor->values[0]);
centerY=static_cast<double>(passageAnchor->values[1]);
}
return std::array<std::int64_t,2>{
static_cast<std::int64_t>(std::llround(centerX+radius*directions[directionIndex][0]/65536.0)),
static_cast<std::int64_t>(std::llround(centerY+radius*directions[directionIndex][1]/65536.0))};
@@ -748,7 +773,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const std::int64_t anchorY=passageAnchor->values[1];
const std::int64_t rootRadius=passageAnchor->values[2];
const std::int64_t rootBottom=passageAnchor->values[5];
helixBedrockZ=rootBottom!=0?rootBottom:contentZQ(upper.bedrock.topMicrometres);
const std::int64_t bedrockTop=rootBottom!=0?rootBottom
:contentZQ(upper.bedrock.topMicrometres);
// Passage route heights are player-center positions. End one capsule
// half-height above the bedrock top so the final ramp step is walkable.
helixBedrockZ=bedrockTop+qPerMetre;
const std::int64_t helixRadius=spiralRadius;
if(rootRadius<helixRadius+midRadius+qPerMetre/4
||std::hypot(static_cast<double>(upperMouth[0]-anchorX),
@@ -796,6 +825,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
helixEndIndex=xy.size()-1;
hasAnchorHelix=helixEndIndex>0;
}
const std::int64_t routeGradeQ16=hasAnchorHelix
&&lower.generatorKind=="SurfaceWorld"?8000:TargetGradeQ16;
const std::array<std::int64_t,2> firstRing=ringPoint(phase);
if(hasAnchorHelix&&pathStyle==1u)
{
@@ -843,12 +874,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const std::size_t start=hasAnchorHelix?helixEndIndex:0;
for(std::size_t i=start+1;i<xy.size();++i)
total+=distanceQ(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1]);
if(!hasLowerTangent&&!xy.empty())
total+=distanceQ(lowerMouth[0]-xy.back()[0],lowerMouth[1]-xy.back()[1]);
return total;
};
while(loops<256)
{
totalHorizontal=measurePath();
if(totalHorizontal*static_cast<std::uint64_t>(TargetGradeQ16)
if(totalHorizontal*static_cast<std::uint64_t>(routeGradeQ16)
>=static_cast<std::uint64_t>(verticalDistance)*65536ull)break;
for(int step=1;step<=16;++step)
{
File diff suppressed because it is too large. Load diff
+84
View File
@@ -1164,6 +1164,44 @@ namespace VoxelForgeCore
}
return false;
}
bool ResolvedPassageTouchesBox(const ResolvedLayoutSnapshotV3& layout,
const FIntVector& minimum,const FIntVector& maximum,std::uint32_t coreVoxelSizeMicrons)
{
if(layout.passages.empty())return false;
constexpr double Q=static_cast<double>(WorldAssemblySubvoxelsPerVoxel);
const double voxelsPerMetre=coreVoxelSizeMicrons>0
?1000000.0/coreVoxelSizeMicrons:4.0;
const double bridgeHalfWidthVoxels=3.5*voxelsPerMetre;
const double bridgeFootDepthVoxels=(5.0-0.13)*voxelsPerMetre;
const double tileMinimum[3]={static_cast<double>(minimum.X),
static_cast<double>(minimum.Y),static_cast<double>(minimum.Z)};
const double tileMaximum[3]={static_cast<double>(maximum.X),
static_cast<double>(maximum.Y),static_cast<double>(maximum.Z)};
for(const auto& passage:layout.passages)
for(std::size_t segment=1;segment<passage.controlPoints.size();++segment)
{
const auto& a=passage.controlPoints[segment-1];
const auto& b=passage.controlPoints[segment];
const double radius=static_cast<double>(std::max(
a.radiusSubvoxels,b.radiusSubvoxels))/Q;
const double horizontalExtent=std::max(radius,bridgeHalfWidthVoxels);
const double low[3]={
std::min(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q-horizontalExtent,
std::min(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q-horizontalExtent,
std::min(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q-radius
-bridgeFootDepthVoxels};
const double high[3]={
std::max(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q+horizontalExtent,
std::max(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q+horizontalExtent,
std::max(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q+radius};
bool overlap=true;
for(int axis=0;axis<3;++axis)
overlap&=high[axis]>=tileMinimum[axis]&&low[axis]<=tileMaximum[axis];
if(overlap)return true;
}
return false;
}
}
bool World::compile(const ShapeBuildRequest& request,const JobScheduler& scheduler,std::string& error)
@@ -1246,6 +1284,8 @@ namespace VoxelForgeCore
if(IntersectsBox(feature.minimumSubvoxels,feature.maximumSubvoxels,
subMinimum,subMaximum))return false;
if(RouteTouchesBox(*selectedPlan,subMinimum,subMaximum))return false;
if(ResolvedPassageTouchesBox(*impl_->resolvedLayout,boundsMin,boundsMax,
impl_->owner->CoreVoxelSizeMicrons))return false;
if(OwnerPassageTouchesBox(*impl_->owner,boundsMin,boundsMax))return false;
FStandaloneShapeWorld proofGeometry;
if(!proofGeometry.BuildShapeDependencyProof(*impl_->owner,boundsMin,boundsMax,
@@ -1502,6 +1542,44 @@ 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<PassageVoidCrossingAuditV1> World::passageVoidCrossings() const
{
std::vector<PassageVoidCrossingAuditV1> result;
if(!impl_||!impl_->shapeReady.load(std::memory_order_acquire)||!impl_->shape)return result;
const auto& crossings=impl_->shape->GetPassageVoidCrossings();
result.reserve(crossings.size());
for(const auto& crossing:crossings)
{
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::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->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
?impl_->shape->DensityDispatchPathAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z))
@@ -2059,6 +2137,12 @@ namespace VoxelForgeCore
out.diagnostics.featureListMilliseconds=std::chrono::duration<double,std::milli>(
std::chrono::steady_clock::now()-FeatureListStart).count();
const ScopedWorldAssemblyFeatureQueriesV1 featureScope(featureQueries);
// GenerateMesh samples only origin..origin+extent plus the one-step normal halo;
// queryMinimum/queryMaximum above are exactly that inclusive domain.
// GenerateMesh n'échantillonne que origin..origin+extent et la marge de normale d'un pas ;
// queryMinimum/queryMaximum ci-dessus couvrent exactement ce domaine inclusif.
const FStandaloneShapeWorld::FScopedPassageTileQueries passageFeatureScope(
tileShape,queryMinimum,queryMaximum);
const bool bDiagnosticColumnSampling=options.diagnosticGlobalOctaveDrop!=0
||options.diagnosticColumnInterpolationStride>1;
const std::uint32_t PreviousOctaveDrop=bDiagnosticColumnSampling
@@ -0,0 +1,86 @@
# World Assembler L25 — FI helix inside the root
**The ribbon came from two causes.** The shared passage compositor stamped route-mouth tread/support into native air, and the L24 6 m root could not contain this route: its measured centerline reached 5.562 m from the root axis and the mouth bore is 4.5 m. That leaves a nominal `6 - 5.562 - 4.5 = -4.062 m` wall allowance. The axis and units were correct; the support pass ignored surrounding rock, and the root was too small.
L25 gates shared route-mouth support on negative pre-passage density, so it can reinforce existing rock but cannot create a shelf in air. The FI anchor root is now a relief-bearing 13.25 m nominal rock column. I chose a sturdier column with the existing uneven relief over a thin cylinder; it remains column-shaped from outside. The authored spiral stays centered on the root axis.
## Root and passage measurements
Axis `(9.800, 4.571) m`; helix centerline radius `2.999–5.562 m`; bore radius `4.5 m` at the mouth and `3.0 m` through the middle. The conservative wall estimate uses the largest path offset and mouth bore at every height.
| Height (m) | Solid radius min / mean / max (m) |
|---:|---:|
| -68.209 | 12.000 / 12.129 / 12.375 |
| -80.643 | 12.125 / 12.254 / 12.500 |
| -93.595 | 12.500 / 12.672 / 12.875 |
| -106.548 | 12.875 / 13.012 / 13.250 |
| -118.982 | 13.000 / 13.168 / 13.375 |
Minimum measured wall allowance is `1.938 m`, above the existing `1.5 m` reserve.
## Audits
The authored FI Spiral passed on Clang and GCC: 61,173 capsule samples, `blocked=0`, 5,318 support samples, `unsupported=0`, `grade_failures=0`; both route bindings pass, and walkability is 1,135/1,135. Strict layout validation accepted with zero issues; malformed controls were rejected 9/9.
The open-air audit sampled 813,632 passage support points at 0.25 m spacing: `violations=0`, including 11,520 route-support samples. Its L24 ungated-support negative control found 1,438 violations. Naturalness passed with a 0 m flat run and 0.767 m wall-relief peak-to-peak; the L23 smooth-wall negative control was detected at 0 m relief. The capsule, open-air, and naturalness results match between Clang and GCC.
All four style overrides in both recipes passed the open-air audit (zero violations; the L24 control was detected each time). The capsule sweep has failures outside the authored FI Spiral: FI styles 0/1/3 have 7/13/6 blocked samples; SurfaceWorld styles 0/1/2/3 have 4,255/4,071/3,948/4,117 unsupported samples after the safe support gate. Their blocked/grade counts are zero. These are alternate-style walkability failures, not open-air emissions; the canonical FI Spiral and composed SurfaceWorld route pass. The individual logs are `Saved/Linux/linux25-style-*.log`.
L13 parity passed on both compilers: FI 8/8 page pairs, 14 higher-LOD pairs, 782,026 exact-query samples, zero mismatches; SurfaceWorld 5 page pairs, 9 native-only pairs, 14 higher-LOD pairs, 910,651 exact-query samples, zero mismatches. Both had one passing edit pair. L9 uniform-block proofs had zero violations: SurfaceWorld checked 26,977 blocks / 35,906,387 samples; FI used its expected 21,504 fallbacks/unknowns and checked no blocks.
The 24 m crossing passed both compilers and recipes. FI processed 314 moving tiles and SurfaceWorld 432; compiler hashes match per recipe. Crossing whole-view density/mesh/payload/topology hashes (FI 2,370 tiles; SurfaceWorld 2,553):
- FI: `c284b42ced276f4c / f6a90d0027d8d6fe / fdec2a7f61215a1e / 60a99d7c20700cd6`
- SurfaceWorld: `cee18b39a9271559 / c1713be06b92bd8e / fd7954350ebfacfc / c58b075a1b7f2895`
## Determinism and SurfaceWorld
The exact LOD0–8 hash matrix passed at W1/W8/W12 for Clang and GCC: 2,370 whole-view tiles, 960 full-detail tiles, all nine LOD rows and exact-query hashes identical across workers and compilers. Hash vectors are density/mesh/payload/topology:
| Recipe | Whole view (2,370 tiles) | Full detail (960 tiles) | Exact-query density / detail / collision |
|---|---|---|---|
| SurfaceWorld | `8d494f8f843171b2 / 37d21941f6d9cce8 / 47248393fa2f3322 / 36d03d874daef4ae` | `ace56c8f205238ad / a9c603a1248de6b8 / ea55f1f4fcc6a894 / 5ea7bc78a1b678ae` | `c949c4df2ce6f9d9 / 114c501e2d830d94 / e6011d3a248d4849` |
| Floating Islands | `6f0095c01b066744 / efea60f7a9c1d675 / 849c1829e1dcddd5 / 4f7cc65dc1adc234` | `d18e722b37a2479e / 0e410a8e80a3e7f7 / 0751926f0c67d8a4 / f01208bc2f7841ec` | `7b7c50ac24ccadcc / efcba20c0c70c415 / e604823a249029bf` |
Re-run command, with `N=1,8,12`, both compiler binaries, and both recipes:
```sh
timeout 1800s taskset -c 0-11 env LP_NUM_THREADS=12 prlimit --as=6442450944 -- Standalone/bin/linux/VoxelForgeCoreHeadless-linux25-<clang|gcc> --world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate --clip-radius=3 --max-clip-level=8 --far-horizon-lod8-step=0 --workers=N --recipe=<surface-world|floating-islands> Standalone/data/owner_world.json
```
SurfaceWorld away from the passage was directly compared with L23 in L24 and matched at 960 full-detail tiles: `66ac781666579e3e / 914873894a0e38c4 / ec8b03ade039cd56 / a2b621b0321d43dc`. L25 changes only passage/root generation and the shared passage composition region; it does not change the away-from-passage SurfaceWorld field. The L25 full-view hashes above cover a different tile selection from that away-only comparison.
## Captures
The four final captures are 1920×1080 JPEGs under `captures/`, each below 300 KB:
- `fi-pillar-exterior.jpg` (43 KB): wide exterior; thick relief-bearing root, no outside ribbon.
- `fi-pillar-cutaway.jpg` (53 KB): vertical cutaway exposing the helix and central rock.
- `fi-helix-inside.jpg` (37 KB): headlamp on, 90° FOV, camera `(11.495, 7.047, -87.858) m` at resolved route point 200, about 2 m above the tread, aimed down the route tangent. The tight turn leaves a close, wall-heavy view; the cutaway is clearer for the full spiral.
- `sw-arrival-mouth.jpg` (55 KB): headlamp on, 80° FOV, camera `(9.800, 4.571, -133.000) m`, 5.5 m below the lower mouth, looking up into the SW arrival.
## Changes, invariants, and run history
Core evaluator version is 12; FI geometry version is 7; resolved-layout schema V3 is unchanged. Source changes are in the Core passage planner/compositor, FI root geometry, and the standalone audit/hash reporting. `ARCHITECTURE.md` §8.43 and `CODEMAP.md` §3.26 document the change. The only Unreal edit is the adapter's FI geometry-version assignment (`geometryVersion = 7`); Unreal was unavailable, so that adapter edit was not compiled here.
L3 FP-contract preamble/self-test, L4 `FLazy`, L7 shared cache, L9/L12 proofs, L11 readiness/crash fix, L13 route binding, L18/L19 shared ceiling, L21/L22 layout and bands, L23/L24 passages, ARCHITECTURE §8.10, and CLAUDE.md async rules remain intact. No commit, push, or stash was made.
Failed or retried runs:
- The first scene export omitted `--render-distance-chunks=0`; it expanded to 593,068 tiles / about 640 MB and was stopped before 15 minutes, then its partial export was removed. A render-distance-48 retry returned 844 plane-dominated tiles / 31 MB and was discarded. Clipmap-only (195 tiles) and focused 27-tile detail exports succeeded.
- Two extra GCC audit invocations exited 2 because the headless binary needs the owner JSON as a positional path; the corrected invocation with `Standalone/data/owner_world.json` passed. The requested six-worker/compiler/recipe hash matrix itself passed.
- Early interior camera trials missed the resolved helix centerline and showed wall-only frames; the final interior frame uses a point extracted from the current resolved layout. No build or audit exceeded 30 minutes, and no step was left stuck for 15 minutes.
## Orchestrator review (Claude) — side branch, not merged yet
- The FI helix fix is confirmed by my capture review: `fi-pillar-exterior.jpg` shows a solid relief-bearing
column with no outside ribbon, and `fi-pillar-cutaway.jpg` shows the helix inside it.
- **Regression that blocks merge:** the support gate makes non-FI passages unwalkable. With the SurfaceWorld
recipe (the owner world's TunnelNetwork strate above SurfaceWorld), every style has ~4,000 unsupported
capsule samples (L24: 0). FI styles 0/1/3 have blocked samples. The owner world's real TN→SW passage is
affected, so a player can fall through it.
- Kept on side branch `wip/l25-helix`; `assembler/world` stays at L24 (`cb9236c`) until L26 makes every style
in both recipes pass with 0 blocked / 0 unsupported / 0 open-air violations.
- Design decision (owner delegated decisions to me, 2026-10-21): passages are tunnels in rock. The planner keeps
the path inside solid ground where possible; unavoidable open-air crossings get a natural, grounded rock
bridge (thick, relief, connected to rock on both ends), never a floating tread.
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

@@ -0,0 +1,144 @@
# World Assembler L26 — passages walkable in rock
**All four styles pass for both recipes.** Clang and GCC report zero blocked capsule samples, zero
unsupported samples, zero grade failures, zero open-air violations, passing naturalness, and passing
route bindings. The L24 open-air control and L23 smooth-wall control were detected.
## Where support was missing
In the owner SurfaceWorld recipe, the default Spiral passage has 1,083 control points. Its unsupported
bridge range is segments 98–1077, a 1,957.395 m gap. Segment 98 is at about `(0,-5,-142.7) m`; segment
1077 is at `(-4.6,-1.9,-497.4) m`. Both are inside the SurfaceWorld stratum (`-632..-120 m`), below
its native terrain. The gap starts after the TunnelNetwork transition; it is neither TunnelNetwork
cave air nor a stratum seam. The first L25 failure sample had only 2/5 native support probes, and
following samples had 0/5. Their dispatch path was `SurfaceWorld-native`.
Core now scans the native field sign and adds a deterministic bridge only over contiguous unsupported
ranges. The shared density field gives the bridge at least 5 m width, 3–5 m planned thickness and
surface relief. The audit measured two connected ends, at least 5 m width, 256/256 cross-sections,
3.5–6 m thickness and 2.5 m relief on the default Spiral. All four SurfaceWorld styles use connected
bridges; Floating Islands already has supporting rock and needs none. The capsule clearance gate also
checks the resolved player capsule, fixing FI styles 0/1/3 at their bent mouth segments.
The first bridge export still contained no passage mesh because tile readiness classified all nearby
tiles as native-only. Resolved passage and bridge bounds now keep those tiles shape-dependent. The final
local export changed `shape_free_desired` from 27/27 to 4/27 and contains the composed bridge density.
## Eight-row audit
Counts are from the Clang W12 run; GCC W12 matched every row. `B/U/G` means blocked, unsupported and
grade failures. Route bindings are required bindings passed / required bindings.
| Recipe | Style | Capsule samples | Support samples | B/U/G | Open-air samples / violations | Wall relief | Bindings | Bridge segments / length |
|---|---:|---:|---:|---:|---:|---:|---:|---|
| SurfaceWorld | 0 | 301,140 | 32,765 | 0/0/0 | 3,887,808 / 0 | 0.472 m | 1/1 | 30–293 / 2,004.318 m |
| SurfaceWorld | 1 | 284,949 | 31,046 | 0/0/0 | 3,707,328 / 0 | 0.449 m | 1/1 | 33–357 / 1,945.857 m |
| SurfaceWorld | 2 | 275,877 | 30,072 | 0/0/0 | 3,664,064 / 0 | 0.410 m | 1/1 | 98–1077 / 1,957.395 m |
| SurfaceWorld | 3 | 287,154 | 31,298 | 0/0/0 | 3,741,792 / 0 | 0.552 m | 1/1 | 34–373 / 1,980.607 m |
| Floating Islands | 0 | 50,589 | 4,407 | 0/0/0 | 695,616 / 0 | 0.779 m | 2/2 | none |
| Floating Islands | 1 | 57,015 | 5,060 | 0/0/0 | 742,016 / 0 | 0.806 m | 2/2 | none |
| Floating Islands | 2 | 61,173 | 5,318 | 0/0/0 | 813,632 / 0 | 0.767 m | 2/2 | none |
| Floating Islands | 3 | 54,369 | 4,325 | 0/0/0 | 743,456 / 0 | 0.681 m | 2/2 | none |
Every row passed naturalness (0 m flat run; relief threshold 0.2 m), route binding and strict layout
validation. The validator accepted with zero issues and rejected its malformed controls 9/9. Each L24
open-air negative control and L23 smooth-wall negative control was detected.
## Captures
All are 16:9 JPEGs below 300 KB in `captures/`:
| Capture | View | Size | SHA-256 |
|---|---|---:|---|
| `sw-passage-outside.jpg` | Midspan from outside, 1920×1080 | 90,937 B | `28378eeee755faf7446c0b2ce0eb8d2368c79b42f7de4c15e8b2f4d58fb7754d` |
| `sw-passage-inside.jpg` | Eye-height at first bridged segment, 1600×900 | 47,519 B | `ccadc33c36366a0ca7b2fcda0a21e4cea67bda107f0e20015171fd620d495249` |
| `sw-natural-bridge-wide.jpg` | Wide midspan view, 1920×1080 | 70,192 B | `f4a66fec1adebfbdf5806bb2e7c5a6470e3e8d9dcd60f495d930bbb1d0c5669e` |
| `fi-pillar-exterior.jpg` | Floating Islands pillar exterior, 1600×900 | 35,857 B | `b977ff34acee1294a24c2465b1c9d3d78014cff4b8eceb667f317a0a0b46cc67` |
## Determinism and regressions
The L25 hash command was rerun with the L26 binaries for both recipes, W1/W8/W12, Clang/GCC:
```sh
timeout 1800s taskset -c 0-11 env LP_NUM_THREADS=12 prlimit --as=6442450944 -- \
Saved/Linux/bin/VoxelForgeCoreHeadless-linux26-<clang|gcc> \
--world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate \
--clip-radius=3 --max-clip-level=8 --far-horizon-lod8-step=0 --workers=N \
--recipe=<surface-world|floating-islands> Standalone/data/owner_world.json
```
All six runs per recipe matched. Hash vectors are density / mesh / payload / topology; full detail is
960 tiles and whole view is 2,370 tiles.
| Recipe | Full detail | Whole view | Exact query: density / unclamped / detail / collision |
|---|---|---|---|
| SurfaceWorld | `ace56c8f205238ad / a9c603a1248de6b8 / ea55f1f4fcc6a894 / 5ea7bc78a1b678ae` | `307d5df80e0165b4 / 1d61f30e5733beca / 3aaef136176c4b12 / aa5ff7c2a821196f` | `c949c4df2ce6f9d9 / c949c4df2ce6f9d9 / 114c501e2d830d94 / e6011d3a248d4849` |
| Floating Islands | `d18e722b37a2479e / 0e410a8e80a3e7f7 / 0751926f0c67d8a4 / f01208bc2f7841ec` | `51decfb71d282506 / 69448ec1c7fc954f / e2ff37c98fe8e494 / 5beeb7f94fdbf3d4` | `7b7c50ac24ccadcc / 7b7c50ac24ccadcc / efcba20c0c70c415 / e604823a249029bf` |
The 24 m crossing passed for both compilers and recipes. Each processed 314 moving tiles, with identical
compiler hashes. Moving-tile vectors (density / mesh / payload / topology): SurfaceWorld
`3561ea23485e359f / e8331620fb0fb908 / 765f7dad67c852aa / 3ccc09ac81c05d71`; Floating Islands
`e3d0ea833bca4215 / 6b3d0f148ed83d93 / d6ed85f16acd895e / 9745683036522461`.
SurfaceWorld away from the passage was compared directly between L25 Clang and final L26 Clang at
`--camera=10000,10000,-100,0,0`. Full detail, whole view, all LOD0–8 rows and exact-query hashes were
identical (12/12). Full-detail vector: `1c6abc5e9c657e98 / a1624a3c19bbe554 / bf98934c9d846f3a /
bbdc2a6b821c66d6`; whole-view vector: `40c2be0c7bbdaf28 / 7d9ac2a85020dc7d / c378e48bab2d194f /
81014ec4b888107a`; exact-query vector: `482500abbe835b11 / c4948c7179963784 / efcba20c0c70c415 /
137e8f6c0b03a624`.
Strict validation passed on both compilers and recipes. L13 route parity passed on both compilers/recipes:
8/8 page pairs, 14 higher-LOD pairs, one edit pair, 782,026 exact-query samples and zero mismatches.
For L9 proofs, the passage-centered view has no eligible native blocks. At the same 10 km away-from-route
view, SurfaceWorld checked 4,848 blocks / 6,452,688 samples with 1,296 fallbacks and zero violations
on both compilers. Floating Islands had its expected 21,504 unknown fallbacks and zero violations.
Final headless binary SHA-256: Clang `fc0a5a74f17566384e094cb2429d8925147dd3eb32fb925417393e00c9bb19d5`; GCC
`54843bef3a64087e55d3eb9a76fb0856162b6ad9aeb03d6e1c204c3e91d21ca5`.
Clang built with FP contraction off; GCC used its default FP mode. Both built and started without the L3
FP-contract self-test rejecting them. Core evaluator version is 13; FI geometry remains 7 and layout
schema V3 is unchanged. Changes are shared Core, standalone audits, Linux build output configuration,
and ARCHITECTURE §8.44 / CODEMAP §3.27. No Unreal files changed, and no async path was added. The L4
`FLazy`, L7 cache, L9/L12 proofs, L11 readiness/crash handling, L13 binding, L18/L19 ceiling,
L21/L22 layout and bands, L23–L25 passage/helix, §8.10 and CLAUDE.md async rules remain intact.
## Failed and retried runs
- The first build command used an invalid `clang` variant; corrected to Clang/GCC variants. Early build
iterations R3–R6 had compiler errors and were corrected before final binaries were produced.
- An unsupported `--world-assembler-audit` option exited 2; the correct option is
`--audit-resolved-layout-passages`. One early invocation omitted that flag and performed no passage
audit. Early bridge probes also segfaulted while crossing stratum dispatch; final audits use bounded
resolved-layout queries.
- Support iterations R22–R30 exposed successive failures: FI style 0 had 767, then 27, then 5 blocked /
33 unsupported samples; an offset experiment caused 746 unsupported samples; a control-point capsule
reference left 7 blocked samples. Correcting the capsule reference cleared those. R30 still had SW
bridge sections 254/255, four SW style-1 mouth blocks, and an invalid SW style-2 bridge thickness
sample. R31 corrected them; final matrix is clean.
- The first final audit batch labeled FI JSON files as Floating Islands but omitted `--recipe`, so those
invocations used SurfaceWorld. All 16 style audits were rerun with explicit recipe flags. An initial
proof run used `--force-generate`, which disables L9 block auditing; it was repeated without that flag.
The validator-only command also exited 2 until the required streaming flags were included; all four
corrected strict-validator runs passed.
- `FloorProfileBlend` still reports its L25 alternate-style failures: SurfaceWorld style 1 is 2.544 vox
over the 2.000 threshold and style 3 is 3.645 vox. Both values are identical in the L25 logs; they are
pre-existing and are not capsule, support, open-air or naturalness failures.
- Initial capture attempts used a wrong yaw and missed/partially missed the FI export volume. After
correcting the view and centering the export, the final captures above were rendered. Several inside
camera placements showed wall-only or void-only views; the selected interior frame is at the first
bridged segment.
No run exceeded 30 minutes or remained stuck for 15 minutes. Exports and logs are under `Saved/Linux/`;
this round added only this report and the four small JPEGs under `Standalone/`. An unrelated pre-existing
untracked `Linux18/exports/` directory was left untouched. No Unreal edits, commit, push or stash were made.
## Orchestrator review (Claude) — side branch, not merged
- The audits pass (8/8 rows at 0/0/0), but the SW "natural bridge" is a ~2 km rock ramp spiralling through the
open SurfaceWorld sky from the ceiling (≈−143 m) to the ground (≈−497 m). `sw-natural-bridge-wide.jpg` and
`sw-passage-outside.jpg` show fragmented floating slabs with thin shard spikes: not natural, and visible
from far away.
- Decision (delegated by the owner): one shared mechanism for every strate. When a passage must cross a large
open void inside a strate, it descends inside a natural rock column (ceiling-to-ground, like a
stalactite/stalagmite pair joined), with the spiral tunnel inside, generalising the L25 FI anchor root.
No long bridges through open air. Implemented in L27 on `wip/l25-helix`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@@ -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

@@ -0,0 +1,125 @@
# Linux L28 — tile-bounded columns and passages
Branch: wip/l25-helix, based on L27. No commit. No Unreal files changed.
## Cost and culling
The plain interleaved baseline puts the L27 overhead in tile streaming/meshing, not shape
compilation: mean whole-view time was 2.058 s versus L24's 1.527 s for SurfaceWorld (+34.8%),
and 19.961 s versus 16.699 s for FloatingIslands (+19.5%). Shape time stayed near 0.46 s
(SurfaceWorld) and 0.97 s (FloatingIslands). The initial extra work was passage composition
inside the map-wide density sampling loop.
GenerateMesh now enters a passage-query scope using the exact inclusive tile sample bounds,
including the normal halo. A conservative feature AABB BVH supplies candidate route segments,
columns and mouth support. Long route nearest-distance searches use a per-passage segment BVH.
L9 proof boxes use a separate passage-bound BVH; disjoint roots reject far boxes without scanning
segments. If a native-only negative-control shape has no proof index, its box check falls back to
a conservative linear test.
Instrumented full-view counts (diagnostic build; 2,370 desired tiles):
| Recipe | Composition samples | Column guard: calls / tiles | Exact column SDF: calls / tiles | Route band samples / tiles | Route SDF unions / tiles | Route samples skipped / tiles | Feature candidates: tiles / total |
|---|---:|---:|---:|---:|---:|---:|---:|
| SurfaceWorld | 12,039,941 | 1,885,887 / 692 | 3,017 / 4 | 1,380,907 / 870 | 164,337 / 543 | 7,470,572 / 1,792 | 8 / 1,222 |
| FloatingIslands | 58,019,623 | 7,619,575 / 689 | 7,213 / 6 | 1,902,086 / 708 | 62,507 / 89 | 54,848,675 / 2,212 | 14 / 1,331 |
The exact column SDF is spatially culled. The cheaper radial guard remains in tiles sharing the
column's Z slab because positive SDF values can lower positive base density; a broader tile skip
would need an exact bound on that field. This is part of the remaining SurfaceWorld cost.
Per composition sample, the profile counted 0.125 carve-segment tests, 0.036 support-segment tests
and 0.0136 route SDF unions in SurfaceWorld; FloatingIslands counted 0.0125, 0.0028 and 0.00108.
Column guards ran on 15.7% / 13.1% of samples, while the complex column SDF ran on 0.025% / 0.012%.
## Interleaved whole-view cost
Five W12 quartets ran in order L24, L28a, fresh L27-source build, L28b. Hashing was off.
Values below are means of the five samples; raw samples are in
Saved/Linux/linux28-r28-finalfix-cost5-{recipe}-{l24,l27,r28a,r28b}-p1..p5.log.
L24 used Saved/Linux/l24-source/bin/linux/VoxelForgeCoreHeadless-linux24-clang19;
L27 was rebuilt from the current L27 source for this comparison.
| Recipe | L24 | L27 | L28a | L28b | L28a / L28b vs L24 |
|---|---:|---:|---:|---:|---:|
| SurfaceWorld | 1.527 s | 2.058 s | 1.592 s | 1.605 s | +4.30% / +5.12% |
| FloatingIslands | 16.699 s | 19.961 s | 16.651 s | 16.787 s | -0.29% / +0.53% |
FloatingIslands returned to L24 cost. SurfaceWorld misses the ~3% target by 1.3–2.1 percentage
points. Its remaining excess is about 69–80 ms in streaming wall time and 13–15 ms in shape
time; the density-aware radial guard and per-tile query setup/traversal remain. The guard cannot
be removed bit-exactly without a proven upper bound on the incoming positive density.
## Bit parity and audits
Final Clang and GCC binaries match L27 for both recipes at W1, W8 and W12: all 12 hash records per
run match (full detail, whole view, LOD0–8, exact query). This is 12 compiler/recipe/worker
combinations with zero mismatches. Logs:
Saved/Linux/linux28-r28-hash-finalfix-{clang,gcc}-{surface-world,floating-islands}-w{1,8,12}.log.
Representative hashes, equal to L27:
| Recipe | Full detail: density / mesh / payload / topology | Whole view: density / mesh / payload / topology | Exact query: density / detail / collision |
|---|---|---|---|
| SurfaceWorld | ace56c8f205238ad / a9c603a1248de6b8 / ea55f1f4fcc6a894 / 5ea7bc78a1b678ae | 117547e5e18c6847 / db5fa276315ff2d4 / b4e9d01d70413fea / 03caf881fa047f1c | c949c4df2ce6f9d9 / 114c501e2d830d94 / e6011d3a248d4849 |
| FloatingIslands | ed550e0c8b182695 / 0e410a8e80a3e7f7 / 0751926f0c67d8a4 / f01208bc2f7841ec | 70ab5bc87dd174d2 / 6f357f9085a496f0 / 08ce7d4e036da65a / eb5eef04a5cb85d9 | 7b7c50ac24ccadcc / efcba20c0c70c415 / e604823a249029bf |
The 24 m crossing matches fresh L27-source builds on both compilers and recipes:
SurfaceWorld, 314 tiles: density 3561ea23485e359f, mesh e8331620fb0fb908,
payload 765f7dad67c852aa, topology 3ccc09ac81c05d71.
FloatingIslands: density e3d0ea833bca4215, mesh 6b3d0f148ed83d93,
payload d6ed85f16acd895e, topology 9745683036522461.
Across 4 styles × 2 recipes, capsule walkability, open air, naturalness, no-long-bridge,
strict-validator controls, route bindings and passage audits pass on final Clang/GCC binaries.
Final passage logs are
Saved/Linux/linux28-r28-finalpassage-{clang,gcc}-{surface-world,floating-islands}-style{0..3}.log.
The final route/proof/readiness matrix also passes in all 16 compiler/style/recipe runs:
L13 route parity verifies 8/8 page pairs and 14 higher-LOD exact pairs with zero mismatches;
the readiness guard catches its negative control; L9 reports zero proof violations.
SurfaceWorld has 0 unknown blocks; FloatingIslands has 21,504 fallback/unknown blocks for each
style. The diagnostic full-view profile queried 26,946 FI proof boxes with only 40 path-bound and
1 column-bound tests, so far boxes reject at the BVH root. These unknowns are not evidence of a
fat passage bound. A fresh rerun of the saved L27 binary with the default owner input also reports
21,504; older L27 logs showing 17,408 did not reproduce. Final matrix logs are
Saved/Linux/linux28-r28-finalmatrix-{clang,gcc}-{surface-world,floating-islands}-style{0..3}.log.
Two inherited SurfaceWorld FloorProfileBlend checks remain over the 2-voxel threshold in styles
1 and 3: 2.544 and 3.645 voxels. The same failures and values are in L27 logs for both compilers;
other styles pass.
## Invariants, edits and run history
Changed Core files: Standalone/Core/src/ShapeWorldInternal.h and
Standalone/Core/src/VoxelForgeCore.cpp. Navigation/design docs and this report were updated.
No Unreal edits or Unreal compile. L3 FP-contract preamble/self-test, L4 FLazy, L7 shared cache,
L9/L12 proof rules, L11 readiness, L13 route binding, L18/L19 shared ceiling, L21/L22 layout and
bands, L23–L27 passage behavior, ARCHITECTURE §8.10 and CLAUDE.md async rules remain intact.
Failed or retried runs:
- First parity/readiness command omitted --stream-benchmark and --stream-pipeline; rerun with both.
- Initial readiness negative-control crashed on an empty proof BVH in a temporary native-only
shape. Added the conservative no-index fallback; final readiness checks pass.
- The first final W1 hash command omitted the explicit owner data path and failed to open data
under Saved/Linux. Preserved as linux28-r28-hash-finalfix-clang-surface-world-w1-attempt1-failed.log;
rerun with Standalone/data/owner_world.json and all final W1/W8 hashes passed.
- Initial moving-crossing comparison used stale L27 logs. Rebuilt L27 from source and reran; all
four compiler/recipe hashes then matched.
- Older saved L27 proof logs reported 17,408 FloatingIslands unknown blocks. Reran the saved L27
binaries and compared with final L28: both report 21,504, zero violations.
- An exploratory composed-bound FloatingIslands W12 hash differed; the density-threshold variant
restored equality and is the version measured here. An interrupted/empty Clang R15 build was
rerun successfully.
No run exceeded 30 minutes or remained stuck for 15 minutes. Builds were Clang 19 and GCC 14,
W12 CPU affinity 0–11, with the 6 GiB address-space cap. No commit, push or stash was performed.
## Orchestrator review (Claude)
- Re-run by me (W12, no hashing, interleaved): SW L24 1.455/1.485/1.484 s vs L28 1.502/1.539/1.555 s (median +3.7%).
Accepted as the cost of the passage/column feature. FI is back to L24 cost.
- Bit-identical to L27 (12/12 configs + crossing). With this, `wip/l25-helix` (L25–L28) is merged into
`assembler/world`.
- Note for later: the pre-existing SW FloorProfileBlend check over threshold in styles 1/3 (2.544/3.645 voxels)
is unchanged since L27.
+35
View File
@@ -10,7 +10,11 @@
#include "VoxelTerrainOpDefinition.h"
#include <cmath>
#include <array>
#include <cstdint>
#include <memory>
#include <mutex>
#include <unordered_map>
struct FStandaloneParitySample
{
@@ -20,6 +24,35 @@ struct FStandaloneParitySample
int32 StrateIndex = INDEX_NONE;
};
struct FStandalonePassageVoidCrossing
{
std::size_t passageIndex=0;
std::size_t firstSegment=0;
std::size_t lastSegment=0;
std::uint64_t unsupportedSamples=0;
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 FStandalonePassageVoidCrossingCache
{
std::mutex mutex;
std::unordered_map<std::string,std::vector<FStandalonePassageVoidCrossing>> byLayout;
};
struct FStandaloneOwnerWorld
{
std::unique_ptr<UVoxelSettings> Settings;
@@ -45,6 +78,8 @@ struct FStandaloneOwnerWorld
std::uint32_t CoreVoxelSizeMicrons = 250000;
std::uint32_t StrateLayoutChunkSizeMicrometres = 8000000;
std::int64_t StrateLayoutChunkWidthSubvoxels = 8192;
std::shared_ptr<FStandalonePassageVoidCrossingCache> PassageVoidCrossingCache =
std::make_shared<FStandalonePassageVoidCrossingCache>();
};
namespace StandaloneOwnerLoader
+739 -20
View File
@@ -453,17 +453,31 @@ namespace StandaloneStreamBenchmark
std::array<std::array<double,4>,8> firstUnsupported{};
std::array<std::array<bool,5>,8> firstSupportMasks{};
std::size_t firstBlockedCount=0,firstUnsupportedCount=0;
std::array<double,4> firstDeepUnsupported{};
std::array<bool,5> firstDeepSupportMask{};
bool hasDeepUnsupported=false;
bool passed=false;
};
struct FPassageSegmentSupportAudit
{
std::uint64_t centers=0,unsupported=0,nativeUnsupported=0;
std::array<double,3> firstUnsupported{};
std::array<double,4> firstNativeDensities{};
std::uint32_t firstNativeSupportedProbes=0;
bool hasUnsupported=false;
};
const double coreMetres=static_cast<double>(World.CoreVoxelSizeMicrons)/1000000.0;
const auto auditPlayerPath=[&](const VoxelForgeCore::World& Field,
const std::vector<std::array<double,3>>& path,
double supportStartMetres,double supportStepMetres,
double supportMaximumMetres,std::uint32_t minimumSupportProbes,
double supportProbeRadiusMetres)
double supportProbeRadiusMetres,
const VoxelForgeCore::World* nativeField=nullptr,
std::vector<FPassageSegmentSupportAudit>* segmentSupport=nullptr)
{
FWalkAudit audit;
if(path.size()<2)return audit;
if(segmentSupport)segmentSupport->assign(path.size()-1,{});
constexpr std::array<double,7> heights{{-0.84,-0.60,-0.30,0.0,0.30,0.60,0.84}};
constexpr std::array<std::array<double,2>,8> directions{{
{{1.0,0.0}},{{0.7071067811865475,0.7071067811865475}},{{0.0,1.0}},
@@ -507,6 +521,9 @@ namespace StandaloneStreamBenchmark
const double y=(a[1]+dy*t)*coreMetres;
const double z=(a[2]+dz*t)*coreMetres;
++audit.centers;
FPassageSegmentSupportAudit* segmentAudit=segmentSupport
?&(*segmentSupport)[segment-1]:nullptr;
if(segmentAudit)++segmentAudit->centers;
for(const double h:heights)
{
const double capOffset=std::max(0.0,std::abs(h)-0.54);
@@ -523,6 +540,7 @@ namespace StandaloneStreamBenchmark
{{0.0,supportProbeRadiusMetres}},
{{0.0,-supportProbeRadiusMetres}}}};
std::uint32_t supportedProbes=0;
std::uint32_t nativeSupportedProbes=0;
double firstUnsupportedX=x,firstUnsupportedY=y,lastUnsupportedDensity=0.0;
std::array<bool,5> supportMask{};
for(std::size_t offsetIndex=0;offsetIndex<supportOffsets.size();++offsetIndex)
@@ -541,12 +559,48 @@ namespace StandaloneStreamBenchmark
supported=true;break;
}
}
if(nativeField)
{
for(double depth=supportStartMetres;
depth<=supportMaximumMetres+1.0e-6;depth+=supportStepMetres)
if(nativeField->densityAt({supportX/coreMetres,
supportY/coreMetres,(footZ-depth)/coreMetres})<0.0f)
{++nativeSupportedProbes;break;}
}
if(supported){++supportedProbes;supportMask[offsetIndex]=true;}
else{firstUnsupportedX=supportX;firstUnsupportedY=supportY;}
}
if(nativeField&&segmentAudit
&&nativeSupportedProbes<minimumSupportProbes)
++segmentAudit->nativeUnsupported;
if(supportedProbes<minimumSupportProbes)
{
++audit.unsupported;
if(segmentAudit)
{
++segmentAudit->unsupported;
if(!segmentAudit->hasUnsupported)
{
segmentAudit->hasUnsupported=true;
segmentAudit->firstUnsupported={x,y,footZ};
segmentAudit->firstNativeSupportedProbes=nativeSupportedProbes;
if(nativeField)
{
constexpr std::array<double,4> depths{{0.125,1.0,2.0,4.0}};
for(std::size_t depthIndex=0;depthIndex<depths.size();++depthIndex)
segmentAudit->firstNativeDensities[depthIndex]=nativeField->densityAt({
x/coreMetres,y/coreMetres,
(footZ-depths[depthIndex])/coreMetres});
}
}
}
if(!audit.hasDeepUnsupported&&footZ<-80.0)
{
audit.hasDeepUnsupported=true;
audit.firstDeepUnsupported={firstUnsupportedX,firstUnsupportedY,
footZ,lastUnsupportedDensity};
audit.firstDeepSupportMask=supportMask;
}
if(audit.firstUnsupportedCount<audit.firstUnsupported.size())
{
const std::size_t sample=audit.firstUnsupportedCount++;
@@ -658,6 +712,487 @@ namespace StandaloneStreamBenchmark
[index](const auto& s){return s.strateIndex==index;});
return it==ResolvedLayout->strates.end()?nullptr:&*it;
};
const auto controlSnapshot=CoreSnapshot.withoutResolvedLayoutPassages();
VoxelForgeCore::World blockedWorld(controlSnapshot);
std::string blockedCompileError;
const bool blockedCompiled=controlSnapshot
&&blockedWorld.compile(ShapeRequest,Scheduler,blockedCompileError);
if(!blockedCompiled)
{
Streamer.Stop();
std::fprintf(stderr,"[ResolvedPassageBlockedControl] compile_failed=%s\n",
blockedCompileError.c_str());
return 10;
}
struct FPassageOpenAirAudit
{
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;
};
constexpr double PassageSupportAuditSpacingMetres=0.25;
constexpr std::array<double,2> PassageSupportAuditDepthsMetres{{0.125,0.375}};
constexpr std::array<std::array<double,2>,16> PassageSupportAuditDirections{{
{{1.0000000000000000,0.0000000000000000}},
{{0.9238795325112867,0.3826834323650898}},
{{0.7071067811865476,0.7071067811865476}},
{{0.3826834323650898,0.9238795325112867}},
{{0.0000000000000000,1.0000000000000000}},
{{-0.3826834323650898,0.9238795325112867}},
{{-0.7071067811865476,0.7071067811865476}},
{{-0.9238795325112867,0.3826834323650898}},
{{-1.0000000000000000,0.0000000000000000}},
{{-0.9238795325112867,-0.3826834323650898}},
{{-0.7071067811865476,-0.7071067811865476}},
{{-0.3826834323650898,-0.9238795325112867}},
{{0.0000000000000000,-1.0000000000000000}},
{{0.3826834323650898,-0.9238795325112867}},
{{0.7071067811865476,-0.7071067811865476}},
{{0.9238795325112867,-0.3826834323650898}}}};
const auto auditPassageOpenAir=[&](const VoxelForgeCore::World& Field,
const VoxelForgeCore::World& Native,
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
std::size_t passageIndex)
{
FPassageOpenAirAudit audit;
const auto inspect=[&](double xMetres,double yMetres,double floorMetres,
double depthMetres,double supportThicknessMetres,bool routeSupport=false,
std::size_t passageSegment=std::numeric_limits<std::size_t>::max())
{
if(depthMetres<=0.0||depthMetres>supportThicknessMetres+1.0e-6)return;
++audit.supportSamples;
audit.routeSupportSamples+=routeSupport;
const VoxelForgeCore::Vec3d sample{xMetres/coreMetres,yMetres/coreMetres,
(floorMetres-depthMetres)/coreMetres};
const float nativeDensity=Native.densityAt(sample);
const float passageDensity=Field.densityAt(sample);
const float legacySupportDensity=std::min(nativeDensity,
static_cast<float>(-depthMetres/coreMetres));
if(nativeDensity>=0.0f&&legacySupportDensity<0.0f)
++audit.legacyViolations;
if(nativeDensity>=0.0f&&passageDensity<0.0f)
{
const bool connectedColumn=!routeSupport
&&passageSegment!=std::numeric_limits<std::size_t>::max()
&&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,
floorMetres-depthMetres,passageDensity};
++audit.violations;
}
};
const auto inspectFloorDisc=[&](double xMetres,double yMetres,double floorMetres,
double supportRadiusMetres,double depthMetres,double supportThicknessMetres,
bool routeSupport=false,
std::size_t passageSegment=std::numeric_limits<std::size_t>::max())
{
const std::size_t radialSteps=static_cast<std::size_t>(std::ceil(
supportRadiusMetres/PassageSupportAuditSpacingMetres));
for(std::size_t radialStep=0;radialStep<=radialSteps;++radialStep)
{
const double radial=std::min(supportRadiusMetres,
radialStep*PassageSupportAuditSpacingMetres);
for(const auto& direction:PassageSupportAuditDirections)
inspect(xMetres+direction[0]*radial,yMetres+direction[1]*radial,
floorMetres,depthMetres,supportThicknessMetres,routeSupport,
passageSegment);
}
};
for(std::size_t segment=1;segment<passage.controlPoints.size();++segment)
{
const auto& a=passage.controlPoints[segment-1];
const auto& b=passage.controlPoints[segment];
const double ax=qToMetres(a.positionSubvoxels[0]);
const double ay=qToMetres(a.positionSubvoxels[1]);
const double az=qToMetres(a.positionSubvoxels[2]);
const double bx=qToMetres(b.positionSubvoxels[0]);
const double by=qToMetres(b.positionSubvoxels[1]);
const double bz=qToMetres(b.positionSubvoxels[2]);
const double length=std::sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay)+(bz-az)*(bz-az));
const std::size_t intervals=std::max<std::size_t>(1,static_cast<std::size_t>(
std::ceil(length/PassageSupportAuditSpacingMetres)));
for(std::size_t sample=0;sample<=intervals;++sample)
{
if(segment>1&&sample==0)continue;
const double t=static_cast<double>(sample)/intervals;
const double centerX=ax+(bx-ax)*t,centerY=ay+(by-ay)*t;
const double centerZ=az+(bz-az)*t;
const double radius=qToMetres(a.radiusSubvoxels)
+(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t;
const double floorZ=centerZ-radius+0.20;
for(const double depth:PassageSupportAuditDepthsMetres)
inspectFloorDisc(centerX,centerY,floorZ,radius,depth,1.0,
false,segment-1);
}
}
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[&](const auto& value)
{return value.strateIndex==passage.upperStrateIndex;});
if(upperStratum!=ResolvedLayout->strates.end())
{
std::array<const VoxelForgeCore::ResolvedLayoutAnchorV2*,5> route{};
std::size_t routeCount=0;
for(const auto& anchor:upperStratum->anchors)
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
{
if(routeCount<route.size())route[routeCount++]=&anchor;
else
{
std::move(route.begin()+1,route.end(),route.begin());
route.back()=&anchor;
}
}
const double mouthX=qToMetres(passage.upperMouthSubvoxels[0]);
const double mouthY=qToMetres(passage.upperMouthSubvoxels[1]);
constexpr double RouteSupportReachMetres=13.0;
constexpr double RouteFloorOffsetMetres=1.20;
constexpr double RouteSupportThicknessMetres=1.0;
constexpr double RouteSupportDepthStepMetres=0.125;
for(std::size_t segment=1;segment<routeCount;++segment)
{
const auto& a=*route[segment-1];
const auto& b=*route[segment];
const double ax=qToMetres(a.values[0]),ay=qToMetres(a.values[1]);
const double az=qToMetres(a.values[2]);
const double bx=qToMetres(b.values[0]),by=qToMetres(b.values[1]);
const double bz=qToMetres(b.values[2]);
const double dx=bx-ax,dy=by-ay,dz=bz-az;
const double length=std::sqrt(dx*dx+dy*dy+dz*dz);
const std::size_t intervals=std::max<std::size_t>(1,
static_cast<std::size_t>(std::ceil(length
/PassageSupportAuditSpacingMetres)));
const double routeRadius=a.values.size()>=4
?std::max(0.75,qToMetres(a.values[3])):0.75;
for(std::size_t sample=0;sample<=intervals;++sample)
{
if(segment>1&&sample==0)continue;
const double t=static_cast<double>(sample)/intervals;
const double centerX=ax+dx*t,centerY=ay+dy*t;
const double centerZ=az+dz*t;
for(std::size_t radialStep=0;radialStep<=static_cast<std::size_t>(
std::ceil(routeRadius/PassageSupportAuditSpacingMetres));++radialStep)
{
const double radial=std::min(routeRadius,
radialStep*PassageSupportAuditSpacingMetres);
for(const auto& direction:PassageSupportAuditDirections)
{
const double x=centerX+direction[0]*radial;
const double y=centerY+direction[1]*radial;
if(std::hypot(x-mouthX,y-mouthY)>RouteSupportReachMetres)continue;
const double floorZ=centerZ-RouteFloorOffsetMetres;
for(double depth=RouteSupportDepthStepMetres;
depth<=RouteSupportThicknessMetres+1.0e-6;
depth+=RouteSupportDepthStepMetres)
inspect(x,y,floorZ,depth,RouteSupportThicknessMetres,true);
}
}
}
}
}
return audit;
};
struct FPassageColumnAudit
{
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 auditPassageColumns=[&](const VoxelForgeCore::World& Field,
const VoxelForgeCore::World& Native,
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
std::size_t passageIndex)
{
FPassageColumnAudit audit;
const double qMetres=coreMetres
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
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}}}};
const auto endpointConnected=[&](const std::array<double,4>& point)
{
const double x=point[0]*qMetres,y=point[1]*qMetres;
const double floor=point[2]*qMetres-point[3]*qMetres+0.13;
std::uint32_t supported=0;
for(const auto& offset:supportOffsets)
{
bool solid=false;
for(const double depth:{0.125,0.25})
if(Native.densityAt({(x+offset[0])/coreMetres,
(y+offset[1])/coreMetres,(floor-depth)/coreMetres})<0.0f)
{solid=true;break;}
supported+=solid;
}
return supported>=3;
};
const auto columnSolidAt=[&](std::size_t segment,double x,double y,double z)
{
return Field.isPassageColumnSample(passageIndex,segment,
{x/coreMetres,y/coreMetres,z/coreMetres});
};
const auto shortSpanSolidAt=[&](std::size_t segment,double x,double y,double z)
{
return Field.isPassageShortSpanSample(passageIndex,segment,
{x/coreMetres,y/coreMetres,z/coreMetres});
};
const auto crossings=Field.passageVoidCrossings();
for(const auto& crossing:crossings)
{
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 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=crossing.firstSegment
+std::min(segmentCount-1,(probe*segmentCount)/probeCount);
const auto& a=passage.controlPoints[segment];
const auto& b=passage.controlPoints[segment+1];
const double ax=qToMetres(a.positionSubvoxels[0]);
const double ay=qToMetres(a.positionSubvoxels[1]);
const double az=qToMetres(a.positionSubvoxels[2]);
const double bx=qToMetres(b.positionSubvoxels[0]);
const double by=qToMetres(b.positionSubvoxels[1]);
const double bz=qToMetres(b.positionSubvoxels[2]);
const double x=(ax+bx)*0.5,y=(ay+by)*0.5;
const double z=(az+bz)*0.5;
const double radius=(qToMetres(a.radiusSubvoxels)
+qToMetres(b.radiusSubvoxels))*0.5;
const double floor=z-radius+0.13;
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;
}
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;
};
if(Assembly)
for(const auto& stratum:ResolvedLayout->strates)
{
if(stratum.generatorKind!="FloatingIslands")continue;
const auto anchor=std::find_if(stratum.anchors.begin(),stratum.anchors.end(),
[](const auto& value){return value.kind=="passage_anchor"&&value.values.size()>=7;});
const auto islandPlan=std::find_if(Assembly->floatingIslands.begin(),
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];
const double axisX=qToMetres(anchor->values[0]);
const double axisY=qToMetres(anchor->values[1]);
const double rootBottom=qToMetres(anchor->values[5]);
const auto& islandRecipe=islandPlan->manifest.recipe;
const std::int64_t crustRatioQ16=islandRecipe.thicknessRatioQ16
+islandRecipe.crustDepthBonusQ16;
const std::int64_t crustDepthQ=(anchorIsland.radiusSubvoxels*crustRatioQ16
+32768)/65536;
const double rootTop=qToMetres(anchorIsland.topZSubvoxels-crustDepthQ);
const double nominalRootRadius=qToMetres(anchor->values[2]);
double helixMinimumRadius=std::numeric_limits<double>::infinity();
double helixMaximumRadius=0.0;
for(const auto& passage:ResolvedLayout->passages)
if(passage.upperStrateIndex==stratum.strateIndex)
for(const auto& point:passage.controlPoints)
{
const double z=qToMetres(point.positionSubvoxels[2]);
if(z<rootBottom||z>rootTop)continue;
const double radial=std::hypot(
qToMetres(point.positionSubvoxels[0]-anchor->values[0]),
qToMetres(point.positionSubvoxels[1]-anchor->values[1]));
helixMinimumRadius=std::min(helixMinimumRadius,radial);
helixMaximumRadius=std::max(helixMaximumRadius,radial);
}
if(!std::isfinite(helixMinimumRadius))continue;
double minimumMeasuredRootRadius=std::numeric_limits<double>::infinity();
std::uint64_t rootRaySamples=0;
constexpr std::array<double,5> RootHeightFractions{{0.01,0.25,0.5,0.75,0.99}};
for(const double fraction:RootHeightFractions)
{
const double z=rootTop+(rootBottom-rootTop)*fraction;
double minimumRadius=std::numeric_limits<double>::infinity();
double maximumRadius=0.0,meanRadius=0.0;
constexpr std::size_t DirectionCount=32;
constexpr double RayStepMetres=0.125;
const std::size_t raySteps=static_cast<std::size_t>(std::ceil(
(nominalRootRadius+2.0)/RayStepMetres));
for(std::size_t direction=0;direction<DirectionCount;++direction)
{
const double angle=2.0*3.14159265358979323846*direction/DirectionCount;
double radius=0.0;
for(std::size_t step=0;step<=raySteps;++step)
{
const double probeRadius=step*RayStepMetres;
const VoxelForgeCore::Vec3d probe{
(axisX+probeRadius*std::cos(angle))/coreMetres,
(axisY+probeRadius*std::sin(angle))/coreMetres,z/coreMetres};
if(blockedWorld.densityAt(probe)>=0.0f)break;
radius=probeRadius;
}
minimumRadius=std::min(minimumRadius,radius);
maximumRadius=std::max(maximumRadius,radius);
meanRadius+=radius;
++rootRaySamples;
}
meanRadius/=DirectionCount;
minimumMeasuredRootRadius=std::min(minimumMeasuredRootRadius,minimumRadius);
std::printf("[PassageRootRadiusMeasure] strate=%d z_m=%.3f solid_radius_min_m=%.3f mean_m=%.3f max_m=%.3f nominal_root_m=%.3f rays=%zu\n",
stratum.strateIndex,z,minimumRadius,meanRadius,maximumRadius,
nominalRootRadius,DirectionCount);
}
const auto firstRootPassage=std::find_if(ResolvedLayout->passages.begin(),
ResolvedLayout->passages.end(),[&](const auto& passage)
{return passage.upperStrateIndex==stratum.strateIndex;});
const double mouthBoreRadius=firstRootPassage==ResolvedLayout->passages.end()?0.0
:qToMetres(firstRootPassage->mouthRadiusSubvoxels);
const double midBoreRadius=firstRootPassage==ResolvedLayout->passages.end()?0.0
:qToMetres(firstRootPassage->midRadiusSubvoxels);
const double maximumBoreRadius=std::max(mouthBoreRadius,midBoreRadius);
std::printf("[PassageRootMeasure] strate=%d axis_m=(%.3f,%.3f) helix_centerline_radius_min_m=%.3f max_m=%.3f mouth_bore_radius_m=%.3f mid_bore_radius_m=%.3f nominal_root_m=%.3f measured_min_root_m=%.3f minimum_wall_m=%.3f samples=%llu\n",
stratum.strateIndex,axisX,axisY,helixMinimumRadius,helixMaximumRadius,
mouthBoreRadius,midBoreRadius,nominalRootRadius,minimumMeasuredRootRadius,
minimumMeasuredRootRadius-helixMaximumRadius-maximumBoreRadius,
static_cast<unsigned long long>(rootRaySamples));
}
const auto mouthInContent=[&](std::int32_t index,const std::array<std::int64_t,3>& mouth)
{
const auto* stratum=findStratum(index);if(!stratum)return false;
@@ -667,8 +1202,38 @@ namespace StandaloneStreamBenchmark
return zUm>=stratum->content.bottomMicrometres&&zUm<stratum->content.topMicrometres;
};
std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0;
for(const auto& passage:ResolvedLayout->passages)
std::uint64_t openAirViolations=0,openAirLegacyViolations=0,openAirSamples=0;
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];
std::vector<std::array<double,3>> path;path.reserve(passage.controlPoints.size());
for(const auto& point:passage.controlPoints)
{
@@ -678,8 +1243,28 @@ namespace StandaloneStreamBenchmark
path.push_back({qToMetres(point.positionSubvoxels[0])/coreMetres,
qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0});
}
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45);
std::vector<FPassageSegmentSupportAudit> segmentSupport;
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45,
&blockedWorld,&segmentSupport);
const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage);
const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld,
passage,passageIndex);
const FPassageColumnAudit columnAudit=auditPassageColumns(Shape,blockedWorld,
passage,passageIndex);
openAirSamples+=openAirAudit.supportSamples;
openAirViolations+=openAirAudit.violations;
openAirLegacyViolations+=openAirAudit.legacyViolations;
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];};
const bool mouthsInRadius=radialSquared(passage.upperMouthSubvoxels)
@@ -706,16 +1291,109 @@ 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 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.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),
PassageSupportAuditSpacingMetres,
openAirAudit.violations==0?"PASS":"FAIL");
for(std::size_t i=0;i<openAirAudit.firstViolationCount;++i)
std::printf("[PassageOpenAirAuditSample] id=%s kind=unsupported_support xyz_m=(%.3f,%.3f,%.3f) density=%.6f\n",
passage.stableId.c_str(),openAirAudit.firstViolations[i][0],
openAirAudit.firstViolations[i][1],openAirAudit.firstViolations[i][2],
openAirAudit.firstViolations[i][3]);
for(std::size_t i=0;i<passageAudit.firstBlockedCount;++i)
std::printf("[ResolvedPassageAuditSample] id=%s kind=blocked xyz_m=(%.3f,%.3f,%.3f) density=%.6f\n",
passage.stableId.c_str(),passageAudit.firstBlocked[i][0],passageAudit.firstBlocked[i][1],
passageAudit.firstBlocked[i][2],passageAudit.firstBlocked[i][3]);
{
const auto& sample=passageAudit.firstBlocked[i];
double nearestDistanceSquared=std::numeric_limits<double>::infinity();
std::size_t nearestSegment=0;
double nearestT=0.0;
double nearestPassageSdf=std::numeric_limits<double>::infinity();
std::size_t nearestPassageSegment=0;
for(std::size_t segment=0;segment+1<path.size();++segment)
{
const auto& a=path[segment];const auto& b=path[segment+1];
const double dx=b[0]-a[0],dy=b[1]-a[1],dz=b[2]-a[2];
const double lengthSquared=dx*dx+dy*dy+dz*dz;
const double t=lengthSquared>0.0?std::clamp(
((sample[0]/coreMetres-a[0])*dx+(sample[1]/coreMetres-a[1])*dy
+(sample[2]/coreMetres-a[2])*dz)/lengthSquared,0.0,1.0):0.0;
const double ex=sample[0]/coreMetres-(a[0]+t*dx);
const double ey=sample[1]/coreMetres-(a[1]+t*dy);
const double ez=sample[2]/coreMetres-(a[2]+t*dz);
const double distanceSquared=ex*ex+ey*ey+ez*ez;
if(distanceSquared<nearestDistanceSquared)
{nearestDistanceSquared=distanceSquared;nearestSegment=segment;nearestT=t;}
}
for(std::size_t segment=0;segment+1<passage.controlPoints.size();++segment)
{
const auto& a=passage.controlPoints[segment];
const auto& b=passage.controlPoints[segment+1];
const double ax=qToMetres(a.positionSubvoxels[0]);
const double ay=qToMetres(a.positionSubvoxels[1]);
const double az=qToMetres(a.positionSubvoxels[2]);
const double dx=qToMetres(b.positionSubvoxels[0]-a.positionSubvoxels[0]);
const double dy=qToMetres(b.positionSubvoxels[1]-a.positionSubvoxels[1]);
const double dz=qToMetres(b.positionSubvoxels[2]-a.positionSubvoxels[2]);
const double lengthSquared=dx*dx+dy*dy+dz*dz;
const double t=lengthSquared>0.0?std::clamp(
((sample[0]-ax)*dx+(sample[1]-ay)*dy+(sample[2]-az)*dz)
/lengthSquared,0.0,1.0):0.0;
const double ex=sample[0]-(ax+t*dx),ey=sample[1]-(ay+t*dy),
ez=sample[2]-(az+t*dz);
const double radius=qToMetres(a.radiusSubvoxels)
+(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t;
const double signedDistance=std::sqrt(ex*ex+ey*ey+ez*ez)-radius;
if(signedDistance<nearestPassageSdf)
{nearestPassageSdf=signedDistance;nearestPassageSegment=segment;}
}
const VoxelForgeCore::Vec3d nativePosition{sample[0]/coreMetres,
sample[1]/coreMetres,sample[2]/coreMetres};
const float nativeDensity=blockedWorld.densityAt(nativePosition);
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 passage_column=%d native_path=%s\n",
passage.stableId.c_str(),sample[0],sample[1],sample[2],sample[3],
nativeDensity,nearestSegment,nearestT,nearestPassageSegment,
nearestPassageSdf,passageColumn?1:0,
blockedWorld.densityDispatchPathAt(nativePosition).c_str());
}
for(std::size_t i=0;i<passageAudit.firstUnsupportedCount;++i)
{
std::printf("[ResolvedPassageAuditSample] id=%s kind=unsupported xyz_m=(%.3f,%.3f,%.3f) density=%.6f\n",
passage.stableId.c_str(),passageAudit.firstUnsupported[i][0],
passageAudit.firstUnsupported[i][1],passageAudit.firstUnsupported[i][2],
passageAudit.firstUnsupported[i][3]);
}
for(std::size_t segment=0;segment<segmentSupport.size();++segment)
{
const auto& item=segmentSupport[segment];
if(!item.hasUnsupported)continue;
const auto& a=path[segment];const auto& b=path[segment+1];
const auto& sample=item.firstUnsupported;
const double firstX=sample[0]/coreMetres;
const double firstY=sample[1]/coreMetres;
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 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) 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],columnAtSupport?1:0,
item.firstNativeSupportedProbes,item.firstNativeDensities[0],item.firstNativeDensities[1],
item.firstNativeDensities[2],item.firstNativeDensities[3],
blockedWorld.densityDispatchPathAt({firstX,firstY,firstZ}).c_str());
}
}
std::uint64_t routePoints=0,routePasses=0,routeWalkPasses=0,routeBindings=0,routeBindingFailures=0;
struct FRouteAuditInput
{
@@ -787,7 +1465,7 @@ namespace StandaloneStreamBenchmark
}
const FWalkAudit routeAudit=auditPlayerPath(Shape,route,supportStartMetres,
supportStepMetres,supportMaximumMetres,minimumSupportProbes,
supportProbeRadiusMetres);
supportProbeRadiusMetres,nullptr,nullptr);
routeAuditInputs.push_back({stratum.strateIndex,route,supportStartMetres,
supportStepMetres,supportMaximumMetres,supportProbeRadiusMetres,
minimumSupportProbes});
@@ -798,14 +1476,27 @@ namespace StandaloneStreamBenchmark
{return a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2];};
if(passage.upperStrateIndex==stratum.strateIndex)
{
const std::array<std::int64_t,3> departure{{anchors.back()->values[0],
const auto rootedMouth=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_anchor"&&anchor.values.size()>=10;});
const std::array<std::int64_t,3> departure=
rootedMouth!=stratum.anchors.end()
?std::array<std::int64_t,3>{{rootedMouth->values[7],
rootedMouth->values[8],rootedMouth->values[9]}}
:std::array<std::int64_t,3>{{anchors.back()->values[0],
anchors.back()->values[1],anchors.back()->values[2]}};
binding&=equalPosition(passage.upperMouthSubvoxels,
departure);
}
if(passage.lowerStrateIndex==stratum.strateIndex)
{
const std::array<std::int64_t,3> arrival{{anchors.front()->values[0],
const auto passageArrival=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_arrival"&&anchor.values.size()>=3;});
const std::array<std::int64_t,3> arrival=passageArrival!=stratum.anchors.end()
?std::array<std::int64_t,3>{{passageArrival->values[0],
passageArrival->values[1],passageArrival->values[2]}}
:std::array<std::int64_t,3>{{anchors.front()->values[0],
anchors.front()->values[1],anchors.front()->values[2]}};
binding&=equalPosition(passage.lowerMouthSubvoxels,
arrival);
@@ -831,12 +1522,6 @@ namespace StandaloneStreamBenchmark
routeAudit.firstUnsupported[i][1],routeAudit.firstUnsupported[i][2],
routeAudit.firstUnsupported[i][3]);
}
const auto controlSnapshot=CoreSnapshot.withoutResolvedLayoutPassages();
VoxelForgeCore::World blockedWorld(controlSnapshot);
std::string blockedCompileError;
const bool blockedCompiled=controlSnapshot
&&blockedWorld.compile(ShapeRequest,Scheduler,blockedCompileError);
if(blockedCompiled)
for(const auto& passage:ResolvedLayout->passages)
{
std::vector<std::array<double,3>> path;path.reserve(passage.controlPoints.size());
@@ -849,25 +1534,57 @@ namespace StandaloneStreamBenchmark
qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0});
}
const FWalkAudit blockedAudit=auditPlayerPath(blockedWorld,path,
0.125,0.125,0.25,3,0.45);
0.125,0.125,0.25,3,0.45,nullptr,nullptr);
blockedControls+=blockedAudit.blocked>0&&!blockedAudit.passed;
std::printf("[ResolvedPassageBlockedControl] id=%s blocked_capsule_samples=%llu detected=%s\n",
passage.stableId.c_str(),static_cast<unsigned long long>(blockedAudit.blocked),
blockedAudit.blocked>0&&!blockedAudit.passed?"true":"false");
}
else
std::fprintf(stderr,"[ResolvedPassageBlockedControl] compile_failed=%s\n",blockedCompileError.c_str());
if(blockedCompiled)
for(const auto& input:routeAuditInputs)
{
const FWalkAudit controlRoute=auditPlayerPath(blockedWorld,input.path,
input.supportStart,input.supportStep,input.supportMaximum,
input.minimumSupportProbes,input.supportProbeRadius);
input.minimumSupportProbes,input.supportProbeRadius,nullptr,nullptr);
std::printf("[ResolvedStrateRouteBlockedControl] strate=%d blocked=%llu unsupported=%llu status=%s\n",
input.strateIndex,static_cast<unsigned long long>(controlRoute.blocked),
static_cast<unsigned long long>(controlRoute.unsupported),
controlRoute.passed?"PASS":"FAIL");
}
const bool l24OpenAirControlDetected=openAirLegacyViolations>0;
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 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>(openAirColumnSamples),
static_cast<unsigned long long>(openAirShortSpanSamples),
l24OpenAirControlDetected?"DETECTED":"MISSED",
openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
?"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");
@@ -877,6 +1594,8 @@ namespace StandaloneStreamBenchmark
MinimumWallReliefMetres,naturalPasses==passageCount&&l23SmoothWallDetected?"PASS":"FAIL");
const bool auditPassed=passageCount>0&&passagePasses==passageCount
&&naturalPasses==passageCount&&l23SmoothWallDetected
&&openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
&&columnAuditsPassed&&noLongBridgeAuditPassed
&&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings
&&routeBindingFailures==0
&&blockedCompiled&&blockedControls==passageCount;
+84 -13
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=5;
recipe.geometryVersion=8;
recipe.ownerVoxelSizeMicrons=owner.OwnerVoxelSizeMicrons;
recipe.coreVoxelSizeMicrons=owner.CoreVoxelSizeMicrons;
recipe.ownerToCoreScaleNumerator=owner.OwnerVoxelSizeMicrons/static_cast<std::uint32_t>(divisor);
@@ -573,17 +573,22 @@ namespace StandaloneWorldAssemblyPrototype
recipe.anchorPlacementRadiusSubvoxels=ownerVoxelsToCoreQ(passage.DistanceMax);
const std::int64_t spiralRadius=ownerVoxelsToCoreQ(passage.SpiralRadius);
const std::int64_t mouthBore=std::max(ownerVoxelsToCoreQ(passage.MouthRadius),
ownerVoxelsToCoreQ(12.0));
ownerVoxelsToCoreQ(36.0));
const std::int64_t bore=std::max(ownerVoxelsToCoreQ(passage.MidRadius),
ownerVoxelsToCoreQ(12.0));
const std::int64_t wallReserve=ownerVoxelsToCoreQ(12.0);
// Put the mouth near the island rim, with enough island and root around the
// first coil to read as a cave entrance instead of a hole in open air.
recipe.anchorMouthOffsetSubvoxels=spiralRadius+mouthBore+ownerVoxelsToCoreQ(4.0);
const std::int64_t excursion=std::max(ownerVoxelsToCoreQ(passage.Wander),spiralRadius);
recipe.anchorRootRadiusSubvoxels=excursion+bore+wallReserve;
ownerVoxelsToCoreQ(24.0));
const std::int64_t wallReserve=ownerVoxelsToCoreQ(20.0);
// Retain a 4.5-metre mouth for capsule clearance while keeping the long
// ramp at three metres to leave more rock around the first coil.
recipe.anchorMouthOffsetSubvoxels=ownerVoxelsToCoreQ(40.0);
const std::int64_t supportOverhang=ownerVoxelsToCoreQ(16.0);
const std::int64_t rootTaperReserve=ownerVoxelsToCoreQ(10.0);
const std::int64_t mouthEnvelope=recipe.anchorMouthOffsetSubvoxels+mouthBore;
const std::int64_t treadEnvelope=spiralRadius+bore+supportOverhang;
recipe.anchorRootRadiusSubvoxels=std::max(mouthEnvelope,treadEnvelope)
+wallReserve+rootTaperReserve;
recipe.anchorIslandMinimumRadiusSubvoxels=std::max(recipe.minimumRadiusSubvoxels,
recipe.anchorMouthOffsetSubvoxels+mouthBore+ownerVoxelsToCoreQ(4.0));
std::max(recipe.anchorMouthOffsetSubvoxels+mouthBore+ownerVoxelsToCoreQ(4.0),
recipe.anchorRootRadiusSubvoxels+wallReserve));
recipe.anchorRootBottomZSubvoxels=recipe.layoutMinimumZSubvoxels
+recipe.boundarySealSubvoxels;
@@ -713,6 +718,39 @@ namespace StandaloneWorldAssemblyPrototype
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
if(it!=assembly.floatingIslands.end())
{
std::size_t passageMouthRouteIndex=it->manifest.plan.route.empty()?0
:it->manifest.plan.route.size()-1;
std::size_t resolvedRoutePointCount=it->manifest.plan.route.size();
if(it->manifest.recipe.geometryVersion>=5
&&!it->manifest.plan.route.empty()
&&it->manifest.recipe.anchorIslandOrdinal<it->manifest.plan.islands.size())
{
const auto& rootedIsland=it->manifest.plan.islands[
it->manifest.recipe.anchorIslandOrdinal];
const double qPerMetre=static_cast<double>(
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)*1000000.0
/owner.CoreVoxelSizeMicrons;
const double thresholdQ=static_cast<double>(
it->manifest.recipe.anchorMouthOffsetSubvoxels)+qPerMetre;
for(std::size_t reverse=it->manifest.plan.route.size();reverse>1;--reverse)
{
const std::size_t index=reverse-1;
const auto& point=it->manifest.plan.route[index].positionSubvoxels;
const double dx=static_cast<double>(point[0]-rootedIsland.centerSubvoxels[0]);
const double dy=static_cast<double>(point[1]-rootedIsland.centerSubvoxels[1]);
if(std::hypot(dx,dy)>thresholdQ)
{
passageMouthRouteIndex=std::min(index+1,
it->manifest.plan.route.size()-1);
break;
}
}
// Stop the island surface route immediately before it enters
// the outer coil. The helical passage owns the walkable path
// from its mouth inward.
resolvedRoutePointCount=passageMouthRouteIndex>1
?passageMouthRouteIndex-1:passageMouthRouteIndex;
}
const auto recipeBottom=fixedToMicrons(it->manifest.recipe.layoutMinimumZSubvoxels);
const auto recipeTop=fixedToMicrons(it->manifest.recipe.layoutMaximumZSubvoxels);
if(recipeBottom!=bottom||recipeTop!=top)
@@ -737,10 +775,17 @@ namespace StandaloneWorldAssemblyPrototype
it->manifest.recipe.anchorPlacementRadiusSubvoxels,
it->manifest.recipe.anchorRootBottomZSubvoxels,
a.radiusSubvoxels};
if(!it->manifest.plan.route.empty())
{
const auto& routeMouth=it->manifest.plan.route[
passageMouthRouteIndex].positionSubvoxels;
passageAnchor.values.insert(passageAnchor.values.end(),
{routeMouth[0],routeMouth[1],routeMouth[2]});
}
s.anchors.push_back(std::move(passageAnchor));
}
}
for(std::size_t n=0;n<it->manifest.plan.route.size();++n)
for(std::size_t n=0;n<resolvedRoutePointCount;++n)
{
const auto& p=it->manifest.plan.route[n];ResolvedLayoutAnchorV2 anchor;
anchor.kind="route_point";anchor.stableId="route/"+std::to_string(n);
@@ -788,6 +833,32 @@ namespace StandaloneWorldAssemblyPrototype
{const auto& p=plan->route[n];ResolvedLayoutAnchorV2 a;a.kind="route_point";a.stableId="route/"+std::to_string(n);
a.units="1/256 Core voxel";a.values={p.positionSubvoxels[0],p.positionSubvoxels[1],p.positionSubvoxels[2],p.radiusSubvoxels};
s.anchors.push_back(std::move(a));}
const auto upperAnchorStratum=std::find_if(out.strates.begin(),out.strates.end(),
[](const auto& candidate)
{return candidate.generatorKind=="FloatingIslands"
&&std::any_of(candidate.anchors.begin(),candidate.anchors.end(),
[](const auto& anchor){return anchor.kind=="passage_anchor"
&&anchor.values.size()>=7;});});
if(upperAnchorStratum!=out.strates.end())
{
const auto rootAnchor=std::find_if(upperAnchorStratum->anchors.begin(),
upperAnchorStratum->anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_anchor"&&anchor.values.size()>=7;});
const std::int64_t arrivalZMicrometres=top-seal-1250000;
if(rootAnchor!=upperAnchorStratum->anchors.end()
&&arrivalZMicrometres>=bottom+seal&&arrivalZMicrometres<top-seal)
{
ResolvedLayoutAnchorV2 arrival;arrival.kind="passage_arrival";
arrival.stableId="passage-arrival/from-strate/"
+std::to_string(upperAnchorStratum->strateIndex);
arrival.units="1/256 Core voxel";
arrival.values={rootAnchor->values[0],rootAnchor->values[1],
static_cast<std::int64_t>(std::llround(
static_cast<double>(arrivalZMicrometres)
*WorldAssemblySubvoxelsPerVoxel/owner.CoreVoxelSizeMicrons))};
s.anchors.push_back(std::move(arrival));
}
}
}
out.strates.push_back(std::move(s));
}
@@ -803,9 +874,9 @@ namespace StandaloneWorldAssemblyPrototype
config.connections=authored.Connections;
config.style=static_cast<std::uint32_t>(authored.Style);
config.mouthRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MouthRadius),
ownerVoxelsToCoreQ(12.0));
ownerVoxelsToCoreQ(36.0));
config.midRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MidRadius),
ownerVoxelsToCoreQ(12.0));
ownerVoxelsToCoreQ(24.0));
config.reachMinimumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMin);
config.reachMaximumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMax);
config.distanceMinimumSubvoxels=ownerVoxelsToCoreQ(authored.DistanceMin);