wip(assembler): round L24 -- per-strate passage styles; natural Worm default; FI anchor island
Core plans inter-strate passages from each upper strate's FStratePassageConfig for every generator: Straight / Worm (the new natural default: meander, variable radius, rough walls) / Spiral / Cascading. A naturalness audit (no >8 m flat runs, >=0.20 m wall relief) fails on L23's smooth tube. FloatingIslands selects Spiral, with a deterministic unique anchor island (ordinal 2) joined to the bedrock floor by a rock root. The SW arrival no longer stamps flat shelves. Capsule audits 0 blocked / 0 unsupported / 0 grade failures, all styles. Full-view hashes deterministic W1/W8/W12, Clang = GCC (reviewer re-run). Evaluator 10, FI geometry 5. KNOWN: the FI helix renders as a spiral ribbon in open air around the pillar instead of a tunnel enclosed in rock; fix next round. Unreal edits uncompiled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
71d09a8c52
commit
cb9236c265
17 files changed
+922
-122
No files matched your search
@@ -188,6 +188,15 @@ namespace floating_island_detail
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.crustDepthBonusQ16), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.rootDepthRatioQ16), 8);
|
||||
}
|
||||
if (recipe.geometryVersion >= 5)
|
||||
{
|
||||
HashWord(hash, recipe.anchorIslandOrdinal, 4);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.anchorPlacementRadiusSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.anchorRootRadiusSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.anchorIslandMinimumRadiusSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.anchorRootBottomZSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.anchorMouthOffsetSubvoxels), 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);
|
||||
@@ -247,7 +256,7 @@ namespace floating_island_detail
|
||||
|
||||
inline bool ValidateRecipe(const FloatingIslandRecipeV1& recipe, std::string& error)
|
||||
{
|
||||
const std::array<std::int64_t, 26> values = {
|
||||
const std::array<std::int64_t, 32> values = {
|
||||
recipe.layoutOriginXSubvoxels, recipe.layoutOriginYSubvoxels,
|
||||
recipe.layoutCenterTopZSubvoxels, recipe.layoutMinimumZSubvoxels,
|
||||
recipe.layoutMaximumZSubvoxels, recipe.layoutChunkWidthSubvoxels, recipe.islandDensityQ16,
|
||||
@@ -259,6 +268,10 @@ namespace floating_island_detail
|
||||
recipe.blendRadiusSubvoxels, recipe.contourWarpSubvoxels,
|
||||
recipe.roughnessSubvoxels, recipe.boundarySealSubvoxels,
|
||||
recipe.bridgeHalfWidthSubvoxels, recipe.bridgeThicknessSubvoxels,
|
||||
static_cast<std::int64_t>(recipe.anchorIslandOrdinal),
|
||||
recipe.anchorPlacementRadiusSubvoxels, recipe.anchorRootRadiusSubvoxels,
|
||||
recipe.anchorIslandMinimumRadiusSubvoxels, recipe.anchorRootBottomZSubvoxels,
|
||||
recipe.anchorMouthOffsetSubvoxels,
|
||||
recipe.routeConstraints.capsuleRadiusSubvoxels,
|
||||
recipe.routeConstraints.capsuleHeightSubvoxels,
|
||||
recipe.routeConstraints.maximumGradeQ16};
|
||||
@@ -268,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 > 4
|
||||
if (recipe.schemaVersion != 1 || recipe.geometryVersion < 1 || recipe.geometryVersion > 5
|
||||
|| (recipe.geometryVersion == 1
|
||||
&& (recipe.crustDepthBonusQ16 != 0 || recipe.rootDepthRatioQ16 != 0))
|
||||
|| recipe.unitsPerVoxel != Q
|
||||
@@ -323,6 +336,21 @@ namespace floating_island_detail
|
||||
|| constraints.minimumClearanceSubvoxels < 0
|
||||
|| constraints.minimumSupportProbes == 0 || constraints.minimumSupportProbes > 5)
|
||||
{ error = "floating-island shape or route parameters are outside the supported range"; return false; }
|
||||
if (recipe.geometryVersion >= 5
|
||||
&& (recipe.anchorIslandOrdinal != recipe.primaryIslandCount - 1
|
||||
|| recipe.anchorPlacementRadiusSubvoxels <= 0
|
||||
|| recipe.anchorRootRadiusSubvoxels < recipe.anchorMouthOffsetSubvoxels
|
||||
+ recipe.routeConstraints.capsuleRadiusSubvoxels + Q
|
||||
|| recipe.anchorIslandMinimumRadiusSubvoxels
|
||||
< recipe.anchorMouthOffsetSubvoxels
|
||||
+ recipe.routeConstraints.capsuleRadiusSubvoxels + Q
|
||||
|| recipe.anchorIslandMinimumRadiusSubvoxels > 64 * Q
|
||||
|| recipe.anchorRootBottomZSubvoxels < recipe.layoutMinimumZSubvoxels
|
||||
+ recipe.boundarySealSubvoxels
|
||||
|| recipe.anchorRootBottomZSubvoxels >= recipe.layoutCenterTopZSubvoxels
|
||||
|| recipe.anchorMouthOffsetSubvoxels <= 0
|
||||
|| recipe.anchorMouthOffsetSubvoxels > 64 * Q))
|
||||
{ error = "floating-island bedrock anchor is outside its passage or rock-thickness bounds"; return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -725,6 +753,25 @@ 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
|
||||
&& recipe.anchorRootBottomZSubvoxels < island.bottomZSubvoxels)
|
||||
{
|
||||
const double rootTop = static_cast<double>(island.bottomZSubvoxels);
|
||||
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)
|
||||
* 0.12, 3.0 * Q, 6.0 * Q);
|
||||
// A slightly flared lower buttress joins the island's own root lobes to bedrock.
|
||||
// Une base legerement evasee relie les racines de l'ile a la roche de fond.
|
||||
const double t = std::clamp((rootTop - z) / depth, 0.0, 1.0);
|
||||
const double rootRadius = static_cast<double>(recipe.anchorRootRadiusSubvoxels)
|
||||
* (0.92 + 0.08 * SmoothStep(t));
|
||||
double rootSdf = std::max({Column.Radial - rootRadius,
|
||||
rootBottom - z, z - rootTop});
|
||||
rootSdf = ApplySurfaceDetail(recipe, island.stableId ^ 0x414e43484f52524full,
|
||||
rootSdf, x, y, z, 0.75);
|
||||
sdf = SmoothMin(sdf, rootSdf, blend);
|
||||
}
|
||||
const double topDetailScale = topDistance >= std::max(sideDistance, undersideDistance)
|
||||
|| z >= static_cast<double>(IslandCrustBottom(recipe, island)) + radius * 0.45
|
||||
? 0.25 : 1.0;
|
||||
@@ -895,9 +942,15 @@ namespace floating_island_detail
|
||||
FloatingIslandAnchorV1& island)
|
||||
{
|
||||
const std::int64_t pad = IslandBlendMargin(recipe) + recipe.roughnessSubvoxels;
|
||||
const std::int64_t reach = island.radiusSubvoxels + recipe.contourWarpSubvoxels + pad;
|
||||
const bool isAnchor=recipe.geometryVersion>=5
|
||||
&&island.ordinal==recipe.anchorIslandOrdinal;
|
||||
const std::int64_t reach = std::max(island.radiusSubvoxels,
|
||||
isAnchor?recipe.anchorRootRadiusSubvoxels:std::int64_t{0})
|
||||
+ recipe.contourWarpSubvoxels + pad;
|
||||
island.influenceMinimumSubvoxels = {island.centerSubvoxels[0] - reach,
|
||||
island.centerSubvoxels[1] - reach, island.bottomZSubvoxels - pad};
|
||||
island.centerSubvoxels[1] - reach,
|
||||
(isAnchor?std::min(island.bottomZSubvoxels,recipe.anchorRootBottomZSubvoxels)
|
||||
:island.bottomZSubvoxels)-pad};
|
||||
island.influenceMaximumSubvoxels = {island.centerSubvoxels[0] + reach,
|
||||
island.centerSubvoxels[1] + reach, island.topZSubvoxels + pad};
|
||||
}
|
||||
@@ -942,12 +995,19 @@ namespace floating_island_detail
|
||||
|
||||
std::unordered_set<std::uint64_t> islandIds;
|
||||
std::unordered_set<std::uint32_t> ordinals;
|
||||
const FloatingIslandAnchorV1* anchorIsland = nullptr;
|
||||
for (const auto& island : plan.islands)
|
||||
{
|
||||
const bool isAnchor=recipe.geometryVersion>=5
|
||||
&&island.ordinal==recipe.anchorIslandOrdinal;
|
||||
if(isAnchor)anchorIsland=&island;
|
||||
if (island.stableId == 0 || !islandIds.insert(island.stableId).second
|
||||
|| !ordinals.insert(island.ordinal).second
|
||||
|| island.radiusSubvoxels < recipe.minimumRadiusSubvoxels
|
||||
|| island.radiusSubvoxels > recipe.maximumRadiusSubvoxels
|
||||
|| island.radiusSubvoxels < (isAnchor?recipe.anchorIslandMinimumRadiusSubvoxels
|
||||
:recipe.minimumRadiusSubvoxels)
|
||||
|| island.radiusSubvoxels > (isAnchor
|
||||
?std::max(recipe.anchorIslandMinimumRadiusSubvoxels,recipe.maximumRadiusSubvoxels)
|
||||
:recipe.maximumRadiusSubvoxels)
|
||||
|| island.topHalfSubvoxels <= 0 || island.topZSubvoxels <= island.bottomZSubvoxels
|
||||
|| island.taperEndQ16 < recipe.taperEndMinimumQ16
|
||||
|| island.taperEndQ16 > recipe.taperEndMaximumQ16
|
||||
@@ -964,12 +1024,16 @@ 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 std::int64_t reach = island.radiusSubvoxels + recipe.contourWarpSubvoxels + pad;
|
||||
const std::int64_t reach = std::max(island.radiusSubvoxels,
|
||||
isAnchor?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] > island.bottomZSubvoxels - pad
|
||||
|| island.influenceMinimumSubvoxels[2] > (isAnchor
|
||||
?std::min(island.bottomZSubvoxels,recipe.anchorRootBottomZSubvoxels)
|
||||
:island.bottomZSubvoxels) - pad
|
||||
|| island.influenceMaximumSubvoxels[2] < island.topZSubvoxels + pad
|
||||
|| island.bottomZSubvoxels < recipe.layoutMinimumZSubvoxels + recipe.boundarySealSubvoxels
|
||||
|| island.topZSubvoxels > recipe.layoutMaximumZSubvoxels - recipe.boundarySealSubvoxels)
|
||||
@@ -978,6 +1042,19 @@ namespace floating_island_detail
|
||||
for (std::uint32_t ordinal = 0; ordinal < recipe.primaryIslandCount; ++ordinal)
|
||||
if (!ordinals.contains(ordinal))
|
||||
{ error = "floating-island route chain is missing a primary seeded anchor"; return false; }
|
||||
if(recipe.geometryVersion>=5)
|
||||
{
|
||||
if(!anchorIsland)
|
||||
{error="floating-island plan is missing its unique passage anchor island";return false;}
|
||||
const double anchorDistance=std::hypot(
|
||||
static_cast<double>(anchorIsland->centerSubvoxels[0]),
|
||||
static_cast<double>(anchorIsland->centerSubvoxels[1]));
|
||||
if(anchorDistance>recipe.anchorPlacementRadiusSubvoxels
|
||||
||recipe.anchorRootBottomZSubvoxels>=anchorIsland->bottomZSubvoxels
|
||||
||recipe.anchorMouthOffsetSubvoxels+recipe.routeConstraints.capsuleRadiusSubvoxels
|
||||
>=anchorIsland->radiusSubvoxels)
|
||||
{error="floating-island anchor island or its mouth leaves the passage radius or rock envelope";return false;}
|
||||
}
|
||||
|
||||
std::unordered_set<std::uint64_t> edgeIds;
|
||||
std::unordered_map<std::uint64_t, std::vector<std::uint64_t>> adjacency;
|
||||
@@ -1239,6 +1316,22 @@ std::optional<FloatingIslandManifestV1> FloatingIslandManifestV1::FromJson(
|
||||
&& manifest.recipe.layoutChunkWidthSubvoxels!=resolvedLayoutChunkWidthSubvoxels)
|
||||
{error="floating-island recipe layout width disagrees with the resolved world layout";return std::nullopt;}
|
||||
}
|
||||
if(manifest.recipe.geometryVersion>=5)
|
||||
{
|
||||
if(!floating_island_detail::ReadU32(recipeValue.Get("anchor_island_ordinal"),
|
||||
manifest.recipe.anchorIslandOrdinal)
|
||||
||!floating_island_detail::ReadInteger(recipeValue.Get("anchor_placement_radius_q"),
|
||||
manifest.recipe.anchorPlacementRadiusSubvoxels)
|
||||
||!floating_island_detail::ReadInteger(recipeValue.Get("anchor_root_radius_q"),
|
||||
manifest.recipe.anchorRootRadiusSubvoxels)
|
||||
||!floating_island_detail::ReadInteger(recipeValue.Get("anchor_island_minimum_radius_q"),
|
||||
manifest.recipe.anchorIslandMinimumRadiusSubvoxels)
|
||||
||!floating_island_detail::ReadInteger(recipeValue.Get("anchor_root_bottom_z_q"),
|
||||
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;}
|
||||
}
|
||||
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)
|
||||
@@ -1391,6 +1484,13 @@ std::string FloatingIslandManifestV1::ToJson() const
|
||||
<< ",\"root_depth_ratio_q16\":" << recipe.rootDepthRatioQ16;
|
||||
if(recipe.geometryVersion>=4)
|
||||
out << ",\"layout_chunk_width_q\":" << recipe.layoutChunkWidthSubvoxels;
|
||||
if(recipe.geometryVersion>=5)
|
||||
out << ",\"anchor_island_ordinal\":" << recipe.anchorIslandOrdinal
|
||||
<< ",\"anchor_placement_radius_q\":" << recipe.anchorPlacementRadiusSubvoxels
|
||||
<< ",\"anchor_root_radius_q\":" << recipe.anchorRootRadiusSubvoxels
|
||||
<< ",\"anchor_island_minimum_radius_q\":" << recipe.anchorIslandMinimumRadiusSubvoxels
|
||||
<< ",\"anchor_root_bottom_z_q\":" << recipe.anchorRootBottomZSubvoxels
|
||||
<< ",\"anchor_mouth_offset_q\":" << recipe.anchorMouthOffsetSubvoxels;
|
||||
out << ",\"blend_radius_q\":" << recipe.blendRadiusSubvoxels
|
||||
<< ",\"contour_warp_q\":" << recipe.contourWarpSubvoxels
|
||||
<< ",\"roughness_q\":" << recipe.roughnessSubvoxels
|
||||
@@ -1552,6 +1652,9 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
|
||||
auto island = floating_island_detail::MakeIsland(recipe, i,
|
||||
primaryXY[i][0], primaryXY[i][1], tops[i], site);
|
||||
island.radiusSubvoxels = radii[i];
|
||||
if(recipe.geometryVersion>=5&&i==recipe.anchorIslandOrdinal)
|
||||
island.radiusSubvoxels=std::max(island.radiusSubvoxels,
|
||||
recipe.anchorIslandMinimumRadiusSubvoxels);
|
||||
island.topHalfSubvoxels = std::max<std::int64_t>(1, island.radiusSubvoxels / 5);
|
||||
island.centerSubvoxels[2] = island.topZSubvoxels - island.topHalfSubvoxels;
|
||||
island.bottomZSubvoxels = floating_island_detail::IslandBottom(recipe,
|
||||
@@ -1638,14 +1741,31 @@ std::optional<FloatingIslandManifestV1> PlanFloatingIslandCluster(
|
||||
static_cast<double>(a.centerSubvoxels[0]) + dx * t);
|
||||
const std::int64_t y = floating_island_detail::RoundQ(
|
||||
static_cast<double>(a.centerSubvoxels[1]) + dy * t);
|
||||
std::int64_t routeX=x,routeY=y;
|
||||
if(recipe.geometryVersion>=5&&segment+2==count&&piece==pieces)
|
||||
{
|
||||
const auto& anchor=islands[recipe.anchorIslandOrdinal];
|
||||
const std::uint32_t side=static_cast<std::uint32_t>(
|
||||
floating_island_detail::UnitQ16(recipe.seed,anchor.stableId,
|
||||
0x414e43484f524d50ull)&1u);
|
||||
const double routeAngle=std::atan2(dy,dx);
|
||||
const double angle=routeAngle+(side?1.0:-1.0)
|
||||
*floating_island_detail::Pi/2.0;
|
||||
const double mouthX=static_cast<double>(anchor.centerSubvoxels[0])
|
||||
+static_cast<double>(recipe.anchorMouthOffsetSubvoxels)*std::cos(angle);
|
||||
const double mouthY=static_cast<double>(anchor.centerSubvoxels[1])
|
||||
+static_cast<double>(recipe.anchorMouthOffsetSubvoxels)*std::sin(angle);
|
||||
routeX=floating_island_detail::RoundQ(mouthX);
|
||||
routeY=floating_island_detail::RoundQ(mouthY);
|
||||
}
|
||||
const auto surface = floating_island_detail::FindCapsuleFootingTopZ(
|
||||
recipe, manifest.plan, x, y);
|
||||
recipe, manifest.plan, routeX, routeY);
|
||||
if (!surface)
|
||||
{ error = "island planner could not find a full capsule-width support surface along its connector chain"; return std::nullopt; }
|
||||
WorldAssemblyRoutePointV1 point;
|
||||
point.stableFeatureId = floating_island_detail::StableId(recipe.seed,
|
||||
0x500000000ull + routeOrdinal, 0x524f555445ull);
|
||||
point.positionSubvoxels = {x, y, *surface + capsuleHalf
|
||||
point.positionSubvoxels = {routeX, routeY, *surface + capsuleHalf
|
||||
+ recipe.routeConstraints.minimumClearanceSubvoxels
|
||||
+ (recipe.geometryVersion >= 2 ? floating_island_detail::Q / 8 : 0)};
|
||||
point.radiusSubvoxels = routeRadius;
|
||||
|
||||
Reference in new issue
Block a user