feat(core): native Core caves generator, slice 1 -- spine + room, whole view 0.73 s (L54); research R23
Core.Caves.PrimitiveField v1, opt-in per strate (legacy TunnelNetwork assets stay legacy): solid host rock and one smooth union of two elliptical spine tubes and an ellipsoid room, each intersected with its rising floor by cubic smooth-max (W 2.4 m, measured fillet 0.70 m, no trailing floor cap). Bound in the L40 field table and L42 capabilities, BVH feature candidates, isTileShapeFree aware, exact interval boxes (0 misses). Capsule flood fill arrival -> departure passes (headroom >= 0.3 m, grade <= 15 deg); the generalized whole-surface audit passes with its controls failing. Cold whole view 0.727 s, near ring 0.19 s. Graph ordering/serialization changes are scoped to native caves (the flagged L47 demo is unchanged); verify tiers write captures under --out only. fast/medium/full PASS, Clang and GCC. Research R23 (deepened): per-tile LOD0 kernel speed plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
20f6c98ec5
commit
9458217d34
24 files changed
+471136
-59
No files matched your search
@@ -56,12 +56,14 @@ namespace
|
||||
bool HasRenderDistanceOverride=false;
|
||||
int RenderDistanceOverride=0;
|
||||
bool FloatingIslandsRecipe=false;
|
||||
bool CavesRecipe=false;
|
||||
bool AuditHeightfieldProfile=false;
|
||||
bool LandmarkChamberDemo=false;
|
||||
bool LandmarkL45RampControl=false;
|
||||
bool OreVeinsDemo=false;
|
||||
bool AuditOreVeinYield=false;
|
||||
bool AuditLandmarkReachability=false;
|
||||
bool AuditNativeCaves=false;
|
||||
bool TlsProbeRequested=false;
|
||||
int TlsProbeWorkers=0;
|
||||
std::string TlsProbeTouch="none";
|
||||
@@ -779,6 +781,163 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MakeNativeCavesSpine(const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
|
||||
std::vector<VoxelForgeCore::ResolvedCavernRoomV1>& rooms,
|
||||
std::vector<VoxelForgeCore::ResolvedCavernEdgeV1>& edges,
|
||||
std::string& error)
|
||||
{
|
||||
using namespace VoxelForgeCore;
|
||||
rooms.clear();edges.clear();error.clear();
|
||||
const auto cave=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[](const auto& value){return value.generatorKind=="Caves"
|
||||
&&value.recipeId=="Core.Caves.PrimitiveField"&&value.recipeVersion==1;});
|
||||
if(cave==layout.strates.end())
|
||||
{error="native caves recipe has no version-1 cave strate";return false;}
|
||||
std::vector<const ResolvedLayoutPassageV1*> mouths;
|
||||
for(const auto& passage:layout.passages)
|
||||
if(passage.lowerStrateIndex==cave->strateIndex)
|
||||
mouths.push_back(&passage);
|
||||
std::sort(mouths.begin(),mouths.end(),[](const auto* a,const auto* b)
|
||||
{return a->stableId<b->stableId;});
|
||||
if(mouths.size()!=2)
|
||||
{
|
||||
std::fprintf(stderr,"[CavesMouthBindingAudit] cave_strate=%d passages=%zu matching=%zu",
|
||||
cave->strateIndex,layout.passages.size(),mouths.size());
|
||||
for(const auto& passage:layout.passages)
|
||||
std::fprintf(stderr," [%s upper=%d lower=%d]",passage.stableId.c_str(),
|
||||
passage.upperStrateIndex,passage.lowerStrateIndex);
|
||||
std::fprintf(stderr,"\n");
|
||||
error="native caves spine fixture requires exactly two resolved arrival/departure mouths";return false;
|
||||
}
|
||||
const double micrometresPerSubvoxel=static_cast<double>(layout.coreVoxelSizeMicrometres)
|
||||
/WorldAssemblySubvoxelsPerVoxel;
|
||||
std::array<std::array<std::int64_t,3>,2> mouthMicrometres{};
|
||||
for(std::size_t mouth=0;mouth<2;++mouth)
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
mouthMicrometres[mouth][axis]=static_cast<std::int64_t>(std::llround(
|
||||
mouths[mouth]->lowerMouthSubvoxels[axis]*micrometresPerSubvoxel));
|
||||
const double x0=mouthMicrometres[0][0]/1000000.0;
|
||||
const double y0=mouthMicrometres[0][1]/1000000.0;
|
||||
const double x1=mouthMicrometres[1][0]/1000000.0;
|
||||
const double y1=mouthMicrometres[1][1]/1000000.0;
|
||||
const double floorZ=0.5*(mouthMicrometres[0][2]+mouthMicrometres[1][2])/1000000.0;
|
||||
const double dx=x1-x0,dy=y1-y0;
|
||||
const double length=std::hypot(dx,dy);
|
||||
std::printf("[CavesResolvedMouths] arrival=%s xyz_m=(%.3f,%.3f,%.3f) departure=%s xyz_m=(%.3f,%.3f,%.3f) horizontal_separation_m=%.3f\n",
|
||||
mouths[0]->stableId.c_str(),x0,y0,mouthMicrometres[0][2]/1e6,
|
||||
mouths[1]->stableId.c_str(),x1,y1,mouthMicrometres[1][2]/1e6,length);
|
||||
const double mouthZ0=mouthMicrometres[0][2]/1000000.0;
|
||||
const double mouthZ1=mouthMicrometres[1][2]/1000000.0;
|
||||
const std::array<double,2> startFloorZ={mouthZ0-0.75,mouthZ1-0.75};
|
||||
double directionX=0.0,directionY=0.0;
|
||||
for(const auto* passage:mouths)
|
||||
{
|
||||
if(passage->controlPoints.size()<2)
|
||||
{error="native caves lower mouth has no resolved passage tangent";return false;}
|
||||
const auto last=std::min(passage->lowerMouthControlIndex,
|
||||
passage->controlPoints.size()-1);
|
||||
const auto previous=last>0?last-1:passage->controlPoints.size()-2;
|
||||
const double tx=static_cast<double>(passage->controlPoints[last].positionSubvoxels[0]
|
||||
-passage->controlPoints[previous].positionSubvoxels[0]);
|
||||
const double ty=static_cast<double>(passage->controlPoints[last].positionSubvoxels[1]
|
||||
-passage->controlPoints[previous].positionSubvoxels[1]);
|
||||
const double tangentLength=std::hypot(tx,ty);
|
||||
if(!(tangentLength>1.0e-9))
|
||||
{error="native caves lower mouth has a degenerate passage tangent";return false;}
|
||||
directionX+=tx/tangentLength;directionY+=ty/tangentLength;
|
||||
}
|
||||
const double directionLength=std::hypot(directionX,directionY);
|
||||
if(!(directionLength>1.0e-9))
|
||||
{error="native caves lower mouths have opposing passage tangents";return false;}
|
||||
directionX/=directionLength;directionY/=directionLength;
|
||||
if(std::hypot(length,mouthZ1-mouthZ0)<4.0)
|
||||
{error="native caves arrival and departure mouths resolve to the same location";return false;}
|
||||
|
||||
ResolvedCavernRoomV1 room;
|
||||
room.stableId="caves/spine/chamber-v1";room.strateIndex=cave->strateIndex;
|
||||
const double roomOffset=std::max(32.0,
|
||||
std::max(std::abs(floorZ-startFloorZ[0]),
|
||||
std::abs(floorZ-startFloorZ[1]))/0.2679491924311227+27.0);
|
||||
const double perpendicularX=-directionY;
|
||||
const double perpendicularY=directionX;
|
||||
room.centerMicrometres={static_cast<std::int64_t>(std::llround(
|
||||
((x0+x1)*0.5+directionX*roomOffset)*1000000.0)),
|
||||
static_cast<std::int64_t>(std::llround(
|
||||
((y0+y1)*0.5+directionY*roomOffset)*1000000.0)),
|
||||
static_cast<std::int64_t>(std::llround((floorZ+3.5)*1000000.0))};
|
||||
room.halfExtentsMicrometres={7000000,6500000,4500000};
|
||||
room.floorMicrometres=static_cast<std::int64_t>(std::llround(floorZ*1000000.0));
|
||||
room.smoothWidthMicrometres=2400000;
|
||||
rooms.push_back(room);
|
||||
|
||||
for(std::size_t route=0;route<2;++route)
|
||||
{
|
||||
const auto& mouth=mouthMicrometres[route];
|
||||
const auto* passage=mouths[route];
|
||||
const auto tangentLast=std::min(passage->lowerMouthControlIndex,
|
||||
passage->controlPoints.size()-1);
|
||||
const auto tangentPrevious=tangentLast>0?tangentLast-1:
|
||||
passage->controlPoints.size()-2;
|
||||
const double tangentX=static_cast<double>(
|
||||
passage->controlPoints[tangentLast].positionSubvoxels[0]
|
||||
-passage->controlPoints[tangentPrevious].positionSubvoxels[0]);
|
||||
const double tangentY=static_cast<double>(
|
||||
passage->controlPoints[tangentLast].positionSubvoxels[1]
|
||||
-passage->controlPoints[tangentPrevious].positionSubvoxels[1]);
|
||||
const double tangentLength=std::hypot(tangentX,tangentY);
|
||||
if(!(tangentLength>1.0e-9))
|
||||
{error="native caves lower-mouth overlap has a degenerate passage tangent";return false;}
|
||||
constexpr double mouthOverlap=3.0;
|
||||
const double startX=mouth[0]/1000000.0+tangentX/tangentLength*mouthOverlap;
|
||||
const double startY=mouth[1]/1000000.0+tangentY/tangentLength*mouthOverlap;
|
||||
const double roomX=room.centerMicrometres[0]/1000000.0;
|
||||
const double roomY=room.centerMicrometres[1]/1000000.0;
|
||||
const double toRoomX=roomX-startX,toRoomY=roomY-startY;
|
||||
const double toRoomLength=std::hypot(toRoomX,toRoomY);
|
||||
if(!(toRoomLength>5.0))
|
||||
{error="native caves mouth does not clear the chamber portal";return false;}
|
||||
const double portalSide=route==0?-3.5:3.5;
|
||||
const double portalX=roomX+perpendicularX*portalSide;
|
||||
const double portalY=roomY+perpendicularY*portalSide;
|
||||
const double endZ=floorZ;
|
||||
const double portalRun=std::hypot(portalX-startX,portalY-startY);
|
||||
const double edgeStartFloorZ=startFloorZ[route]
|
||||
+(endZ-startFloorZ[route])*mouthOverlap/(portalRun+mouthOverlap);
|
||||
const double verticalRun=std::abs(endZ-edgeStartFloorZ);
|
||||
const double maximumGrade=verticalRun/portalRun;
|
||||
if(maximumGrade>0.2679492)
|
||||
{error="native caves spine segment exceeds the 15 degree walk grade";return false;}
|
||||
const double edgeX=portalX-startX,edgeY=portalY-startY;
|
||||
ResolvedCavernEdgeV1 edge;
|
||||
edge.stableId=route==0?"caves/spine/arrival-edge-v1"
|
||||
:"caves/spine/departure-edge-v1";
|
||||
edge.startAnchorStableId=mouths[route]->stableId+"/lower-mouth";
|
||||
edge.endRoomStableId=room.stableId;edge.strateIndex=cave->strateIndex;
|
||||
// Match the resolved lower-mouth opening so the native spine does not
|
||||
// create a sudden shoulder where the legacy passage ends.
|
||||
edge.boreRadiusMicrometres=4500000;
|
||||
edge.boreHeightMicrometres=4500000;
|
||||
edge.floorSupportDepthMicrometres=0;
|
||||
edge.smoothWidthMicrometres=2400000;
|
||||
const std::array<std::array<double,3>,4> points={{
|
||||
{startX,startY,edgeStartFloorZ},
|
||||
{startX+edgeX/3.0,startY+edgeY/3.0,
|
||||
edgeStartFloorZ+(endZ-edgeStartFloorZ)/3.0},
|
||||
{startX+2.0*edgeX/3.0,startY+2.0*edgeY/3.0,
|
||||
edgeStartFloorZ+2.0*(endZ-edgeStartFloorZ)/3.0},
|
||||
{portalX,portalY,endZ}}};
|
||||
for(std::size_t point=0;point<points.size();++point)
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
edge.controlPointsMicrometres[point][axis]=static_cast<std::int64_t>(
|
||||
std::llround(points[point][axis]*1000000.0));
|
||||
edges.push_back(std::move(edge));
|
||||
}
|
||||
std::printf("[CavesSpinePlan] recipe=Core.Caves.PrimitiveField version=1 density_sign=negative_solid_positive_air arrival=%s departure=%s room=%s edges=%zu bore_radius_m=4.500 bore_height_m=4.500 mouth_overlap_m=3.000 horizontal_separation_m=%.3f heading=(%.3f,%.3f) room_offset_m=%.3f lower_mouth_floor_offset_m=-0.750 floor_blend_width_m=2.400000 ideal_fillet_radius_m=0.848528 grade_limit_deg=15.000 shared_layer=shared-bedrock status=PASS\n",
|
||||
mouths[0]->stableId.c_str(),mouths[1]->stableId.c_str(),room.stableId.c_str(),
|
||||
edges.size(),length,directionX,directionY,roomOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MakeOreVeinDemoRequests(
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
|
||||
std::vector<VoxelForgeCore::ResolvedLayoutOreVeinRequestV1>& requests,
|
||||
@@ -964,7 +1123,7 @@ namespace
|
||||
" --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n"
|
||||
" --world-assembler-manifest-output=FILE (write the canonical Core recipe and plan)\n"
|
||||
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
|
||||
" --seed=N --recipe=surface-world|floating-islands\n"
|
||||
" --seed=N --recipe=surface-world|floating-islands|caves\n"
|
||||
" --landmark-chamber-demo (opt-in SW cavern room and swept tunnel)\n"
|
||||
" --ore-veins-demo (opt-in material-only SW capsule veins)\n"
|
||||
" --audit-ore-vein-yield (measure one deterministic sphere carve)\n"
|
||||
@@ -977,6 +1136,7 @@ namespace
|
||||
" --audit-resolved-layout-passages (capsule, support, route-binding and blocked-control audit)\n"
|
||||
" --audit-heightfield-profile (brute-force the profiled field intervals and route)\n"
|
||||
" --audit-landmark-reachability (capsule, support, grade and buried-L43 control)\n"
|
||||
" --audit-native-caves (arrival-to-departure capsule flood fill and interval oracle)\n"
|
||||
" --audit-surface-clearance (sample biome terrain/caps against the resolved ceiling)\n"
|
||||
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
|
||||
" --mesh-coverage (report non-empty tiles and indexed triangles)\n"
|
||||
@@ -1003,6 +1163,7 @@ namespace
|
||||
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
|
||||
else if(arg=="--audit-resolved-layout-passages")options.AuditResolvedLayoutPassages=true;
|
||||
else if(arg=="--audit-landmark-reachability")options.AuditLandmarkReachability=true;
|
||||
else if(arg=="--audit-native-caves")options.AuditNativeCaves=true;
|
||||
else if(arg=="--audit-surface-clearance")options.AuditSurfaceClearance=true;
|
||||
else if(arg=="--audit-strate-transitions")options.AuditStrateTransitions=true;
|
||||
else if(arg.starts_with("--transition-mode="))
|
||||
@@ -1037,8 +1198,12 @@ namespace
|
||||
else if(arg.starts_with("--recipe="))
|
||||
{
|
||||
const std::string_view recipe=arg.substr(std::string_view("--recipe=").size());
|
||||
if(recipe=="surface-world")options.FloatingIslandsRecipe=false;
|
||||
else if(recipe=="floating-islands")options.FloatingIslandsRecipe=true;
|
||||
if(recipe=="surface-world")
|
||||
{options.FloatingIslandsRecipe=false;options.CavesRecipe=false;}
|
||||
else if(recipe=="floating-islands")
|
||||
{options.FloatingIslandsRecipe=true;options.CavesRecipe=false;}
|
||||
else if(recipe=="caves")
|
||||
{options.FloatingIslandsRecipe=false;options.CavesRecipe=true;}
|
||||
else {std::fprintf(stderr,"Invalid --recipe value: %.*s\n",static_cast<int>(recipe.size()),recipe.data());return false;}
|
||||
}
|
||||
else if(arg=="--landmark-chamber-demo")options.LandmarkChamberDemo=true;
|
||||
@@ -1154,7 +1319,8 @@ int main(int argc,char** argv)
|
||||
std::printf("[HeadlessConfig] data=%s workers=%d clip_radius=%d max_clip_level=%d max_level=%d hash=%s column_overlap=%s force_generate=%s recipe=%s shared_column_cache=%s camera_step_m=(%.3f,%.3f,%.3f) seed_override=%s render_distance_override=%s\n",
|
||||
options.DataPath.string().c_str(),options.WorkerCount,options.ClipRadius,options.MaxClipLevel,
|
||||
options.MaxLevel,options.StreamHash?"on":"off",options.ProfileColumnOverlap?"on":"off",
|
||||
options.ForceGenerate?"on":"off",options.FloatingIslandsRecipe?"floating-islands":"surface-world",
|
||||
options.ForceGenerate?"on":"off",options.CavesRecipe?"caves"
|
||||
:options.FloatingIslandsRecipe?"floating-islands":"surface-world",
|
||||
options.UseSharedColumnCache?"on":"off",options.CameraStepMeters.X,options.CameraStepMeters.Y,
|
||||
options.CameraStepMeters.Z,
|
||||
options.HasSeedOverride?"yes":"no",options.HasRenderDistanceOverride?"yes":"no");
|
||||
@@ -1227,7 +1393,8 @@ int main(int argc,char** argv)
|
||||
}
|
||||
VoxelForgeCore::ResolvedLayoutSnapshotV3 resolvedLayout;
|
||||
{
|
||||
const std::string_view variant=options.FloatingIslandsRecipe?"floating-islands":"surface-world";
|
||||
const std::string_view variant=options.CavesRecipe?"caves"
|
||||
:options.FloatingIslandsRecipe?"floating-islands":"surface-world";
|
||||
if(!StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot(
|
||||
*ownerWorld,worldAssembly,variant,resolvedLayout,error))
|
||||
{std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;}
|
||||
@@ -1277,6 +1444,15 @@ int main(int argc,char** argv)
|
||||
resolvedLayout.cavernRooms.size(),resolvedLayout.cavernEdges.size(),
|
||||
resolvedLayout.stamps.size(),resolvedLayout.cavernGraphVocabularyVersion);
|
||||
}
|
||||
if(options.CavesRecipe)
|
||||
{
|
||||
std::vector<VoxelForgeCore::ResolvedCavernRoomV1> rooms;
|
||||
std::vector<VoxelForgeCore::ResolvedCavernEdgeV1> edges;
|
||||
if(!MakeNativeCavesSpine(resolvedLayout,rooms,edges,error)
|
||||
||!VoxelForgeCore::ResolveResolvedCavernGraphV1(
|
||||
resolvedLayout,seed,rooms,edges,error))
|
||||
{std::fprintf(stderr,"Native caves spine resolution failed: %s\n",error.c_str());return 2;}
|
||||
}
|
||||
if(options.OreVeinsDemo)
|
||||
{
|
||||
std::vector<VoxelForgeCore::ResolvedLayoutOreVeinRequestV1> requests;
|
||||
@@ -1371,8 +1547,9 @@ int main(int argc,char** argv)
|
||||
slot.StrateIndex,resolvedStrate->generatorKind.c_str(),
|
||||
static_cast<std::uint32_t>(slot.Definition->PassageConfig.Style));
|
||||
}
|
||||
const auto requestedRecipe=options.FloatingIslandsRecipe
|
||||
?std::string_view("floating-islands"):std::string_view("surface-world");
|
||||
const auto requestedRecipe=options.CavesRecipe?std::string_view("caves")
|
||||
:options.FloatingIslandsRecipe?std::string_view("floating-islands")
|
||||
:std::string_view("surface-world");
|
||||
const auto topStratum=std::max_element(resolvedLayout.strates.begin(),resolvedLayout.strates.end(),
|
||||
[](const auto& a,const auto& b)
|
||||
{return a.interiorTopMicrometres<b.interiorTopMicrometres;});
|
||||
@@ -1386,7 +1563,12 @@ int main(int argc,char** argv)
|
||||
&&std::any_of(worldAssembly.plan.strates.begin(),worldAssembly.plan.strates.end(),
|
||||
[&](const auto& plan){return plan.strateIndex==stratum.strateIndex;});
|
||||
});
|
||||
const auto actualRecipe=hasFloatingIslands?std::string_view("floating-islands")
|
||||
const bool hasNativeCavesRecipe=std::any_of(resolvedLayout.strates.begin(),resolvedLayout.strates.end(),
|
||||
[](const auto& stratum){return stratum.generatorKind=="Caves"
|
||||
&&stratum.recipeId=="Core.Caves.PrimitiveField"&&stratum.recipeVersion==1
|
||||
&&stratum.passageCapabilities.hasNativeCaveField;});
|
||||
const auto actualRecipe=hasNativeCavesRecipe?std::string_view("caves")
|
||||
:hasFloatingIslands?std::string_view("floating-islands")
|
||||
:hasSurfaceWorldPlan?std::string_view("surface-world")
|
||||
:std::string_view("missing");
|
||||
const char* topGenerator=topStratum==resolvedLayout.strates.end()
|
||||
@@ -1586,5 +1768,5 @@ int main(int argc,char** argv)
|
||||
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
|
||||
options.AuditResolvedLayoutPassages,options.AuditStrateTransitions,
|
||||
&resolvedLayout,options.StreamHashTiles,options.AuditLandmarkReachability,
|
||||
options.AuditOreVeinYield);
|
||||
options.AuditOreVeinYield,options.AuditNativeCaves);
|
||||
}
|
||||
Reference in new issue
Block a user