wip: continuous backbone floor profile for the cave planner (L134 design 4, untested)

Written by Luna before the Codex usage limit cut the round: one shared distance/floor profile across backbone rooms
and edges, edge cubic floors derived from it, sloped route-room floors, lower-floor backing cap at overlaps, and
validator checks for joint height/slope continuity. Not yet built or audited.

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-31 12:03:48 +01:00
1 parent 379093401e
commit 4a97023b24
3 files changed
+296 -19

No files matched your search

+49 -8
View File
@@ -3583,6 +3583,7 @@ private:
double minimumFloorMetres=std::numeric_limits<double>::infinity();
double maximumFloorMetres=-std::numeric_limits<double>::infinity();
double maximumSegmentGrade=0.0;
std::array<double,2> floorGradient{};
std::array<float,3> centerVoxels{},halfExtentsVoxels{};
std::array<std::array<float,3>,4> controlPointsVoxels{};
float floorVoxels=0.0f;
@@ -4011,8 +4012,10 @@ private:
{
CavernRuntime.clear();CavernSpatialNodes.clear();CavernSpatialOrder.clear();
if(!ResolvedLayout||!Owner||Owner->CoreVoxelSizeMicrons==0
||ResolvedLayout->cavernGraphVocabularyVersion
!=VoxelForgeCore::ResolvedLayoutCavernGraphVocabularyVersionV1)return;
||(ResolvedLayout->cavernGraphVocabularyVersion
!=VoxelForgeCore::ResolvedLayoutCavernGraphVocabularyVersionV1
&&ResolvedLayout->cavernGraphVocabularyVersion
!=VoxelForgeCore::ResolvedLayoutCavernGraphVocabularyVersionV2))return;
const auto isNativeGraphStrate=[this](std::int32_t strateIndex)
{
const auto found=std::find_if(ResolvedLayout->strates.begin(),
@@ -4042,6 +4045,8 @@ private:
}
runtime.floorVoxels=static_cast<float>(
static_cast<double>(room.floorMicrometres)/micronsPerVoxel);
runtime.floorGradient={room.floorGradientQ16[0]/65536.0,
room.floorGradientQ16[1]/65536.0};
runtime.smoothWidthVoxels=static_cast<float>(
static_cast<double>(room.smoothWidthMicrometres)/micronsPerVoxel);
runtime.irregularityAmplitudeVoxels=static_cast<float>(
@@ -5314,7 +5319,18 @@ public:
(std::sqrt(normalizedMinimumSquared)-1.0)*meanRadius,
(std::sqrt(normalizedMaximumSquared)-1.0)*meanRadius,true};
const double floorZ=feature.room->floorMicrometres/1000000.0;
const FMetricInterval floor={floorZ-hi[2],floorZ-lo[2],true};
const double centerX=feature.room->centerMicrometres[0]/1000000.0;
const double centerY=feature.room->centerMicrometres[1]/1000000.0;
const double gx=feature.room->floorGradientQ16[0]/65536.0;
const double gy=feature.room->floorGradientQ16[1]/65536.0;
const double x0=lo[0]-centerX,x1=hi[0]-centerX;
const double y0=lo[1]-centerY,y1=hi[1]-centerY;
const double gradientMinimum=(gx>=0.0?gx*x0:gx*x1)
+(gy>=0.0?gy*y0:gy*y1);
const double gradientMaximum=(gx>=0.0?gx*x1:gx*x0)
+(gy>=0.0?gy*y1:gy*y0);
const FMetricInterval floor={floorZ-hi[2]+gradientMinimum,
floorZ-lo[2]+gradientMaximum,true};
const double width=feature.room->smoothWidthMicrometres/1000000.0;
featureVoid={SmoothMaxMetres(ellipsoid.minimum,floor.minimum,width),
SmoothMaxMetres(ellipsoid.maximum,floor.maximum,width),true};
@@ -7463,6 +7479,7 @@ private:
double floorSupportScore=std::numeric_limits<double>::infinity();
double floorSupportDepth=0.0,floorSupportFloor=0.0,floorSupportGrade=0.0;
const std::string* floorSupportEdgeId=nullptr;
const std::string* floorSupportProfileId=nullptr;
for(const std::uint32_t index:*candidates)
{
if(index>=CavernRuntime.size())continue;
@@ -7491,7 +7508,9 @@ private:
feature.irregularityWavelengthVoxels,feature.irregularitySeed)
*feature.irregularityAmplitudeVoxels*metresPerVoxel*fade;
}
const double floor=feature.room->floorMicrometres/1000000.0-point[2];
const double floor=feature.room->floorMicrometres/1000000.0-point[2]
+feature.floorGradient[0]*(point[0]-feature.centerMetres[0])
+feature.floorGradient[1]*(point[1]-feature.centerMetres[1]);
const double width=feature.room->smoothWidthMicrometres/1000000.0;
featureVoid=SmoothMaxMetres(ellipsoid,floor,width);
}
@@ -7599,10 +7618,32 @@ private:
{
const double deltaZ=point[2]-nearestFloor;
const double candidateScore=nearestRadial*nearestRadial+deltaZ*deltaZ;
if(candidateScore<floorSupportScore
||(candidateScore==floorSupportScore
&&(!floorSupportEdgeId
||feature.edge->stableId<*floorSupportEdgeId)))
if(!feature.edge->floorProfileStableId.empty())
{
const bool sameProfile=floorSupportProfileId
&&*floorSupportProfileId==feature.edge->floorProfileStableId;
if(!floorSupportProfileId||sameProfile)
{
// Backbone edges share h(s). At a geometric joint their
// cave volumes overlap, so the backing top is the lower
// of the local floors, never the closer higher segment.
if(!floorSupportProfileId||nearestFloor<floorSupportFloor
||(nearestFloor==floorSupportFloor
&&feature.edge->stableId<*floorSupportEdgeId))
{
floorSupportDepth=candidateSupportDepth;
floorSupportFloor=nearestFloor;
floorSupportGrade=nearestGrade;
floorSupportEdgeId=&feature.edge->stableId;
}
floorSupportProfileId=&feature.edge->floorProfileStableId;
}
}
else if(!floorSupportProfileId
&&(candidateScore<floorSupportScore
||(candidateScore==floorSupportScore
&&(!floorSupportEdgeId
||feature.edge->stableId<*floorSupportEdgeId))))
{
floorSupportScore=candidateScore;
floorSupportDepth=candidateSupportDepth;