wip(assembler): round L32 -- smooth Gradient interface at full amplitude (no rings, not flat)
Band faces now use signed distance to the displaced solid intervals, continuous across bands, so MC interpolates the interface instead of terracing at density levels. The Gradient amplitude is restored to width/8 (about 4 m peak-to-peak at 16 m). Ring/terrace audit at LOD0-8 on the FI floor and SW ceiling passes; negative controls: L30 (rings) and L31 (flat) both fail. Hole/interface audits, 16 passage rows and 24/24 determinism pass. Evaluator 20. Cost vs L31 SW +1.9%, FI +1.5%. 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
28069f0d98
commit
d0158c6019
31 files changed
+2207
-111
No files matched your search
@@ -270,7 +270,7 @@ public:
|
||||
{
|
||||
const std::int64_t width=std::max<std::int64_t>(0,Upper.transitionWidthMicrometres);
|
||||
if(Upper.transitionMode=="Gradient")
|
||||
return width/(Upper.generatorKind=="FloatingIslands"?256:8);
|
||||
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);
|
||||
@@ -385,6 +385,70 @@ public:
|
||||
return weight;
|
||||
}
|
||||
|
||||
VoxelForgeCore::ResolvedLayoutTransitionBandsV1 ResolvedTransitionBandsAtXY(
|
||||
const VoxelForgeCore::ResolvedLayoutStratumV2& Upper,
|
||||
const VoxelForgeCore::ResolvedLayoutStratumV2& Lower,
|
||||
std::int64_t XMicrometres,std::int64_t YMicrometres,bool SkipPassageFade=false) const
|
||||
{
|
||||
auto bands=VoxelForgeCore::EvaluateResolvedLayoutTransitionBandsV1(Upper,Lower,
|
||||
Owner?Owner->Seed:0,ResolvedLayout?ResolvedLayout->strateLayoutChunkSizeMicrometres:0,
|
||||
XMicrometres,YMicrometres);
|
||||
constexpr std::int64_t TransitionQ16=1ll<<16;
|
||||
const std::int64_t weight=SkipPassageFade?TransitionQ16:
|
||||
ResolvedTransitionPassageWeightQ16(Upper,Lower,XMicrometres,YMicrometres);
|
||||
if(weight>=TransitionQ16)return bands;
|
||||
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*weight)/TransitionQ16;};
|
||||
bands.upperBedrockBottomMicrometres=seam+scaled(
|
||||
bands.upperBedrockBottomMicrometres-seam);
|
||||
bands.upperBedrockTopMicrometres=bands.upperBedrockBottomMicrometres+upperThickness;
|
||||
bands.lowerCeilingTopMicrometres=seam+scaled(
|
||||
bands.lowerCeilingTopMicrometres-seam);
|
||||
bands.lowerCeilingBottomMicrometres=bands.lowerCeilingTopMicrometres-lowerThickness;
|
||||
bands.crossingDepthMicrometres=std::max<std::int64_t>(0,
|
||||
bands.lowerCeilingTopMicrometres-bands.upperBedrockBottomMicrometres);
|
||||
return bands;
|
||||
}
|
||||
|
||||
bool ResolvedBedrockTopAt(const VoxelForgeCore::ResolvedLayoutStratumV2& Upper,
|
||||
double X,double Y,double& TopZ) const
|
||||
{
|
||||
const auto* lower=FindResolvedLayoutStratumByOrder(Upper.order+1);
|
||||
if(!lower||!Owner||Owner->CoreVoxelSizeMicrons==0
|
||||
||!IsResolvedLayoutTransitionActive(Upper))return false;
|
||||
const auto toMicrometres=[&](double value)
|
||||
{return static_cast<std::int64_t>(std::llround(value*Owner->CoreVoxelSizeMicrons));};
|
||||
const auto* tileQueries=ActivePassageTileQueries;
|
||||
const bool skipPassageFade=tileQueries&&tileQueries->matches(*this)
|
||||
&&!tileQueries->mayContainTransitionPassageFade();
|
||||
const auto bands=ResolvedTransitionBandsAtXY(Upper,*lower,toMicrometres(X),
|
||||
toMicrometres(Y),skipPassageFade);
|
||||
TopZ=static_cast<double>(bands.upperBedrockTopMicrometres)
|
||||
/Owner->CoreVoxelSizeMicrons;
|
||||
return std::isfinite(TopZ);
|
||||
}
|
||||
|
||||
bool ResolvedCeilingBottomAt(const VoxelForgeCore::ResolvedLayoutStratumV2& Lower,
|
||||
double X,double Y,double& BottomZ) const
|
||||
{
|
||||
const auto* upper=FindResolvedLayoutStratumByOrder(Lower.order-1);
|
||||
if(!upper||!Owner||Owner->CoreVoxelSizeMicrons==0
|
||||
||!IsResolvedLayoutTransitionActive(*upper))return false;
|
||||
const auto toMicrometres=[&](double value)
|
||||
{return static_cast<std::int64_t>(std::llround(value*Owner->CoreVoxelSizeMicrons));};
|
||||
const auto* tileQueries=ActivePassageTileQueries;
|
||||
const bool skipPassageFade=tileQueries&&tileQueries->matches(*this)
|
||||
&&!tileQueries->mayContainTransitionPassageFade();
|
||||
const auto bands=ResolvedTransitionBandsAtXY(*upper,Lower,toMicrometres(X),
|
||||
toMicrometres(Y),skipPassageFade);
|
||||
BottomZ=static_cast<double>(bands.lowerCeilingBottomMicrometres)
|
||||
/Owner->CoreVoxelSizeMicrons;
|
||||
return std::isfinite(BottomZ);
|
||||
}
|
||||
|
||||
bool IsInsideResolvedStrateBoundaryBand(float Z) const
|
||||
{
|
||||
#if defined(VF_L30_ENABLE_COST_COUNTERS)
|
||||
@@ -471,12 +535,72 @@ public:
|
||||
return density;
|
||||
}
|
||||
}
|
||||
if(!ResolvedLayout||!Owner||!Owner->Manager||!std::isfinite(Z))return density;
|
||||
if(!ResolvedLayout||!Owner||!Owner->Manager||Owner->CoreVoxelSizeMicrons==0
|
||||
||!std::isfinite(Z))return density;
|
||||
const double zMicrometres=static_cast<double>(Z)*Owner->CoreVoxelSizeMicrons;
|
||||
if(ResolvedLayout->strates.size()==2)
|
||||
{
|
||||
const auto* transitionUpper=FindResolvedLayoutStratumByOrder(0);
|
||||
const auto* transitionLower=FindResolvedLayoutStratumByOrder(1);
|
||||
if(transitionUpper&&transitionLower
|
||||
&&IsResolvedLayoutTransitionActive(*transitionUpper))
|
||||
{
|
||||
#if defined(VF_L30_ENABLE_COST_COUNTERS)
|
||||
++ThreadClassificationStats().TransitionWindowChecks;
|
||||
#endif
|
||||
const auto maximumDisplacement=ResolvedTransitionMaximumFaceDisplacementMicrometres(
|
||||
*transitionUpper,*transitionLower);
|
||||
const double minimum=std::min(transitionUpper->bedrock.bottomMicrometres,
|
||||
transitionLower->ceiling.bottomMicrometres)-maximumDisplacement;
|
||||
const double maximum=std::max(transitionUpper->bedrock.topMicrometres,
|
||||
transitionLower->ceiling.topMicrometres)+maximumDisplacement;
|
||||
if(zMicrometres>=minimum&&zMicrometres<maximum)
|
||||
{
|
||||
#if defined(VF_L30_ENABLE_COST_COUNTERS)
|
||||
++ThreadClassificationStats().TransitionWindowHits;
|
||||
++ThreadClassificationStats().TransitionEvaluatorCalls;
|
||||
#endif
|
||||
const auto* tileQueries=ActivePassageTileQueries;
|
||||
const bool skipPassageFade=tileQueries&&tileQueries->matches(*this)
|
||||
&&!tileQueries->mayContainTransitionPassageFade();
|
||||
#if defined(VF_L30_ENABLE_COST_COUNTERS)
|
||||
if(skipPassageFade)
|
||||
++ThreadClassificationStats().TransitionPassageTileSkips;
|
||||
#endif
|
||||
const auto xMicrometres=static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(X)*Owner->CoreVoxelSizeMicrons));
|
||||
const auto yMicrometres=static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(Y)*Owner->CoreVoxelSizeMicrons));
|
||||
const auto bands=ResolvedTransitionBandsAtXY(*transitionUpper,
|
||||
*transitionLower,xMicrometres,yMicrometres,skipPassageFade);
|
||||
const std::int64_t solidBottom=std::min(
|
||||
bands.upperBedrockBottomMicrometres,bands.lowerCeilingBottomMicrometres);
|
||||
const std::int64_t solidTop=std::max(
|
||||
bands.upperBedrockTopMicrometres,bands.lowerCeilingTopMicrometres);
|
||||
const double signedDistanceMicrometres=zMicrometres<solidBottom
|
||||
?static_cast<double>(solidBottom-zMicrometres)
|
||||
:zMicrometres>solidTop
|
||||
?static_cast<double>(zMicrometres-solidTop)
|
||||
:-static_cast<double>(std::min(zMicrometres-solidBottom,
|
||||
solidTop-zMicrometres));
|
||||
const std::int64_t seam=transitionUpper->bedrock.bottomMicrometres;
|
||||
const bool floatingIslandAirGap=
|
||||
transitionUpper->generatorKind=="FloatingIslands"
|
||||
&&transitionUpper->transitionMode=="Gradient"
|
||||
&&bands.upperBedrockTopMicrometres<seam
|
||||
&&zMicrometres>=bands.upperBedrockTopMicrometres
|
||||
&&zMicrometres<seam;
|
||||
if(!(signedDistanceMicrometres>0.0&&density<0.0f
|
||||
&&!floatingIslandAirGap))
|
||||
return static_cast<float>(signedDistanceMicrometres
|
||||
/Owner->CoreVoxelSizeMicrons);
|
||||
}
|
||||
}
|
||||
}
|
||||
const double worldZCentimetres=static_cast<double>(Z)*GetCoreVoxelSizeCm();
|
||||
const int32 strateIndex=Owner->Manager->GetStrateIndex(static_cast<float>(worldZCentimetres));
|
||||
const auto* stratum=FindResolvedLayoutStratum(strateIndex);
|
||||
if(!stratum)return density;
|
||||
const double zMicrometres=static_cast<double>(Z)*Owner->CoreVoxelSizeMicrons;
|
||||
const auto solidAt=[&](const VoxelForgeCore::ResolvedLayoutBandV2& band)
|
||||
{return band.presentInCurrentField&&zMicrometres>=band.bottomMicrometres
|
||||
&&zMicrometres<band.topMicrometres;};
|
||||
@@ -502,77 +626,46 @@ public:
|
||||
#endif
|
||||
if(upper==stratum)bBedrockHandledByTransition=true;
|
||||
if(lower==stratum)bCeilingHandledByTransition=true;
|
||||
const auto* tileQueries=ActivePassageTileQueries;
|
||||
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;
|
||||
constexpr std::int64_t TransitionQ16=1ll<<16;
|
||||
const auto* tileQueries=ActivePassageTileQueries;
|
||||
const bool skipPassageFade=tileQueries&&tileQueries->matches(*this)
|
||||
&&!tileQueries->mayContainTransitionPassageFade();
|
||||
const std::int64_t transitionWeight=skipPassageFade?TransitionQ16
|
||||
:ResolvedTransitionPassageWeightQ16(*upper,*lower,xMicrometres,yMicrometres);
|
||||
#if defined(VF_L30_ENABLE_COST_COUNTERS)
|
||||
if(skipPassageFade)++ThreadClassificationStats().TransitionPassageTileSkips;
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
// FloatingIslands can retain native solid density above a negatively
|
||||
// displaced Gradient face, creating a second surface instead of the
|
||||
// resolved transition top. Keep that air-side gap open in the owner field.
|
||||
const std::int64_t seam=upper->bedrock.bottomMicrometres;
|
||||
if(upper->generatorKind=="FloatingIslands"
|
||||
&&upper->transitionMode=="Gradient"
|
||||
&&resolvedBands.upperBedrockTopMicrometres<seam
|
||||
&&zMicrometres>=resolvedBands.upperBedrockTopMicrometres
|
||||
&&zMicrometres<seam)
|
||||
{
|
||||
const double distanceVoxels=static_cast<double>(zMicrometres
|
||||
-resolvedBands.upperBedrockTopMicrometres)
|
||||
/std::max<std::uint32_t>(1,Owner->CoreVoxelSizeMicrons);
|
||||
density=std::max(0.05f,static_cast<float>(distanceVoxels));
|
||||
return true;
|
||||
}
|
||||
const auto resolvedBands=ResolvedTransitionBandsAtXY(*upper,*lower,
|
||||
xMicrometres,yMicrometres,skipPassageFade);
|
||||
// Treat the two authored bands as one continuous solid interval. Its
|
||||
// exterior faces remain the lower ceiling bottom and upper bedrock top;
|
||||
// measuring signed distance from those faces also clears native generator
|
||||
// density on both air sides of the displaced interface.
|
||||
const std::int64_t solidBottom=std::min(
|
||||
resolvedBands.upperBedrockBottomMicrometres,
|
||||
resolvedBands.lowerCeilingBottomMicrometres);
|
||||
const std::int64_t solidTop=std::max(
|
||||
resolvedBands.upperBedrockTopMicrometres,
|
||||
resolvedBands.lowerCeilingTopMicrometres);
|
||||
const double signedDistanceMicrometres=zMicrometres<solidBottom
|
||||
?static_cast<double>(solidBottom-zMicrometres)
|
||||
:zMicrometres>solidTop
|
||||
?static_cast<double>(zMicrometres-solidTop)
|
||||
:-static_cast<double>(std::min(zMicrometres-solidBottom,
|
||||
solidTop-zMicrometres));
|
||||
const std::int64_t seam=upper->bedrock.bottomMicrometres;
|
||||
const bool floatingIslandAirGap=upper->generatorKind=="FloatingIslands"
|
||||
&&upper->transitionMode=="Gradient"
|
||||
&&resolvedBands.upperBedrockTopMicrometres<seam
|
||||
&&zMicrometres>=resolvedBands.upperBedrockTopMicrometres
|
||||
&&zMicrometres<seam;
|
||||
// A native solid may continue beyond either authored face. Keep that
|
||||
// connected rock; the FI gap is the explicit exception that must stay open.
|
||||
if(signedDistanceMicrometres>0.0&&density<0.0f&&!floatingIslandAirGap)
|
||||
return false;
|
||||
}
|
||||
const auto& band=upperBedrock?upper->bedrock:lower->ceiling;
|
||||
if(upperBedrock&&upper->generatorKind=="FloatingIslands"
|
||||
&&upper->transitionMode=="Gradient")
|
||||
{
|
||||
const double distanceVoxels=static_cast<double>(
|
||||
resolvedBands.upperBedrockTopMicrometres-zMicrometres)
|
||||
/std::max<std::uint32_t>(1,Owner->CoreVoxelSizeMicrons);
|
||||
density=-std::max(0.05f,static_cast<float>(distanceVoxels));
|
||||
}
|
||||
else density=-std::max(0.05f,static_cast<float>(band.solidDensityQ16)/65536.0f);
|
||||
density=static_cast<float>(signedDistanceMicrometres
|
||||
/std::max<std::uint32_t>(1,Owner->CoreVoxelSizeMicrons));
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user