wip(assembler): round L35 -- smooth passage walls without regular ribs (evaluator v21)

The shared passage carve took the minimum of piecewise-linear capsules (scallops at joins) and added
wall relief on regular 8 m / 4 m octaves, which read as evenly spaced ribs. Interior sweep joins are
now Catmull-Rom smoothed and the relief uses irregular rotated 43/29/19 m scales; the natural wobble
remains. New axial ripple audit (0.125 m radius samples, 0.5-8 m periods): beaded control and L34
geometry fail, all 24 passage rows pass. FI mouth tread apron tapered. 30/30 determinism, 16/16
invariants, ring audits LOD0-8 pass; cost within noise.

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-22 07:28:50 +02:00
1 parent 49e29fcd36
commit ba017077d1
28 files changed
+1727 -17

No files matched your search

+91 -13
View File
@@ -911,7 +911,34 @@ public:
DeterministicSqrt(playerDx*playerDx+playerDy*playerDy
+playerVertical*playerVertical)-0.34*qPerMetre);
}
const double cx=ax+t*dx,cy=ay+t*dy,cz=az+t*dz;
double cx=ax+t*dx,cy=ay+t*dy,cz=az+t*dz;
const bool smoothCarveJoin=index>2&&index+12<lastIndex
&&DeterministicSqrt(lengthSq)<=8.0*qPerMetre
&&!IsPassageShortSpanSegment(passageIndex,segmentIndex-1)
&&!IsPassageShortSpanSegment(passageIndex,segmentIndex)
&&!IsPassageShortSpanSegment(passageIndex,segmentIndex+1);
if(smoothCarveJoin)
{
const auto& p0=passage.controlPoints[static_cast<std::size_t>(index-1)];
const auto& p3=passage.controlPoints[static_cast<std::size_t>(index+2)];
constexpr double SmoothJoinWeight=1.0;
const double t2=t*t,t3=t2*t;
for(std::size_t axis=0;axis<3;++axis)
{
const double v0=static_cast<double>(p0.positionSubvoxels[axis]);
const double v1=static_cast<double>(a.positionSubvoxels[axis]);
const double v2=static_cast<double>(b.positionSubvoxels[axis]);
const double v3=static_cast<double>(p3.positionSubvoxels[axis]);
const double curve=0.5*((2.0*v1)+(-v0+v2)*t
+(2.0*v0-5.0*v1+4.0*v2-v3)*t2
+(-v0+3.0*v1-3.0*v2+v3)*t3);
const double line=axis==0?cx:axis==1?cy:cz;
const double blended=line+(curve-line)*SmoothJoinWeight;
if(axis==0)cx=blended;
else if(axis==1)cy=blended;
else cz=blended;
}
}
const double ex=qx-cx,ey=qy-cy,ez=qz-cz;
const double radius=static_cast<double>(a.radiusSubvoxels)
+t*(b.radiusSubvoxels-a.radiusSubvoxels);
@@ -963,11 +990,11 @@ public:
?std::clamp(-(qz-(nearestA.positionSubvoxels[2]+bestT*(
static_cast<double>(nearestB.positionSubvoxels[2])-nearestA.positionSubvoxels[2])))
/distanceToCenter,0.0,1.0):0.0;
const float relief=VF_FieldSurfaceRelief(static_cast<float>(X),static_cast<float>(Y),
const float relief=VF_FieldPassageWallRelief(static_cast<float>(X),static_cast<float>(Y),
static_cast<float>(Z),static_cast<std::uint32_t>(Owner?Owner->Seed:0));
const double wallReliefWeight=1.0-0.80*verticalWallAlignment;
const double roughSignedDistance=bestSignedDistance
+static_cast<double>(std::clamp(relief,-1.0f,1.0f))*0.24*qPerMetre*wallReliefWeight;
+static_cast<double>(std::clamp(relief,-1.0f,1.0f))*0.21*qPerMetre*wallReliefWeight;
if(IsPassageShortSpanSegment(passageIndex,static_cast<std::size_t>(bestIndex)))
{
const double bridgeDistance=PassageBridgeSignedDistance(passageIndex,
@@ -986,6 +1013,7 @@ public:
const double dy=static_cast<double>(segmentB.positionSubvoxels[1])-segmentA.positionSubvoxels[1];
const double radiusA=segmentA.radiusSubvoxels;
const double radiusB=segmentB.radiusSubvoxels;
const bool entryMouthShoulder=index<=2;
// Keep the tread within the probe band and below the capsule's
// lowest sampled point.
const double floorOffset=IsPassageShortSpanSegment(passageIndex,
@@ -1000,10 +1028,33 @@ public:
:bestT;
const double centerX=segmentA.positionSubvoxels[0]+supportT*dx;
const double centerY=segmentA.positionSubvoxels[1]+supportT*dy;
const double centerZ=segmentA.positionSubvoxels[2]+supportT*(
double centerZ=segmentA.positionSubvoxels[2]+supportT*(
static_cast<double>(segmentB.positionSubvoxels[2])-segmentA.positionSubvoxels[2]);
const double radius=segmentA.radiusSubvoxels+supportT*(
double radius=segmentA.radiusSubvoxels+supportT*(
static_cast<double>(segmentB.radiusSubvoxels)-segmentA.radiusSubvoxels);
const bool smoothSupportJoin=index>0&&index+12<lastIndex
&&!IsPassageShortSpanSegment(passageIndex,static_cast<std::size_t>(index-1))
&&!IsPassageShortSpanSegment(passageIndex,static_cast<std::size_t>(index))
&&!IsPassageShortSpanSegment(passageIndex,static_cast<std::size_t>(index+1));
if(smoothSupportJoin)
{
const auto& p0=passage.controlPoints[static_cast<std::size_t>(index-1)];
const auto& p3=passage.controlPoints[static_cast<std::size_t>(index+2)];
const double t2=supportT*supportT,t3=t2*supportT;
const auto interpolate=[&](double v0,double v1,double v2,double v3)
{
return 0.5*((2.0*v1)+(-v0+v2)*supportT
+(2.0*v0-5.0*v1+4.0*v2-v3)*t2
+(-v0+3.0*v1-3.0*v2+v3)*t3);
};
constexpr double SmoothSupportHeightWeight=0.25;
centerZ+=(interpolate(p0.positionSubvoxels[2],segmentA.positionSubvoxels[2],
segmentB.positionSubvoxels[2],p3.positionSubvoxels[2])-centerZ)
*SmoothSupportHeightWeight;
radius+=(interpolate(p0.radiusSubvoxels,segmentA.radiusSubvoxels,
segmentB.radiusSubvoxels,p3.radiusSubvoxels)-radius)
*SmoothSupportHeightWeight;
}
const double horizontalX=qx-centerX,horizontalY=qy-centerY;
const double horizontalDistance=DeterministicSqrt(horizontalX*horizontalX
+horizontalY*horizontalY);
@@ -1016,16 +1067,42 @@ public:
const bool fallbackSupport=qz>=supportPlayerCenterZ-1.50*qPerMetre;
const double supportThicknessVoxels=fallbackSupport
?qPerMetre/Q:0.5*qPerMetre/Q;
const double floorQ=centerZ-radius+floorOffset*qPerMetre;
const double floorVoxels=floorQ/Q;
// Keep the supported ramp to a comfortable walking width. Extending a
// full bore-radius shelf across overlapping helix coils can block the
// capsule on the neighbouring turn.
const bool lowerMouthBodyOverlap=index>=lowerMouthIndex-2
&&supportQueryDepth<0.98*qPerMetre;
const double supportEdgeNoise=entryMouthShoulder?std::clamp(
static_cast<double>(VF_FieldPassageGroundGrain(static_cast<float>(X),
static_cast<float>(Y),
static_cast<std::uint32_t>(Owner?Owner->Seed:0))),-1.0,1.0):0.0;
const double supportHalfWidthMetres=lowerMouthBodyOverlap?0.90
:entryMouthShoulder?1.20+0.20*supportEdgeNoise:1.25;
const double supportHalfWidth=std::min(radius,
(lowerMouthBodyOverlap?0.90:1.25)*qPerMetre);
if(Z<floorVoxels-supportThicknessVoxels||Z>floorVoxels+1.0/Q)return;
supportHalfWidthMetres*qPerMetre);
// Keep the walk core within a 0.50 m span with shallow relief, then
// taper the outer shoulder; capsule and probe widths remain supported.
const double supportEdgeCoreMetres=entryMouthShoulder?0.60:0.90;
const double supportEdgeBlendMetres=std::min(
entryMouthShoulder?0.85:0.35,
std::max(0.0,supportHalfWidth/qPerMetre-supportEdgeCoreMetres));
const double supportEdgeT=supportEdgeBlendMetres>1.0e-6
?std::clamp((horizontalDistance
-(supportHalfWidth-supportEdgeBlendMetres*qPerMetre))
/(supportEdgeBlendMetres*qPerMetre),0.0,1.0):0.0;
const double supportEdgeSmooth=supportEdgeT*supportEdgeT
*(3.0-2.0*supportEdgeT);
const double localSupportThicknessVoxels=entryMouthShoulder
?supportThicknessVoxels*(1.0-0.72*supportEdgeSmooth)
:supportThicknessVoxels;
const double supportEdgeDepth=entryMouthShoulder
?0.35+0.15*supportEdgeNoise:0.35;
const double floorQ=centerZ-radius+floorOffset*qPerMetre
+supportEdgeNoise*(horizontalDistance>0.60*qPerMetre
?0.35:0.14)*qPerMetre
-supportEdgeSmooth*supportEdgeDepth*qPerMetre;
const double floorVoxels=floorQ/Q;
if(Z<floorVoxels-localSupportThicknessVoxels||Z>floorVoxels+1.0/Q)return;
if(horizontalDistance>supportHalfWidth)return;
const double supportDistanceSq=horizontalDistance*horizontalDistance
+(Z-floorVoxels)*(Z-floorVoxels);
@@ -1034,7 +1111,7 @@ public:
hasSupportFloor=true;
bestSupportSegmentIndex=index;
bestSupportDensity=std::clamp(Z-floorVoxels,
-supportThicknessVoxels,0.0);
-localSupportThicknessVoxels,0.0);
};
std::ptrdiff_t supportCenterIndex=bestIndex;
if(bestIndex<lowerMouthIndex)
@@ -4541,9 +4618,10 @@ private:
const float StrataRelief=1.35f*(Relief+0.5f*OwnerRelief);
const float CaveRelief=1.00f*Relief;
const float FloorRelief=0.55f*Relief;
// Passage walls keep the broad coherent relief bands but omit the shortest
// octave, which makes repeated rings on the authored shafts.
const float PassageRelief=0.75f*PassageBandRelief;
// The shared passage sweep supplies its own irregular relief. Keep only a
// small trace of the terrain value-noise bands so their cell edges cannot
// dominate the passage wall and read as repeated rings.
const float PassageRelief=0.10f*PassageBandRelief;
return StrataWeight*StrataRelief+CaveWeight*CaveRelief
+FloorWeight*FloorRelief+Passage*PassageRelief;
}