wip(assembler): M3 round 2 -- islands get real mass: deep crust, separate tapered roots, arched spans

Pinch cause: SmoothStep taper drove the underside radius to zero at one point. Version 2: depth 0.75x
diameter (thin-pad control at 0.30 fails), 3-4 seeded roots, bounded contour warp + roughness, one
off-route side island, 3 m rock spans. Bounds/route/W1-W8-W16 pass. Open: legacy probe metadata says
25 cm but production legacy is 12.5 cm -- round 3 must fix the import scale contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-10 12:24:35 +02:00
1 parent 53a1e69af7
commit 4afea7c802
15 files changed
+1000 -92

No files matched your search

+10
View File
@@ -150,6 +150,7 @@ remains `0`, and lateral regions remain gated off.
| `../../VoxelForgeCore/Private/Manifest/VFCore_*.cpp` | Eighteen one-source UBT shims that include canonical files under `Standalone/`; they do not copy Core implementation. The API-boundary row includes `Core/src/VoxelForgeCore.cpp` directly. |
| `../../VoxelForgeCore/Private/ModuleEntry/` | Unreal module entry and an isolated `CoreMinimal.h` shim for the actual engine header. |
| `../../Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h` | Standard-library-only public Core API. `VOXELFORGECORE_API` exports the API from the Unreal module and is empty for standalone builds. |
| `../../Standalone/Core/src/FloatingIslandsInternal.h` | Canonical standalone/Core floating-island planner, geometry-versioned field, manifest serializer, influence bounds, capsule-route checks, and thickness audit. |
| `Tools/VoxelForgeTest.ps1` | The single guarded test entry point. `-Scenario canonical|owner|probe|perf|tests|surface-fall|crossing|gate-stress|visual-edit|visual-lod|visual-gap-walk|visual-gap-inject|dig-motion|parity|horizon|horizon-render|determinism|region-eval|step2d|step2e|step2f|step2f-capture|step3-scale|step3-game`, optional `-Build`, `-Assets owner|default`, `-Cvars`, absolute `-Out`, `-Label`, `-HorizonLevel`, `-HorizonRenderDistanceChunks`, `-Step2fProfile=0..7`, `-Step2fCaptureView=inside|wall-closeup`, `-ParityExportSize=32|64|128`, `-ParityExportTile=x,y,z`, `-SharedDDC`, `-SampleDensityStacks`, `-StackSampleIntervalUs`, and `-RegionHashProbe -RegionWorkers N -RegionReferenceHash HASH`; stages the host/assets, isolates user/DDC/config state, serializes one Unreal launch at a time, enforces the 8 GiB/30-minute guards, waits for 6 GiB free RAM before launches, and emits compact `result.json`/`summary.txt` plus full logs. Parity can render its game leg with `-EnableRender` and compares the selected export region against the exact streamed tile hashes. `visual-gap-walk` records camera-frustum surface-point coverage at 6000 cm/s; `visual-gap-inject` proves an early component hide is detected; `dig-motion` logs per-frame vertical velocity, gate, support readiness, and movement mode. `-Cvars @{ 'voxel.TestGapAuditLegacyHandoff'=1 }` replays the old visibility handoff for A/B audit baselines. Horizon traces report desired/loaded tiles, resident stream geometry, worker seconds, steady wall time, and peak private memory; `horizon-render` captures the owner view; `step2f-capture` selects one of eight parameter sets, finds a positive-density camera point and aims at a sampled rock wall for an inside or wall-closeup view, then saves it under `Saved/Research/step2f/captures` (pass the persistent render DDC with `-SharedDDC`); `determinism` compares per-tile hashes across the default CRT path and `-voxel.CrtFma3=0`; `region-eval` compares the live path with the default-off editor chunk program on the 259³ lattice and five-seed probe set; `step2d` retains the earlier independent field; `step2e` retains its earlier benchmark; `step2f` compares frozen step 2e and the coherent field for all eight profiles on the same 259³ ring, applies geometry gates, and checks sound bounds, seams, and 1-vs-6-worker hashes. `-RegionHashProbe -RegionWorkers N -RegionReferenceHash HASH` checks a full-ring hash at another partition count. `-SampleDensityStacks` captures profiles, and `-StackSampleIntervalUs` sets the sampling interval.
| Step-3 scale and game validation | `step3-scale` measures the same 519³ and 259³ six-worker lattices at 12.5 cm. The cached medians are 7.347496 s and 1.169567 s respectively; determinism and brick sound-proof audits pass. `step3-game` routes in-game generation through the brick evaluator and records tile timings, spawn fill, moving frames, and profile-switch rebuilds. The visible D3D12 run measured tile generation p50/p95/max 3.326/31.045/169.867 ms, full-detail L0 fill 12.369 s for 2,765 tiles, and moving-frame p50/p95/p99/max 4.856/8.922/13.090/80.575 ms. Switching profiles rebuilt 5,815 loaded tiles. Both high-resolution screenshot requests were logged, but the harness found only one fresh PNG and it is a blank pale viewport; no lit comparison capture is accepted. Raw output: `Saved/TestHarness/step3_game_visible_final`; scale output: `Saved/Research/step3/scale/step3_scale_cacheperf_v1`. |
| `Public/VoxelForgeModule.h` / `Private/VoxelForgeModule.cpp` | `FVoxelForgeModule` boilerplate (Startup/Shutdown just log). |
@@ -833,6 +834,15 @@ World assembler field types and `AuditHeightfieldBounds`, `AuditHeightfieldShelf
`AuditHeightfieldRoute` are declared in
[`Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`](Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h)
and implemented in [`Standalone/Core/src/WorldAssemblerInternal.h`](Standalone/Core/src/WorldAssemblerInternal.h).
`FloatingIslandRecipeV1`, `FloatingIslandManifestV1`, `FloatingIslandFieldV1`,
`AuditFloatingIslandBounds`, `AuditFloatingIslandRoute`, and `AuditFloatingIslandThickness` are in the
same public header; their canonical implementation is
[`Standalone/Core/src/FloatingIslandsInternal.h`](Standalone/Core/src/FloatingIslandsInternal.h).
M3 round 2 added geometry version 2's thick crust, lobed roots, bounded detail and arched spans while
preserving version-1 field and hash behavior. The standalone audit driver remains under
[`Standalone/Research/WorldAssemblerM3/Round1/FloatingIslandsAudit.cpp`](Standalone/Research/WorldAssemblerM3/Round1/FloatingIslandsAudit.cpp);
round-2 matched capture source and results are under
[`Standalone/Research/WorldAssemblerM3/Round2/`](Standalone/Research/WorldAssemblerM3/Round2/).
`RefineLod8NativeCap` in [`Standalone/Core/src/VoxelForgeCore.cpp`](Standalone/Core/src/VoxelForgeCore.cpp)
replaces coarse LOD8 ceiling surfaces with the planned 2D cap field while retaining ceiling skirts.
The standalone SurfaceWorld plan composer and capture/audit entry point live in
+14 -6
View File
@@ -153,16 +153,24 @@ radius range, top flattening, taper, bounded contour warp, roughness, blend, con
route constraints. `PlanFloatingIslandCluster` emits stable island and connector IDs, a connected
cluster graph, conservative influence AABBs, and a centerline route. At least the primary chain is
always planned; `islandDensityQ16` controls up to two optional side sites. Connectors carry a sharp-tag
ready bit for a later hybrid-mesher adapter.
ready bit for a later hybrid-mesher adapter. The schema accepts geometry version 1 and 2. Manifests
without a geometry version retain version-1 evaluation and canonical hashes.
`FloatingIslandFieldV1::densitySubvoxels` evaluates the canonical island and connector field.
`interval` returns unknown for boxes overlapping any influence AABB and a certified all-air range
outside them. AABBs include contour displacement, roughness, taper height and smoothing reach.
outside them. Geometry version 2 builds a flat walkable crust plus deterministic lobed rock roots,
keeps bounded oblique surface detail inside its certified envelope, and arches the connector
undersides. AABBs include root depth, contour displacement, detail, arch sag and smoothing reach.
`AuditFloatingIslandBounds` checks sampled boxes and void beside connectors and includes a deliberately
shrunken island-bound negative control. `AuditFloatingIslandRoute` samples the player capsule and
support along the serialized route. The current field block is not yet composed into
`WorldAssemblyManifest` or the Unreal adapter; M3 round 1 proves the standalone Core representation.
The frozen owner evaluator is used as a visual and timing oracle, not as a hash target.
shrunken island-bound negative control. `AuditFloatingIslandThickness` reports each island's
`(topZ - bottomZ) / (2 * radius)` and checks a caller-supplied minimum; `AuditFloatingIslandRoute`
samples the player capsule and support along the serialized route. M3 round 2 passed at a minimum
depth-to-diameter ratio of 0.75 against a 0.70 threshold, while a 0.30 thin-pad control failed.
The family is still separate from `WorldAssemblyManifest` and the Unreal adapter. M3 rounds 1–2 prove
the standalone Core representation, bounded geometry, route, determinism and matched legacy timing.
The frozen owner evaluator is a visual and timing oracle, not a hash target. Unreal import and cooked
collision are planned for M3 round 3.
## Queries and tiles
@@ -301,29 +301,36 @@ namespace VoxelForgeCore
struct FloatingIslandRecipeV1
{
std::uint32_t schemaVersion = 1;
// Profile 1 preserves the original shallow pads. Profile 2 adds a thick crust,
// bounded lobed roots and arched spans without changing the feature-family schema.
std::uint32_t geometryVersion = 2;
std::uint32_t unitsPerVoxel = static_cast<std::uint32_t>(WorldAssemblySubvoxelsPerVoxel);
std::uint32_t seed = 0;
std::int64_t layoutOriginXSubvoxels = 0;
std::int64_t layoutOriginYSubvoxels = 0;
std::int64_t layoutCenterTopZSubvoxels = -128 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t layoutMinimumZSubvoxels = -256 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t layoutCenterTopZSubvoxels = -64 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t layoutMinimumZSubvoxels = -128 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t layoutMaximumZSubvoxels = 0;
std::uint32_t primaryIslandCount = 5;
std::uint32_t primaryIslandCount = 3;
std::int64_t islandDensityQ16 = 1ll << 15;
std::int64_t spacingSubvoxels = 112 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t minimumRadiusSubvoxels = 40 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t maximumRadiusSubvoxels = 48 * WorldAssemblySubvoxelsPerVoxel;
// Legacy owner lengths use 12.5 cm voxels; Core uses 25 cm, so halve the owner lengths.
// Les longueurs owner utilisent des voxels de 12,5 cm ; Core utilise 25 cm, donc les diviser par deux.
std::int64_t spacingSubvoxels = 56 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t minimumRadiusSubvoxels = 12 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t maximumRadiusSubvoxels = 24 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t thicknessRatioQ16 = 39322; // 0.60
std::int64_t verticalJitterQ16 = 26214; // 0.40
std::int64_t topFlattenQ16 = 51118; // 0.78
std::int64_t verticalJitterQ16 = 39322; // 0.60
std::int64_t topFlattenQ16 = 39322; // 0.60
std::int64_t taperEndMinimumQ16 = 29491; // 0.45
std::int64_t taperEndMaximumQ16 = 45875; // 0.70
std::int64_t blendRadiusSubvoxels = 4 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t contourWarpSubvoxels = 15 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t roughnessSubvoxels = WorldAssemblySubvoxelsPerVoxel / 2;
std::int64_t boundarySealSubvoxels = 4 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t bridgeHalfWidthSubvoxels = 4 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t bridgeThicknessSubvoxels = 3 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t crustDepthBonusQ16 = 9830; // 0.15 radius, profile 2 only
std::int64_t rootDepthRatioQ16 = 49152; // 0.75 radius, profile 2 only
std::int64_t blendRadiusSubvoxels = 3 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t contourWarpSubvoxels = 6 * WorldAssemblySubvoxelsPerVoxel + 77; // 6.3
std::int64_t roughnessSubvoxels = 3 * WorldAssemblySubvoxelsPerVoxel / 2;
std::int64_t boundarySealSubvoxels = 2 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t bridgeHalfWidthSubvoxels = 6 * WorldAssemblySubvoxelsPerVoxel;
std::int64_t bridgeThicknessSubvoxels = 4 * WorldAssemblySubvoxelsPerVoxel;
WorldAssemblyRouteConstraintsV1 routeConstraints;
std::uint64_t contentHash = 0;
};
@@ -409,6 +416,16 @@ namespace VoxelForgeCore
bool passed = false;
};
struct FloatingIslandThicknessAuditResult
{
std::uint64_t islandsTested = 0;
std::uint64_t islandsBelowMinimum = 0;
std::uint64_t minimumIslandStableId = 0;
double minimumDepthToDiameterRatio = 0.0;
double requiredDepthToDiameterRatio = 0.70;
bool passed = false;
};
struct FloatingIslandInfluenceBounds
{
bool finite = false;
@@ -451,6 +468,8 @@ namespace VoxelForgeCore
std::uint64_t seed = 0x49534c414e444231ull);
VFCORE_API FloatingIslandRouteAuditResult AuditFloatingIslandRoute(
const FloatingIslandFieldV1& field, std::int64_t routeOffsetSubvoxels = 0);
VFCORE_API FloatingIslandThicknessAuditResult AuditFloatingIslandThickness(
const FloatingIslandPlanV1& plan, double minimumDepthToDiameterRatio = 0.70);
struct HeightfieldPointSample
{
+291 -41
View File
@@ -174,6 +174,12 @@ namespace floating_island_detail
HashWord(hash, static_cast<std::uint64_t>(recipe.topFlattenQ16), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.taperEndMinimumQ16), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.taperEndMaximumQ16), 8);
if (recipe.geometryVersion >= 2)
{
HashWord(hash, recipe.geometryVersion, 4);
HashWord(hash, static_cast<std::uint64_t>(recipe.crustDepthBonusQ16), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.rootDepthRatioQ16), 8);
}
HashWord(hash, static_cast<std::uint64_t>(recipe.blendRadiusSubvoxels), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.contourWarpSubvoxels), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.roughnessSubvoxels), 8);
@@ -233,7 +239,7 @@ namespace floating_island_detail
inline bool ValidateRecipe(const FloatingIslandRecipeV1& recipe, std::string& error)
{
const std::array<std::int64_t, 23> values = {
const std::array<std::int64_t, 25> values = {
recipe.layoutOriginXSubvoxels, recipe.layoutOriginYSubvoxels,
recipe.layoutCenterTopZSubvoxels, recipe.layoutMinimumZSubvoxels,
recipe.layoutMaximumZSubvoxels, recipe.islandDensityQ16,
@@ -241,22 +247,28 @@ namespace floating_island_detail
recipe.maximumRadiusSubvoxels, recipe.thicknessRatioQ16,
recipe.verticalJitterQ16, recipe.topFlattenQ16,
recipe.taperEndMinimumQ16, recipe.taperEndMaximumQ16,
recipe.crustDepthBonusQ16, recipe.rootDepthRatioQ16,
recipe.blendRadiusSubvoxels, recipe.contourWarpSubvoxels,
recipe.roughnessSubvoxels, recipe.boundarySealSubvoxels,
recipe.bridgeHalfWidthSubvoxels, recipe.bridgeThicknessSubvoxels,
recipe.routeConstraints.capsuleRadiusSubvoxels,
recipe.routeConstraints.capsuleHeightSubvoxels,
recipe.routeConstraints.maximumGradeQ16};
if (recipe.schemaVersion != 1 || recipe.unitsPerVoxel != Q
if (recipe.schemaVersion != 1 || (recipe.geometryVersion != 1 && recipe.geometryVersion != 2)
|| (recipe.geometryVersion == 1
&& (recipe.crustDepthBonusQ16 != 0 || recipe.rootDepthRatioQ16 != 0))
|| recipe.unitsPerVoxel != Q
|| recipe.primaryIslandCount < 3 || recipe.primaryIslandCount > 9
|| recipe.layoutMaximumZSubvoxels <= recipe.layoutMinimumZSubvoxels
|| recipe.layoutMaximumZSubvoxels - recipe.layoutMinimumZSubvoxels > 2048 * Q
|| std::any_of(values.begin(), values.end(), [](auto value) { return !ValidScalar(value); }))
{ error = "floating-island recipe version, scale, layout or scalar range is invalid"; return false; }
const auto& constraints = recipe.routeConstraints;
const std::int64_t minimumSpacing = recipe.geometryVersion >= 2 ? 32 * Q : 64 * Q;
const std::int64_t minimumRadius = recipe.geometryVersion >= 2 ? 12 * Q : 24 * Q;
if (recipe.islandDensityQ16 < 6554 || recipe.islandDensityQ16 > (1ll << 15)
|| recipe.spacingSubvoxels < 64 * Q || recipe.spacingSubvoxels > 256 * Q
|| recipe.minimumRadiusSubvoxels < 24 * Q
|| recipe.spacingSubvoxels < minimumSpacing || recipe.spacingSubvoxels > 256 * Q
|| recipe.minimumRadiusSubvoxels < minimumRadius
|| recipe.maximumRadiusSubvoxels < recipe.minimumRadiusSubvoxels
|| recipe.maximumRadiusSubvoxels > 64 * Q
|| recipe.thicknessRatioQ16 < 29491 || recipe.thicknessRatioQ16 > 49152
@@ -264,6 +276,9 @@ namespace floating_island_detail
|| recipe.topFlattenQ16 < 39322 || recipe.topFlattenQ16 > 52429
|| recipe.taperEndMinimumQ16 < 26214 || recipe.taperEndMaximumQ16 > 52429
|| recipe.taperEndMinimumQ16 > recipe.taperEndMaximumQ16
|| (recipe.geometryVersion >= 2
&& (recipe.crustDepthBonusQ16 < 6554 || recipe.crustDepthBonusQ16 > 16384
|| recipe.rootDepthRatioQ16 < 32768 || recipe.rootDepthRatioQ16 > 65536))
|| recipe.blendRadiusSubvoxels < 2 * Q || recipe.blendRadiusSubvoxels > 6 * Q
|| recipe.contourWarpSubvoxels <= 0
|| recipe.contourWarpSubvoxels > recipe.maximumRadiusSubvoxels / 2
@@ -325,18 +340,30 @@ namespace floating_island_detail
}
inline double Roughness(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island,
double x, double y, double z)
std::uint64_t featureId, double x, double y, double z)
{
const double phase = static_cast<double>(Roll(recipe.seed, island.stableId, 0x524f5547ull)
const double phase = static_cast<double>(Roll(recipe.seed, featureId, 0x524f5547ull)
& 0xffffffffull) * (2.0 * Pi / 4294967296.0);
const double xv = x / static_cast<double>(Q);
const double yv = y / static_cast<double>(Q);
const double zv = z / static_cast<double>(Q);
if (recipe.geometryVersion < 2)
{
const double oldNoise = 0.52 * std::sin(xv * 0.071 + yv * 0.053 + zv * 0.089 + phase)
+ 0.31 * std::sin(xv * 0.127 - yv * 0.097 + zv * 0.061 - phase * 0.73)
+ 0.17 * std::cos(xv * 0.043 + yv * 0.139 - zv * 0.113 + phase * 1.39);
return static_cast<double>(recipe.roughnessSubvoxels) * oldNoise;
}
// Four oblique bands span about 7 m down to 0.9 m at 25 cm per voxel.
// Their absolute weights sum to one, keeping displacement inside the 3-voxel envelope.
const double noise = 0.52 * std::sin(xv * 0.071 + yv * 0.053 + zv * 0.089 + phase)
+ 0.31 * std::sin(xv * 0.127 - yv * 0.097 + zv * 0.061 - phase * 0.73)
+ 0.17 * std::cos(xv * 0.043 + yv * 0.139 - zv * 0.113 + phase * 1.39);
return static_cast<double>(recipe.roughnessSubvoxels) * noise;
const double fine = 0.46 * std::sin(xv * 0.22 + yv * 0.31 - zv * 0.17 + phase * 0.41)
+ 0.32 * std::cos(xv * 0.38 - yv * 0.21 + zv * 0.29 - phase * 0.67)
+ 0.22 * std::sin(xv * 0.74 + yv * 0.53 + zv * 0.61 + phase * 1.17);
return static_cast<double>(recipe.roughnessSubvoxels)
* std::clamp(0.42 * noise + 0.58 * fine, -1.0, 1.0);
}
inline double IslandTopSurface(const FloatingIslandRecipeV1& recipe,
@@ -355,9 +382,86 @@ namespace floating_island_detail
return static_cast<double>(island.topZSubvoxels) - drop;
}
inline std::int64_t ScaledQ16(std::int64_t value, std::int64_t scaleQ16)
{ return (value * scaleQ16 + Q16 / 2) / Q16; }
inline std::int64_t IslandCrustBottom(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island)
{
const std::int64_t ratio = recipe.thicknessRatioQ16
+ (recipe.geometryVersion >= 2 ? recipe.crustDepthBonusQ16 : 0);
return island.topZSubvoxels - ScaledQ16(island.radiusSubvoxels, ratio);
}
inline std::int64_t IslandBottom(const FloatingIslandRecipeV1& recipe,
std::int64_t topZ, std::int64_t radius)
{
const std::int64_t crustRatio = recipe.thicknessRatioQ16
+ (recipe.geometryVersion >= 2 ? recipe.crustDepthBonusQ16 : 0);
const std::int64_t rootRatio = recipe.geometryVersion >= 2
? recipe.rootDepthRatioQ16 : 0;
return topZ - ScaledQ16(radius, crustRatio) - ScaledQ16(radius, rootRatio);
}
inline std::int32_t RootCount(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island)
{
return 3 + static_cast<std::int32_t>(Roll(recipe.seed, island.stableId,
0x524f4f54434e54ull) & 1ull);
}
inline double UnitHash(std::uint64_t hash)
{ return static_cast<double>(hash & 0xffffull) / 65535.0; }
inline double RootLobeDensity(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island,
std::int32_t rootIndex, double x, double y, double z)
{
constexpr std::array<std::array<double, 2>, 4> pattern{{
{{-0.92, -0.12}}, {{0.28, 0.98}}, {{0.83, -0.42}}, {{-0.16, -0.94}}}};
const std::uint64_t salt = 0x524f4f540000ull + static_cast<std::uint64_t>(rootIndex);
const std::uint64_t roll = Roll(recipe.seed, island.stableId, salt);
const double radius = static_cast<double>(island.radiusSubvoxels);
const double rootDepth = radius * Q16ToDouble(recipe.rootDepthRatioQ16);
const double crustBottom = static_cast<double>(IslandCrustBottom(recipe, island));
const double orbit = radius * (0.17 + 0.07 * UnitHash(roll));
const double rootX = static_cast<double>(island.centerSubvoxels[0])
+ pattern[static_cast<std::size_t>(rootIndex)][0] * orbit;
const double rootY = static_cast<double>(island.centerSubvoxels[1])
+ pattern[static_cast<std::size_t>(rootIndex)][1] * orbit;
const double shortRootVariation = UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x4c454eull));
const double lengthRatio = rootIndex == 0 ? 1.0
: Q16ToDouble(island.taperEndQ16) * (0.82 + 0.18 * shortRootVariation);
const double lowerDepth = rootDepth * lengthRatio;
const double embedDepth = rootDepth * (rootIndex == 0 ? 0.30 : 0.22);
const double verticalRadius = 0.5 * (lowerDepth + embedDepth);
const double centerZ = crustBottom + 0.5 * (embedDepth - lowerDepth);
const double rx = radius * (0.15 + 0.055 * UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x5258ull)));
const double ry = radius * (0.15 + 0.065 * UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x5259ull)));
const double q = (x - rootX) * (x - rootX) / (rx * rx)
+ (y - rootY) * (y - rootY) / (ry * ry)
+ (z - centerZ) * (z - centerZ) / (verticalRadius * verticalRadius);
return (std::sqrt(std::max(q, 0.0)) - 1.0) * std::min({rx, ry, verticalRadius});
}
inline double ApplySurfaceDetail(const FloatingIslandRecipeV1& recipe,
std::uint64_t featureId, double structural,
double x, double y, double z, double detailScale = 1.0)
{
if (recipe.geometryVersion < 2)
return structural + Roughness(recipe, featureId, x, y, z);
const double amplitude = static_cast<double>(recipe.roughnessSubvoxels) * detailScale;
const double band = 2.0 * amplitude;
if (!(amplitude > 0.0) || std::abs(structural) >= band) return structural;
const double fade = 1.0 - SmoothStep(std::abs(structural) / band);
return structural + Roughness(recipe, featureId, x, y, z) * detailScale * fade;
}
inline double IslandDensity(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island,
double x, double y, double z)
{
if (recipe.geometryVersion < 2)
{
const double dx = x - static_cast<double>(island.centerSubvoxels[0]);
const double dy = y - static_cast<double>(island.centerSubvoxels[1]);
@@ -374,12 +478,42 @@ namespace floating_island_detail
const double top = IslandTopSurface(recipe, island,
static_cast<double>(island.centerSubvoxels[0]) + dx,
static_cast<double>(island.centerSubvoxels[1]) + dy);
const double sdf = std::max({z - top, radial - envelope, bottomZ - z});
return sdf + Roughness(recipe, island, x, y, z);
return ApplySurfaceDetail(recipe, island.stableId,
std::max({z - top, radial - envelope, bottomZ - z}), x, y, z);
}
inline double ConnectorDensity(const FloatingIslandConnectorV1& edge,
double x, double y, double z)
const double dx = x - static_cast<double>(island.centerSubvoxels[0]);
const double dy = y - static_cast<double>(island.centerSubvoxels[1]);
const double radial = std::hypot(dx, dy);
const double topZ = static_cast<double>(island.topZSubvoxels);
const double radius = static_cast<double>(island.radiusSubvoxels);
const double effectiveRadius = std::max(0.0,
radius + LobeOffset(recipe, island, dx, dy, z));
const double edge = std::clamp(radial / std::max(effectiveRadius, 1.0), 0.0, 1.0);
const double lowerSurface = static_cast<double>(IslandCrustBottom(recipe, island))
+ radius * 0.16 * edge * edge;
const double top = IslandTopSurface(recipe, island,
static_cast<double>(island.centerSubvoxels[0]) + dx,
static_cast<double>(island.centerSubvoxels[1]) + dy);
const double topDistance = z - top;
const double sideDistance = radial - effectiveRadius;
const double undersideDistance = lowerSurface - z;
double sdf = std::max({topDistance, sideDistance, undersideDistance});
const std::int32_t rootCount = RootCount(recipe, island);
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);
const double topDetailScale = topDistance >= std::max(sideDistance, undersideDistance)
|| z >= static_cast<double>(IslandCrustBottom(recipe, island)) + radius * 0.45
? 0.25 : 1.0;
return ApplySurfaceDetail(recipe, island.stableId, sdf, x, y, z, topDetailScale);
}
inline double ConnectorDensity(const FloatingIslandRecipeV1& recipe,
const FloatingIslandConnectorV1& edge,
double x, double y, double z,
bool* topSurface = nullptr,
double* alongFraction = nullptr)
{
const double ax = static_cast<double>(edge.startSubvoxels[0]);
const double ay = static_cast<double>(edge.startSubvoxels[1]);
@@ -397,9 +531,15 @@ namespace floating_island_detail
const double outside = std::hypot(std::max(qx, 0.0), std::max(qy, 0.0));
const double horizontal = outside + std::min(std::max(qx, qy), 0.0);
const double t = std::clamp(along / length, 0.0, 1.0);
if (alongFraction) *alongFraction = t;
const double deck = az + (static_cast<double>(edge.endSubvoxels[2]) - az) * t;
return std::max({horizontal, z - deck,
deck - static_cast<double>(edge.thicknessSubvoxels) - z});
const double arch = recipe.geometryVersion >= 2
? 2.0 * static_cast<double>(edge.thicknessSubvoxels) * (4.0 * t * (1.0 - t))
: 0.0;
const double upper = z - deck;
const double lower = deck - static_cast<double>(edge.thicknessSubvoxels) - arch - z;
if (topSurface) *topSurface = upper >= std::max(horizontal, lower);
return std::max({horizontal, upper, lower});
}
inline std::int64_t FieldDensity(const FloatingIslandRecipeV1& recipe,
@@ -416,8 +556,16 @@ namespace floating_island_detail
for (const auto& edge : plan.clusterEdges)
{
if (edge.fromIslandId != island.stableId) continue;
group = SmoothMin(group, ConnectorDensity(edge,
static_cast<double>(x), static_cast<double>(y), static_cast<double>(z)), blend);
bool topSurface = false;
double alongFraction = 0.0;
double connector = ConnectorDensity(recipe, edge,
static_cast<double>(x), static_cast<double>(y), static_cast<double>(z),
&topSurface, &alongFraction);
if (recipe.geometryVersion >= 2)
connector = ApplySurfaceDetail(recipe, edge.stableId, connector,
static_cast<double>(x), static_cast<double>(y), static_cast<double>(z),
topSurface || alongFraction < 0.12 || alongFraction > 0.88 ? 0.25 : 1.0);
group = SmoothMin(group, connector, blend);
}
result = std::min(result, group);
}
@@ -439,11 +587,14 @@ namespace floating_island_detail
FloatingIslandConnectorV1& edge)
{
const std::int64_t pad = recipe.blendRadiusSubvoxels + recipe.roughnessSubvoxels;
const std::int64_t archDepth = recipe.geometryVersion >= 2
? 2 * edge.thicknessSubvoxels : 0;
const std::int64_t xyPad = edge.halfWidthSubvoxels + pad;
edge.influenceMinimumSubvoxels = {
std::min(edge.startSubvoxels[0], edge.endSubvoxels[0]) - xyPad,
std::min(edge.startSubvoxels[1], edge.endSubvoxels[1]) - xyPad,
std::min(edge.startSubvoxels[2], edge.endSubvoxels[2]) - edge.thicknessSubvoxels - pad};
edge.influenceMinimumSubvoxels[2] -= archDepth;
edge.influenceMaximumSubvoxels = {
std::max(edge.startSubvoxels[0], edge.endSubvoxels[0]) + xyPad,
std::max(edge.startSubvoxels[1], edge.endSubvoxels[1]) + xyPad,
@@ -483,6 +634,10 @@ namespace floating_island_detail
|| island.taperEndQ16 > recipe.taperEndMaximumQ16
|| island.centerSubvoxels[2] != island.topZSubvoxels - island.topHalfSubvoxels)
{ error = "floating-island anchor has an invalid or unstable identity or profile"; return false; }
if (recipe.geometryVersion >= 2
&& static_cast<double>(island.topZSubvoxels - island.bottomZSubvoxels)
/ (2.0 * static_cast<double>(island.radiusSubvoxels)) < 0.70)
{ error = "floating-island crust/root depth is below its minimum width ratio"; return false; }
for (std::size_t axis = 0; axis < 3; ++axis)
{
if (!ValidScalar(island.centerSubvoxels[axis])
@@ -527,6 +682,7 @@ namespace floating_island_detail
|| edge.influenceMaximumSubvoxels[1] < std::max(edge.startSubvoxels[1], edge.endSubvoxels[1]) + xyPad
|| edge.influenceMinimumSubvoxels[2] > std::min(edge.startSubvoxels[2], edge.endSubvoxels[2])
- edge.thicknessSubvoxels - pad
- (recipe.geometryVersion >= 2 ? 2 * edge.thicknessSubvoxels : 0)
|| edge.influenceMaximumSubvoxels[2] < std::max(edge.startSubvoxels[2], edge.endSubvoxels[2]) + pad)
{ error = "floating-island connector bound omits its swept bridge, blend or thickness"; return false; }
adjacency[edge.fromIslandId].push_back(edge.toIslandId);
@@ -593,8 +749,7 @@ namespace floating_island_detail
* radiusRoll / 65535;
island.topHalfSubvoxels = std::max<std::int64_t>(1, island.radiusSubvoxels / 5);
island.topZSubvoxels = topZ;
island.bottomZSubvoxels = topZ
- island.radiusSubvoxels * recipe.thicknessRatioQ16 / Q16;
island.bottomZSubvoxels = IslandBottom(recipe, topZ, island.radiusSubvoxels);
island.centerSubvoxels = {x, y, topZ - island.topHalfSubvoxels};
island.taperEndQ16 = recipe.taperEndMinimumQ16
+ (recipe.taperEndMaximumQ16 - recipe.taperEndMinimumQ16)
@@ -619,14 +774,16 @@ namespace floating_island_detail
// Land each connector well inside the broad top so the full capsule footprint remains
// supported across the bridge-to-island transition, including bounded surface roughness.
// Les connecteurs recouvrent le plateau pour soutenir toute la capsule au raccord.
const double fromReach = static_cast<double>(from.radiusSubvoxels) * 0.62;
const double toReach = static_cast<double>(to.radiusSubvoxels) * 0.62;
const double landingFraction = recipe.geometryVersion >= 2 ? 0.38 : 0.62;
const double fromReach = static_cast<double>(from.radiusSubvoxels) * landingFraction;
const double toReach = static_cast<double>(to.radiusSubvoxels) * landingFraction;
const double sx = from.centerSubvoxels[0] + ux * fromReach;
const double sy = from.centerSubvoxels[1] + uy * fromReach;
const double ex = to.centerSubvoxels[0] - ux * toReach;
const double ey = to.centerSubvoxels[1] - uy * toReach;
const double sz = IslandTopSurface(recipe, from, sx, sy);
const double ez = IslandTopSurface(recipe, to, ex, ey);
const double routeDeckLift = recipe.geometryVersion >= 2 ? 1.0 * Q : 0.0;
const double sz = IslandTopSurface(recipe, from, sx, sy) + routeDeckLift;
const double ez = IslandTopSurface(recipe, to, ex, ey) + routeDeckLift;
edge.startSubvoxels = {RoundQ(sx), RoundQ(sy), RoundQ(sz)};
edge.endSubvoxels = {RoundQ(ex), RoundQ(ey), RoundQ(ez)};
edge.halfWidthSubvoxels = recipe.bridgeHalfWidthSubvoxels;
@@ -734,6 +891,23 @@ std::optional<FloatingIslandManifestV1> FloatingIslandManifestV1::FromJson(
const auto& recipeValue = root.Get("recipe");
const auto& planValue = root.Get("plan");
std::uint64_t manifestHash = 0, recipeHash = 0, planHash = 0;
const auto& geometryVersionValue = recipeValue.Get("geometry_version");
if (geometryVersionValue.IsNumber())
{
if (!floating_island_detail::ReadU32(geometryVersionValue, manifest.recipe.geometryVersion)
|| !floating_island_detail::ReadInteger(recipeValue.Get("crust_depth_bonus_q16"),
manifest.recipe.crustDepthBonusQ16)
|| !floating_island_detail::ReadInteger(recipeValue.Get("root_depth_ratio_q16"),
manifest.recipe.rootDepthRatioQ16))
{ error = "floating-island geometry profile is incomplete"; return std::nullopt; }
}
else
{
// Frozen M3 round-1 manifests omit profile metadata and retain their original field.
manifest.recipe.geometryVersion = 1;
manifest.recipe.crustDepthBonusQ16 = 0;
manifest.recipe.rootDepthRatioQ16 = 0;
}
if (!floating_island_detail::ReadU32(root.Get("schema_version"), schema)
|| !floating_island_detail::ReadHash(root.Get("content_hash"), manifestHash)
|| !floating_island_detail::ReadU32(recipeValue.Get("schema_version"), manifest.recipe.schemaVersion)
@@ -867,8 +1041,12 @@ std::string FloatingIslandManifestV1::ToJson() const
<< ",\"vertical_jitter_q16\":" << recipe.verticalJitterQ16
<< ",\"top_flatten_q16\":" << recipe.topFlattenQ16
<< ",\"taper_end_min_q16\":" << recipe.taperEndMinimumQ16
<< ",\"taper_end_max_q16\":" << recipe.taperEndMaximumQ16
<< ",\"blend_radius_q\":" << recipe.blendRadiusSubvoxels
<< ",\"taper_end_max_q16\":" << recipe.taperEndMaximumQ16;
if (recipe.geometryVersion >= 2)
out << ",\"geometry_version\":" << recipe.geometryVersion
<< ",\"crust_depth_bonus_q16\":" << recipe.crustDepthBonusQ16
<< ",\"root_depth_ratio_q16\":" << recipe.rootDepthRatioQ16;
out << ",\"blend_radius_q\":" << recipe.blendRadiusSubvoxels
<< ",\"contour_warp_q\":" << recipe.contourWarpSubvoxels
<< ",\"roughness_q\":" << recipe.roughnessSubvoxels
<< ",\"boundary_seal_q\":" << recipe.boundarySealSubvoxels
@@ -961,11 +1139,40 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
radii[i] = recipe.minimumRadiusSubvoxels
+ (recipe.maximumRadiusSubvoxels - recipe.minimumRadiusSubvoxels) * radiusRoll / 65535;
}
std::vector<std::array<std::int64_t, 2>> primaryXY(count);
const std::int64_t rowJitter = recipe.spacingSubvoxels / 10;
for (std::uint32_t i = 0; i < count; ++i)
{
const std::uint64_t site = 0x100000000ull + i;
if (recipe.geometryVersion < 2)
{
const std::int64_t yOffset = i == middle ? 0
: floating_island_detail::SignedRange(recipe.seed, site, 0x594a4954544552ull, rowJitter);
primaryXY[i] = {recipe.layoutOriginXSubvoxels
- static_cast<std::int64_t>(middle) * recipe.spacingSubvoxels
+ static_cast<std::int64_t>(i) * recipe.spacingSubvoxels,
recipe.layoutOriginYSubvoxels + yOffset};
}
else
{
const std::int64_t along = (static_cast<std::int64_t>(i)
- static_cast<std::int64_t>(middle)) * recipe.spacingSubvoxels * 7 / 10;
const std::int64_t side = (i % 2 == 0 ? 1 : -1) * recipe.spacingSubvoxels / 3;
const std::int64_t jitter = floating_island_detail::SignedRange(
recipe.seed, site, 0x594a4954544552ull, rowJitter / 2);
primaryXY[i] = {recipe.layoutOriginXSubvoxels + along,
recipe.layoutOriginYSubvoxels + side + jitter};
}
}
const double maxGrade = floating_island_detail::Q16ToDouble(recipe.routeConstraints.maximumGradeQ16);
const double levelFactor = floating_island_detail::Q16ToDouble(recipe.verticalJitterQ16) * 1.5;
const auto riseLimit = [&](std::uint32_t a, std::uint32_t b)
{
const double gap = static_cast<double>(recipe.spacingSubvoxels)
const double centerDistance = recipe.geometryVersion < 2
? static_cast<double>(recipe.spacingSubvoxels)
: std::hypot(static_cast<double>(primaryXY[b][0] - primaryXY[a][0]),
static_cast<double>(primaryXY[b][1] - primaryXY[a][1]));
const double gap = centerDistance
- 0.78 * (static_cast<double>(radii[a]) + static_cast<double>(radii[b]));
return std::max(0.0, gap * maxGrade * levelFactor);
};
@@ -983,22 +1190,16 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
static_cast<std::int64_t>(std::ceil(riseLimit(static_cast<std::uint32_t>(i),
static_cast<std::uint32_t>(i + 1)))));
}
const std::int64_t rowJitter = recipe.spacingSubvoxels / 10;
const std::int64_t startX = recipe.layoutOriginXSubvoxels
- static_cast<std::int64_t>(middle) * recipe.spacingSubvoxels;
for (std::uint32_t i = 0; i < count; ++i)
{
const std::uint64_t site = 0x100000000ull + i;
const std::int64_t yOffset = i == middle ? 0
: floating_island_detail::SignedRange(recipe.seed, site, 0x594a4954544552ull, rowJitter);
auto island = floating_island_detail::MakeIsland(recipe, i,
startX + static_cast<std::int64_t>(i) * recipe.spacingSubvoxels,
recipe.layoutOriginYSubvoxels + yOffset, tops[i], site);
primaryXY[i][0], primaryXY[i][1], tops[i], site);
island.radiusSubvoxels = radii[i];
island.topHalfSubvoxels = std::max<std::int64_t>(1, island.radiusSubvoxels / 5);
island.centerSubvoxels[2] = island.topZSubvoxels - island.topHalfSubvoxels;
island.bottomZSubvoxels = island.topZSubvoxels
- island.radiusSubvoxels * recipe.thicknessRatioQ16 / floating_island_detail::Q16;
island.bottomZSubvoxels = floating_island_detail::IslandBottom(recipe,
island.topZSubvoxels, island.radiusSubvoxels);
floating_island_detail::SetIslandBounds(recipe, island);
islands.push_back(island);
}
@@ -1016,26 +1217,41 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
const std::uint64_t site = 0x300000000ull + branch;
if (floating_island_detail::UnitQ16(recipe.seed, site, 0x53495445524f4c4cull)
>= static_cast<std::uint32_t>(recipe.islandDensityQ16)) continue;
const std::uint32_t hostIndex = branch == 0 ? 0 : count - 1;
const std::uint32_t hostIndex = recipe.geometryVersion < 2
? (branch == 0 ? 0 : count - 1)
: (branch == 0 ? middle : std::min(middle + 1, count - 1));
const auto& host = islands[hostIndex];
const std::int64_t xOffset = recipe.geometryVersion < 2 ? 0
: (branch == 0 ? -1 : 1) * recipe.spacingSubvoxels * 9 / 20;
const std::int64_t yOffset = branch == 0 ? -recipe.spacingSubvoxels : recipe.spacingSubvoxels;
const std::int64_t gap = recipe.spacingSubvoxels - static_cast<std::int64_t>(
std::llround(0.78 * static_cast<double>(host.radiusSubvoxels + recipe.minimumRadiusSubvoxels)));
const std::int64_t rise = static_cast<std::int64_t>(std::ceil(std::max(0.0,
static_cast<double>(gap) * maxGrade * levelFactor)));
const std::int64_t topZ = host.topZSubvoxels
+ floating_island_detail::SignedRange(recipe.seed, site, 0x4252414e43484c56ull, rise);
const std::int64_t sideRise = recipe.geometryVersion < 2 ? rise
: std::min<std::int64_t>(24 * floating_island_detail::Q,
(recipe.layoutMaximumZSubvoxels - recipe.layoutMinimumZSubvoxels)
* recipe.verticalJitterQ16 / (8 * floating_island_detail::Q16));
std::int64_t topZ = host.topZSubvoxels
+ floating_island_detail::SignedRange(recipe.seed, site, 0x4252414e43484c56ull, sideRise);
const std::uint32_t radiusRoll = floating_island_detail::UnitQ16(recipe.seed, site, 0x524144495553ull);
const std::int64_t branchRadius = recipe.minimumRadiusSubvoxels
+ (recipe.maximumRadiusSubvoxels - recipe.minimumRadiusSubvoxels) * radiusRoll / 65535;
if (recipe.geometryVersion >= 2)
{
const std::int64_t maximumTop = recipe.layoutMaximumZSubvoxels
- recipe.boundarySealSubvoxels - branchRadius / 5;
const std::int64_t minimumTop = recipe.layoutMinimumZSubvoxels
+ recipe.boundarySealSubvoxels + floating_island_detail::IslandBottom(recipe, 0, branchRadius) * -1;
topZ = std::clamp(topZ, minimumTop, maximumTop);
}
auto island = floating_island_detail::MakeIsland(recipe,
recipe.primaryIslandCount + branch,
host.centerSubvoxels[0], host.centerSubvoxels[1] + yOffset, topZ, site);
host.centerSubvoxels[0] + xOffset, host.centerSubvoxels[1] + yOffset, topZ, site);
island.radiusSubvoxels = branchRadius;
island.topHalfSubvoxels = std::max<std::int64_t>(1, branchRadius / 5);
island.centerSubvoxels[2] = topZ - island.topHalfSubvoxels;
island.bottomZSubvoxels = topZ - branchRadius * recipe.thicknessRatioQ16
/ floating_island_detail::Q16;
island.bottomZSubvoxels = floating_island_detail::IslandBottom(recipe, topZ, branchRadius);
floating_island_detail::SetIslandBounds(recipe, island);
const std::uint64_t islandId = island.stableId;
islands.push_back(island);
@@ -1074,7 +1290,8 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
point.stableFeatureId = floating_island_detail::StableId(recipe.seed,
0x500000000ull + routeOrdinal, 0x524f555445ull);
point.positionSubvoxels = {x, y, *surface + capsuleHalf
+ recipe.routeConstraints.minimumClearanceSubvoxels};
+ recipe.routeConstraints.minimumClearanceSubvoxels
+ (recipe.geometryVersion >= 2 ? floating_island_detail::Q / 8 : 0)};
point.radiusSubvoxels = routeRadius;
route.push_back(point);
++routeOrdinal;
@@ -1471,4 +1688,37 @@ FloatingIslandRouteAuditResult AuditFloatingIslandRoute(const FloatingIslandFiel
return result;
}
FloatingIslandThicknessAuditResult AuditFloatingIslandThickness(
const FloatingIslandPlanV1& plan, double minimumDepthToDiameterRatio)
{
FloatingIslandThicknessAuditResult result;
result.requiredDepthToDiameterRatio = minimumDepthToDiameterRatio;
if (plan.islands.empty() || !std::isfinite(minimumDepthToDiameterRatio)
|| minimumDepthToDiameterRatio <= 0.0) return result;
result.minimumDepthToDiameterRatio = std::numeric_limits<double>::infinity();
for (const auto& island : plan.islands)
{
++result.islandsTested;
if (island.radiusSubvoxels <= 0 || island.topZSubvoxels <= island.bottomZSubvoxels)
{
++result.islandsBelowMinimum;
result.minimumDepthToDiameterRatio = 0.0;
result.minimumIslandStableId = island.stableId;
continue;
}
const double ratio = static_cast<double>(island.topZSubvoxels - island.bottomZSubvoxels)
/ (2.0 * static_cast<double>(island.radiusSubvoxels));
if (ratio < result.minimumDepthToDiameterRatio)
{
result.minimumDepthToDiameterRatio = ratio;
result.minimumIslandStableId = island.stableId;
}
if (ratio + 1.0e-12 < minimumDepthToDiameterRatio) ++result.islandsBelowMinimum;
}
if (!std::isfinite(result.minimumDepthToDiameterRatio)) result.minimumDepthToDiameterRatio = 0.0;
result.passed = result.islandsTested == plan.islands.size()
&& result.islandsBelowMinimum == 0;
return result;
}
}
@@ -1027,3 +1027,39 @@ files are listed there. No `Source/` or `Standalone/Source/` file, owner project
commit, push, or stash was touched.
— Luna
## Luna, M3 round 2 — FloatingIslands look pass
Hi Claude,
Round 2 replaces the thin profile with a broad crust and three or four deterministic tapered roots
per island. The previous underside pinch came from tapering the cross-section to zero at its bottom
plane; version 2 uses a broad underside and independent root lobes. Bounded contour warp and surface
roughness add broken edges inside the certified detail bounds. One side island sits above and away
from the three-island route; the route spans are broad, arched and sharp-tag-ready. The main route is
still a connected backbone, and the native cluster is intentionally denser than the owner's sampled
field.
The owner settings describe a stochastic site process, not a fixed count: density is 0.5 per hashed
XY cell, spacing is 112 legacy voxels and radius fields are 24–48 voxels. I used the production
12.5 cm legacy scale against 25 cm Core, mapping lengths by 0.5. This gives 14 m spacing and 3–6 m
radii. The frozen probe metadata and a radius comment instead assume 25 cm; Round 3 must reconcile
that at the snapshot producer before finalizing the Unreal import contract.
The five fresh matched views are in the [contact sheet](../../WorldAssemblerM3/Round2/results/captures/contact_sheet.jpg).
All images are below 300 KB. Bounds passed 515 boxes with zero misses and the shrunken-bound control
was detected. All four islands measured at least 0.75 depth/diameter; the 0.30 thin-pad control
failed. The route passed 254 capsule centers / 69,088 field samples; its raised control failed at all
254 centers. W1/W8/W16 hashes match. On 32,768 same-physical-location queries, native was 38.06 ms
vs 64.64 ms legacy, with 1,380 vs 130 solid samples.
The full report, scale caveat, captures, run ledger and Round 3 plan are in
[`WorldAssemblerM3/Round2/REPORT.md`](../../WorldAssemblerM3/Round2/REPORT.md). It lists one failed
Core compile, eight failed audit iterations and one corrected renderer failure; the final build and
audit passed, with no crash or `0xC0000142` retry. The old M1 and SurfaceWorld manifest hashes still
match; the M2 mesher hash matrix was not replayed. No editor/viewer, project build, `.uasset`,
`Source/` edit, commit, push or stash was used.
New source file this round: `RenderFloatingIslandRound2.py`.
— Luna
@@ -143,10 +143,11 @@ namespace
float LegacyDensity(const FStandaloneOwnerWorld& owner, const Point& q)
{
constexpr double CoreToLegacyVoxelScale = 2.0;
return owner.Generator->GetDensityAt(
static_cast<float>(q[0] / static_cast<double>(Q)),
static_cast<float>(q[1] / static_cast<double>(Q)),
static_cast<float>(q[2] / static_cast<double>(Q)));
static_cast<float>(CoreToLegacyVoxelScale * q[0] / static_cast<double>(Q)),
static_cast<float>(CoreToLegacyVoxelScale * q[1] / static_cast<double>(Q)),
static_cast<float>(CoreToLegacyVoxelScale * q[2] / static_cast<double>(Q)));
}
OracleAnchor FindLegacyAnchor(const FStandaloneOwnerWorld& owner)
@@ -425,9 +426,13 @@ namespace
void WriteJson(const std::filesystem::path& path, const FloatingIslandManifestV1& manifest,
const FloatingIslandBoundsAuditResult& bounds, const FloatingIslandRouteAuditResult& route,
const FloatingIslandRouteAuditResult& raised, const SampleStats& sample,
const FloatingIslandThicknessAuditResult& thickness,
const FloatingIslandThicknessAuditResult& thinThickness,
const OracleAnchor& anchor, const std::array<MeshResult, 4>& meshes,
const std::array<std::string, 3>& fieldHashes, const ExistingHashes& oldHashes)
{
const Point ownerAnchorQ = anchor.surfaceQ;
const Point coreAnchorQ{ownerAnchorQ[0] / 2, ownerAnchorQ[1] / 2, ownerAnchorQ[2] / 2};
std::ofstream out(path, std::ios::trunc);
if (!out) throw std::runtime_error("cannot create audit result JSON");
out << std::setprecision(12);
@@ -437,13 +442,20 @@ namespace
<< "\",\n \"unchanged_existing_hashes\":{\"m1_round1_manifest\":\""
<< oldHashes.round1Manifest << "\",\"surfaceworld_round4_manifest\":\""
<< oldHashes.surfaceWorldRound4Manifest << "\"}"
<< ",\n \"geometry_version\":" << manifest.recipe.geometryVersion
<< ",\n \"owner_voxel_size_cm\":12.5,\n \"core_voxel_size_cm\":25"
<< ",\n \"owner_to_core_length_scale\":0.5"
<< ",\n \"plan_islands\":" << manifest.plan.islands.size()
<< ",\n \"plan_connectors\":" << manifest.plan.clusterEdges.size()
<< ",\n \"route_points\":" << manifest.plan.route.size()
<< ",\n \"legacy_anchor_voxels\":[" << anchor.surfaceQ[0] / static_cast<double>(Q)
<< ',' << anchor.surfaceQ[1] / static_cast<double>(Q) << ','
<< anchor.surfaceQ[2] / static_cast<double>(Q) << "],\n \"legacy_anchor_plateau_samples\":"
<< ",\n \"legacy_anchor_owner_voxels\":[" << ownerAnchorQ[0] / static_cast<double>(Q)
<< ',' << ownerAnchorQ[1] / static_cast<double>(Q) << ','
<< ownerAnchorQ[2] / static_cast<double>(Q) << ']'
<< ",\n \"comparison_anchor_core_voxels\":[" << coreAnchorQ[0] / static_cast<double>(Q)
<< ',' << coreAnchorQ[1] / static_cast<double>(Q) << ','
<< coreAnchorQ[2] / static_cast<double>(Q) << "],\n \"legacy_anchor_plateau_samples\":"
<< anchor.supportScore << ",\n \"recipe_parameters\":{\"seed\":" << manifest.recipe.seed
<< ",\"primary_island_count\":" << manifest.recipe.primaryIslandCount
<< ",\"density_q16\":" << manifest.recipe.islandDensityQ16
<< ",\"spacing_voxels\":" << manifest.recipe.spacingSubvoxels / static_cast<double>(Q)
<< ",\"radius_voxels\":[" << manifest.recipe.minimumRadiusSubvoxels / static_cast<double>(Q)
@@ -452,20 +464,53 @@ namespace
<< ",\"vertical_jitter_q16\":" << manifest.recipe.verticalJitterQ16
<< ",\"top_flatten_q16\":" << manifest.recipe.topFlattenQ16
<< ",\"contour_warp_voxels\":" << manifest.recipe.contourWarpSubvoxels / static_cast<double>(Q)
<< ",\"crust_depth_bonus_q16\":" << manifest.recipe.crustDepthBonusQ16
<< ",\"root_depth_ratio_q16\":" << manifest.recipe.rootDepthRatioQ16
<< ",\"roughness_voxels\":" << manifest.recipe.roughnessSubvoxels / static_cast<double>(Q)
<< ",\"blend_voxels\":" << manifest.recipe.blendRadiusSubvoxels / static_cast<double>(Q) << "},\n \"stable_island_ids\":[";
<< ",\"blend_voxels\":" << manifest.recipe.blendRadiusSubvoxels / static_cast<double>(Q)
<< ",\"bridge_half_width_voxels\":" << manifest.recipe.bridgeHalfWidthSubvoxels / static_cast<double>(Q)
<< ",\"bridge_thickness_voxels\":" << manifest.recipe.bridgeThicknessSubvoxels / static_cast<double>(Q)
<< "},\n \"stable_island_ids\":[";
for (std::size_t i = 0; i < manifest.plan.islands.size(); ++i)
{ if (i) out << ','; out << '\"' << Hex64(manifest.plan.islands[i].stableId) << '\"'; }
out << "],\n \"stable_connector_ids\":[";
for (std::size_t i = 0; i < manifest.plan.clusterEdges.size(); ++i)
{ if (i) out << ','; out << '\"' << Hex64(manifest.plan.clusterEdges[i].stableId) << '\"'; }
out << "],\n \"island_profiles\":[";
for (std::size_t i = 0; i < manifest.plan.islands.size(); ++i)
{
if (i) out << ',';
const auto& island = manifest.plan.islands[i];
const double ratio = static_cast<double>(island.topZSubvoxels - island.bottomZSubvoxels)
/ (2.0 * static_cast<double>(island.radiusSubvoxels));
out << "{\"id\":\"" << Hex64(island.stableId) << "\",\"ordinal\":" << island.ordinal
<< ",\"center_voxels\":[" << island.centerSubvoxels[0] / static_cast<double>(Q)
<< ',' << island.centerSubvoxels[1] / static_cast<double>(Q)
<< ',' << island.centerSubvoxels[2] / static_cast<double>(Q)
<< "],\"radius_voxels\":" << island.radiusSubvoxels / static_cast<double>(Q)
<< ",\"top_voxels\":" << island.topZSubvoxels / static_cast<double>(Q)
<< ",\"bottom_voxels\":" << island.bottomZSubvoxels / static_cast<double>(Q)
<< ",\"depth_to_diameter\":" << ratio << '}';
}
out << "],\n \"bounds\":{\"passed\":" << (bounds.passed ? "true" : "false")
<< ",\"negative_control_detected\":" << (bounds.negativeControlDetected ? "true" : "false")
<< ",\"boxes\":" << bounds.boxesTested << ",\"samples\":" << bounds.pointSamples
<< ",\"unknown\":" << bounds.unknownBounds << ",\"missed\":" << bounds.missedBounds
<< ",\"island_boxes\":" << bounds.islandBoundsTested
<< ",\"connector_boxes\":" << bounds.connectorBoundsTested
<< ",\"void_boxes_proved_air\":" << bounds.voidBoxesProvedAir << "},\n \"route\":{\"passed\":"
<< ",\"void_boxes_proved_air\":" << bounds.voidBoxesProvedAir << "},\n \"thickness\":{\"passed\":"
<< (thickness.passed ? "true" : "false")
<< ",\"islands_tested\":" << thickness.islandsTested
<< ",\"islands_below_minimum\":" << thickness.islandsBelowMinimum
<< ",\"minimum_depth_to_diameter_ratio\":" << thickness.minimumDepthToDiameterRatio
<< ",\"required_depth_to_diameter_ratio\":" << thickness.requiredDepthToDiameterRatio
<< ",\"minimum_island_id\":\"" << Hex64(thickness.minimumIslandStableId) << "\"}"
<< ",\n \"thin_pad_negative_control\":{\"detected\":"
<< ((!thinThickness.passed && thinThickness.islandsBelowMinimum == thinThickness.islandsTested)
? "true" : "false")
<< ",\"failed_islands\":" << thinThickness.islandsBelowMinimum
<< ",\"minimum_depth_to_diameter_ratio\":" << thinThickness.minimumDepthToDiameterRatio << "}"
<< ",\n \"route\":{\"passed\":"
<< (route.passed ? "true" : "false") << ",\"segments\":" << route.segmentsTested
<< ",\"centers\":" << route.centerSamples << ",\"capsule_samples\":"
<< route.capsuleFieldSamples << ",\"blocked\":" << route.blockedCapsuleSamples
@@ -494,7 +539,7 @@ namespace
out << "{\"name\":\"" << names[i] << "\",\"grid_samples\":" << meshes[i].gridSamples
<< ",\"triangles\":" << meshes[i].triangles << ",\"bytes\":" << meshes[i].bytes << '}';
}
out << "],\n \"route_points_voxels\":[";
out << "],\n \"route_points_core_voxels\":[";
for (std::size_t i = 0; i < manifest.plan.route.size(); ++i)
{
if (i) out << ',';
@@ -531,30 +576,33 @@ int main(int argc, char** argv)
const OracleAnchor anchor = FindLegacyAnchor(owner);
if (anchor.supportScore < 9)
throw std::runtime_error("legacy scan found no broad FloatingIslands top in the frozen strate range");
const Point coreAnchorQ{anchor.surfaceQ[0] / 2,
anchor.surfaceQ[1] / 2, anchor.surfaceQ[2] / 2};
FloatingIslandRecipeV1 recipe;
recipe.seed = 0;
recipe.layoutOriginXSubvoxels = anchor.surfaceQ[0];
recipe.layoutOriginYSubvoxels = anchor.surfaceQ[1];
recipe.layoutCenterTopZSubvoxels = anchor.surfaceQ[2];
recipe.layoutMinimumZSubvoxels = anchor.surfaceQ[2] - 96 * Q;
recipe.layoutMaximumZSubvoxels = anchor.surfaceQ[2] + 96 * Q;
recipe.primaryIslandCount = 5;
recipe.layoutOriginXSubvoxels = coreAnchorQ[0];
recipe.layoutOriginYSubvoxels = coreAnchorQ[1];
recipe.layoutCenterTopZSubvoxels = coreAnchorQ[2];
recipe.geometryVersion = 2;
recipe.layoutMinimumZSubvoxels = coreAnchorQ[2] - 80 * Q;
recipe.layoutMaximumZSubvoxels = coreAnchorQ[2] + 48 * Q;
recipe.primaryIslandCount = 3;
recipe.islandDensityQ16 = 32768;
recipe.spacingSubvoxels = 112 * Q;
recipe.minimumRadiusSubvoxels = 24 * Q;
recipe.maximumRadiusSubvoxels = 48 * Q;
recipe.spacingSubvoxels = 56 * Q;
recipe.minimumRadiusSubvoxels = 12 * Q;
recipe.maximumRadiusSubvoxels = 24 * Q;
recipe.thicknessRatioQ16 = 39322;
recipe.verticalJitterQ16 = 39322;
recipe.topFlattenQ16 = 39322;
recipe.taperEndMinimumQ16 = 29491;
recipe.taperEndMaximumQ16 = 45875;
recipe.blendRadiusSubvoxels = 6 * Q;
recipe.contourWarpSubvoxels = VoxQ((24.0 + 48.0) * 0.35 * 0.5);
recipe.roughnessSubvoxels = 3 * Q;
recipe.boundarySealSubvoxels = 4 * Q;
recipe.bridgeHalfWidthSubvoxels = 4 * Q;
recipe.bridgeThicknessSubvoxels = 3 * Q;
recipe.blendRadiusSubvoxels = 3 * Q;
recipe.contourWarpSubvoxels = VoxQ(6.3);
recipe.roughnessSubvoxels = VoxQ(1.5);
recipe.boundarySealSubvoxels = 2 * Q;
recipe.bridgeHalfWidthSubvoxels = 6 * Q;
recipe.bridgeThicknessSubvoxels = 4 * Q;
const auto beginPlanning = Clock::now();
auto planned = PlanFloatingIslandCluster(recipe, error);
@@ -579,6 +627,12 @@ int main(int argc, char** argv)
const auto bounds = AuditFloatingIslandBounds(field, 512);
const auto route = AuditFloatingIslandRoute(field);
const auto raisedRoute = AuditFloatingIslandRoute(field, 8 * Q);
const auto thickness = AuditFloatingIslandThickness(planned->plan);
auto thinPlan = planned->plan;
for (auto& island : thinPlan.islands)
island.bottomZSubvoxels = island.topZSubvoxels
- island.radiusSubvoxels * planned->recipe.thicknessRatioQ16 / 65536;
const auto thinThickness = AuditFloatingIslandThickness(thinPlan);
const auto influence = field.influenceBounds();
const auto points = MakeSamples(influence, 32768, 0x4d33524f554e4431ull);
const auto w1 = HashWithWorkers(field, owner, points, 1, false);
@@ -588,6 +642,9 @@ int main(int argc, char** argv)
if (w1.hash != w8.hash || w1.hash != w16.hash)
throw std::runtime_error("native field sample hash differs between W1/W8/W16");
if (!bounds.passed) throw std::runtime_error("native island bounds audit or negative control failed");
if (!thickness.passed || thinThickness.passed
|| thinThickness.islandsBelowMinimum != thinThickness.islandsTested)
throw std::runtime_error("native island thickness audit or thin-pad negative control failed");
std::cout << "route_diagnostics pass=" << route.passed << " segments=" << route.segmentsTested
<< " centers=" << route.centerSamples << " capsule_samples=" << route.capsuleFieldSamples
<< " blocked=" << route.blockedCapsuleSamples << " support_samples=" << route.supportProbeSamples
@@ -602,6 +659,22 @@ int main(int argc, char** argv)
if (!route.passed)
{
const auto& routePoints = planned->plan.route;
if (route.firstBlockedSegment != ~std::uint64_t{0})
std::cout << "first_blocked_position_voxels="
<< route.firstBlockedPositionSubvoxels[0] / static_cast<double>(Q) << ','
<< route.firstBlockedPositionSubvoxels[1] / static_cast<double>(Q) << ','
<< route.firstBlockedPositionSubvoxels[2] / static_cast<double>(Q) << '\n';
const std::size_t debugBegin = route.firstUnsupportedSegment == ~std::uint64_t{0}
? 0 : static_cast<std::size_t>(route.firstUnsupportedSegment);
for (std::size_t i = debugBegin > 1 ? debugBegin - 1 : 0;
i < std::min(routePoints.size(), debugBegin + 3); ++i)
{
const auto& point = routePoints[i].positionSubvoxels;
std::cout << "route_point=" << i << ' '
<< point[0] / static_cast<double>(Q) << ','
<< point[1] / static_cast<double>(Q) << ','
<< point[2] / static_cast<double>(Q) << '\n';
}
const double maxGrade = static_cast<double>(planned->recipe.routeConstraints.maximumGradeQ16) / 65536.0;
for (std::size_t i = 0; i + 1 < routePoints.size(); ++i)
{
@@ -628,6 +701,9 @@ int main(int argc, char** argv)
const auto& unsupported = route.firstUnsupportedCenterSubvoxels;
const double foot = unsupported[2] / static_cast<double>(Q)
- constraints.capsuleHeightSubvoxels / (2.0 * Q);
std::cout << "unsupported_route_probe=" << unsupported[0] / static_cast<double>(Q)
<< ',' << unsupported[1] / static_cast<double>(Q) << ','
<< unsupported[2] / static_cast<double>(Q) << " foot=" << foot << '\n';
const double probeRadius = constraints.supportProbeRadiusSubvoxels / static_cast<double>(Q);
const std::array<std::array<double, 2>, 5> supportPoints{{
{0.0,0.0},{probeRadius,0.0},{-probeRadius,0.0},{0.0,probeRadius},{0.0,-probeRadius}}};
@@ -645,6 +721,16 @@ int main(int argc, char** argv)
if (density < 0) { firstSolidDepth = depth; break; }
}
std::cout << "support_probe=" << probeIndex << " first_solid_depth_vox=" << firstSolidDepth << '\n';
std::cout << "support_profile=" << probeIndex << ':';
for (double depth = 0.5; depth <= 5.0; depth += 0.5)
{
const auto density = field.densitySubvoxels(
std::llround(unsupported[0] + supportPoints[probeIndex][0] * Q),
std::llround(unsupported[1] + supportPoints[probeIndex][1] * Q),
std::llround((foot - depth) * Q));
std::cout << ' ' << depth << '=' << density;
}
std::cout << '\n';
}
for (std::size_t i = 0; i < planned->plan.clusterEdges.size(); ++i)
{
@@ -662,12 +748,15 @@ int main(int argc, char** argv)
&& raisedRoute.blockedCapsuleSamples == 0))
throw std::runtime_error("raised-route negative control did not detect unsupported traversal");
const std::int64_t ox = anchor.surfaceQ[0], oy = anchor.surfaceQ[1], oz = anchor.surfaceQ[2];
std::array<MeshResult, 4> meshes{};
const Point clusterMin{ox - 320 * Q, oy - 208 * Q, oz - 80 * Q};
const Point clusterMax{ox + 320 * Q, oy + 208 * Q, oz + 16 * Q};
const Point detailMin{ox - 64 * Q, oy - 64 * Q, oz - 48 * Q};
const Point detailMax{ox + 64 * Q, oy + 64 * Q, oz + 10 * Q};
const auto clusterBounds = field.influenceBounds();
if (!clusterBounds.finite) throw std::runtime_error("native cluster mesh bounds are not finite");
const Point clusterMin{clusterBounds.minimumSubvoxels[0] - 8 * Q,
clusterBounds.minimumSubvoxels[1] - 8 * Q, clusterBounds.minimumSubvoxels[2] - 8 * Q};
const Point clusterMax{clusterBounds.maximumSubvoxels[0] + 8 * Q,
clusterBounds.maximumSubvoxels[1] + 8 * Q, clusterBounds.maximumSubvoxels[2] + 8 * Q};
const Point detailMin{coreAnchorQ[0] - 64 * Q, coreAnchorQ[1] - 64 * Q, coreAnchorQ[2] - 80 * Q};
const Point detailMax{coreAnchorQ[0] + 64 * Q, coreAnchorQ[1] + 64 * Q, coreAnchorQ[2] + 16 * Q};
meshes[0] = ExtractMesh(outputDir / "cluster_legacy.vfmesh", clusterMin, clusterMax, 4 * Q,
[&](const Point& q) { return SampleLegacy(owner, q); });
meshes[1] = ExtractMesh(outputDir / "cluster_native.vfmesh", clusterMin, clusterMax, 4 * Q,
@@ -681,11 +770,14 @@ int main(int argc, char** argv)
throw std::runtime_error("matched legacy/native mesh extraction produced an empty field");
WriteJson(outputDir / "audit.json", *planned, bounds, route, raisedRoute,
w16, anchor, meshes, hashes, oldHashes);
w16, thickness, thinThickness, anchor, meshes, hashes, oldHashes);
std::cout << std::setprecision(4)
<< "legacy_anchor_voxels=" << anchor.surfaceQ[0] / static_cast<double>(Q) << ','
<< "legacy_anchor_owner_voxels=" << anchor.surfaceQ[0] / static_cast<double>(Q) << ','
<< anchor.surfaceQ[1] / static_cast<double>(Q) << ','
<< anchor.surfaceQ[2] / static_cast<double>(Q)
<< " comparison_anchor_core_voxels=" << coreAnchorQ[0] / static_cast<double>(Q) << ','
<< coreAnchorQ[1] / static_cast<double>(Q) << ','
<< coreAnchorQ[2] / static_cast<double>(Q)
<< " plateau_samples=" << anchor.supportScore << '\n'
<< "recipe_hash=" << Hex64(planned->recipe.contentHash)
<< " plan_hash=" << Hex64(planned->plan.contentHash)
@@ -708,6 +800,12 @@ int main(int argc, char** argv)
<< "raised_route_detected=" << (!raisedRoute.passed && raisedRoute.unsupportedCenterSamples > 0)
<< " unsupported=" << raisedRoute.unsupportedCenterSamples
<< " blocked=" << raisedRoute.blockedCapsuleSamples << '\n'
<< "thickness_pass=" << thickness.passed << " islands=" << thickness.islandsTested
<< " min_depth_diameter=" << thickness.minimumDepthToDiameterRatio
<< " threshold=" << thickness.requiredDepthToDiameterRatio
<< " thin_pad_detected=" << (!thinThickness.passed
&& thinThickness.islandsBelowMinimum == thinThickness.islandsTested)
<< " thin_ratio=" << thinThickness.minimumDepthToDiameterRatio << '\n'
<< "field_hashes W1=" << w1.hash << " W8=" << w8.hash << " W16=" << w16.hash
<< " legacy_ms=" << w16.legacyMilliseconds << " native_ms=" << w16.nativeMilliseconds
<< " mismatch_percent=" << (100.0 * w16.signMismatches / 32768.0)
@@ -0,0 +1,172 @@
# M3 Round 2 — FloatingIslands look and standalone gates
**Result:** geometry version 2 gives the islands a deep, rough underside with separated tapered
roots, variable-height placement, and broad arched connectors. Fresh matched CPU captures include
overview, underside, edge/cliff, player-eye and route views. The measurable bounds, thickness,
capsule-route and determinism gates pass. The native sample remains much denser than the owner
field, so this is a deliberate routeable recipe rather than a visual-parity claim.
## Owner recipe and scale
The legacy settings do not request a fixed island count. `IslandDensity=0.5` is a per-hashed-XY-site
existence chance. The owner parameters are spacing 112 legacy voxels, radius fields 24–48 legacy
voxels, thickness ratio 0.6, vertical jitter/top flatten 0.6, roughness 3, blend radius 6 and boundary
seal 4. The production `Source` constant and plugin-root `CLAUDE.md` say a legacy voxel is 12.5 cm;
Core uses 25 cm. Round 2 therefore queries the legacy field at twice each Core coordinate and maps
owner lengths to Core lengths at 0.5 scale:
| Setting | Owner | Round 2 Core | Physical intent at production scale |
|---|---:|---:|---:|
| Site spacing | 112 voxels | 56 voxels | 14 m |
| Radius | 24–48 voxels | 12–24 voxels | 3–6 m radius |
| Roughness | 3 voxels | 1.5 voxels | 0.375 m amplitude bound |
| Blend radius | 6 voxels | 3 voxels | 0.75 m |
| Boundary seal | 4 voxels | 2 voxels | 0.5 m |
There is a scale conflict to resolve before importing this recipe. The frozen owner probe metadata
and `Standalone/Source` mirror say 25 cm, and the radius comment describes 12–24 m diameters at that
scale. Production `Source` and `CLAUDE.md` say 12.5 cm, which makes the same radius fields 6–12 m
diameters. The audit uses the production 12.5 cm field, with legacy anchor `(48, 16, -1904.035)`
mapped to Core `(24, 8, -952.016)`. Round 3 must fix the snapshot producer/metadata and publish one
import scale contract; it must not silently choose between these interpretations.
The native planner requires three route-connected primary islands, then uses the 0.5 density roll
for optional off-route sites; this seed made one, for four islands and three connectors. That is a
stated routeability constraint, not an owner fixed-count setting. Geometry version 2 adds a crust
depth bonus of 0.15 radius and a root depth of 0.75 radius to the owner 0.6-ratio body. Total measured
depth is 0.75 of island diameter. The deeper roots and guaranteed route account for the local density
increase below.
## Visual review
The round-1 reading was substantially right. Its low thickness ratio and `SmoothStep` taper drove the
underside radius to zero at the bottom plane. The vanishing cross-section made the underside gradient
collapse at a shared point and produced the radial crease/pinch. The old profile also had no
independent roots, and its main route lay on a nearly straight chain.
Version 2 gives the crust a broad, gently bowed bottom surface, then smooth-unions three or four
seeded ellipsoid roots per island. Their lengths taper independently, so they do not converge at one
apex. The bounded 6.3-Core-voxel contour warp breaks the silhouettes; 1.5-voxel surface roughness is
faded to zero across a three-voxel surface band. The certified boxes include the contour warp,
roughness and blend reach. The underside and edge captures show the additional mass and root lobes.
The three primary islands form a bent, vertically fitted traversal. This seed also produces one
higher side island that is not on the route. There are still three connectors because the route has
to cross the three primary sites; they are 3 m wide, 1 m thick at the ends, and their underside sags
by up to 2 m at midspan. Each is marked sharp-tag-ready. The captures show a rock-span profile rather
than the old narrow straight rods, although the route-connected backbone remains visually legible as
a chain. The route-island tops vary by about 0.67 m; the off-route island is about 1.46 m above the
middle route island.
The underside and edge captures are close views of the middle island so the larger cluster does not
set their scale. The player-eye view is an offline perspective render from 1.8 m above the route
floor, using the 25 cm Core voxel scale and the approximately 1.8 m player height. These are
field-mesh review images, not Unreal camera, traversal, or collision evidence.
| View | Capture |
|---|---|
| All five matched views | [Contact sheet](results/captures/contact_sheet.jpg) |
| Cluster overview | [overview_matched.jpg](results/captures/overview_matched.jpg) |
| Underside and roots | [underside_matched.jpg](results/captures/underside_matched.jpg) |
| Thick crust and edge/cliff | [edge_cliff_matched.jpg](results/captures/edge_cliff_matched.jpg) |
| Player-eye toward next island | [player_eye_matched.jpg](results/captures/player_eye_matched.jpg) |
| Planned route | [route_matched.jpg](results/captures/route_matched.jpg) |
The CPU renderer lowered its process priority. All images are 640×258 pixels individually; the
contact sheet is 640×1,290 pixels and 71,668 bytes. Every JPEG is below 300 KB. Legacy/native pairs
use the same target, camera and scale. The legacy side remains much smaller because it is the exact
stochastic owner field at the same physical anchor, not a hand-expanded parity target.
## Standalone gates
The final `Target All` Core build and the audit wrapper passed. The wrapper samples the same 32,768
physical query locations for legacy and native timing.
| Gate | Final result |
|---|---:|
| Recipe / plan / manifest hashes | `5b8f27274bad89ba` / `ac33c9460b16337a` / `0db30684eaefa75e` |
| Bounds | 515 boxes, 13,851 point samples, 74 unknown, **0 missed**; shrunken-box control detected |
| Thickness | 4 islands; minimum depth/diameter 0.75 vs 0.70 required; all pass |
| Thin-pad control | Ratio 0.2999; all 4 islands fail, control detected |
| Route | 28 segments, 254 capsule centers, 69,088 capsule samples, 1,430 support probes; 0 blocked, 0 unsupported, 0 grade failures |
| Minimum sampled density clearance | 78 subvoxels (0.305 Core voxel) |
| Raised-route control (+8 voxels) | Detected: 254 unsupported centers, 0 blocked |
| Field hash at W1 / W8 / W16 | `566b6115f1aaeb71` for all three; repeated plan stable |
| Query timing, 32,768 locations | Legacy 64.64 ms; native 38.06 ms (0.589× legacy time, about 1.70× faster) |
| Local sign / occupancy difference | 4.437% sign mismatch; 130 legacy-solid vs 1,380 native-solid samples |
The sample contains 10.6× as many native-solid points as legacy (1,352 native-only and 102
legacy-only). This is a local sparse-field sample, not a global volume estimate. It confirms the
native density difference visible in the matched images. The extra route backbone, thick crust and
deep roots are the stated reasons; the native field is not being presented as owner occupancy parity.
The audit reparsed the unchanged existing M1 round-1 manifest hash `c87ae279b0e26f53` and
SurfaceWorld round-4 manifest hash `8933693d9560ba9f`. No existing Core world evaluator,
SurfaceWorld recipe or mesher implementation was edited. The complete M2 mesher hash matrix was not
replayed in this round; the M2 report records the prior fixture mesh hash `9d58e0603f1bf9c7` and
cliff tile hash `fc7bd7a3cf997992`.
Full audit data is in [audit.json](results/audit.json); the successful wrapper ledger is
[run_ledger.txt](results/run_ledger.txt). Mesh extracts used for the captures and audit are in the
same `results` directory.
## Round 3 — Unreal delivery plan
1. Reconcile the 12.5 cm production field with the 25 cm frozen-probe metadata at the snapshot
producer. Add one explicit owner-to-Core length scale and reject payloads whose declared scale
conflicts with it.
2. Add the recipe and seeded plan to the existing optional `world_assembly` import path. Parse via
`ResolvedWorldSnapshot::FromJson`; validate schema/geometry versions, recipe/plan/manifest hashes,
stable IDs, bounds and scale before generation. Preserve round-trip JSON and stable IDs.
3. Prove imported generation in a null-RHI BuildHost commandlet. Compare canonical plan/field hashes
at W1/W8/W16 and exercise malformed-hash, unknown-version and mismatched-scale controls.
4. Build the islands and sharp-tag-ready spans through the selected mesher path. Check chunk borders,
LOD transitions, route visibility and finite bounds in Unreal. Keep the Core field available to
server queries without requiring render meshes.
5. Cook collision and sweep the actual player capsule over the imported route. Check floor support,
clearance, grade and connector landings against cooked collision, then hand the owner the imported
build, capture set, collision evidence, resolved scale note and exact source/hash manifest.
Round 2 did not add Unreal import, cooked collision, BuildHost proof or owner hand-off evidence.
## Run ledger and scope
The final build used four compile workers at BelowNormal priority and completed in about 51 seconds.
The final audit completed in 1.65 seconds and peaked at 58.8 MiB private memory; the CPU renderer
completed in about 2 seconds. No run approached the 15-minute limit, no process crash occurred, and
there was no `0xC0000142` retry. The build emitted the existing French `vswhere.exe`-not-found
warning and `VoxelStrateManager.cpp` double-to-float conversion warnings before succeeding.
Every failed iteration before that final pass:
| Failed run | Result and correction |
|---|---|
| Core `Target All` compile | Failed on one unqualified fixed-scale `Q`; qualified it and rebuilt successfully. |
| Audit 1 | One unsupported route center at segment 36. |
| Audit 2 | Diagnostic repeat showed support just beyond the 2.5-voxel search depth (solid by 3); extended/adjusted support fitting. |
| Audit 3 | Used a stale Core library after source changes and repeated the route failure; rebuilt Core before continuing. |
| Audit 4 | Raising the connector deck fixed support but caused 17 blocked capsule samples; reduced the route margin. |
| Audit 5 | No blocked samples, but one unsupported center at segment 49 near a connector end; tapered endpoint detail. |
| Audit 6 | After converting owner dimensions to production physical scale, the old 0.62-radius landing produced 17 blocked and 9 unsupported samples. |
| Audit 7 | Top-detail attenuation alone left those same counts. |
| Audit 8 | Diagnostic repeat located the route near a root-lobe edge; moving the landing to 0.38 radius and using a 1-voxel deck lift fixed it. |
| Renderer run | The first renderer pass stopped after four views when a raster row reached `HEIGHT`; clamped the row to `HEIGHT - 1`, then regenerated all five captures successfully. |
The repeated pre-final audit processes peaked at 44.6–58.8 MiB. No editor, viewer or GPU was
launched. No owner project file, `.uasset` or `Source/` file was opened for writing or changed; no
project build was run. No commit, push or stash was made.
### Source inventory
New source file in this round:
- `RenderFloatingIslandRound2.py` — CPU-only matched capture renderer.
Modified source files:
- `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`
- `Standalone/Core/src/FloatingIslandsInternal.h`
- `Standalone/Research/WorldAssemblerM3/Round1/FloatingIslandsAudit.cpp` (extended for round-2 physical-scale and visual audits)
Documentation and dialogue changes are in `Standalone/Core/API.md`, `Standalone/DESIGN_WORLD_ASSEMBLER.md`,
`CODEMAP.md` and `Standalone/Research/OwnerShapeWorld/gpu_field_port/LUNA_DIALOGUE.md`.
@@ -0,0 +1,286 @@
#!/usr/bin/env python3
"""Small CPU-only matched views of the legacy and native FloatingIslands fields."""
from __future__ import annotations
import ctypes
import json
import math
import struct
from pathlib import Path
from PIL import Image, ImageDraw
ROOT = Path(__file__).resolve().parent
RESULTS = ROOT / "results"
CAPTURES = RESULTS / "captures"
CAPTURES.mkdir(parents=True, exist_ok=True)
WIDTH, HEIGHT = 320, 226
BACKGROUND = (236, 240, 242)
LEGACY_COLOR = (133, 127, 105)
NATIVE_COLOR = (78, 135, 151)
ROUTE_COLOR = (223, 72, 45)
TILE_COLOR = (178, 60, 52)
LOD_COLOR = (211, 136, 45)
Q = 256.0
def lower_priority() -> None:
if hasattr(ctypes, "windll"):
ctypes.windll.kernel32.SetPriorityClass(ctypes.windll.kernel32.GetCurrentProcess(), 0x00004000)
def read_mesh(path: Path):
raw = path.read_bytes()
if len(raw) < 8 or raw[:4] != b"VFMI":
raise RuntimeError(f"invalid field mesh: {path}")
count = struct.unpack_from("<I", raw, 4)[0]
stride = struct.calcsize("<12f")
if len(raw) != 8 + count * stride:
raise RuntimeError(f"truncated field mesh: {path}")
triangles = [struct.unpack_from("<12f", raw, 8 + i * stride) for i in range(count)]
vertices = [tri[0:3] for tri in triangles]
vertices.extend(tri[3:6] for tri in triangles)
vertices.extend(tri[6:9] for tri in triangles)
return triangles, vertices
def normalize(vector):
size = math.sqrt(sum(value * value for value in vector))
return tuple(value / size for value in vector) if size > 1.0e-12 else (0.0, 0.0, 1.0)
def dot(a, b):
return sum(x * y for x, y in zip(a, b))
def cross(a, b):
return (a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0])
def project(points, target, view_dir, scale=None):
direction = normalize(view_dir)
forward = tuple(-value for value in direction)
reference_up = (0.0, 1.0, 0.0) if abs(forward[2]) > 0.98 else (0.0, 0.0, 1.0)
right = normalize(cross(forward, reference_up))
up = normalize(cross(right, forward))
camera_points = []
for point in points:
delta = tuple(point[i] - target[i] for i in range(3))
camera_points.append((dot(delta, right), dot(delta, up), dot(delta, forward)))
if scale is None:
span_x = max((p[0] for p in camera_points), default=1.0) - min((p[0] for p in camera_points), default=0.0)
span_y = max((p[1] for p in camera_points), default=1.0) - min((p[1] for p in camera_points), default=0.0)
scale = 0.86 * min((WIDTH - 30) / max(span_x, 1.0e-6), (HEIGHT - 30) / max(span_y, 1.0e-6))
pixels = [
(WIDTH * 0.5 + point[0] * scale, 31 + (HEIGHT - 31) * 0.5 - point[1] * scale, point[2])
for point in camera_points
]
return pixels, scale, right, up, forward
def common_scale(mesh_pair, target, view_dir):
vertices = mesh_pair[0][1] + mesh_pair[1][1]
_, scale, _, _, _ = project(vertices, target, view_dir)
return scale
def projected_line(a, b, target, basis, scale):
right, up, forward = basis
points = []
for point in (a, b):
delta = tuple(point[i] - target[i] for i in range(3))
points.append((WIDTH * 0.5 + dot(delta, right) * scale,
31 + (HEIGHT - 31) * 0.5 - dot(delta, up) * scale))
return points
def render(mesh, mesh_pair, method, target, view_dir, title, subtitle, *, route=None,
guide=None, camera_eye=None, framing_radius=None):
triangles, vertices = mesh
perspective = camera_eye is not None
if perspective:
forward = normalize(tuple(target[i] - camera_eye[i] for i in range(3)))
reference_up = (0.0, 1.0, 0.0) if abs(forward[2]) > 0.98 else (0.0, 0.0, 1.0)
right = normalize(cross(forward, reference_up))
up = normalize(cross(right, forward))
scale = WIDTH * 0.91
origin = camera_eye
else:
if framing_radius is None:
scale = common_scale(mesh_pair, target, view_dir)
else:
scale = 0.86 * min((WIDTH - 30) / (2.0 * framing_radius),
(HEIGHT - 30) / (2.0 * framing_radius))
_, _, right, up, forward = project((), target, view_dir, scale)
origin = target
def screen(point):
delta = tuple(point[i] - origin[i] for i in range(3))
cx, cy, depth = dot(delta, right), dot(delta, up), dot(delta, forward)
if perspective:
if depth <= 1.0:
return None
return (WIDTH * 0.5 + cx * scale / depth,
31 + (HEIGHT - 31) * 0.5 - cy * scale / depth, depth)
return (WIDTH * 0.5 + cx * scale,
31 + (HEIGHT - 31) * 0.5 - cy * scale, depth)
background = Image.new("RGB", (WIDTH, HEIGHT + 32), BACKGROUND)
draw = ImageDraw.Draw(background)
draw.rectangle((0, 0, WIDTH - 1, 31), fill=(34, 46, 54))
draw.text((8, 4), title, fill=(250, 252, 253))
draw.text((8, 17), subtitle, fill=(190, 207, 215))
pixels = background.load()
zbuffer = [float("inf")] * (WIDTH * (HEIGHT - 31))
camera_fill = forward if perspective else normalize(view_dir)
light = normalize((-0.25 + 1.2 * camera_fill[0],
-0.35 + 1.2 * camera_fill[1],
0.45 + 1.2 * camera_fill[2]))
base = LEGACY_COLOR if method == "legacy" else NATIVE_COLOR
for tri in triangles:
points = [screen(tri[offset:offset + 3]) for offset in (0, 3, 6)]
if any(point is None for point in points):
continue
x0 = max(0, int(math.floor(min(p[0] for p in points))))
x1 = min(WIDTH - 1, int(math.ceil(max(p[0] for p in points))))
y0 = max(31, int(math.floor(min(p[1] for p in points))))
y1 = min(HEIGHT - 1, int(math.ceil(max(p[1] for p in points))))
if x0 > x1 or y0 > y1:
continue
(ax, ay, az), (bx, by, bz), (cx, cy, cz) = points
denominator = (by - cy) * (ax - cx) + (cx - bx) * (ay - cy)
if abs(denominator) < 1.0e-10:
continue
normal = normalize(tri[9:12])
shade = 0.50 + 0.50 * max(0.0, dot(normal, light))
color = tuple(max(0, min(255, int(channel * shade))) for channel in base)
for y in range(y0, y1 + 1):
row = (y - 31) * WIDTH
for x in range(x0, x1 + 1):
sx, sy = x + 0.5, y + 0.5
u = ((by - cy) * (sx - cx) + (cx - bx) * (sy - cy)) / denominator
v = ((cy - ay) * (sx - cx) + (ax - cx) * (sy - cy)) / denominator
w = 1.0 - u - v
if u < -1e-8 or v < -1e-8 or w < -1e-8:
continue
if perspective:
depth = 1.0 / (u / az + v / bz + w / cz)
else:
depth = u * az + v * bz + w * cz
index = row + x
if depth < zbuffer[index]:
zbuffer[index] = depth
pixels[x, y] = color
basis = (right, up, forward)
if guide:
origin = guide["origin_voxels"]
top = guide["top_voxels"]
for x_delta, color, label in ((32.0, TILE_COLOR, "32v tile"), (64.0, LOD_COLOR, "64v LOD1")):
line = projected_line((origin[0] + x_delta, origin[1] - 190.0, top - 65.0),
(origin[0] + x_delta, origin[1] + 190.0, top + 14.0),
target, basis, scale)
draw.line(line, fill=color, width=2)
draw.text((max(2, min(WIDTH - 55, int(line[1][0]) + 2)),
max(33, min(HEIGHT - 11, int(line[1][1]) - 12))), label, fill=color)
if route:
points = [screen(point) for point in route]
points = [point[:2] for point in points if point is not None]
if len(points) >= 2:
draw.line(points, fill=(250, 248, 239), width=5, joint="curve")
draw.line(points, fill=ROUTE_COLOR, width=3, joint="curve")
for index in (0, len(points) - 1):
x, y = points[index]
draw.ellipse((x - 4, y - 4, x + 4, y + 4), fill=(250, 248, 239), outline=ROUTE_COLOR, width=2)
return background
def titled_pair(left, right, category):
pair = Image.new("RGB", (WIDTH * 2, HEIGHT + 32), (220, 226, 229))
pair.paste(left, (0, 0))
pair.paste(right, (WIDTH, 0))
draw = ImageDraw.Draw(pair)
draw.rectangle((0, 0, WIDTH * 2 - 1, HEIGHT + 31), outline=(72, 84, 91), width=1)
draw.text((8, HEIGHT + 14), f"{category} | same target, camera and scale", fill=(45, 55, 61))
return pair
def main():
lower_priority()
data = json.loads((RESULTS / "audit.json").read_text(encoding="utf-8"))
anchor = data["comparison_anchor_core_voxels"]
route = data["route_points_core_voxels"]
profiles = data["island_profiles"]
middle_island = profiles[1]
cluster = {
"legacy": read_mesh(RESULTS / "cluster_legacy.vfmesh"),
"native": read_mesh(RESULTS / "cluster_native.vfmesh"),
}
detail = {
"legacy": read_mesh(RESULTS / "detail_legacy.vfmesh"),
"native": read_mesh(RESULTS / "detail_native.vfmesh"),
}
a = anchor
scenes = (
("overview", "Cluster overview", cluster, (a[0], a[1], a[2] - 28.0), (8.0, -10.0, 7.0), None, None),
("underside", "Cluster underside and lobed roots", detail,
(middle_island["center_voxels"][0], middle_island["center_voxels"][1],
middle_island["bottom_voxels"] - 6.0), (0.12, -0.08, -1.0), None, None),
("edge_cliff", "Thick crust and bounded rock detail", detail,
(middle_island["center_voxels"][0], middle_island["center_voxels"][1],
middle_island["top_voxels"] - middle_island["radius_voxels"] * 0.65),
(1.0, -0.25, 0.18), None, None),
("route", "Supported route across the cluster", cluster,
(middle_island["center_voxels"][0], middle_island["center_voxels"][1],
middle_island["top_voxels"] - 18.0), (8.0, -10.0, 7.0), route, None),
)
pairs = []
for key, title, meshes, target, camera, path, grid in scenes:
framing_radius = 28.0 if key in ("underside", "edge_cliff") else None
left = render(meshes["legacy"], (meshes["legacy"], meshes["native"]), "legacy",
target, camera, title, "Legacy bridge | exact owner field", route=None,
guide=grid, framing_radius=framing_radius)
route_caption = "Core native | planner route" if path else "Core native | matched field view"
right = render(meshes["native"], (meshes["legacy"], meshes["native"]), "native",
target, camera, title, route_caption, route=path, guide=grid,
framing_radius=framing_radius)
pair = titled_pair(left, right, title)
out = CAPTURES / f"{key}_matched.jpg"
pair.save(out, quality=82, optimize=True)
pairs.append(pair)
print(f"capture={out.name} bytes={out.stat().st_size} size={pair.size[0]}x{pair.size[1]}")
eye_index = 5
eye_route = route[eye_index]
eye = (eye_route[0], eye_route[1], eye_route[2] + 3.68)
next_island = profiles[1]
look = (next_island["center_voxels"][0], next_island["center_voxels"][1],
next_island["top_voxels"] + 5.0)
perspective_pair = []
for method, meshes in (("legacy", cluster), ("native", cluster)):
perspective_pair.append(render(meshes[method], (meshes["legacy"], meshes["native"]), method,
look, (0.0, 0.0, -1.0), "Island-edge player view", "Eye at 1.8 m | route span to next island",
route=None, camera_eye=eye))
eye_pair = titled_pair(perspective_pair[0], perspective_pair[1], "Island-edge player view")
eye_path = CAPTURES / "player_eye_matched.jpg"
eye_pair.save(eye_path, quality=80, optimize=True)
pairs.insert(3, eye_pair)
print(f"capture={eye_path.name} bytes={eye_path.stat().st_size} size={eye_pair.size[0]}x{eye_pair.size[1]}")
sheet = Image.new("RGB", (WIDTH * 2, (HEIGHT + 32) * len(pairs)), (218, 225, 228))
for row, pair in enumerate(pairs):
sheet.paste(pair, (0, row * (HEIGHT + 32)))
sheet_path = CAPTURES / "contact_sheet.jpg"
sheet.save(sheet_path, quality=76, optimize=True)
oversized = [(path.name, path.stat().st_size) for path in sorted(CAPTURES.glob("*.jpg"))
if path.stat().st_size >= 300_000]
for path in sorted(CAPTURES.glob("*.jpg")):
print(f"capture_size={path.name} bytes={path.stat().st_size}")
if oversized:
raise RuntimeError(f"captures exceed the 300 KB limit: {oversized}")
print(f"contact_sheet={sheet_path.name} bytes={sheet_path.stat().st_size} views=5 matched_pairs=5")
if __name__ == "__main__":
main()
@@ -0,0 +1,29 @@
{
"recipe_hash":"5b8f27274bad89ba",
"plan_hash":"ac33c9460b16337a",
"manifest_hash":"0db30684eaefa75e",
"unchanged_existing_hashes":{"m1_round1_manifest":"c87ae279b0e26f53","surfaceworld_round4_manifest":"8933693d9560ba9f"},
"geometry_version":2,
"owner_voxel_size_cm":12.5,
"core_voxel_size_cm":25,
"owner_to_core_length_scale":0.5,
"plan_islands":4,
"plan_connectors":3,
"route_points":29,
"legacy_anchor_owner_voxels":[48,16,-1904.03515625],
"comparison_anchor_core_voxels":[24,8,-952.015625],
"legacy_anchor_plateau_samples":25,
"recipe_parameters":{"seed":0,"primary_island_count":3,"density_q16":32768,"spacing_voxels":56,"radius_voxels":[12,24],"thickness_ratio_q16":39322,"vertical_jitter_q16":39322,"top_flatten_q16":39322,"contour_warp_voxels":6.30078125,"crust_depth_bonus_q16":9830,"root_depth_ratio_q16":49152,"roughness_voxels":1.5,"blend_voxels":3,"bridge_half_width_voxels":6,"bridge_thickness_voxels":4},
"stable_island_ids":["e6e461e18b3a9c87","2bc1820baba047f6","adc259cbe2a395e9","7855fb022cc561c9"],
"stable_connector_ids":["eaa5dd310e846520","034023599b466c51","4962fa885545fb26"],
"island_profiles":[{"id":"e6e461e18b3a9c87","ordinal":0,"center_voxels":[-15.19921875,25.2734375,-957.5078125],"radius_voxels":14.08203125,"top_voxels":-954.69140625,"bottom_voxels":-975.81640625,"depth_to_diameter":0.750069348128},{"id":"2bc1820baba047f6","ordinal":1,"center_voxels":[24,-12.2265625,-954.8984375],"radius_voxels":14.42578125,"top_voxels":-952.015625,"bottom_voxels":-973.65625,"depth_to_diameter":0.75006769564},{"id":"adc259cbe2a395e9","ordinal":2,"center_voxels":[63.19921875,26.28515625,-958.57421875],"radius_voxels":20.23828125,"top_voxels":-954.52734375,"bottom_voxels":-984.88671875,"depth_to_diameter":0.750048253233},{"id":"7855fb022cc561c9","ordinal":3,"center_voxels":[-1.19921875,-68.2265625,-950.75390625],"radius_voxels":22.8125,"top_voxels":-946.19140625,"bottom_voxels":-980.41015625,"depth_to_diameter":0.75}],
"bounds":{"passed":true,"negative_control_detected":true,"boxes":515,"samples":13851,"unknown":74,"missed":0,"island_boxes":4,"connector_boxes":3,"void_boxes_proved_air":1},
"thickness":{"passed":true,"islands_tested":4,"islands_below_minimum":0,"minimum_depth_to_diameter_ratio":0.75,"required_depth_to_diameter_ratio":0.7,"minimum_island_id":"7855fb022cc561c9"},
"thin_pad_negative_control":{"detected":true,"failed_islands":4,"minimum_depth_to_diameter_ratio":0.299891686975},
"route":{"passed":true,"segments":28,"centers":254,"capsule_samples":69088,"blocked":0,"support_samples":1430,"unsupported":0,"grade_failures":0,"minimum_clearance_subvoxels":78},
"raised_route_negative_control":{"detected":true,"passed":false,"unsupported":254,"blocked":0},
"determinism":{"W1":"566b6115f1aaeb71","W8":"566b6115f1aaeb71","W16":"566b6115f1aaeb71","plan_repeat":true,"hash_samples":32768},
"timing":{"same_queries":32768,"legacy_ms":64.6405,"native_ms":38.0581,"native_over_legacy":0.588765557197,"sign_mismatches":1454,"sign_mismatch_percent":4.43725585938,"legacy_solid_samples":130,"native_solid_samples":1380,"legacy_only_solid_samples":102,"native_only_solid_samples":1352},
"mesh":[{"name":"cluster_legacy","grid_samples":36613,"triangles":1532,"bytes":73544},{"name":"cluster_native","grid_samples":36613,"triangles":8764,"bytes":420680},{"name":"detail_legacy","grid_samples":207025,"triangles":4124,"bytes":197960},{"name":"detail_native","grid_samples":207025,"triangles":27794,"bytes":1334120}],
"route_points_core_voxels":[[-15.19921875,25.2734375,-950.4375],[-12.3984375,22.59375,-949.54296875],[-9.59765625,19.91796875,-949.453125],[-6.80078125,17.23828125,-949.3125],[-4,14.55859375,-949.23046875],[-1.19921875,11.87890625,-949.0234375],[1.6015625,9.203125,-948.734375],[4.40234375,6.5234375,-948.53515625],[7.19921875,3.84375,-948.328125],[10,1.16796875,-947.99609375],[12.80078125,-1.51171875,-947.6953125],[15.6015625,-4.19140625,-947.5390625],[18.3984375,-6.87109375,-947.33984375],[21.19921875,-9.546875,-947.93359375],[24,-12.2265625,-947.87109375],[26.80078125,-9.4765625,-946.87109375],[29.6015625,-6.7265625,-946.93359375],[32.3984375,-3.97265625,-947.31640625],[35.19921875,-1.22265625,-947.72265625],[38,1.52734375,-948.17578125],[40.80078125,4.27734375,-948.34375],[43.6015625,7.03125,-948.48046875],[46.3984375,9.78125,-948.72265625],[49.19921875,12.53125,-949.046875],[52,15.28125,-949.2109375],[54.80078125,18.03125,-949.265625],[57.59765625,20.78515625,-949.52734375],[60.3984375,23.53515625,-950.3984375],[63.19921875,26.28515625,-950.265625]]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB