parity: Unreal and headless resolve the same four-strate plan (L70, v214)

- Export commandlet writes the live Core adapter's world_assembly + resolved layout pair;
  the headless owner path imports that pair (manifest/layout equal, layout_chunk_width_q
  validated). owner_world.json re-exported from the owner's staged assets on the Linux host.
- Adapter SW route: Core clearance/radius floors, 0.5 m support search, outward-facing
  tie-break; passage mouth/mid radius floors match Core (36/24 owner voxels).
- FI in Unreal now uses the legacy (compiled analytic) generator unless a plan is imported:
  the auto native-FI plan failed the passage audit on the owner plan (1843 blocked samples,
  945 open-air violations). Owner decides whether native FI returns.
- In-engine spawn traces per strate (3 each): SW GenerateTile 42.7 worker-s vs 20.1 headless
  for equal tile counts; LOD0 p95 45-169 ms in UE.
- Fast tier green; all three passages pass on the shared plan.

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-27 06:22:48 +01:00
1 parent 81e2452a3d
commit bd68aee1ca
16 files changed
+939 -62

No files matched your search

@@ -2502,23 +2502,6 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
{bestAlignment=alignment;phase=candidate;}
}
}
if(hasUpperRoute&&upperIsSurfaceWorld)
{
const auto& directionAtPhase=directions[phase];
const std::int64_t radialAlignment=upperMouth[0]*directionAtPhase[0]
+upperMouth[1]*directionAtPhase[1];
if(radialAlignment<0)
{
std::int64_t bestOutwardAlignment=std::numeric_limits<std::int64_t>::min();
for(std::uint32_t candidate=0;candidate<directions.size();++candidate)
{
const std::int64_t alignment=upperMouth[0]*directions[candidate][0]
+upperMouth[1]*directions[candidate][1];
if(alignment>bestOutwardAlignment)
{bestOutwardAlignment=alignment;phase=candidate;}
}
}
}
bool clockwise=(PassageSeed(seed,upper.strateIndex,lower.strateIndex,
connection,0x44495245u)&1u)!=0;
if(style==0&&anchoredIslandPassage&&!anchoredSpiral&&passageAnchor)
+83 -21
View File
@@ -973,7 +973,7 @@ public:
float composed=density;
float deferredSupportDensity=std::numeric_limits<float>::infinity();
const auto composeRouteMouthSupport=[&](std::int32_t strateIndex,
const std::array<std::int64_t,3>& mouth,bool departure)
const std::array<std::int64_t,3>& mouth)
{
// Surface-route treads may reinforce native solid terrain only.
if(!(density<0.0f))return;
@@ -985,25 +985,18 @@ public:
ResolvedLayout->strates.end(),[strateIndex](const auto& value)
{return value.strateIndex==strateIndex;});
if(stratum==ResolvedLayout->strates.end())return;
std::array<const VoxelForgeCore::ResolvedLayoutAnchorV2*,5> route{};
std::size_t routeCount=0;
std::vector<const VoxelForgeCore::ResolvedLayoutAnchorV2*> route;
route.reserve(stratum->anchors.size());
for(const auto& anchor:stratum->anchors)
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
{
if(departure)
{
if(routeCount<route.size())route[routeCount++]=&anchor;
else
{
std::move(route.begin()+1,route.end(),route.begin());
route.back()=&anchor;
}
}
else if(routeCount<route.size())route[routeCount++]=&anchor;
}
if(routeCount<2)return;
const std::size_t lastSegment=routeCount-1;
route.push_back(&anchor);
if(route.size()<2)return;
const std::size_t lastSegment=route.size()-1;
constexpr double MouthSupportBlendMetres=0.45;
// Route anchors encode the player center at half the authored capsule
// height above the tread. Keep the support deck below that same foot
// plane so the route audit's 0.5 m support search reaches solid tread.
constexpr double RouteCenterAboveFootMetres=0.88;
const double mouthBlendWidth=MouthSupportBlendMetres*qPerMetre;
double mouthSupportDistance=std::numeric_limits<double>::infinity();
for(std::size_t index=0;index<lastSegment;++index)
@@ -1023,8 +1016,8 @@ public:
const double horizontalX=qx-centerX,horizontalY=qy-centerY;
const double horizontalDistance=DeterministicSqrt(
horizontalX*horizontalX+horizontalY*horizontalY);
const double floorQ=centerZ-(VoxelForgeCore::WorldAssemblyEvaluatorVersion>=184
?playerCenterAboveFloorQ+0.25*qPerMetre:1.20*qPerMetre);
const double floorQ=centerZ-RouteCenterAboveFootMetres*qPerMetre
-0.25*qPerMetre;
const double sideDistance=horizontalDistance-halfWidth;
const double topDistance=qz-floorQ;
const double bottomDistance=floorQ-qPerMetre-qz;
@@ -1883,7 +1876,7 @@ public:
if(!tileHasSupport
||ActivePassageTileQueries->hasMouthSupport(passageIndex))
composeRouteMouthSupport(passage.upperStrateIndex,
passage.upperMouthSubvoxels,true);
passage.upperMouthSubvoxels);
}
composed=std::min(composed,deferredSupportDensity);
return composed;
@@ -4986,7 +4979,7 @@ private:
// Add a subtle host-rock root only when the unmodified column lacks the
// vertical relief required for walkable passage support.
const double rootTaper=crossing.needsRootTaper
?0.08*qPerMetre*smoothStep((t-0.35)/0.50):0.0;
?0.30*qPerMetre*smoothStep((t-0.35)/0.50):0.0;
const double radius=static_cast<double>(crossing.minimumRadiusSubvoxels)
+std::max(0.15*qPerMetre,irregularity)+rootTaper+baseFlare+ceilingFlare;
const double radialDistanceField=radialDistance-radius;
@@ -10912,6 +10905,75 @@ private:
bool ValidatePassageRoutes()
{
if(Owner&&Owner->bHasUnrealResolvedCorePlan
&&ResolvedLayout&&!ResolvedLayout->passages.empty())
{
constexpr double SampleStep=0.5;
uint32 PassageIndex=0;
for(const auto& passage:ResolvedLayout->passages)
{
const auto& points=passage.controlPoints;
if(points.size()<2){++PassageIndex;continue;}
uint64 routeSamples=0,routeFailures=0;
int32 firstFailure[3]={0,0,0};
for(std::size_t segment=0;segment+1<points.size();++segment)
{
const auto& a=points[segment].positionSubvoxels;
const auto& b=points[segment+1].positionSubvoxels;
const double ax=static_cast<double>(a[0])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double ay=static_cast<double>(a[1])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double az=static_cast<double>(a[2])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double bx=static_cast<double>(b[0])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double by=static_cast<double>(b[1])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double bz=static_cast<double>(b[2])/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const double length=std::sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay)+(bz-az)*(bz-az));
const int32 count=std::max(1,static_cast<int32>(std::ceil(length/SampleStep)));
uint64 segmentFailures=0;
for(int32 sample=0;sample<=count;++sample)
{
const double t=static_cast<double>(sample)/count;
const int32 vx=static_cast<int32>(std::lround(ax+(bx-ax)*t));
const int32 vy=static_cast<int32>(std::lround(ay+(by-ay)*t));
const int32 vz=static_cast<int32>(std::lround(az+(bz-az)*t));
++Stats.WalkSamples;
++routeSamples;
const float density=DensityAt(static_cast<float>(ax+(bx-ax)*t),
static_cast<float>(ay+(by-ay)*t),
static_cast<float>(az+(bz-az)*t));
if(!std::isfinite(density)||density<0.0f)
{
++Stats.WalkFailures;
++routeFailures;
++segmentFailures;
if(routeFailures==1)
{firstFailure[0]=vx;firstFailure[1]=vy;firstFailure[2]=vz;}
}
}
if(segmentFailures)
std::fprintf(stderr,"[WalkabilitySegment] source=resolved_core_layout passage=%s segment=%zu failures=%llu/%llu length=%.2f\n",
passage.stableId.c_str(),segment,
static_cast<unsigned long long>(segmentFailures),
static_cast<unsigned long long>(std::max(1,static_cast<int32>(std::ceil(length/SampleStep))+1)),
length);
}
if(routeFailures)
std::fprintf(stderr,"[WalkabilityRoute] source=resolved_core_layout passage=%u id=%s points=%zu failures=%llu/%llu first_solid=(%d,%d,%d)\n",
PassageIndex,passage.stableId.c_str(),points.size(),
static_cast<unsigned long long>(routeFailures),
static_cast<unsigned long long>(routeSamples),firstFailure[0],
firstFailure[1],firstFailure[2]);
++PassageIndex;
}
if(Stats.WalkFailures)
std::fprintf(stderr,"[Walkability] FAIL source=resolved_core_layout %llu/%llu compiled Core passage centerline samples are solid\n",
static_cast<unsigned long long>(Stats.WalkFailures),
static_cast<unsigned long long>(Stats.WalkSamples));
else
std::printf("[Walkability] PASS source=resolved_core_layout %llu/%llu compiled Core passage centerline samples remain open\n",
static_cast<unsigned long long>(Stats.WalkSamples),
static_cast<unsigned long long>(Stats.WalkSamples));
return Stats.WalkFailures==0;
}
constexpr double SampleStep=0.5;
uint32 PassageIndex=0;
for(const FVoxelPassage& P:Owner->Manager->GetPassages())