wip(assembler): round L29 -- strate transitions honoured at the bedrock/ceiling interface

EVoxelStrateTransition from the upper strate shapes the bedrock(N)/ceiling(N+1) interface in the
shared composition layer: Hard flat; Gradient = smooth 2D hash surface (16 m owner width, about 4 m
measured undulation); Interleaved = 3D domain-warped fingered overlap within the width. Each band
keeps >= 2 Core voxels solid; faces return to the seam near passage mouths. Interface audit over
512 m: 0 hole columns for all modes; wider-than-declared and too-thin controls rejected. All passage,
route, proof and validator audits pass; deterministic Clang = GCC. Evaluator 15. Cost +4% SW,
+1.3% FI vs L28. Open: ring-like artifact on the FI floor capture; transition look unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-21 09:16:12 +02:00
1 parent f23ab7b9fa
commit 63c7e563d0
16 files changed
+794 -42

No files matched your search

@@ -250,7 +250,7 @@ namespace VoxelForgeCore
inline constexpr std::int64_t WorldAssemblySubvoxelsPerVoxel = 256;
inline constexpr std::uint32_t WorldAssemblySchemaVersion = 2;
// Version 14 adds shared passage columns for long native open-air crossings.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 14;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 15;
enum class FieldChannel : std::uint32_t
{
@@ -639,6 +639,18 @@ namespace VoxelForgeCore
std::vector<ResolvedLayoutAnchorV2> anchors;
};
/** Per-column resolved bands for one adjacent bedrock/ceiling interface.
* crossingDepthMicrometres is the actual overlap depth between the two facing bands.
*/
struct ResolvedLayoutTransitionBandsV1
{
std::int64_t crossingDepthMicrometres = 0;
std::int64_t upperBedrockBottomMicrometres = 0;
std::int64_t upperBedrockTopMicrometres = 0;
std::int64_t lowerCeilingBottomMicrometres = 0;
std::int64_t lowerCeilingTopMicrometres = 0;
};
struct ResolvedLayoutIssueV2
{
std::string code;
@@ -730,6 +742,17 @@ namespace VoxelForgeCore
std::string_view json, std::string& error);
};
/**
* Resolve the deterministic band faces at one XY column. Gradient shares one smooth
* displaced face; Interleaved moves the faces inward by a total crossing no larger than
* the declared width. Both bands retain authored thickness and touch or overlap, so no
* air gap can form.
*/
VFCORE_API ResolvedLayoutTransitionBandsV1 EvaluateResolvedLayoutTransitionBandsV1(
const ResolvedLayoutStratumV2& upper, const ResolvedLayoutStratumV2& lower,
std::int32_t worldSeed, std::int64_t layoutChunkSizeMicrometres,
std::int64_t xMicrometres, std::int64_t yMicrometres);
struct ResolvedLayoutValidatorAuditV3
{
std::uint32_t controlsRun = 0;
+184 -8
View File
@@ -13,6 +13,97 @@ namespace VoxelForgeCore
{
namespace
{
constexpr std::int64_t TransitionQ16 = 1ll << 16;
void TransitionHashWord(std::uint64_t& hash, std::uint64_t word)
{
for (int byte = 0; byte < 8; ++byte)
{
hash ^= static_cast<std::uint8_t>(word >> (byte * 8));
hash *= 1099511628211ull;
}
}
std::uint64_t TransitionHash(std::int32_t seed, std::int32_t interfaceIndex,
std::int64_t x, std::int64_t y, std::int64_t z, std::uint32_t salt)
{
std::uint64_t hash = 14695981039346656037ull;
TransitionHashWord(hash, static_cast<std::uint32_t>(seed));
TransitionHashWord(hash, static_cast<std::uint32_t>(interfaceIndex));
TransitionHashWord(hash, static_cast<std::uint64_t>(x));
TransitionHashWord(hash, static_cast<std::uint64_t>(y));
TransitionHashWord(hash, static_cast<std::uint64_t>(z));
TransitionHashWord(hash, salt);
hash ^= hash >> 30; hash *= 0xbf58476d1ce4e5b9ull;
hash ^= hash >> 27; hash *= 0x94d049bb133111ebull;
hash ^= hash >> 31;
return hash;
}
std::int64_t TransitionNoiseValue(std::int32_t seed, std::int32_t interfaceIndex,
std::int64_t x, std::int64_t y, std::int64_t z, std::uint32_t salt)
{
const std::uint32_t bits = static_cast<std::uint32_t>(
TransitionHash(seed, interfaceIndex, x, y, z, salt) >> 32);
return static_cast<std::int64_t>(bits >> 15) - TransitionQ16;
}
std::int64_t TransitionFloorDiv(std::int64_t value, std::int64_t divisor)
{
const std::int64_t quotient = value / divisor;
const std::int64_t remainder = value % divisor;
return quotient - (remainder < 0 ? 1 : 0);
}
std::int64_t TransitionFade(std::int64_t valueQ16)
{
valueQ16 = std::clamp(valueQ16, std::int64_t{0}, TransitionQ16);
const std::int64_t square = (valueQ16 * valueQ16) / TransitionQ16;
return (square * (3 * TransitionQ16 - 2 * valueQ16)) / TransitionQ16;
}
std::int64_t TransitionLerp(std::int64_t a, std::int64_t b, std::int64_t tQ16)
{ return a + ((b - a) * tQ16) / TransitionQ16; }
std::int64_t TransitionValueNoise2D(std::int32_t seed, std::int32_t interfaceIndex,
std::int64_t x, std::int64_t y, std::int64_t cell, std::uint32_t salt)
{
const std::int64_t ix = TransitionFloorDiv(x, cell), iy = TransitionFloorDiv(y, cell);
const std::int64_t tx = TransitionFade(((x - ix * cell) * TransitionQ16) / cell);
const std::int64_t ty = TransitionFade(((y - iy * cell) * TransitionQ16) / cell);
const auto at = [&](std::int64_t dx, std::int64_t dy)
{ return TransitionNoiseValue(seed, interfaceIndex, ix + dx, iy + dy, 0, salt); };
return TransitionLerp(TransitionLerp(at(0, 0), at(1, 0), tx),
TransitionLerp(at(0, 1), at(1, 1), tx), ty);
}
std::int64_t TransitionValueNoise3D(std::int32_t seed, std::int32_t interfaceIndex,
std::int64_t x, std::int64_t y, std::int64_t z, std::int64_t cell,
std::uint32_t salt)
{
const std::int64_t ix = TransitionFloorDiv(x, cell), iy = TransitionFloorDiv(y, cell);
const std::int64_t iz = TransitionFloorDiv(z, cell);
const std::int64_t tx = TransitionFade(((x - ix * cell) * TransitionQ16) / cell);
const std::int64_t ty = TransitionFade(((y - iy * cell) * TransitionQ16) / cell);
const std::int64_t tz = TransitionFade(((z - iz * cell) * TransitionQ16) / cell);
const auto at = [&](std::int64_t dx, std::int64_t dy, std::int64_t dz)
{ return TransitionNoiseValue(seed, interfaceIndex, ix + dx, iy + dy, iz + dz, salt); };
const std::int64_t z0 = TransitionLerp(
TransitionLerp(at(0, 0, 0), at(1, 0, 0), tx),
TransitionLerp(at(0, 1, 0), at(1, 1, 0), tx), ty);
const std::int64_t z1 = TransitionLerp(
TransitionLerp(at(0, 0, 1), at(1, 0, 1), tx),
TransitionLerp(at(0, 1, 1), at(1, 1, 1), tx), ty);
return TransitionLerp(z0, z1, tz);
}
std::int64_t LayoutTransitionLimit(const ResolvedLayoutStratumV2& stratum)
{
if (stratum.transitionMode == "Hard" || stratum.transitionFallsBackToHard)
return 0;
return std::max<std::int64_t>(0, stratum.transitionWidthMicrometres);
}
std::string LayoutEscape(std::string_view value)
{
std::string out="\"";
@@ -41,12 +132,6 @@ namespace
}
std::string LayoutHex(std::uint64_t value)
{std::ostringstream out;out<<std::hex<<std::setfill('0')<<std::setw(16)<<value;return out.str();}
std::int64_t LayoutTransitionLimit(const ResolvedLayoutStratumV2& stratum)
{
if(stratum.transitionMode=="Hard"||stratum.transitionFallsBackToHard)return 0;
return stratum.transitionWidthMicrometres
+(stratum.transitionMode=="Interleaved"?stratum.transitionWarpAmplitudeMicrometres:0);
}
std::string LayoutBandJson(const ResolvedLayoutBandV2& band)
{
std::ostringstream out;out<<"{\"kind\":"<<LayoutEscape(band.kind)
@@ -205,6 +290,84 @@ namespace
}
}
ResolvedLayoutTransitionBandsV1 EvaluateResolvedLayoutTransitionBandsV1(
const ResolvedLayoutStratumV2& upper, const ResolvedLayoutStratumV2& lower,
std::int32_t worldSeed, std::int64_t layoutChunkSizeMicrometres,
std::int64_t xMicrometres, std::int64_t yMicrometres)
{
ResolvedLayoutTransitionBandsV1 result;
const std::int64_t seam = upper.bedrock.bottomMicrometres;
const std::int64_t upperThickness = upper.bedrock.topMicrometres - seam;
const std::int64_t lowerThickness = lower.ceiling.topMicrometres
- lower.ceiling.bottomMicrometres;
result.upperBedrockBottomMicrometres = seam;
result.upperBedrockTopMicrometres = seam + std::max<std::int64_t>(0, upperThickness);
result.lowerCeilingBottomMicrometres = seam - std::max<std::int64_t>(0, lowerThickness);
result.lowerCeilingTopMicrometres = seam;
const std::int64_t width = upper.transitionFallsBackToHard
? 0 : std::max<std::int64_t>(0, upper.transitionWidthMicrometres);
if (upper.transitionMode == "Hard" || width == 0
|| (upper.transitionMode != "Gradient" && upper.transitionMode != "Interleaved")
|| !upper.bedrock.presentInCurrentField || !lower.ceiling.presentInCurrentField
|| upperThickness <= 0 || lowerThickness <= 0)
return result;
if (width <= 0) return result;
std::int64_t noise = 0;
if (upper.transitionMode == "Gradient")
{
const std::int64_t wavelength = std::max<std::int64_t>(
1000000, std::max<std::int64_t>(1, layoutChunkSizeMicrometres) * 4);
noise = TransitionValueNoise2D(worldSeed, upper.strateIndex,
xMicrometres, yMicrometres, wavelength, 0x47524144u);
}
else
{
// A face crossing wider than the sum of the authored bands would separate
// their far edges and leave an air slab. Limit the physical crossing to the
// smaller of the declared transition width and the combined band thickness.
const std::int64_t maximumContinuousCrossing=upperThickness+lowerThickness;
const std::int64_t crossingLimit=std::min(width,maximumContinuousCrossing);
const std::int64_t cell = std::max<std::int64_t>(1000000,
std::max<std::int64_t>(1, layoutChunkSizeMicrometres) * 2);
const std::int64_t warp = std::min(crossingLimit / 2, cell / 2);
const std::int64_t warpX = (TransitionValueNoise3D(worldSeed, upper.strateIndex,
xMicrometres, yMicrometres, seam, cell, 0x49574158u) * warp) / TransitionQ16;
const std::int64_t warpY = (TransitionValueNoise3D(worldSeed, upper.strateIndex,
xMicrometres, yMicrometres, seam, cell, 0x49574159u) * warp) / TransitionQ16;
const std::int64_t warpZ = (TransitionValueNoise3D(worldSeed, upper.strateIndex,
xMicrometres, yMicrometres, seam, cell, 0x4957415au) * warp) / TransitionQ16;
noise = TransitionValueNoise3D(worldSeed, upper.strateIndex,
xMicrometres + warpX, yMicrometres + warpY, seam + warpZ,
cell, 0x494e544cu);
// Interleaved means physical crossing: the two faces enter each other's
// bands by a total depth in [0, declared width]. Split that overlap across
// both faces so neither stratum owns the entire displacement. Since both
// resulting intervals are solid and overlap, the transition cannot open a gap.
const std::int64_t overlap = ((noise + TransitionQ16) * crossingLimit)
/ (2 * TransitionQ16);
const std::int64_t upperInset = overlap / 2;
const std::int64_t lowerInset = overlap - upperInset;
result.crossingDepthMicrometres = overlap;
result.upperBedrockBottomMicrometres = seam - upperInset;
result.upperBedrockTopMicrometres = result.upperBedrockBottomMicrometres + upperThickness;
result.lowerCeilingTopMicrometres = seam + lowerInset;
result.lowerCeilingBottomMicrometres = result.lowerCeilingTopMicrometres - lowerThickness;
return result;
}
const std::int64_t displacement = (noise * (width / 8)) / TransitionQ16;
const std::int64_t interfaceZ = seam + displacement;
result.upperBedrockBottomMicrometres = interfaceZ;
result.upperBedrockTopMicrometres = interfaceZ + upperThickness;
result.lowerCeilingBottomMicrometres = interfaceZ - lowerThickness;
result.lowerCeilingTopMicrometres = interfaceZ;
return result;
}
std::string ResolvedLayoutSnapshotV3::ToJson() const
{
const std::string body=LayoutBodyJson(*this);
@@ -216,7 +379,8 @@ bool ResolvedLayoutSnapshotV3::finalize(std::string& error)
{
error.clear();
if(schemaVersion!=ResolvedLayoutSchemaVersionV3||worldIdentity.empty()||strates.empty()
||strateLayoutChunkSizeMicrometres==0||strateLayoutChunkWidthSubvoxels<=0)
||coreVoxelSizeMicrometres==0||strateLayoutChunkSizeMicrometres==0
||strateLayoutChunkWidthSubvoxels<=0)
{error="resolved layout has an unsupported version, empty world identity, or no strates";return false;}
std::stable_sort(strates.begin(),strates.end(),[](const auto& a,const auto& b)
{return a.interiorTopMicrometres!=b.interiorTopMicrometres
@@ -257,7 +421,8 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
{
issues.clear();error.clear();
if(schemaVersion!=ResolvedLayoutSchemaVersionV3||worldIdentity.empty()||strates.empty()
||strateLayoutChunkSizeMicrometres==0||strateLayoutChunkWidthSubvoxels<=0)
||coreVoxelSizeMicrometres==0||strateLayoutChunkSizeMicrometres==0
||strateLayoutChunkWidthSubvoxels<=0)
{error="resolved layout schema/world/strata header is invalid";return false;}
const auto add=[&](std::string code,std::string detail)
{issues.push_back({std::move(code),std::move(detail)});};
@@ -271,6 +436,8 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
if(s.transitionInterpenetrationMicrometres>effectiveTransitionWidth
||s.transitionInterpenetrationMicrometres<0)
add("transition_overlap_exceeds_width",s.stableId+" transition interpenetration exceeds its declared width");
if(s.transitionWidthMicrometres<0||s.transitionBlendChunks<0)
add("invalid_transition_width",s.stableId+" has a negative transition width");
if(s.managerChunkWidthMicrometres>0&&s.dispatchChunkWidthMicrometres>0
&&s.managerChunkWidthMicrometres!=s.dispatchChunkWidthMicrometres)
add("ambiguous_dispatch_units",s.stableId+" manager chunk width differs from Core dispatch chunk width");
@@ -290,6 +457,10 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
{
if(b.kind!=expected||b.topMicrometres<=b.bottomMicrometres)
add("wrong_order",s.stableId+" has an invalid "+std::string(expected)+" band");
const std::int64_t minimumThickness=2ll*coreVoxelSizeMicrometres;
if(b.topMicrometres-b.bottomMicrometres<minimumThickness)
add("band_thinner_than_minimum",s.stableId+" "+std::string(expected)
+" is thinner than the two-Core-voxel minimum");
if(b.protectedBand&&b.diggable)
add("invalid_protection",s.stableId+" band is both protected and diggable");
if(b.solidDensityQ16<=0)
@@ -1055,6 +1226,11 @@ ResolvedLayoutValidatorAuditV3 AuditResolvedLayoutValidatorV3()
auto missingCeiling=base;missingCeiling.strates[0].ceiling.presentInCurrentField=false;expectReject("missing ceiling",missingCeiling);
auto wrongOrder=base;wrongOrder.strates[0].content.kind="bedrock";expectReject("wrong band order",wrongOrder);
auto largeOverlap=base;largeOverlap.strates[0].transitionInterpenetrationMicrometres=4000001;expectReject("interpenetration exceeds transition width",largeOverlap);
auto thinBand=base;
thinBand.strates[0].bedrock.topMicrometres=thinBand.strates[0].bedrock.bottomMicrometres
+2ll*base.coreVoxelSizeMicrometres-1;
thinBand.strates[0].content.bottomMicrometres=thinBand.strates[0].bedrock.topMicrometres;
expectReject("bedrock band below minimum thickness",thinBand);
auto genericOverlap=base;genericOverlap.strates[0].bedrock.bottomMicrometres-=1;expectReject("nominal band overlap",genericOverlap);
auto genericGap=base;genericGap.strates[0].bedrock.bottomMicrometres+=1;expectReject("nominal band gap",genericGap);
result.passed=result.controlsRun==result.controlsRejectedAsExpected&&result.failures.empty();return result;
+162 -2
View File
@@ -144,11 +144,96 @@ public:
const VoxelForgeCore::ResolvedLayoutStratumV2* FindResolvedLayoutStratum(int32 StrateIndex) const
{
if(!ResolvedLayout)return nullptr;
if(StrateIndex>=0&&static_cast<std::size_t>(StrateIndex)<ResolvedLayout->strates.size())
{
const auto& direct=ResolvedLayout->strates[static_cast<std::size_t>(StrateIndex)];
if(direct.strateIndex==StrateIndex)return &direct;
}
const auto it=std::find_if(ResolvedLayout->strates.begin(),ResolvedLayout->strates.end(),
[StrateIndex](const auto& item){return item.strateIndex==StrateIndex;});
return it==ResolvedLayout->strates.end()?nullptr:&*it;
}
const VoxelForgeCore::ResolvedLayoutStratumV2* FindResolvedLayoutStratumByOrder(int32 Order) const
{
if(!ResolvedLayout||Order<0)return nullptr;
if(static_cast<std::size_t>(Order)<ResolvedLayout->strates.size())
{
const auto& direct=ResolvedLayout->strates[static_cast<std::size_t>(Order)];
if(direct.order==Order)return &direct;
}
const auto it=std::find_if(ResolvedLayout->strates.begin(),ResolvedLayout->strates.end(),
[Order](const auto& item){return item.order==Order;});
return it==ResolvedLayout->strates.end()?nullptr:&*it;
}
bool IsResolvedLayoutTransitionActive(const VoxelForgeCore::ResolvedLayoutStratumV2& Upper) const
{
return Upper.transitionMode!="Hard"&&!Upper.transitionFallsBackToHard
&&Upper.transitionWidthMicrometres>0
&&Upper.transitionHonouredInCore;
}
std::int64_t ResolvedTransitionMaximumFaceDisplacementMicrometres(
const VoxelForgeCore::ResolvedLayoutStratumV2& Upper,
const VoxelForgeCore::ResolvedLayoutStratumV2& Lower) const
{
const std::int64_t width=std::max<std::int64_t>(0,Upper.transitionWidthMicrometres);
if(Upper.transitionMode=="Gradient")return width/8;
if(Upper.transitionMode!="Interleaved")return 0;
const std::int64_t upperThickness=std::max<std::int64_t>(0,
Upper.bedrock.topMicrometres-Upper.bedrock.bottomMicrometres);
const std::int64_t lowerThickness=std::max<std::int64_t>(0,
Lower.ceiling.topMicrometres-Lower.ceiling.bottomMicrometres);
const std::int64_t maximumCrossing=std::min(width,upperThickness+lowerThickness);
return (maximumCrossing+1)/2;
}
std::int64_t ResolvedTransitionPassageWeightQ16(
const VoxelForgeCore::ResolvedLayoutStratumV2& Upper,
const VoxelForgeCore::ResolvedLayoutStratumV2& Lower,
std::int64_t XMicrometres,std::int64_t YMicrometres) const
{
constexpr std::int64_t Q16=1ll<<16;
constexpr std::int64_t SupportMarginMicrometres=1000000;
constexpr std::int64_t FadeWidthMicrometres=2000000;
if(!ResolvedLayout||!Owner||Owner->CoreVoxelSizeMicrons==0)return Q16;
const std::int64_t seam=Upper.bedrock.bottomMicrometres;
const std::int64_t coreMicrometres=Owner->CoreVoxelSizeMicrons;
const std::int64_t subvoxelsPerVoxel=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
std::int64_t weight=Q16;
for(const auto& passage:ResolvedLayout->passages)
{
if(passage.upperStrateIndex!=Upper.strateIndex
||passage.lowerStrateIndex!=Lower.strateIndex)continue;
const std::int64_t mouthRadiusMicrometres=std::max<std::int64_t>(0,
passage.mouthRadiusSubvoxels*coreMicrometres/subvoxelsPerVoxel);
const std::int64_t protectedRadius=mouthRadiusMicrometres
+SupportMarginMicrometres;
for(const auto* mouth:{&passage.upperMouthSubvoxels,&passage.lowerMouthSubvoxels})
{
const std::int64_t mouthZMicrometres=mouth->at(2)*coreMicrometres
/subvoxelsPerVoxel;
if(std::abs(mouthZMicrometres-seam)
>Upper.transitionWidthMicrometres/2+mouthRadiusMicrometres)continue;
const double dx=static_cast<double>(XMicrometres-mouth->at(0)*coreMicrometres
/subvoxelsPerVoxel);
const double dy=static_cast<double>(YMicrometres-mouth->at(1)*coreMicrometres
/subvoxelsPerVoxel);
const std::int64_t fadeEnd=protectedRadius+FadeWidthMicrometres;
const double distanceSquared=dx*dx+dy*dy;
if(distanceSquared>=static_cast<double>(fadeEnd)*fadeEnd)continue;
if(distanceSquared<=static_cast<double>(protectedRadius)*protectedRadius)return 0;
const double distance=std::sqrt(distanceSquared);
const double t=static_cast<double>(static_cast<std::int64_t>(distance)
-protectedRadius)/FadeWidthMicrometres;
const double smooth=t*t*(3.0-2.0*t);
weight=std::min(weight,static_cast<std::int64_t>(std::llround(smooth*Q16)));
}
}
return weight;
}
bool IsInsideResolvedStrateBoundaryBand(float Z) const
{
if(!ResolvedLayout||!Owner||!Owner->Manager||!std::isfinite(Z))return false;
@@ -160,6 +245,21 @@ public:
const auto solidAt=[&](const VoxelForgeCore::ResolvedLayoutBandV2& band)
{return band.presentInCurrentField&&zMicrometres>=band.bottomMicrometres
&&zMicrometres<band.topMicrometres;};
const auto mayTouchTransition=[&](const VoxelForgeCore::ResolvedLayoutStratumV2* Upper,
const VoxelForgeCore::ResolvedLayoutStratumV2* Lower)
{
if(!Upper||!Lower||!IsResolvedLayoutTransitionActive(*Upper))return false;
const auto maxDisplacement=ResolvedTransitionMaximumFaceDisplacementMicrometres(
*Upper,*Lower);
const double minimum=std::min(Upper->bedrock.bottomMicrometres,
Lower->ceiling.bottomMicrometres)-maxDisplacement;
const double maximum=std::max(Upper->bedrock.topMicrometres,
Lower->ceiling.topMicrometres)+maxDisplacement;
return zMicrometres>=minimum&&zMicrometres<maximum;
};
const auto* lower=FindResolvedLayoutStratumByOrder(stratum->order+1);
const auto* upper=stratum->order>0?FindResolvedLayoutStratumByOrder(stratum->order-1):nullptr;
if(mayTouchTransition(stratum,lower)||mayTouchTransition(upper,stratum))return true;
return solidAt(stratum->ceiling)||solidAt(stratum->bedrock);
}
@@ -175,8 +275,68 @@ public:
const auto solidAt=[&](const VoxelForgeCore::ResolvedLayoutBandV2& band)
{return band.presentInCurrentField&&zMicrometres>=band.bottomMicrometres
&&zMicrometres<band.topMicrometres;};
const auto* band=solidAt(stratum->ceiling)?&stratum->ceiling
:solidAt(stratum->bedrock)?&stratum->bedrock:nullptr;
bool bCeilingHandledByTransition=false,bBedrockHandledByTransition=false;
const auto applyInterface=[&](const VoxelForgeCore::ResolvedLayoutStratumV2* upper,
const VoxelForgeCore::ResolvedLayoutStratumV2* lower)
{
if(!upper||!lower||!IsResolvedLayoutTransitionActive(*upper))return false;
const auto maxDisplacement=ResolvedTransitionMaximumFaceDisplacementMicrometres(
*upper,*lower);
const double minimum=std::min(upper->bedrock.bottomMicrometres,
lower->ceiling.bottomMicrometres)-maxDisplacement;
const double maximum=std::max(upper->bedrock.topMicrometres,
lower->ceiling.topMicrometres)+maxDisplacement;
if(zMicrometres<minimum||zMicrometres>=maximum)return false;
if(upper==stratum)bBedrockHandledByTransition=true;
if(lower==stratum)bCeilingHandledByTransition=true;
const std::int64_t xMicrometres=static_cast<std::int64_t>(std::llround(
static_cast<double>(X)*Owner->CoreVoxelSizeMicrons));
const std::int64_t yMicrometres=static_cast<std::int64_t>(std::llround(
static_cast<double>(Y)*Owner->CoreVoxelSizeMicrons));
const auto bands=VoxelForgeCore::EvaluateResolvedLayoutTransitionBandsV1(*upper,*lower,
Owner->Seed,ResolvedLayout->strateLayoutChunkSizeMicrometres,
xMicrometres,yMicrometres);
auto resolvedBands=bands;
const std::int64_t transitionWeight=ResolvedTransitionPassageWeightQ16(
*upper,*lower,xMicrometres,yMicrometres);
constexpr std::int64_t TransitionQ16=1ll<<16;
if(transitionWeight<TransitionQ16)
{
const std::int64_t seam=upper->bedrock.bottomMicrometres;
const std::int64_t upperThickness=upper->bedrock.topMicrometres-seam;
const std::int64_t lowerThickness=lower->ceiling.topMicrometres
-lower->ceiling.bottomMicrometres;
const auto scaled=[&](std::int64_t value)
{return (value*transitionWeight)/TransitionQ16;};
resolvedBands.upperBedrockBottomMicrometres=seam+scaled(
bands.upperBedrockBottomMicrometres-seam);
resolvedBands.upperBedrockTopMicrometres=
resolvedBands.upperBedrockBottomMicrometres+upperThickness;
resolvedBands.lowerCeilingTopMicrometres=seam+scaled(
bands.lowerCeilingTopMicrometres-seam);
resolvedBands.lowerCeilingBottomMicrometres=
resolvedBands.lowerCeilingTopMicrometres-lowerThickness;
resolvedBands.crossingDepthMicrometres=std::max<std::int64_t>(0,
resolvedBands.lowerCeilingTopMicrometres
-resolvedBands.upperBedrockBottomMicrometres);
}
const bool upperBedrock=zMicrometres>=resolvedBands.upperBedrockBottomMicrometres
&&zMicrometres<resolvedBands.upperBedrockTopMicrometres;
const bool lowerCeiling=zMicrometres>=resolvedBands.lowerCeilingBottomMicrometres
&&zMicrometres<resolvedBands.lowerCeilingTopMicrometres;
if(!upperBedrock&&!lowerCeiling)return false;
const auto& band=upperBedrock?upper->bedrock:lower->ceiling;
density=-std::max(0.05f,static_cast<float>(band.solidDensityQ16)/65536.0f);
return true;
};
const auto* lower=FindResolvedLayoutStratumByOrder(stratum->order+1);
const auto* upper=stratum->order>0?FindResolvedLayoutStratumByOrder(stratum->order-1):nullptr;
if(applyInterface(stratum,lower)||applyInterface(upper,stratum))return density;
const auto* band=(!bCeilingHandledByTransition&&solidAt(stratum->ceiling))
?&stratum->ceiling:(!bBedrockHandledByTransition&&solidAt(stratum->bedrock))
?&stratum->bedrock:nullptr;
if(!band)return density;
return -std::max(0.05f,static_cast<float>(band->solidDensityQ16)/65536.0f);
}
@@ -0,0 +1,110 @@
# World Assembler L29 — bedrock/ceiling transitions
**Core now honors the upper strate's `EVoxelStrateTransition` at the shared interface.** The owner
world's upper two-chunk Gradient resolves to 16 m at the 8 m layout chunk size. SurfaceWorld's
one-chunk setting remains in the resolved strate record. Core does not blend unrelated generator
parameters. `WorldAssemblyEvaluatorVersion` is 15; recipe versions and resolved-layout schema V3
are unchanged.
## Appearance and safety
| Mode | Result |
|---|---|
| Hard | The original flat, touching boundary. No displacement or overlap. |
| Gradient | Both faces follow one smooth 2D hash surface. On the 16 m interface, the measured peak-to-peak undulation is 3.988 m. |
| Interleaved | A deterministic 3D domain-warped hash field moves both faces inward, producing fingered overlap. Measured peak crossing was 6.487 m in FloatingIslands and 6.952 m in SurfaceWorld, within the declared 16 m. |
Each boundary band keeps at least **two Core voxels** of solid thickness: 0.5 m at the default
25 cm voxel size. The owner bands measured 0.5–1.0 m on the upper side and 6.25 m on the lower
side. Interleaved is capped by both the declared width and the bands' combined thickness, so the
solid intervals still touch or overlap.
The strict interface audit covers a 512 m square: 4,221 columns per interface, with four passage
columns excluded from the hole sweep. Hard, Gradient and Interleaved each report zero hole columns
and zero air samples. Both negative controls reject as expected: crossing one micrometre wider than
declared, and either band one micrometre thinner than the minimum. All six recipe/mode runs pass.
Transition faces return to the nominal seam near passage mouths: the protected radius is the mouth
radius plus 1 m, followed by a 2 m smooth fade. This kept the style-2 FI landing supported; its
final capsule/support audit passes.
## Passage and parity audits
The final matrix has 4 styles × 2 recipes × 2 compilers (16 runs). Capsule and walkability,
open-air, naturalness, no-long-bridge, route bindings, strict-validator controls, L13 route parity,
and L9 proof audits pass. Open-air reports zero violations; validator controls reject 10/10;
route-parity and proof audits report zero mismatches/violations. The L23/L24/L26 negative controls
are detected.
The L28 `FloorProfileBlend` diagnostic still exceeds its 2-voxel threshold in styles 1 and 3:
2.544 and 3.645 voxels. L28 records the same values on both compilers, so this is inherited and
unchanged.
## Hashes
The L25 W1/W8/W12 hash matrix is identical across Clang and GCC for both recipes: full-detail,
whole-view, all LOD rows and exact-query hashes match. Hash order below is density / mesh / payload /
topology.
| Recipe | Full detail (960 tiles) | Whole view (2,370 tiles) | Exact-query density / detail / collision |
|---|---|---|---|
| SurfaceWorld | `ace56c8f205238ad / a9c603a1248de6b8 / ea55f1f4fcc6a894 / 5ea7bc78a1b678ae` | `0e8c5af01df96b14 / 70099e89b77811ed / dbce0fdcf6764126 / ddaf81a1228f9b4b` | `c949c4df2ce6f9d9 / 114c501e2d830d94 / e6011d3a248d4849` |
| FloatingIslands | `ed550e0c8b182695 / 0e410a8e80a3e7f7 / 0751926f0c67d8a4 / f01208bc2f7841ec` | `a492eefa4f534975 / 141f00f3e411a0df / 93f50c569526c5cb / d83b53c8e53df81c` | `7b7c50ac24ccadcc / efcba20c0c70c415 / e604823a249029bf` |
The 24 m moving crossing processed 314 entering tiles per recipe; Clang/GCC crossing hashes match.
SurfaceWorld's away-from-interface probe at z = −400 m also matches L28: all 960 full-detail
tiles and the exact-query density/detail/collision hashes are identical. The broader whole-view
hash differs because its far-LOD coverage also includes the changed interface.
## Cost
Five clean, alternating W12 pairs against
`Saved/Linux/bin/VoxelForgeCoreHeadless-linux28-clang-r28`, hashing off:
| Recipe | L28 whole-view ready | L29 whole-view ready | Change |
|---|---:|---:|---:|
| SurfaceWorld | 1.581 s | 1.644 s | +3.97% |
| FloatingIslands | 16.605 s | 16.814 s | +1.26% |
FloatingIslands is within the ~3% target. SurfaceWorld is about one percentage point above it.
## Captures
All are 1280×720 JPEGs, each under 21 KB (well below 300 KB):
- `captures/fi-floor-gradient-above.jpg` — FI floor from above, inside FI.
- `captures/sw-ceiling-gradient-below.jpg` — SW ceiling from below, inside SW.
- `captures/interface-hard-side-cutaway.jpg`
- `captures/interface-gradient-side-cutaway.jpg`
- `captures/interface-interleaved-side-cutaway.jpg`
## Changes and run history
Core transition evaluation/validation and the shared composition path changed, along with the
headless transition audit, architecture/codemap, and the two Unreal files
`Source/VoxelForge/Public/VoxelStrateTypes.h` and
`Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp`. Unreal was unavailable here, so those edits
were not compiled. No commit, push or stash was made.
Failed or retried runs:
- An early Clang build used a nonexistent dispatch helper; corrected to the current query method and rebuilt with Clang and GCC.
- The first Interleaved overlap used the full sum of band thicknesses and opened gaps (1,085 columns / 20,313 air samples). Capping overlap to `min(declared width, combined thickness)` removed the gaps.
- An initial hole sweep sampled a half-open band edge and reported 752 boundary-rounding holes. Sampling half a voxel inside each band removed those edge artifacts; final sweeps report zero holes.
- The first FI style-2 passage audit had 11 unsupported probes after Gradient moved the mouth face. The local mouth taper fixed it; all 16 final passage runs pass.
- A resolved-layout-only command initially omitted required pipeline flags and exited 2; rerun with the required flags passed. Early cutaway camera/clip settings produced blank framing; the final orientation and clip plane produced the captures above.
- One cost folder contained a duplicated timing sequence and was discarded. The five-pair clean run above was sequential. A cache experiment did not improve cost and was removed. A cost-extraction `sed` typo was rerun with Python; benchmark logs were unaffected.
No build or audit exceeded 30 minutes, and no step remained stuck for 15 minutes. All builds and runs
used CPUs 0–11, at most 12 workers, normal priority, and the 6 GiB address-space cap.
## Orchestrator review (Claude)
- Merged: transitions honoured safely (0 holes over 4,221 columns per interface, negative controls reject, all
passage audits pass, deterministic).
- **The look is not verified by the captures:** `interface-interleaved-side-cutaway.jpg` shows flat faces
(black = uncapped solid between faces), with no visible fingers; `sw-ceiling-gradient-below.jpg` is a flat
plane; `fi-floor-gradient-above.jpg` shows **concentric dashed rings** on the FI floor, which looks like an
artifact (possibly the passage-mouth protected-radius fade, or quantised undulation), not a smooth Gradient.
- Cumulative SW cost vs L24 is now ~+8% (L28 +3.7% plus L29 +4%). L30 covers the ring artifact, readable
transition captures, and cost recovery.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+57 -1
View File
@@ -69,6 +69,9 @@ namespace
bool AuditResolvedLayoutBoundaries=false;
bool AuditResolvedLayoutPassages=false;
bool AuditSurfaceClearance=false;
bool AuditStrateTransitions=false;
int TransitionModeOverride=-1;
int TransitionWidthChunksOverride=-1;
};
bool ParseInteger(std::string_view text,int& output)
@@ -103,6 +106,38 @@ namespace
return true;
}
bool OverrideTransitions(VFJson::Value& root,int mode,int widthChunks,std::string& error)
{
auto* object=std::get_if<VFJson::Value::Object>(&root.Data);
if(!object){error="transition fixture override requires an owner JSON object";return false;}
const auto stratesIt=object->find("strates");
if(stratesIt==object->end())
{error="transition fixture override cannot find the resolved strate array";return false;}
auto* strates=std::get_if<VFJson::Value::Array>(&stratesIt->second.Data);
if(!strates||strates->empty())
{error="transition fixture override found an empty or invalid strate array";return false;}
for(auto& strate:*strates)
{
auto* strateObject=std::get_if<VFJson::Value::Object>(&strate.Data);
if(!strateObject){error="transition fixture contains a malformed strate";return false;}
const auto assetIt=strateObject->find("asset");
if(assetIt==strateObject->end())continue;
auto* asset=std::get_if<VFJson::Value::Object>(&assetIt->second.Data);
if(!asset)continue;
if(mode>=0)
{
VFJson::Value value;value.Data=static_cast<double>(mode);
(*asset)["TransitionType"]=std::move(value);
}
if(widthChunks>=0)
{
VFJson::Value value;value.Data=static_cast<double>(widthChunks);
(*asset)["TransitionBlendChunks"]=std::move(value);
}
}
return true;
}
bool ParseOptions(int argc,char** argv,FOptions& options)
{
const std::filesystem::path executable=std::filesystem::absolute(argv[0]);
@@ -126,6 +161,8 @@ namespace
" --resolved-layout-output=FILE (canonical plan-time layout snapshot)\n"
" --resolved-layout-only (exit after plan and snapshot validation)\n"
" --audit-resolved-layout-boundaries (query Core at each recorded endpoint)\n"
" --audit-strate-transitions (measure interface crossing, band thickness and holes)\n"
" --transition-mode=hard|gradient|interleaved --transition-width-chunks=N (fixture override)\n"
" --audit-resolved-layout-passages (capsule, support, route-binding and blocked-control audit)\n"
" --audit-surface-clearance (sample biome terrain/caps against the resolved ceiling)\n"
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
@@ -149,6 +186,21 @@ namespace
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
else if(arg=="--audit-resolved-layout-passages")options.AuditResolvedLayoutPassages=true;
else if(arg=="--audit-surface-clearance")options.AuditSurfaceClearance=true;
else if(arg=="--audit-strate-transitions")options.AuditStrateTransitions=true;
else if(arg.starts_with("--transition-mode="))
{
const std::string_view mode=arg.substr(std::string_view("--transition-mode=").size());
if(mode=="gradient")options.TransitionModeOverride=0;
else if(mode=="hard")options.TransitionModeOverride=1;
else if(mode=="interleaved")options.TransitionModeOverride=2;
else {std::fprintf(stderr,"Invalid transition mode: %.*s\n",static_cast<int>(mode.size()),mode.data());return false;}
}
else if(arg.starts_with("--transition-width-chunks="))
{
if(!readInt("--transition-width-chunks=",options.TransitionWidthChunksOverride)
||options.TransitionWidthChunksOverride<0||options.TransitionWidthChunksOverride>64)
{std::fprintf(stderr,"transition width chunks must be in 0..64\n");return false;}
}
else if(arg=="--stream-benchmark")options.StreamBenchmark=true;
else if(arg=="--stream-pipeline")options.StreamPipeline=true;
else if(arg=="--stream-hash")options.StreamHash=true;
@@ -303,6 +355,10 @@ int main(int argc,char** argv)
if(options.FloatingIslandsRecipe
&&!StandaloneWorldAssemblyPrototype::SelectTopStrateAsFloatingIslands(ownerJsonRoot,error))
{std::fprintf(stderr,"Floating-island recipe selection failed: %s\n",error.c_str());return 2;}
if((options.TransitionModeOverride>=0||options.TransitionWidthChunksOverride>=0)
&&!OverrideTransitions(ownerJsonRoot,options.TransitionModeOverride,
options.TransitionWidthChunksOverride,error))
{std::fprintf(stderr,"Transition fixture override failed: %s\n",error.c_str());return 2;}
if(!StandaloneOwnerLoader::Resolve(ownerJsonRoot,*ownerWorld,error))
{std::fprintf(stderr,"Owner data load failed: %s\n",error.c_str());return 2;}
std::printf("[ColdTimeline] stage=owner_data_load end_ms=%.3f\n",
@@ -551,6 +607,6 @@ int main(int argc,char** argv)
options.RegionCrossing,options.AuditTileShapeReadiness,
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence,
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
options.AuditResolvedLayoutPassages,
options.AuditResolvedLayoutPassages,options.AuditStrateTransitions,
&resolvedLayout);
}
+175
View File
@@ -240,6 +240,172 @@ namespace StandaloneStreamBenchmark
return Hash;
}
inline bool AuditResolvedStrateTransitions(const VoxelForgeCore::World& Field,
const FStandaloneOwnerWorld& Owner,
const VoxelForgeCore::ResolvedLayoutSnapshotV3& Layout)
{
constexpr std::int64_t XYExtentMicrometres=256000000;
constexpr std::int64_t XYStepMicrometres=8000000;
const std::int64_t coreMicrometres=std::max<std::uint32_t>(1,Owner.CoreVoxelSizeMicrons);
const std::int64_t zStepMicrometres=std::max<std::int64_t>(1,coreMicrometres/2);
const std::int64_t minimumBandMicrometres=2*coreMicrometres;
std::uint64_t interfacesPassed=0,totalColumns=0,passageColumnsSkipped=0;
std::uint64_t holeColumns=0,airSamples=0,solidSamples=0;
bool negativeWidthRejected=false,negativeThinBandRejected=false;
for(std::size_t interfaceIndex=0;interfaceIndex+1<Layout.strates.size();++interfaceIndex)
{
const auto& upper=Layout.strates[interfaceIndex];
const auto& lower=Layout.strates[interfaceIndex+1];
std::int64_t minimumOffset=std::numeric_limits<std::int64_t>::max();
std::int64_t maximumOffset=std::numeric_limits<std::int64_t>::min();
std::int64_t maximumCrossingDepth=0;
std::int64_t minimumUpperThickness=std::numeric_limits<std::int64_t>::max();
std::int64_t minimumLowerThickness=std::numeric_limits<std::int64_t>::max();
std::uint64_t columns=0,skipped=0,holes=0,air=0,solid=0;
bool firstHoleReported=false;
const std::int64_t seam=upper.bedrock.bottomMicrometres;
const auto passageCoversColumn=[&](std::int64_t xUm,std::int64_t yUm,
std::int64_t zMinimumUm,std::int64_t zMaximumUm)
{
constexpr double Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
for(const auto& passage:Layout.passages)
{
if(passage.upperStrateIndex!=upper.strateIndex
||passage.lowerStrateIndex!=lower.strateIndex)continue;
for(std::size_t pointIndex=1;pointIndex<passage.controlPoints.size();++pointIndex)
{
const auto& a=passage.controlPoints[pointIndex-1];
const auto& b=passage.controlPoints[pointIndex];
const double ax=a.positionSubvoxels[0]*coreMicrometres/Q;
const double ay=a.positionSubvoxels[1]*coreMicrometres/Q;
const double az=a.positionSubvoxels[2]*coreMicrometres/Q;
const double bx=b.positionSubvoxels[0]*coreMicrometres/Q;
const double by=b.positionSubvoxels[1]*coreMicrometres/Q;
const double bz=b.positionSubvoxels[2]*coreMicrometres/Q;
const double radius=std::max(a.radiusSubvoxels,b.radiusSubvoxels)
*coreMicrometres/Q+750000.0;
if(std::max(az,bz)+radius<zMinimumUm
||std::min(az,bz)-radius>zMaximumUm)continue;
const double dx=bx-ax,dy=by-ay;
const double lengthSquared=dx*dx+dy*dy;
const double t=lengthSquared>0.0
?std::clamp(((xUm-ax)*dx+(yUm-ay)*dy)/lengthSquared,0.0,1.0):0.0;
const double ex=xUm-(ax+t*dx),ey=yUm-(ay+t*dy);
if(ex*ex+ey*ey<=radius*radius)return true;
}
}
return false;
};
for(std::int64_t iy=-XYExtentMicrometres/XYStepMicrometres;
iy<=XYExtentMicrometres/XYStepMicrometres;++iy)
for(std::int64_t ix=-XYExtentMicrometres/XYStepMicrometres;
ix<=XYExtentMicrometres/XYStepMicrometres;++ix)
{
const std::int64_t xUm=ix*XYStepMicrometres;
const std::int64_t yUm=iy*XYStepMicrometres;
const auto bands=VoxelForgeCore::EvaluateResolvedLayoutTransitionBandsV1(
upper,lower,Owner.Seed,Layout.strateLayoutChunkSizeMicrometres,xUm,yUm);
const std::int64_t offset=bands.upperBedrockBottomMicrometres-seam;
minimumOffset=std::min(minimumOffset,offset);
maximumOffset=std::max(maximumOffset,offset);
maximumCrossingDepth=std::max(maximumCrossingDepth,
bands.crossingDepthMicrometres);
minimumUpperThickness=std::min(minimumUpperThickness,
bands.upperBedrockTopMicrometres-bands.upperBedrockBottomMicrometres);
minimumLowerThickness=std::min(minimumLowerThickness,
bands.lowerCeilingTopMicrometres-bands.lowerCeilingBottomMicrometres);
const std::int64_t zMinimum=std::min(bands.upperBedrockBottomMicrometres,
bands.lowerCeilingBottomMicrometres);
const std::int64_t zMaximum=std::max(bands.upperBedrockTopMicrometres,
bands.lowerCeilingTopMicrometres);
if(passageCoversColumn(xUm,yUm,zMinimum,zMaximum)){++skipped;continue;}
++columns;
bool hasHole=false;
for(std::int64_t zUm=zMinimum+zStepMicrometres/2;
zUm<zMaximum-zStepMicrometres/2;zUm+=zStepMicrometres)
{
const VoxelForgeCore::Vec3d point{
static_cast<double>(xUm)/coreMicrometres,
static_cast<double>(yUm)/coreMicrometres,
static_cast<double>(zUm)/coreMicrometres};
const float density=Field.densityAt(point);
if(!std::isfinite(density)||density>=0.0f)
{
if(!firstHoleReported)
{
std::printf("[StrateTransitionFirstHole] x_um=%lld y_um=%lld z_um=%lld z_min_um=%lld z_max_um=%lld density=%.9g dispatch=%s\n",
static_cast<long long>(xUm),static_cast<long long>(yUm),
static_cast<long long>(zUm),static_cast<long long>(zMinimum),
static_cast<long long>(zMaximum),density,
Field.densityDispatchPathAt(point).c_str());
firstHoleReported=true;
}
hasHole=true;++air;
}
else ++solid;
}
if(hasHole)++holes;
}
const std::int64_t boundaryPeakToPeak=maximumOffset-minimumOffset;
const std::int64_t allowedWidth=upper.transitionMode=="Hard"
||upper.transitionFallsBackToHard?0:upper.transitionWidthMicrometres;
if(interfaceIndex==0)
{
auto wide=Layout;
wide.strates[0].transitionMode="Interleaved";
wide.strates[0].transitionFallsBackToHard=false;
wide.strates[0].transitionWidthMicrometres=8000000;
wide.strates[0].transitionInterpenetrationMicrometres=8000001;
std::vector<VoxelForgeCore::ResolvedLayoutIssueV2> issues;
std::string error;
negativeWidthRejected=!wide.validate(
VoxelForgeCore::ResolvedLayoutValidationModeV3::strict,issues,error);
auto thin=Layout;
auto& bedrock=thin.strates[0].bedrock;
bedrock.topMicrometres=bedrock.bottomMicrometres+minimumBandMicrometres-1;
thin.strates[0].content.bottomMicrometres=bedrock.topMicrometres;
negativeThinBandRejected=!thin.validate(
VoxelForgeCore::ResolvedLayoutValidationModeV3::strict,issues,error);
}
const bool passed=columns>0&&holes==0&&maximumCrossingDepth<=allowedWidth
&&minimumUpperThickness>=minimumBandMicrometres
&&minimumLowerThickness>=minimumBandMicrometres;
interfacesPassed+=passed?1u:0u;
totalColumns+=columns;passageColumnsSkipped+=skipped;
holeColumns+=holes;airSamples+=air;solidSamples+=solid;
std::printf("[StrateTransitionInterface] upper=%d lower=%d mode=%s width_um=%lld max_crossing_depth_um=%lld boundary_peak_to_peak_um=%lld allowed_um=%lld upper_min_band_um=%lld lower_min_band_um=%lld columns=%llu passage_columns=%llu hole_columns=%llu air_samples=%llu status=%s\n",
upper.strateIndex,lower.strateIndex,upper.transitionMode.c_str(),
static_cast<long long>(upper.transitionWidthMicrometres),
static_cast<long long>(maximumCrossingDepth),
static_cast<long long>(boundaryPeakToPeak),static_cast<long long>(allowedWidth),
static_cast<long long>(minimumUpperThickness),static_cast<long long>(minimumLowerThickness),
static_cast<unsigned long long>(columns),static_cast<unsigned long long>(skipped),
static_cast<unsigned long long>(holes),static_cast<unsigned long long>(air),
passed?"PASS":"FAIL");
}
const bool controlsPassed=negativeWidthRejected&&negativeThinBandRejected;
std::printf("[StrateTransitionNegativeControls] wider_than_declared=%s thinner_than_minimum=%s minimum_band_um=%lld status=%s\n",
negativeWidthRejected?"REJECTED":"ACCEPTED",
negativeThinBandRejected?"REJECTED":"ACCEPTED",
static_cast<long long>(minimumBandMicrometres),controlsPassed?"PASS":"FAIL");
const bool passed=!Layout.strates.empty()&&interfacesPassed+1==Layout.strates.size()
&&holeColumns==0&&airSamples==0&&controlsPassed;
std::printf("[StrateTransitionAuditSummary] interfaces=%llu passed=%llu columns=%llu skipped_passage_columns=%llu hole_columns=%llu air_samples=%llu solid_samples=%llu status=%s\n",
static_cast<unsigned long long>(Layout.strates.size()-1),
static_cast<unsigned long long>(interfacesPassed),
static_cast<unsigned long long>(totalColumns),
static_cast<unsigned long long>(passageColumnsSkipped),
static_cast<unsigned long long>(holeColumns),
static_cast<unsigned long long>(airSamples),
static_cast<unsigned long long>(solidSamples),passed?"PASS":"FAIL");
return passed;
}
inline int RunPipelinedStreamingBenchmark(std::shared_ptr<FStandaloneOwnerWorld> OwnerWorld,
const VoxelForgeCore::ResolvedWorldSnapshot& CoreSnapshot,
const FVector& CameraPositionVoxels,int32 WorkerCount,int32 MaxLevel,
@@ -256,6 +422,7 @@ namespace StandaloneStreamBenchmark
bool bAuditBasePageEquivalence=false,bool bAuditRouteParity=false,
bool bAuditResolvedLayoutBoundaries=false,
bool bAuditResolvedLayoutPassages=false,
bool bAuditStrateTransitions=false,
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr)
{
using Clock=std::chrono::steady_clock;
@@ -441,6 +608,14 @@ namespace StandaloneStreamBenchmark
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
}
if(bAuditStrateTransitions)
{
if(ResolvedLayout==nullptr||!CoreSnapshot.resolvedLayout())
{Streamer.Stop();std::fprintf(stderr,"[StrateTransitionAudit] missing resolved-layout snapshot\n");return 2;}
const bool passed=AuditResolvedStrateTransitions(Shape,World,*ResolvedLayout);
Streamer.Stop();
return passed?0:11;
}
if(bAuditResolvedLayoutPassages)
{
if(ResolvedLayout==nullptr||!CoreSnapshot.resolvedLayout())
+14 -6
View File
@@ -801,13 +801,21 @@ namespace StandaloneWorldAssemblyPrototype
s.transitionBlendChunks=slot.Definition->TransitionBlendChunks;
s.transitionWidthMicrometres=static_cast<std::int64_t>(s.transitionBlendChunks)*owner.StrateLayoutChunkSizeMicrometres;
s.transitionWarpAmplitudeMicrometres=s.transitionMode=="Interleaved"
?2*static_cast<std::int64_t>(owner.StrateLayoutChunkSizeMicrometres):0;
s.transitionInterpenetrationMicrometres=0;
s.transitionHonouredInCore=s.transitionMode=="Hard";
s.transitionFallsBackToHard=s.transitionMode!="Hard";
?std::min(s.transitionWidthMicrometres/2,
static_cast<std::int64_t>(owner.StrateLayoutChunkSizeMicrometres)):0;
s.transitionInterpenetrationMicrometres=s.transitionMode=="Interleaved"
?s.transitionWidthMicrometres
:s.transitionMode=="Gradient"?s.transitionWidthMicrometres/4:0;
s.transitionFallsBackToHard=s.transitionMode!="Hard"
&&s.transitionWidthMicrometres<=0;
s.transitionHonouredInCore=s.transitionMode=="Hard"||!s.transitionFallsBackToHard;
s.transitionDispatchPath=s.transitionFallsBackToHard
?"declared Gradient/Interleaved recorded; Core uses explicit Hard fallback with zero interpenetration"
:"declared Hard transition applied at the strate interface";
?"declared zero-width transition uses explicit Hard fallback"
:s.transitionMode=="Hard"
?"declared Hard transition preserves the flat shared bedrock/ceiling interface"
:s.transitionMode=="Interleaved"
?"shared composition overlaps both facing bands with deterministic domain-warped fingers inside the declared width"
:"shared composition moves both band faces together with the smooth declared-width transition field";
s.managerLookup="UVoxelStrateManager selects the slot from the director-resolved layout chunk width";
s.managerChunkWidthMicrometres=owner.StrateLayoutChunkSizeMicrometres;
s.dispatchChunkWidthMicrometres=owner.StrateLayoutChunkSizeMicrometres;