wip(assembler): M3 round 3 -- separated islands + Unreal island route (owner build 18:46)

Islands read as separate (91.89% open sky at mid-height), underside cavity closed,
rim teeth were capture shading. Island manifest import + BuildHost proof passed on the
pre-cache tree; M1 SurfaceWorld and M2 V1/V2 gates passed.

Known open: final XY-column cache compiled in the owner build but is unverified;
island LOD0 p95 ~155 ms misses the 133 ms sprint deadline (legacy ~43 ms); the island
manifest only fits the BuildHost fixture layout (owner's world: Core init fails,
empty world) -> round 4 builds plans inside Unreal.

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 20:53:03 +02:00
1 parent 4afea7c802
commit 48fa028086
37 files changed
+3788 -107

No files matched your search

+226 -35
View File
@@ -158,6 +158,10 @@ namespace floating_island_detail
std::uint64_t hash = StartHash();
HashWord(hash, recipe.schemaVersion, 4);
HashWord(hash, recipe.unitsPerVoxel, 4);
HashWord(hash, recipe.ownerVoxelSizeMicrons, 4);
HashWord(hash, recipe.coreVoxelSizeMicrons, 4);
HashWord(hash, recipe.ownerToCoreScaleNumerator, 4);
HashWord(hash, recipe.ownerToCoreScaleDenominator, 4);
HashWord(hash, recipe.seed, 4);
HashWord(hash, static_cast<std::uint64_t>(recipe.layoutOriginXSubvoxels), 8);
HashWord(hash, static_cast<std::uint64_t>(recipe.layoutOriginYSubvoxels), 8);
@@ -258,6 +262,10 @@ namespace floating_island_detail
|| (recipe.geometryVersion == 1
&& (recipe.crustDepthBonusQ16 != 0 || recipe.rootDepthRatioQ16 != 0))
|| recipe.unitsPerVoxel != Q
|| recipe.ownerVoxelSizeMicrons != 125000
|| recipe.coreVoxelSizeMicrons != 250000
|| recipe.ownerToCoreScaleNumerator != 1
|| recipe.ownerToCoreScaleDenominator != 2
|| recipe.primaryIslandCount < 3 || recipe.primaryIslandCount > 9
|| recipe.layoutMaximumZSubvoxels <= recipe.layoutMinimumZSubvoxels
|| recipe.layoutMaximumZSubvoxels - recipe.layoutMinimumZSubvoxels > 2048 * Q
@@ -339,6 +347,30 @@ namespace floating_island_detail
return static_cast<double>(recipe.contourWarpSubvoxels) * (0.50 * a + 0.30 * b + 0.20 * c);
}
inline double LobePhase(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island)
{
return static_cast<double>(Roll(recipe.seed, island.stableId, 0x4c4f4245ull)
& 0xffffffffull) * (2.0 * Pi / 4294967296.0);
}
inline double LobeOffsetWithPhase(const FloatingIslandRecipeV1& recipe,
double angle,double zSubvoxels,double phase)
{
const double z = zSubvoxels / static_cast<double>(Q);
const double a = std::sin(3.0 * angle + phase + z * 0.017);
const double b = std::sin(5.0 * angle - phase * 0.73 - z * 0.023);
const double c = std::sin(8.0 * angle + phase * 1.41 + z * 0.011);
return static_cast<double>(recipe.contourWarpSubvoxels) * (0.50 * a + 0.30 * b + 0.20 * c);
}
inline double LobeOffsetAtAngle(const FloatingIslandRecipeV1& recipe,
const FloatingIslandAnchorV1& island,
double angle,double zSubvoxels)
{
return LobeOffsetWithPhase(recipe,angle,zSubvoxels,LobePhase(recipe,island));
}
inline double Roughness(const FloatingIslandRecipeV1& recipe,
std::uint64_t featureId, double x, double y, double z)
{
@@ -382,6 +414,83 @@ namespace floating_island_detail
return static_cast<double>(island.topZSubvoxels) - drop;
}
struct FIslandColumnCacheEntry
{
bool bValid=false;
std::uint32_t Seed=0;
std::uint64_t StableId=0;
std::int64_t SampleX=0,SampleY=0,CenterX=0,CenterY=0,TopZ=0,Radius=0,TopHalf=0;
std::int64_t TopFlattenQ16=0,ContourWarp=0;
double DeltaX=0.0,DeltaY=0.0,Radial=0.0,Angle=0.0,LobePhase=0.0,TopSurface=0.0;
};
inline const FIslandColumnCacheEntry& IslandColumnCache(
const FloatingIslandRecipeV1& recipe,const FloatingIslandAnchorV1& island,
double x,double y)
{
// Density samples arrive on integer Core lattice columns; reuse the exact column metrics
// across Z samples without changing the field value or touching shared world state.
// Les echantillons suivent les colonnes Core entieres; reutiliser les memes metriques XY.
constexpr std::size_t Ways=4;
constexpr std::size_t SetCount=2048;
static_assert((SetCount&(SetCount-1))==0);
static thread_local std::array<FIslandColumnCacheEntry,SetCount*Ways> Cache{};
const std::int64_t SampleX=static_cast<std::int64_t>(x);
const std::int64_t SampleY=static_cast<std::int64_t>(y);
std::uint64_t IndexKey=island.stableId
^(static_cast<std::uint64_t>(SampleX)*0x9e3779b97f4a7c15ull)
^(static_cast<std::uint64_t>(SampleY)*0xc2b2ae3d27d4eb4full)
^(static_cast<std::uint64_t>(recipe.seed)<<23);
IndexKey^=IndexKey>>33;
IndexKey*=0xff51afd7ed558ccdull;
IndexKey^=IndexKey>>33;
const std::size_t Base=static_cast<std::size_t>(IndexKey&(SetCount-1))*Ways;
FIslandColumnCacheEntry* Replacement=&Cache[Base+((IndexKey>>11)&(Ways-1))];
for(std::size_t Way=0;Way<Ways;++Way)
{
FIslandColumnCacheEntry& Entry=Cache[Base+Way];
const bool bKeyMatches=Entry.bValid&&Entry.Seed==recipe.seed
&&Entry.StableId==island.stableId
&&Entry.SampleX==SampleX&&Entry.SampleY==SampleY
&&Entry.CenterX==island.centerSubvoxels[0]
&&Entry.CenterY==island.centerSubvoxels[1]
&&Entry.TopZ==island.topZSubvoxels
&&Entry.Radius==island.radiusSubvoxels
&&Entry.TopHalf==island.topHalfSubvoxels
&&Entry.TopFlattenQ16==recipe.topFlattenQ16
&&Entry.ContourWarp==recipe.contourWarpSubvoxels;
if(bKeyMatches)return Entry;
if(!Entry.bValid)Replacement=&Entry;
}
FIslandColumnCacheEntry& Entry=*Replacement;
Entry.bValid=true;
Entry.Seed=recipe.seed;
Entry.StableId=island.stableId;
Entry.SampleX=SampleX;
Entry.SampleY=SampleY;
Entry.CenterX=island.centerSubvoxels[0];
Entry.CenterY=island.centerSubvoxels[1];
Entry.TopZ=island.topZSubvoxels;
Entry.Radius=island.radiusSubvoxels;
Entry.TopHalf=island.topHalfSubvoxels;
Entry.TopFlattenQ16=recipe.topFlattenQ16;
Entry.ContourWarp=recipe.contourWarpSubvoxels;
Entry.DeltaX=x-static_cast<double>(island.centerSubvoxels[0]);
Entry.DeltaY=y-static_cast<double>(island.centerSubvoxels[1]);
Entry.Radial=std::hypot(Entry.DeltaX,Entry.DeltaY);
Entry.Angle=std::atan2(Entry.DeltaY,Entry.DeltaX);
Entry.LobePhase=LobePhase(recipe,island);
const double EffectiveRadius=std::max(1.0,static_cast<double>(island.radiusSubvoxels)
+LobeOffsetWithPhase(recipe,Entry.Angle,static_cast<double>(island.topZSubvoxels),
Entry.LobePhase));
const double Edge=std::clamp(Entry.Radial/EffectiveRadius,0.0,1.0);
const double Drop=(1.0-Q16ToDouble(recipe.topFlattenQ16))
*static_cast<double>(island.topHalfSubvoxels)*2.0*Edge*Edge;
Entry.TopSurface=static_cast<double>(island.topZSubvoxels)-Drop;
return Entry;
}
inline std::int64_t ScaledQ16(std::int64_t value, std::int64_t scaleQ16)
{ return (value * scaleQ16 + Q16 / 2) / Q16; }
@@ -406,42 +515,104 @@ namespace floating_island_detail
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);
// Keep four separate side lobes and a full-depth central buttress to close the measured
// underside cavity without driving the outer roots to one point.
// Garder quatre lobes lateraux et un renfort central profond pour fermer la cavite mesuree.
return 5;
}
inline double UnitHash(std::uint64_t hash)
{ return static_cast<double>(hash & 0xffffull) / 65535.0; }
struct FRootLobeParameters
{
double RootX=0.0,RootY=0.0,CenterZ=0.0;
double RadiusXSquared=1.0,RadiusYSquared=1.0,VerticalRadiusSquared=1.0;
double MinimumRadius=1.0;
};
struct FRootLobeCacheEntry
{
bool bValid=false;
std::uint32_t Seed=0;
std::uint64_t StableId=0;
std::int32_t RootIndex=0,GeometryVersion=0;
std::array<std::int64_t,3> Center{};
std::int64_t TopZ=0,Radius=0,TaperEndQ16=0;
std::int64_t ThicknessRatioQ16=0,CrustDepthBonusQ16=0,RootDepthRatioQ16=0;
FRootLobeParameters Parameters{};
};
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});
// Cache derived root constants per worker. The complete immutable input key keeps this
// value-only cache safe across worlds, epochs and worker schedules.
// Mettre en cache les constantes par worker; la cle complete evite tout partage d'etat.
constexpr std::size_t CacheSize=1024;
static_assert((CacheSize&(CacheSize-1))==0);
static thread_local std::array<FRootLobeCacheEntry,CacheSize> Cache{};
const std::uint64_t IndexKey=island.stableId^(island.stableId>>33)
^(static_cast<std::uint64_t>(recipe.seed)<<17)
^(static_cast<std::uint64_t>(static_cast<std::uint32_t>(rootIndex))*0x9e3779b97f4a7c15ull);
FRootLobeCacheEntry& Entry=Cache[static_cast<std::size_t>(IndexKey)&(CacheSize-1)];
const bool bKeyMatches=Entry.bValid&&Entry.Seed==recipe.seed
&&Entry.StableId==island.stableId&&Entry.RootIndex==rootIndex
&&Entry.GeometryVersion==recipe.geometryVersion
&&Entry.Center==island.centerSubvoxels
&&Entry.TopZ==island.topZSubvoxels&&Entry.Radius==island.radiusSubvoxels
&&Entry.TaperEndQ16==island.taperEndQ16
&&Entry.ThicknessRatioQ16==recipe.thicknessRatioQ16
&&Entry.CrustDepthBonusQ16==recipe.crustDepthBonusQ16
&&Entry.RootDepthRatioQ16==recipe.rootDepthRatioQ16;
if(!bKeyMatches)
{
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 bool centralButtress = rootIndex == 4;
const double orbit = centralButtress ? 0.0
: radius * (0.17 + 0.07 * UnitHash(roll));
const double rootX = static_cast<double>(island.centerSubvoxels[0])
+ (centralButtress ? 0.0 : pattern[static_cast<std::size_t>(rootIndex)][0] * orbit);
const double rootY = static_cast<double>(island.centerSubvoxels[1])
+ (centralButtress ? 0.0 : pattern[static_cast<std::size_t>(rootIndex)][1] * orbit);
const double shortRootVariation = UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x4c454eull));
const double lengthRatio = centralButtress ? 1.0 : (rootIndex == 0 ? 1.0
: Q16ToDouble(island.taperEndQ16) * (0.82 + 0.18 * shortRootVariation));
const double lowerDepth = rootDepth * lengthRatio;
const double embedDepth = rootDepth * (centralButtress ? 0.22 : (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 * (centralButtress ? 0.25
: 0.15 + 0.055 * UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x5258ull)));
const double ry = radius * (centralButtress ? 0.25
: 0.15 + 0.065 * UnitHash(Roll(recipe.seed, island.stableId, salt ^ 0x5259ull)));
Entry.bValid=true;
Entry.Seed=recipe.seed;
Entry.StableId=island.stableId;
Entry.RootIndex=rootIndex;
Entry.GeometryVersion=recipe.geometryVersion;
Entry.Center=island.centerSubvoxels;
Entry.TopZ=island.topZSubvoxels;
Entry.Radius=island.radiusSubvoxels;
Entry.TaperEndQ16=island.taperEndQ16;
Entry.ThicknessRatioQ16=recipe.thicknessRatioQ16;
Entry.CrustDepthBonusQ16=recipe.crustDepthBonusQ16;
Entry.RootDepthRatioQ16=recipe.rootDepthRatioQ16;
Entry.Parameters={rootX,rootY,centerZ,rx*rx,ry*ry,
verticalRadius*verticalRadius,std::min({rx,ry,verticalRadius})};
}
const FRootLobeParameters& Parameters=Entry.Parameters;
const double q = (x - Parameters.RootX) * (x - Parameters.RootX) / Parameters.RadiusXSquared
+ (y - Parameters.RootY) * (y - Parameters.RootY) / Parameters.RadiusYSquared
+ (z - Parameters.CenterZ) * (z - Parameters.CenterZ) / Parameters.VerticalRadiusSquared;
return (std::sqrt(std::max(q, 0.0)) - 1.0) * Parameters.MinimumRadius;
}
inline double ApplySurfaceDetail(const FloatingIslandRecipeV1& recipe,
@@ -482,19 +653,18 @@ namespace floating_island_detail
std::max({z - top, radial - envelope, bottomZ - z}), x, y, 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 FIslandColumnCacheEntry& Column=IslandColumnCache(recipe,island,x,y);
const double dx=Column.DeltaX;
const double dy=Column.DeltaY;
const double radial=Column.Radial;
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));
radius + LobeOffsetWithPhase(recipe,Column.Angle,z,Column.LobePhase));
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 top = Column.TopSurface;
const double topDistance = z - top;
const double sideDistance = radial - effectiveRadius;
const double undersideDistance = lowerSurface - z;
@@ -774,7 +944,9 @@ 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 landingFraction = recipe.geometryVersion >= 2 ? 0.38 : 0.62;
// Keep the narrow span exposed to open sky; a smaller fraction buries most of it in the island tops.
// Garder la passerelle etroite visible dans le vide ; une fraction plus faible l'enfouit dans les plateaux.
const double landingFraction = recipe.geometryVersion >= 2 ? 0.52 : 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;
@@ -912,6 +1084,10 @@ std::optional<FloatingIslandManifestV1> FloatingIslandManifestV1::FromJson(
|| !floating_island_detail::ReadHash(root.Get("content_hash"), manifestHash)
|| !floating_island_detail::ReadU32(recipeValue.Get("schema_version"), manifest.recipe.schemaVersion)
|| !floating_island_detail::ReadU32(recipeValue.Get("units_per_voxel"), manifest.recipe.unitsPerVoxel)
|| !floating_island_detail::ReadU32(recipeValue.Get("owner_voxel_size_microns"), manifest.recipe.ownerVoxelSizeMicrons)
|| !floating_island_detail::ReadU32(recipeValue.Get("core_voxel_size_microns"), manifest.recipe.coreVoxelSizeMicrons)
|| !floating_island_detail::ReadU32(recipeValue.Get("owner_to_core_scale_numerator"), manifest.recipe.ownerToCoreScaleNumerator)
|| !floating_island_detail::ReadU32(recipeValue.Get("owner_to_core_scale_denominator"), manifest.recipe.ownerToCoreScaleDenominator)
|| !floating_island_detail::ReadU32(recipeValue.Get("seed"), manifest.recipe.seed)
|| !floating_island_detail::ReadInteger(recipeValue.Get("origin_x_q"), manifest.recipe.layoutOriginXSubvoxels)
|| !floating_island_detail::ReadInteger(recipeValue.Get("origin_y_q"), manifest.recipe.layoutOriginYSubvoxels)
@@ -1026,6 +1202,10 @@ std::string FloatingIslandManifestV1::ToJson() const
<< floating_island_detail::HashText(value.contentHash) << "\",\"recipe\":{"
<< "\"schema_version\":" << recipe.schemaVersion
<< ",\"units_per_voxel\":" << recipe.unitsPerVoxel
<< ",\"owner_voxel_size_microns\":" << recipe.ownerVoxelSizeMicrons
<< ",\"core_voxel_size_microns\":" << recipe.coreVoxelSizeMicrons
<< ",\"owner_to_core_scale_numerator\":" << recipe.ownerToCoreScaleNumerator
<< ",\"owner_to_core_scale_denominator\":" << recipe.ownerToCoreScaleDenominator
<< ",\"seed\":" << recipe.seed
<< ",\"origin_x_q\":" << recipe.layoutOriginXSubvoxels
<< ",\"origin_y_q\":" << recipe.layoutOriginYSubvoxels
@@ -1190,6 +1370,17 @@ 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)))));
}
if (recipe.geometryVersion >= 2)
{
// Step the outer route islands around the middle island so the connected path still reads as separate floating masses.
// Decaler les iles externes autour de l'ile centrale pour distinguer les masses tout en gardant la route continue.
constexpr std::int64_t VerticalStagger = 3 * floating_island_detail::Q;
for (std::uint32_t i = 0; i < count; ++i)
{
if (i < middle) tops[i] -= VerticalStagger;
else if (i > middle) tops[i] += VerticalStagger;
}
}
for (std::uint32_t i = 0; i < count; ++i)
{
const std::uint64_t site = 0x100000000ull + i;