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
@@ -621,7 +621,18 @@ namespace
|
||||
if(point)out<<',';const auto& p=edge.controlPointsMicrometres[point];
|
||||
out<<'['<<p[0]<<','<<p[1]<<','<<p[2]<<']';
|
||||
}
|
||||
out<<"],\"bore_radius_um\":"<<edge.boreRadiusMicrometres
|
||||
out<<']';
|
||||
if(!edge.polylineMicrometres.empty())
|
||||
{
|
||||
out<<",\"polyline_um\":[";
|
||||
for(std::size_t point=0;point<edge.polylineMicrometres.size();++point)
|
||||
{
|
||||
if(point)out<<',';const auto& p=edge.polylineMicrometres[point];
|
||||
out<<'['<<p[0]<<','<<p[1]<<','<<p[2]<<']';
|
||||
}
|
||||
out<<']';
|
||||
}
|
||||
out<<",\"bore_radius_um\":"<<edge.boreRadiusMicrometres
|
||||
<<",\"bore_height_um\":"<<edge.boreHeightMicrometres
|
||||
<<",\"floor_support_depth_um\":"<<edge.floorSupportDepthMicrometres
|
||||
<<",\"smooth_width_um\":"<<edge.smoothWidthMicrometres
|
||||
@@ -845,6 +856,8 @@ bool ResolvedLayoutSnapshotV3::finalize(std::string& error)
|
||||
x.lowerInterfaceCapabilities={};
|
||||
if(x.generatorKind=="SurfaceWorld")
|
||||
x.passageCapabilities.hasSurfaceLanding=true;
|
||||
else if(x.generatorKind=="Caves")
|
||||
x.passageCapabilities.hasNativeCaveField=true;
|
||||
else if(x.generatorKind=="FloatingIslands")
|
||||
{
|
||||
x.passageCapabilities.hasFloatingIslandLanding=true;
|
||||
@@ -1235,6 +1248,15 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
||std::abs(endpoint[2]-room->floorMicrometres)>500000)
|
||||
add("cavern_edge_portal",edge.stableId+" endpoint does not meet its room floor portal");
|
||||
}
|
||||
const auto* edgeStratum=findStratum(edge.strateIndex);
|
||||
if(edgeStratum&&edgeStratum->generatorKind=="Caves"
|
||||
&&edgeStratum->recipeId=="Core.Caves.PrimitiveField"
|
||||
&&edgeStratum->recipeVersion==1
|
||||
&&(edge.polylineMicrometres.size()<2
|
||||
||edge.polylineMicrometres.front()!=edge.controlPointsMicrometres.front()
|
||||
||edge.polylineMicrometres.back()!=edge.controlPointsMicrometres.back()))
|
||||
add("cavern_edge_polyline",edge.stableId+
|
||||
" has no resolve-time polyline with the cubic endpoints");
|
||||
}
|
||||
}
|
||||
if(oreVeins.empty())
|
||||
@@ -1409,6 +1431,13 @@ std::optional<ResolvedLayoutSnapshotV3> ResolvedLayoutSnapshotV3::FromJson(
|
||||
for(std::size_t axis=0;axis<3&&axis<point.size();++axis)
|
||||
edge.controlPointsMicrometres[i][axis]=point[axis].Integer();
|
||||
}
|
||||
for(const auto& item:v.Get("polyline_um").AsArray())
|
||||
{
|
||||
const auto& point=item.AsArray();
|
||||
if(point.size()!=3)continue;
|
||||
edge.polylineMicrometres.push_back({point[0].Integer(),
|
||||
point[1].Integer(),point[2].Integer()});
|
||||
}
|
||||
const auto readTriplet=[&](std::string_view key,std::array<std::int64_t,3>& target)
|
||||
{
|
||||
const auto& values=v.Get(key).AsArray();
|
||||
@@ -1594,6 +1623,13 @@ bool ResolveResolvedCavernGraphV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
candidate.cavernGraphVocabularyVersion=ResolvedLayoutCavernGraphVocabularyVersionV1;
|
||||
candidate.cavernRooms.assign(rooms.begin(),rooms.end());
|
||||
candidate.cavernEdges.assign(edges.begin(),edges.end());
|
||||
const auto isNativeCavesStrate=[&candidate](std::int32_t strateIndex)
|
||||
{
|
||||
const auto found=std::find_if(candidate.strates.begin(),candidate.strates.end(),
|
||||
[strateIndex](const auto& stratum){return stratum.strateIndex==strateIndex;});
|
||||
return found!=candidate.strates.end()&&found->generatorKind=="Caves"
|
||||
&&found->recipeId=="Core.Caves.PrimitiveField"&&found->recipeVersion==1;
|
||||
};
|
||||
for(auto& room:candidate.cavernRooms)
|
||||
{
|
||||
// The shared JSON value type stores numbers as IEEE-754 doubles. Keep the
|
||||
@@ -1614,6 +1650,75 @@ bool ResolveResolvedCavernGraphV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
{
|
||||
edge.irregularitySeed=LayoutStampSeed(seed,edge.strateIndex,edge.stableId)
|
||||
&0x001fffffffffffffull;
|
||||
using FCurvePoint=std::array<double,3>;
|
||||
std::array<FCurvePoint,4> curve{};
|
||||
for(std::size_t point=0;point<curve.size();++point)
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
curve[point][axis]=static_cast<double>(edge.controlPointsMicrometres[point][axis]);
|
||||
const auto pointSegmentDistance=[](const FCurvePoint& point,
|
||||
const FCurvePoint& a,const FCurvePoint& b)
|
||||
{
|
||||
double lengthSquared=0.0,dot=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double delta=b[axis]-a[axis];
|
||||
lengthSquared+=delta*delta;dot+=(point[axis]-a[axis])*delta;
|
||||
}
|
||||
const double t=lengthSquared>0.0
|
||||
?std::clamp(dot/lengthSquared,0.0,1.0):0.0;
|
||||
double distanceSquared=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double delta=point[axis]-(a[axis]+t*(b[axis]-a[axis]));
|
||||
distanceSquared+=delta*delta;
|
||||
}
|
||||
return std::sqrt(distanceSquared);
|
||||
};
|
||||
edge.polylineMicrometres.clear();
|
||||
if(isNativeCavesStrate(edge.strateIndex))
|
||||
{
|
||||
edge.polylineMicrometres.push_back(edge.controlPointsMicrometres.front());
|
||||
constexpr double MaximumChordErrorMicrometres=10000.0;
|
||||
bool polylineValid=true;
|
||||
const auto subdivide=[&](const auto& self,const std::array<FCurvePoint,4>& points,
|
||||
int depth)->void
|
||||
{
|
||||
if(!polylineValid)return;
|
||||
const double flatness=std::max(pointSegmentDistance(points[1],points[0],points[3]),
|
||||
pointSegmentDistance(points[2],points[0],points[3]));
|
||||
if(flatness<=MaximumChordErrorMicrometres)
|
||||
{
|
||||
std::array<std::int64_t,3> endpoint{};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
if(!std::isfinite(points[3][axis])
|
||||
||std::abs(points[3][axis])>9.0e15)
|
||||
{polylineValid=false;return;}
|
||||
endpoint[axis]=static_cast<std::int64_t>(std::llround(points[3][axis]));
|
||||
}
|
||||
edge.polylineMicrometres.push_back(endpoint);
|
||||
if(edge.polylineMicrometres.size()>65536)polylineValid=false;
|
||||
return;
|
||||
}
|
||||
if(depth>=20){polylineValid=false;return;}
|
||||
std::array<FCurvePoint,4> left{},right{};
|
||||
FCurvePoint a{},b{},c{},d{},e{},mid{};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
a[axis]=(points[0][axis]+points[1][axis])*0.5;
|
||||
b[axis]=(points[1][axis]+points[2][axis])*0.5;
|
||||
c[axis]=(points[2][axis]+points[3][axis])*0.5;
|
||||
d[axis]=(a[axis]+b[axis])*0.5;
|
||||
e[axis]=(b[axis]+c[axis])*0.5;
|
||||
mid[axis]=(d[axis]+e[axis])*0.5;
|
||||
}
|
||||
left={points[0],a,d,mid};right={mid,e,c,points[3]};
|
||||
self(self,left,depth+1);self(self,right,depth+1);
|
||||
};
|
||||
subdivide(subdivide,curve,0);
|
||||
if(!polylineValid)
|
||||
{error="cavern edge "+edge.stableId+" exceeds the bounded polyline subdivision budget";return false;}
|
||||
}
|
||||
std::array<std::int64_t,3> low=edge.controlPointsMicrometres[0];
|
||||
std::array<std::int64_t,3> high=low;
|
||||
for(const auto& point:edge.controlPointsMicrometres)
|
||||
|
||||
Reference in new issue
Block a user