passages: rounded half-pipe crest (L113, v220); floor bands diagnosed, speed not recovered

Open-air walls: 0.75 m rounded shell, relief fades over the top 0.25 m - the needle spikes are
gone. Every owner plan passes the 15 deg forward-grade check (max ~10.7 deg) and all walk audits.
Floor bands: median 1.25 m interval, ~0.21 m drop on a ~10.4 deg floor = one 0.25 m voxel row
projected along the grade (not control points, not slab thickness) - not yet fixed. Exact
segment-to-tile filter did not reduce candidates; removed. Timings this round are unreliable
(a gitea process used ~43% CPU throughout). Fast tier PASS; Clang/GCC deterministic; UE builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-29 21:57:13 +01:00
1 parent 16554cd426
commit 36d954cf2f
114 files changed
+7814 -63

No files matched your search

+82 -29
View File
@@ -1365,8 +1365,6 @@ public:
const double wallElevationMetres=(qz-(floorCenterZ-floorDepth))
/qPerMetre;
const double mouthWallThickness=segment.routeSegment
&&wallElevationMetres>=0.0
&&wallElevationMetres<=OpenAirSideWallHeightMetres
?smoothShellFade*shellThickness:0.0;
double floorExtensionFade=1.0;
if(!segment.routeSegment)
@@ -1380,10 +1378,13 @@ public:
}
const double floorShellThickness=smoothFloorBlend*shellThickness
*floorExtensionFade*smoothShellFade;
const double localThickness=std::max(mouthWallThickness,
floorShellThickness);
const double localShellDistance=std::max(-static_cast<double>(flatDistance),
static_cast<double>(flatDistance)-localThickness);
const double wallShellDistance=PassageRoundedWallShellDistance(
flatDistance,wallElevationMetres*qPerMetre,
OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness);
const double floorShellDistance=std::max(-static_cast<double>(flatDistance),
static_cast<double>(flatDistance)-floorShellThickness);
const double localShellDistance=std::min(wallShellDistance,
floorShellDistance);
nearest.shellSignedDistance=std::min(nearest.shellSignedDistance,
localShellDistance);
};
@@ -1391,11 +1392,17 @@ public:
qx,qy,qz,0,shellSearchBound,visitShellSegment);
}
if(!nearest.valid)continue;
const double wallElevationMetres=(qz-(nearest.floorCenterZ
-nearest.floorDepth))/qPerMetre;
double distanceToCenter=std::max(1.0e-9,
nearest.roundSignedDistance+nearest.radius);
const double verticalWallAlignment=distanceToCenter>1.0e-9
?std::clamp(-(qz-nearest.centerZ)/distanceToCenter,0.0,1.0):0.0;
const double wallReliefWeight=0.05+0.95*(1.0-verticalWallAlignment);
const double crestFade=std::clamp((OpenAirSideWallHeightMetres
-wallElevationMetres)/0.25,0.0,1.0);
const double smoothCrestFade=crestFade*crestFade*(3.0-2.0*crestFade);
const double wallReliefWeight=(0.05+0.95*(1.0-verticalWallAlignment))
*smoothCrestFade;
float relief=0.0f;
if(nearest.swept)
{
@@ -1427,11 +1434,7 @@ public:
const double floorBlend=std::clamp(floorDistanceMetres/0.25,0.0,1.0);
const double smoothFloorBlend=floorBlend*floorBlend
*(3.0-2.0*floorBlend);
const double wallElevationMetres=(qz-(nearest.floorCenterZ-nearest.floorDepth))
/qPerMetre;
const double mouthWallThickness=segment.routeSegment
&&wallElevationMetres>=0.0
&&wallElevationMetres<=OpenAirSideWallHeightMetres
?smoothShellFade*shellThickness:0.0;
double floorExtensionFade=1.0;
if(!segment.routeSegment)
@@ -1445,11 +1448,14 @@ public:
}
const double floorShellThickness=smoothFloorBlend*shellThickness
*floorExtensionFade*smoothShellFade;
const double localShellThickness=std::max(mouthWallThickness,
floorShellThickness);
const double wallShellDistance=PassageRoundedWallShellDistance(
shapedDistance,wallElevationMetres*qPerMetre,
OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness);
const double floorShellDistance=std::max(-static_cast<double>(shapedDistance),
static_cast<double>(shapedDistance)-floorShellThickness);
unionDistance=std::min(unionDistance,static_cast<double>(shapedDistance));
const double localShellDistance=std::max(-static_cast<double>(shapedDistance),
static_cast<double>(shapedDistance)-localShellThickness);
const double localShellDistance=std::min(wallShellDistance,
floorShellDistance);
unionShellDistance=std::min(unionShellDistance,
std::min(localShellDistance,nearest.shellSignedDistance));
}
@@ -3436,6 +3442,25 @@ private:
return SmoothMaxDistance(roundDistanceSubvoxels,floorDistance,
static_cast<float>(CornerBlendMetres*qPerMetre));
}
static double PassageRoundedWallShellDistance(double flatDistanceSubvoxels,
double wallElevationSubvoxels,double wallHeightSubvoxels,
double wallThicknessSubvoxels)
{
if(!(wallThicknessSubvoxels>1.0e-9)||!(wallHeightSubvoxels>0.0))
return std::numeric_limits<double>::infinity();
const double radius=wallThicknessSubvoxels*0.5;
const double capCenter=wallHeightSubvoxels-radius;
if(!(capCenter>0.0))return std::numeric_limits<double>::infinity();
const double x=flatDistanceSubvoxels-radius;
const double boxHalfHeight=capCenter*0.5;
const double boxX=std::abs(x)-radius;
const double boxY=std::abs(wallElevationSubvoxels-boxHalfHeight)
-boxHalfHeight;
const double boxDistance=std::min(std::max(boxX,boxY),0.0)
+std::hypot(std::max(boxX,0.0),std::max(boxY,0.0));
const double capDistance=std::hypot(x,wallElevationSubvoxels-capCenter)-radius;
return std::min(boxDistance,capDistance);
}
struct FPassageNearestNode
{
std::array<double,3> minimum{},maximum{};
@@ -4499,7 +4524,7 @@ private:
if(!ResolvedLayout)
{
if(tracePreparation)
std::printf("[L112PassagePrepare] passages=0 control_spans=0 segments=0 spacing_m=1.00 bytes=0 prepare_ms=%.3f\n",
std::printf("[L113PassagePrepare] passages=0 control_spans=0 segments=0 max_spacing_m=8.00 max_chord_error_m=0.025 bytes=0 prepare_ms=%.3f\n",
std::chrono::duration<double,std::milli>(
std::chrono::steady_clock::now()-preparationStart).count());
return;
@@ -4510,7 +4535,8 @@ private:
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
const double qPerMetre=Q*1000000.0/
std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
constexpr double PassageSegmentSpacingMetres=1.0;
constexpr double PassageSegmentSpacingMetres=8.0;
constexpr double PassageSegmentChordErrorMetres=0.025;
std::size_t preparedSegments=0,controlSpans=0;
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
++passageIndex)
@@ -4569,7 +4595,29 @@ private:
upperMouthFloorDepth*qPerMetre);
const auto sampledSegments=VoxelForgeCore::PassageSpline::BuildSegments(
controls,controls.size()-1,PassageSegmentSpacingMetres,qPerMetre,
plannedFloorProfile);
plannedFloorProfile,PassageSegmentChordErrorMetres);
constexpr double MaximumFloorGradeDegrees=15.0;
constexpr double DegreesPerRadian=180.0/3.14159265358979323846;
double maximumFloorGradeDegrees=0.0;
std::size_t floorGradeSamples=0,floorGradeViolations=0;
for(const auto& segment:sampledSegments)
{
if(segment.controlSpan>=routeEnd)continue;
const double dx=(segment.b[0]-segment.a[0])/qPerMetre;
const double dy=(segment.b[1]-segment.a[1])/qPerMetre;
const double dz=(segment.plannedFloorB-segment.plannedFloorA)/qPerMetre;
const double horizontal=std::hypot(dx,dy);
const double grade=horizontal>1.0e-9
?std::atan2(std::abs(dz),horizontal)*DegreesPerRadian
:(std::abs(dz)>1.0e-9?90.0:0.0);
maximumFloorGradeDegrees=std::max(maximumFloorGradeDegrees,grade);
++floorGradeSamples;
if(grade>MaximumFloorGradeDegrees+1.0e-8)++floorGradeViolations;
}
std::printf("[PassagePlanGradeAudit] id=%s samples=%zu max_grade_deg=%.6f limit_deg=%.3f violations=%zu status=%s\n",
passage.stableId.c_str(),floorGradeSamples,maximumFloorGradeDegrees,
MaximumFloorGradeDegrees,floorGradeViolations,
floorGradeViolations==0?"PASS":"FAIL");
constants.upperMouthX=controls.front()[0];
constants.upperMouthY=controls.front()[1];
constants.upperMouthPlannedFloor=plannedFloorProfile.front();
@@ -4663,9 +4711,10 @@ private:
PassageSegmentOffsets[passageIndex+1]=preparedSegments;
}
if(tracePreparation)
std::printf("[L112PassagePrepare] passages=%zu control_spans=%zu segments=%zu spacing_m=%.2f bytes=%zu prepare_ms=%.3f\n",
std::printf("[L113PassagePrepare] passages=%zu control_spans=%zu segments=%zu max_spacing_m=%.2f max_chord_error_m=%.3f bytes=%zu prepare_ms=%.3f\n",
PassageSegmentData.size(),controlSpans,preparedSegments,
PassageSegmentSpacingMetres,preparedSegments*sizeof(FPassageSegmentData),
PassageSegmentSpacingMetres,PassageSegmentChordErrorMetres,
preparedSegments*sizeof(FPassageSegmentData),
std::chrono::duration<double,std::milli>(
std::chrono::steady_clock::now()-preparationStart).count());
}
@@ -4688,6 +4737,7 @@ private:
constexpr double PassageShellMetres=0.75;
constexpr double ReliefMetres=0.21;
constexpr double SweepReachMetres=4.0;
constexpr double CornerBlendMetres=0.50;
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
++passageIndex)
{
@@ -4707,9 +4757,10 @@ private:
routeMinimum[axis]=std::min(prepared.a[axis],prepared.b[axis])/Q;
routeMaximum[axis]=std::max(prepared.a[axis],prepared.b[axis])/Q;
}
const double routeExtent=maximumRadius+PassageShellMetres
+ReliefMetres+0.01;
const double tileExtent=routeExtent+SweepReachMetres;
const double requiredReach=std::max(SweepReachMetres+ReliefMetres
+CornerBlendMetres*0.25,PassageShellMetres+ReliefMetres);
const double routeExtent=maximumRadius+requiredReach+0.01;
const double tileExtent=routeExtent;
FPassageProofBound proof;
for(std::size_t axis=0;axis<3;++axis)
{
@@ -11414,8 +11465,6 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
const double wallElevationMetres=(qz-(floorCenterZ-floorDepth))
/qPerMetre;
const double mouthWallThickness=segment.routeSegment
&&wallElevationMetres>=0.0
&&wallElevationMetres<=OpenAirSideWallHeightMetres
?smoothShellFade*shellThickness:0.0;
double floorExtensionFade=1.0;
if(!segment.routeSegment)
@@ -11429,10 +11478,14 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
}
const double floorShellThickness=smoothFloorBlend*shellThickness
*floorExtensionFade*smoothShellFade;
const double localThickness=std::max(mouthWallThickness,
floorShellThickness);
const double localShellDistance=std::max(-static_cast<double>(flatDistance),
static_cast<double>(flatDistance)-localThickness);
const double wallShellDistance=
FStandaloneShapeWorld::PassageRoundedWallShellDistance(
flatDistance,wallElevationMetres*qPerMetre,
OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness);
const double floorShellDistance=std::max(-static_cast<double>(flatDistance),
static_cast<double>(flatDistance)-floorShellThickness);
const double localShellDistance=std::min(wallShellDistance,
floorShellDistance);
sample.shellSignedDistance=std::min(sample.shellSignedDistance,
localShellDistance);
if(!sample.valid||flatDistance<sample.signedDistance