wip(L25, side branch): FI helix enclosed in a 13 m rock root; support never created in open air
Fixes the L24 ribbon (owner request). NOT merged: the open-air support gate leaves ~4,000 unsupported samples on every SurfaceWorld-recipe passage style (TN -> SW), a walkability regression. L26 fixes that on this branch. See Linux25/REPORT.md. 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
cb9236c265
commit
ef789aaa00
14 files changed
+662
-110
No files matched your search
@@ -550,6 +550,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
const auto routeAnchor=[](const ResolvedLayoutStratumV2& s,bool departure,
|
||||
std::array<std::int64_t,3>& out)
|
||||
{
|
||||
if(departure)
|
||||
for(const auto& a:s.anchors)
|
||||
if(a.kind=="passage_anchor"&&a.values.size()>=10)
|
||||
{out={a.values[7],a.values[8],a.values[9]};return true;}
|
||||
if(!departure)
|
||||
for(const auto& a:s.anchors)
|
||||
if(a.kind=="passage_arrival"&&a.values.size()>=3)
|
||||
{out={a.values[0],a.values[1],a.values[2]};return true;}
|
||||
const ResolvedLayoutAnchorV2* selected=nullptr;
|
||||
for(const auto& a:s.anchors)
|
||||
if(a.kind=="route_point"&&a.values.size()>=3)
|
||||
@@ -597,8 +605,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
// Leave room for the capsule and bounded wall relief at the floor/wall seam.
|
||||
const std::int64_t mouthRadius=std::max<std::int64_t>(static_cast<std::int64_t>(std::llround(1.5*qPerMetre)),
|
||||
cfg?cfg->mouthRadiusSubvoxels:0);
|
||||
const std::int64_t midRadius=std::max<std::int64_t>(mouthRadius,
|
||||
cfg?cfg->midRadiusSubvoxels:0);
|
||||
const std::int64_t midRadius=std::max<std::int64_t>(
|
||||
static_cast<std::int64_t>(std::llround(1.5*qPerMetre)),
|
||||
cfg?cfg->midRadiusSubvoxels:mouthRadius);
|
||||
const std::int64_t reachMinimum=cfg?std::max<std::int64_t>(0,cfg->reachMinimumSubvoxels):8*qPerMetre;
|
||||
const std::int64_t reachMaximum=cfg?std::max<std::int64_t>(reachMinimum,cfg->reachMaximumSubvoxels):24*qPerMetre;
|
||||
const std::uint32_t style=cfg?std::min<std::uint32_t>(cfg->style,3u):1u;
|
||||
@@ -624,7 +633,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
for(const auto& anchor:upper.anchors)
|
||||
if(anchor.kind=="passage_anchor"&&anchor.values.size()>=7)
|
||||
{passageAnchor=&anchor;break;}
|
||||
const bool anchoredSpiral=style==2&&passageAnchor!=nullptr;
|
||||
const bool anchoredIslandPassage=passageAnchor!=nullptr
|
||||
&&upper.generatorKind=="FloatingIslands";
|
||||
const bool anchoredSpiral=style==2&&anchoredIslandPassage;
|
||||
if(!hasUpperRoute||!hasLowerRoute)
|
||||
{
|
||||
const auto xy=PassageRandomXY(PassageSeed(seed,upper.strateIndex,lower.strateIndex,
|
||||
@@ -652,7 +663,10 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
std::array<std::int64_t,2> upperTangent{},lowerTangent{};
|
||||
const bool hasUpperTangent=hasUpperRoute
|
||||
&&routeTangent(upper,true,upperTangent);
|
||||
const bool hasLowerTangent=hasLowerRoute
|
||||
const bool hasPassageArrival=std::any_of(lower.anchors.begin(),lower.anchors.end(),
|
||||
[](const auto& anchor){return anchor.kind=="passage_arrival"
|
||||
&&anchor.values.size()>=3;});
|
||||
const bool hasLowerTangent=hasLowerRoute&&!hasPassageArrival
|
||||
&&routeTangent(lower,false,lowerTangent);
|
||||
|
||||
const std::int64_t outerRingRadius=std::max<std::int64_t>(1,
|
||||
@@ -671,6 +685,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
std::max<std::int64_t>(0,cfg?cfg->cascadeLedgeSubvoxels:0)
|
||||
*static_cast<std::int64_t>(cfg?cfg->cascadeSteps:4)),
|
||||
mouthRadius+2*qPerMetre,outerRingRadius);
|
||||
if(anchoredIslandPassage)
|
||||
ringRadius=std::min(ringRadius,mouthRadius+qPerMetre/2);
|
||||
std::uint32_t phase=static_cast<std::uint32_t>(PassageSeed(seed,
|
||||
upper.strateIndex,lower.strateIndex,connection,0x50484153u)%16);
|
||||
if(hasUpperRoute)
|
||||
@@ -700,7 +716,7 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
+clockwiseTangentY*upperTangent[1]>=0.0;
|
||||
}
|
||||
const int direction=clockwise?1:-1;
|
||||
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree contract.
|
||||
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree helix contract.
|
||||
const std::int64_t wormRadialWobble=std::min<std::int64_t>(
|
||||
std::max<std::int64_t>(0,wander/3),2*qPerMetre);
|
||||
const std::int64_t wormCenterWobble=std::min<std::int64_t>(
|
||||
@@ -716,10 +732,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
const double loop=static_cast<double>(loopIndex);
|
||||
const double phaseA=loop*0.6180339887498948+0.37;
|
||||
const double phaseB=loop*0.4142135623730950+1.11;
|
||||
const double jitterX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
|
||||
const double jitterY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
|
||||
radius+=static_cast<double>(wormRadialWobble)
|
||||
*std::sin(angle+phaseA);
|
||||
centerX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
|
||||
centerY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
|
||||
centerX=jitterX+(anchoredIslandPassage&&passageAnchor
|
||||
?static_cast<double>(passageAnchor->values[0]):0.0);
|
||||
centerY=jitterY+(anchoredIslandPassage&&passageAnchor
|
||||
?static_cast<double>(passageAnchor->values[1]):0.0);
|
||||
}
|
||||
else if(pathStyle==3u)
|
||||
{
|
||||
@@ -730,6 +750,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
cfg->cascadeLedgeSubvoxels):0));
|
||||
radius-=ledge*(0.5-0.5*std::cos(angle*steps));
|
||||
}
|
||||
if(pathStyle!=1u&&anchoredIslandPassage&&passageAnchor)
|
||||
{
|
||||
centerX=static_cast<double>(passageAnchor->values[0]);
|
||||
centerY=static_cast<double>(passageAnchor->values[1]);
|
||||
}
|
||||
return std::array<std::int64_t,2>{
|
||||
static_cast<std::int64_t>(std::llround(centerX+radius*directions[directionIndex][0]/65536.0)),
|
||||
static_cast<std::int64_t>(std::llround(centerY+radius*directions[directionIndex][1]/65536.0))};
|
||||
@@ -748,7 +773,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
const std::int64_t anchorY=passageAnchor->values[1];
|
||||
const std::int64_t rootRadius=passageAnchor->values[2];
|
||||
const std::int64_t rootBottom=passageAnchor->values[5];
|
||||
helixBedrockZ=rootBottom!=0?rootBottom:contentZQ(upper.bedrock.topMicrometres);
|
||||
const std::int64_t bedrockTop=rootBottom!=0?rootBottom
|
||||
:contentZQ(upper.bedrock.topMicrometres);
|
||||
// Passage route heights are player-center positions. End one capsule
|
||||
// half-height above the bedrock top so the final ramp step is walkable.
|
||||
helixBedrockZ=bedrockTop+qPerMetre;
|
||||
const std::int64_t helixRadius=spiralRadius;
|
||||
if(rootRadius<helixRadius+midRadius+qPerMetre/4
|
||||
||std::hypot(static_cast<double>(upperMouth[0]-anchorX),
|
||||
@@ -796,6 +825,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
helixEndIndex=xy.size()-1;
|
||||
hasAnchorHelix=helixEndIndex>0;
|
||||
}
|
||||
const std::int64_t routeGradeQ16=hasAnchorHelix
|
||||
&&lower.generatorKind=="SurfaceWorld"?8000:TargetGradeQ16;
|
||||
const std::array<std::int64_t,2> firstRing=ringPoint(phase);
|
||||
if(hasAnchorHelix&&pathStyle==1u)
|
||||
{
|
||||
@@ -843,12 +874,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
const std::size_t start=hasAnchorHelix?helixEndIndex:0;
|
||||
for(std::size_t i=start+1;i<xy.size();++i)
|
||||
total+=distanceQ(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1]);
|
||||
if(!hasLowerTangent&&!xy.empty())
|
||||
total+=distanceQ(lowerMouth[0]-xy.back()[0],lowerMouth[1]-xy.back()[1]);
|
||||
return total;
|
||||
};
|
||||
while(loops<256)
|
||||
{
|
||||
totalHorizontal=measurePath();
|
||||
if(totalHorizontal*static_cast<std::uint64_t>(TargetGradeQ16)
|
||||
if(totalHorizontal*static_cast<std::uint64_t>(routeGradeQ16)
|
||||
>=static_cast<std::uint64_t>(verticalDistance)*65536ull)break;
|
||||
for(int step=1;step<=16;++step)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user