feat(core): ore vein records and a materialAt query, off by default (L50); research R18, R19
Versioned capsule vein records (stable ID, resource ID, endpoints, radius, seeded irregularity) resolved into the snapshot only when requested, placed beside the route and away from passages, landings and landmarks (forced-passage control rejected). The bound field table gains materialAt (host + two resource IDs + Q16 weights) behind a per-tile BVH; mesh export v2 carries per-vertex materials; a measurement-only yield computes removed resource volume (0 on already-air space). With veins on, every density, mesh, payload and topology hash is unchanged; demo off: owner hashes identical to L47. fast/medium/full PASS. Research R18 (cavern-graph planner) and R19 (why FloatingIslands costs ~10x SurfaceWorld). 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
b9ccff4ad6
commit
ca85e876ad
15 files changed
+1573
-19
No files matched your search
@@ -22,6 +22,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -57,6 +58,8 @@ namespace
|
||||
bool FloatingIslandsRecipe=false;
|
||||
bool LandmarkChamberDemo=false;
|
||||
bool LandmarkL45RampControl=false;
|
||||
bool OreVeinsDemo=false;
|
||||
bool AuditOreVeinYield=false;
|
||||
bool AuditLandmarkReachability=false;
|
||||
bool TlsProbeRequested=false;
|
||||
int TlsProbeWorkers=0;
|
||||
@@ -620,6 +623,138 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MakeOreVeinDemoRequests(
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
|
||||
std::vector<VoxelForgeCore::ResolvedLayoutOreVeinRequestV1>& requests,
|
||||
std::string& error)
|
||||
{
|
||||
using namespace VoxelForgeCore;
|
||||
requests.clear();
|
||||
const auto surface=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[](const auto& value){return value.generatorKind=="SurfaceWorld";});
|
||||
if(surface==layout.strates.end()||layout.coreVoxelSizeMicrometres==0)
|
||||
{error="ore-vein demo needs a SurfaceWorld strate";return false;}
|
||||
constexpr double Q=static_cast<double>(WorldAssemblySubvoxelsPerVoxel);
|
||||
const double coreMicrometres=layout.coreVoxelSizeMicrometres;
|
||||
const auto addCapsule=[&](std::string id,std::uint16_t resourceId,
|
||||
std::array<double,3> base,std::array<double,3> tangent,
|
||||
std::array<double,3> side,double routeClearRadius,
|
||||
std::int64_t radius,std::int64_t irregularity,std::int64_t blend,
|
||||
std::int64_t length)
|
||||
{
|
||||
const auto normalize=[](std::array<double,3>& value)
|
||||
{
|
||||
const double length=std::sqrt(value[0]*value[0]+value[1]*value[1]
|
||||
+value[2]*value[2]);
|
||||
if(length<=1.0e-9)return false;
|
||||
for(double& component:value)component/=length;
|
||||
return true;
|
||||
};
|
||||
if(!normalize(tangent))return false;
|
||||
const double sideLength=std::sqrt(side[0]*side[0]+side[1]*side[1]);
|
||||
if(sideLength<=1.0e-9)return false;
|
||||
side[0]/=sideLength;side[1]/=sideLength;
|
||||
const double offset=routeClearRadius+radius+irregularity+200000.0;
|
||||
base[0]+=side[0]*offset;base[1]+=side[1]*offset;
|
||||
ResolvedLayoutOreVeinRequestV1 request;
|
||||
request.stableId=std::move(id);request.strateIndex=surface->strateIndex;
|
||||
request.resourceMaterialId=resourceId;request.placementRadiusMicrometres=1500000;
|
||||
request.radiusMicrometres=radius;
|
||||
request.irregularityAmplitudeMicrometres=irregularity;
|
||||
request.irregularityWavelengthMicrometres=1400000;
|
||||
request.blendWidthMicrometres=blend;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double half=static_cast<double>(length)*0.5*tangent[axis];
|
||||
request.anchorEndpointsMicrometres[0][axis]=static_cast<std::int64_t>(
|
||||
std::llround(base[axis]-half));
|
||||
request.anchorEndpointsMicrometres[1][axis]=static_cast<std::int64_t>(
|
||||
std::llround(base[axis]+half));
|
||||
}
|
||||
requests.push_back(std::move(request));return true;
|
||||
};
|
||||
std::vector<const ResolvedLayoutAnchorV2*> route;
|
||||
for(const auto& anchor:surface->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)route.push_back(&anchor);
|
||||
if(route.size()<12)
|
||||
{error="ore-vein demo needs at least twelve resolved SurfaceWorld route points";return false;}
|
||||
const auto routePoint=[&](const ResolvedLayoutAnchorV2& anchor)
|
||||
{
|
||||
return std::array<double,3>{
|
||||
anchor.values[0]*coreMicrometres/Q,
|
||||
anchor.values[1]*coreMicrometres/Q,
|
||||
anchor.values[2]*coreMicrometres/Q};
|
||||
};
|
||||
const auto routeRadius=[&](const ResolvedLayoutAnchorV2& anchor)
|
||||
{
|
||||
return anchor.values.size()>=4?anchor.values[3]*coreMicrometres/Q:0.0;
|
||||
};
|
||||
for(const auto [pointIndex,id,resourceId,sideSign]:{
|
||||
std::tuple<std::size_t,const char*,std::uint16_t,double>{7,
|
||||
"ore/sw-arrival-route-copper-v1",1,1.0},
|
||||
std::tuple<std::size_t,const char*,std::uint16_t,double>{10,
|
||||
"ore/sw-arrival-route-cobalt-v1",2,-1.0}})
|
||||
{
|
||||
const auto a=routePoint(*route[pointIndex]);
|
||||
const auto b=routePoint(*route[pointIndex+1]);
|
||||
std::array<double,3> tangent={b[0]-a[0],b[1]-a[1],b[2]-a[2]};
|
||||
std::array<double,3> side={-tangent[1]*sideSign,tangent[0]*sideSign,0.0};
|
||||
std::array<double,3> center={(a[0]+b[0])*0.5,(a[1]+b[1])*0.5,
|
||||
(a[2]+b[2])*0.5};
|
||||
const double clearance=std::max(routeRadius(*route[pointIndex]),
|
||||
routeRadius(*route[pointIndex+1]));
|
||||
if(!addCapsule(id,resourceId,center,tangent,side,clearance,
|
||||
resourceId==1?650000:750000,100000,600000,2500000))
|
||||
{error="ore-vein route capsule has a degenerate tangent";return false;}
|
||||
}
|
||||
const auto edge=std::find_if(layout.cavernEdges.begin(),layout.cavernEdges.end(),
|
||||
[&](const auto& value){return value.strateIndex==surface->strateIndex;});
|
||||
if(edge!=layout.cavernEdges.end())
|
||||
{
|
||||
constexpr double t=0.12,one=1.0-t;
|
||||
const std::array<double,4> weights={one*one*one,3.0*one*one*t,
|
||||
3.0*one*t*t,t*t*t};
|
||||
const std::array<double,4> derivative={-3.0*one*one,
|
||||
3.0*one*one-6.0*one*t,6.0*one*t-3.0*t*t,3.0*t*t};
|
||||
std::array<double,3> center{},tangent{};
|
||||
for(std::size_t control=0;control<4;++control)
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double point=edge->controlPointsMicrometres[control][axis];
|
||||
center[axis]+=weights[control]*point;
|
||||
tangent[axis]+=derivative[control]*point;
|
||||
}
|
||||
center[2]+=edge->boreHeightMicrometres*0.5;
|
||||
// The room lies west of the entry tangent; use the east wall for the
|
||||
// approach outcrop so its conservative bounds stay outside the room.
|
||||
std::array<double,3> side={tangent[1],-tangent[0],0.0};
|
||||
const double wallOffset=edge->boreRadiusMicrometres+800000.0+100000.0+200000.0;
|
||||
const double sideLength=std::sqrt(side[0]*side[0]+side[1]*side[1]);
|
||||
if(sideLength>1.0e-9)
|
||||
{side[0]*=wallOffset/sideLength;side[1]*=wallOffset/sideLength;}
|
||||
ResolvedLayoutOreVeinRequestV1 request;
|
||||
request.stableId="ore/sw-chamber-approach-quartz-v1";
|
||||
request.strateIndex=surface->strateIndex;request.resourceMaterialId=3;
|
||||
request.placementRadiusMicrometres=1000000;
|
||||
request.radiusMicrometres=800000;
|
||||
request.irregularityAmplitudeMicrometres=100000;
|
||||
request.irregularityWavelengthMicrometres=1800000;
|
||||
request.blendWidthMicrometres=600000;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double half=1250000.0*tangent[axis]
|
||||
/std::sqrt(tangent[0]*tangent[0]+tangent[1]*tangent[1]
|
||||
+tangent[2]*tangent[2]);
|
||||
request.anchorEndpointsMicrometres[0][axis]=static_cast<std::int64_t>(
|
||||
std::llround(center[axis]+side[axis]-half));
|
||||
request.anchorEndpointsMicrometres[1][axis]=static_cast<std::int64_t>(
|
||||
std::llround(center[axis]+side[axis]+half));
|
||||
}
|
||||
requests.push_back(std::move(request));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverrideTransitions(VFJson::Value& root,int mode,int widthChunks,std::string& error)
|
||||
{
|
||||
auto* object=std::get_if<VFJson::Value::Object>(&root.Data);
|
||||
@@ -674,6 +809,8 @@ namespace
|
||||
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
|
||||
" --seed=N --recipe=surface-world|floating-islands\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"
|
||||
" --landmark-l45-ramp-control (use the buried L45 stamp geometry as an audit control)\n"
|
||||
" --resolved-layout-output=FILE (canonical plan-time layout snapshot)\n"
|
||||
" --resolved-layout-only (exit after plan and snapshot validation)\n"
|
||||
@@ -744,6 +881,8 @@ namespace
|
||||
}
|
||||
else if(arg=="--landmark-chamber-demo")options.LandmarkChamberDemo=true;
|
||||
else if(arg=="--landmark-l45-ramp-control")options.LandmarkL45RampControl=true;
|
||||
else if(arg=="--ore-veins-demo")options.OreVeinsDemo=true;
|
||||
else if(arg=="--audit-ore-vein-yield")options.AuditOreVeinYield=true;
|
||||
else if(arg.starts_with("--resolved-layout-output="))
|
||||
options.ResolvedLayoutOutputPath=std::string(arg.substr(std::string_view("--resolved-layout-output=").size()));
|
||||
else if(arg.starts_with("--seed="))
|
||||
@@ -828,6 +967,8 @@ namespace
|
||||
{std::fprintf(stderr,"--region-crossing requires --camera-step=X,Y,Z\n");return false;}
|
||||
if(options.LandmarkL45RampControl&&!options.LandmarkChamberDemo)
|
||||
{std::fprintf(stderr,"--landmark-l45-ramp-control requires --landmark-chamber-demo\n");return false;}
|
||||
if(options.AuditOreVeinYield&&!options.OreVeinsDemo)
|
||||
{std::fprintf(stderr,"--audit-ore-vein-yield requires --ore-veins-demo\n");return false;}
|
||||
if(options.TlsProbeRequested)return true;
|
||||
if(!options.WorldAssemblerPrototype||!options.StreamBenchmark||!options.StreamPipeline)
|
||||
{
|
||||
@@ -969,6 +1110,43 @@ int main(int argc,char** argv)
|
||||
resolvedLayout.cavernRooms.size(),resolvedLayout.cavernEdges.size(),
|
||||
resolvedLayout.stamps.size(),resolvedLayout.cavernGraphVocabularyVersion);
|
||||
}
|
||||
if(options.OreVeinsDemo)
|
||||
{
|
||||
std::vector<VoxelForgeCore::ResolvedLayoutOreVeinRequestV1> requests;
|
||||
if(!MakeOreVeinDemoRequests(resolvedLayout,requests,error)
|
||||
||!VoxelForgeCore::ResolveResolvedLayoutOreVeinsV1(
|
||||
resolvedLayout,seed,requests,error))
|
||||
{std::fprintf(stderr,"Ore-vein demo resolution failed: %s\n",error.c_str());return 2;}
|
||||
const auto audit=VoxelForgeCore::AuditResolvedLayoutOreVeinPlacementV1(resolvedLayout);
|
||||
std::printf("[ResolvedOreVeinPlacementAudit] vocabulary=%u records=%zu forced_clear_passage=rejected controls=%u/%u status=%s\n",
|
||||
resolvedLayout.oreVeinVocabularyVersion,resolvedLayout.oreVeins.size(),
|
||||
audit.negativeControlsRejected,audit.negativeControlsRun,
|
||||
audit.passed?"PASS":"FAIL");
|
||||
if(!audit.passed)
|
||||
{std::fprintf(stderr,"Resolved ore-vein placement negative control failed.\n");return 2;}
|
||||
for(const auto& vein:resolvedLayout.oreVeins)
|
||||
std::printf("[ResolvedOreVein] id=%s strate=%d resource=%u shape=capsule endpoints_m=(%.3f,%.3f,%.3f)->(%.3f,%.3f,%.3f) radius_m=%.2f irregularity_m=%.2f/%.2f blend_m=%.2f bounds_um=[%lld,%lld)x[%lld,%lld)x[%lld,%lld) seed=%llu\n",
|
||||
vein.stableId.c_str(),vein.strateIndex,vein.resourceMaterialId,
|
||||
vein.endpointsMicrometres[0][0]/1000000.0,
|
||||
vein.endpointsMicrometres[0][1]/1000000.0,
|
||||
vein.endpointsMicrometres[0][2]/1000000.0,
|
||||
vein.endpointsMicrometres[1][0]/1000000.0,
|
||||
vein.endpointsMicrometres[1][1]/1000000.0,
|
||||
vein.endpointsMicrometres[1][2]/1000000.0,
|
||||
vein.radiusMicrometres/1000000.0,
|
||||
vein.irregularityAmplitudeMicrometres/1000000.0,
|
||||
vein.irregularityWavelengthMicrometres/1000000.0,
|
||||
vein.blendWidthMicrometres/1000000.0,
|
||||
static_cast<long long>(vein.boundsMinimumMicrometres[0]),
|
||||
static_cast<long long>(vein.boundsMaximumMicrometres[0]),
|
||||
static_cast<long long>(vein.boundsMinimumMicrometres[1]),
|
||||
static_cast<long long>(vein.boundsMaximumMicrometres[1]),
|
||||
static_cast<long long>(vein.boundsMinimumMicrometres[2]),
|
||||
static_cast<long long>(vein.boundsMaximumMicrometres[2]),
|
||||
static_cast<unsigned long long>(vein.irregularitySeed));
|
||||
std::printf("[ResolvedOreVeinDemo] enabled=true seed=%d records=%zu stable_seed=seed,strate,stable_id placement=side-pocket-and-chamber-approach geometry_changes=0 status=PASS\n",
|
||||
seed,resolvedLayout.oreVeins.size());
|
||||
}
|
||||
const std::string layoutJson=resolvedLayout.ToJson();
|
||||
const auto roundTrip=VoxelForgeCore::ResolvedLayoutSnapshotV3::FromJson(layoutJson,error);
|
||||
if(!roundTrip||roundTrip->ToJson()!=layoutJson||roundTrip->stableIdentity!=resolvedLayout.stableIdentity)
|
||||
@@ -1240,5 +1418,6 @@ int main(int argc,char** argv)
|
||||
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence,
|
||||
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
|
||||
options.AuditResolvedLayoutPassages,options.AuditStrateTransitions,
|
||||
&resolvedLayout,options.StreamHashTiles,options.AuditLandmarkReachability);
|
||||
&resolvedLayout,options.StreamHashTiles,options.AuditLandmarkReachability,
|
||||
options.AuditOreVeinYield);
|
||||
}
|
||||
Reference in new issue
Block a user