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:
Fr0zkaandClaude Opus 5.5 committed 2026-10-24 18:25:03 +02:00
1 parent b9ccff4ad6
commit ca85e876ad
15 files changed
+1573 -19

No files matched your search

+98 -7
View File
@@ -808,6 +808,7 @@ namespace StandaloneStreamBenchmark
{
std::ofstream File;
bool bGood=true;
bool bIncludeMaterialAttributes=false;
std::uint32_t TileCount=0;
template<typename T> void Write(const T& Value)
@@ -818,7 +819,7 @@ namespace StandaloneStreamBenchmark
bool Open(const std::filesystem::path& Path,std::uint32_t VoxelSizeMicrons,
const FVector& CameraVoxels,float YawDegrees,float PitchDegrees,
std::uint32_t ExpectedTiles)
std::uint32_t ExpectedTiles,bool IncludeMaterialAttributes)
{
std::error_code Error;
if(!Path.parent_path().empty())
@@ -826,9 +827,11 @@ namespace StandaloneStreamBenchmark
if(Error)return false;
File.open(Path,std::ios::binary|std::ios::trunc);
if(!File)return false;
constexpr char Magic[8]={'V','F','M','S','H','0','0','1'};
bIncludeMaterialAttributes=IncludeMaterialAttributes;
const char Magic[8]={'V','F','M','S','H','0','0',
static_cast<char>(bIncludeMaterialAttributes?'2':'1')};
File.write(Magic,sizeof(Magic));
const std::uint32_t Version=1;
const std::uint32_t Version=bIncludeMaterialAttributes?2u:1u;
Write(Version);Write(VoxelSizeMicrons);Write(ExpectedTiles);
const double MicronsToMeters=static_cast<double>(VoxelSizeMicrons)/1000000.0;
const double Camera[3]={CameraVoxels.X*MicronsToMeters,
@@ -855,6 +858,13 @@ namespace StandaloneStreamBenchmark
for(const float Value:Vertex.Position)Write(Value);
for(const FStandaloneCpuVertex& Vertex:Tile.Vertices)
for(const float Value:Vertex.Normal)Write(Value);
if(bIncludeMaterialAttributes)
for(const FStandaloneCpuVertex& Vertex:Tile.Vertices)
{
Write(Vertex.HostMaterialId);
for(const std::uint16_t id:Vertex.ResourceMaterialIds)Write(id);
for(const std::uint16_t weight:Vertex.ResourceWeightsQ16)Write(weight);
}
if(IndexCount)
File.write(reinterpret_cast<const char*>(Tile.Indices.data()),
static_cast<std::streamsize>(sizeof(std::uint32_t)*Tile.Indices.size()));
@@ -1097,7 +1107,8 @@ namespace StandaloneStreamBenchmark
bool bAuditResolvedLayoutPassages=false,
bool bAuditStrateTransitions=false,
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr,
bool bPrintTileHashes=false,bool bAuditLandmarkReachability=false)
bool bPrintTileHashes=false,bool bAuditLandmarkReachability=false,
bool bAuditOreVeinYield=false)
{
using Clock=std::chrono::steady_clock;
FStandaloneOwnerWorld& World=*OwnerWorld;
@@ -1282,6 +1293,65 @@ namespace StandaloneStreamBenchmark
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
}
if(bAuditOreVeinYield)
{
if(!ResolvedLayout||ResolvedLayout->oreVeins.empty())
{std::fprintf(stderr,"[OreMiningYield] missing resolved ore-vein records\n");return 2;}
const auto vein=std::find_if(ResolvedLayout->oreVeins.begin(),
ResolvedLayout->oreVeins.end(),[](const auto& value)
{return value.stableId.find("arrival-route-copper")!=std::string::npos;});
const auto& selected=vein==ResolvedLayout->oreVeins.end()
?ResolvedLayout->oreVeins.front():*vein;
const auto micrometresToVoxel=[&](const std::array<std::int64_t,3>& point)
{
const double size=static_cast<double>(World.CoreVoxelSizeMicrons);
return VoxelForgeCore::Vec3d{point[0]/size,point[1]/size,point[2]/size};
};
const std::array<std::int64_t,3> editCenterMicrometres={
(selected.endpointsMicrometres[0][0]+selected.endpointsMicrometres[1][0])/2,
(selected.endpointsMicrometres[0][1]+selected.endpointsMicrometres[1][1])/2,
(selected.endpointsMicrometres[0][2]+selected.endpointsMicrometres[1][2])/2};
const VoxelForgeCore::Vec3d editCenter=micrometresToVoxel(editCenterMicrometres);
const auto mined=Shape.measureOreMiningYieldForSphere(editCenter,1.25,0.25);
std::uint64_t weightedSamples=0;double resourceVolume=0.0;
for(const auto& resource:mined.resources)
{weightedSamples+=resource.weightedSamplesQ16;resourceVolume+=resource.volumeCubicMetres;}
const bool yieldPassed=weightedSamples>0&&resourceVolume>0.0;
std::printf("[OreMiningYield] edit=sphere record=%s center_voxel=(%.3f,%.3f,%.3f) radius_m=1.250 resolution_m=%.3f removed_solid_samples=%llu resource_volume_m3=%.6f status=%s\n",
selected.stableId.c_str(),editCenter.x,editCenter.y,editCenter.z,
mined.sampleSpacingMetres,static_cast<unsigned long long>(mined.solidSamplesRemoved),
resourceVolume,yieldPassed?"PASS":"FAIL");
for(const auto& resource:mined.resources)
std::printf("[OreMiningYieldResource] id=%u volume_m3=%.6f weighted_samples_q16=%llu\n",
resource.resourceMaterialId,resource.volumeCubicMetres,
static_cast<unsigned long long>(resource.weightedSamplesQ16));
VoxelForgeCore::Vec3d airCenter{};
if(!ResolvedLayout->cavernEdges.empty())
{
const auto& edge=ResolvedLayout->cavernEdges.front();
airCenter=micrometresToVoxel(edge.controlPointsMicrometres[0]);
airCenter.z+=edge.boreHeightMicrometres*0.5
/static_cast<double>(World.CoreVoxelSizeMicrons);
}
else if(!ResolvedLayout->passages.empty())
{
const auto& mouth=ResolvedLayout->passages.front().lowerMouthSubvoxels;
const double divisor=static_cast<double>(
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
airCenter={mouth[0]/divisor,mouth[1]/divisor,mouth[2]/divisor};
}
const auto air=Shape.measureOreMiningYieldForSphere(airCenter,1.0,0.25);
std::uint64_t airWeightedSamples=0;
double airResourceVolume=0.0;
for(const auto& resource:air.resources)
{airWeightedSamples+=resource.weightedSamplesQ16;airResourceVolume+=resource.volumeCubicMetres;}
const bool airPassed=airWeightedSamples==0&&airResourceVolume==0.0;
std::printf("[OreMiningYieldControl] case=already-air center_voxel=(%.3f,%.3f,%.3f) radius_m=1.000 resolution_m=0.250 removed_solid_samples=%llu resource_volume_m3=%.6f status=%s\n",
airCenter.x,airCenter.y,airCenter.z,
static_cast<unsigned long long>(air.solidSamplesRemoved),
airResourceVolume,airPassed?"PASS":"FAIL");
if(!yieldPassed||!airPassed)return 14;
}
if(bAuditLandmarkReachability)
{
Streamer.Stop();
@@ -3956,7 +4026,8 @@ namespace StandaloneStreamBenchmark
{
bSceneExportPassing=SceneExport.Open(MeshExportPath,World.CoreVoxelSizeMicrons,
CameraPositionVoxels,CameraYawDegrees,CameraPitchDegrees,
static_cast<std::uint32_t>(Update.DesiredTiles));
static_cast<std::uint32_t>(Update.DesiredTiles),
ResolvedLayout&&!ResolvedLayout->oreVeins.empty());
if(!bSceneExportPassing)
{
Streamer.Stop();
@@ -3966,7 +4037,9 @@ namespace StandaloneStreamBenchmark
}
}
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows,MaterialRows;
std::uint64_t MaterialQueries=0,MaterialCandidateChecks=0,MaterialOutsideTiles=0;
double MaterialQueryMilliseconds=0.0;
int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0;
int32 FullDetailExpected=0;
uint64 WholeNonEmptyMeshTiles=0,WholeTriangleCount=0;
@@ -4197,12 +4270,17 @@ namespace StandaloneStreamBenchmark
NativeColumnComputeMilliseconds+=Tile.CoreDiagnostics.columnComputeMilliseconds;
NativeMeshingMilliseconds+=Tile.CoreDiagnostics.meshingMilliseconds;
}
MaterialQueries+=Tile.CoreDiagnostics.materialQueries;
MaterialCandidateChecks+=Tile.CoreDiagnostics.materialCandidateChecks;
MaterialOutsideTiles+=Tile.CoreDiagnostics.materialTileOutsideEveryVein?1u:0u;
MaterialQueryMilliseconds+=Tile.CoreDiagnostics.materialQueryMilliseconds;
if(bHashDensity)
{
if(Tile.bHasDensityHash)DensityRows.push_back({Tile.Key,Tile.DensityHash});
if(Tile.bHasMeshHash)MeshRows.push_back({Tile.Key,Tile.MeshHash});
if(Tile.bHasPayloadHash)PayloadRows.push_back({Tile.Key,Tile.PayloadHash});
if(Tile.bHasTopologyHash)TopologyRows.push_back({Tile.Key,Tile.TopologyHash});
if(Tile.bHasMaterialHash)MaterialRows.push_back({Tile.Key,Tile.MaterialHash});
}
}
if(!bFirstTileReported&&FirstTileReady.time_since_epoch().count()!=0)
@@ -4580,6 +4658,11 @@ namespace StandaloneStreamBenchmark
static_cast<unsigned long long>(NativeColumnMisses),
NativeColumnComputeMilliseconds,NativeClassificationMilliseconds,
NativeMeshingMilliseconds);
std::printf("[MaterialQueryCost] queries=%llu candidate_checks=%llu outside_vein_tiles=%llu tiles=%d elapsed_ms=%.3f outside_query_ms=0 status=%s\n",
static_cast<unsigned long long>(MaterialQueries),
static_cast<unsigned long long>(MaterialCandidateChecks),
static_cast<unsigned long long>(MaterialOutsideTiles),Finished,
MaterialQueryMilliseconds,MaterialQueries==0?"zero":"measured");
if(bAuditUniformBlockProofs)
std::printf("[UniformBlockProofAudit] checked_blocks=%llu checked_samples=%llu fallback_blocks=%llu unknown_blocks=%llu violations=%llu\n",
static_cast<unsigned long long>(BlockProofBlocksChecked),
@@ -4594,7 +4677,8 @@ namespace StandaloneStreamBenchmark
bHashesPassing=DensityRows.size()==Desired.Tiles.size()
&&MeshRows.size()==Desired.Tiles.size()
&&PayloadRows.size()==Desired.Tiles.size()
&&TopologyRows.size()==Desired.Tiles.size();
&&TopologyRows.size()==Desired.Tiles.size()
&&MaterialRows.size()==Desired.Tiles.size();
if(bPrintTileHashes)
{
const auto makeHashIndex=[](const std::vector<FHashedTile>& rows)
@@ -4607,6 +4691,7 @@ namespace StandaloneStreamBenchmark
const auto MeshIndex=makeHashIndex(MeshRows);
const auto PayloadIndex=makeHashIndex(PayloadRows);
const auto TopologyIndex=makeHashIndex(TopologyRows);
const auto MaterialIndex=makeHashIndex(MaterialRows);
const auto findHash=[](const auto& index,const FVoxelTileKey& key)
{
const auto found=index.find(key);
@@ -4619,6 +4704,10 @@ namespace StandaloneStreamBenchmark
static_cast<unsigned long long>(findHash(MeshIndex,row.Key)),
static_cast<unsigned long long>(findHash(PayloadIndex,row.Key)),
static_cast<unsigned long long>(findHash(TopologyIndex,row.Key)));
for(const FHashedTile& row:MaterialRows)
std::printf("[PipelineTileMaterialHash] lod=%d x=%d y=%d z=%d material=0x%016llx\n",
row.Key.Level,row.Key.Coord.X,row.Key.Coord.Y,row.Key.Coord.Z,
static_cast<unsigned long long>(row.Hash));
}
std::vector<FHashedTile> FullDensity,FullMesh,FullPayload,FullTopology;
for(const FHashedTile& Row:DensityRows)if(Row.Key.Level<World.FullResClipLevels)FullDensity.push_back(Row);
@@ -4635,6 +4724,8 @@ namespace StandaloneStreamBenchmark
static_cast<unsigned long long>(HashTileRows(MeshRows)),
static_cast<unsigned long long>(HashTileRows(PayloadRows)),
static_cast<unsigned long long>(HashTileRows(TopologyRows)));
std::printf("[PipelineMaterialHash] tiles=%zu material=0x%016llx\n",
MaterialRows.size(),static_cast<unsigned long long>(HashTileRows(MaterialRows)));
for(std::size_t LOD=0;LOD<TileCountByLOD.size();++LOD)
{
const auto FilterLOD=[LOD](const std::vector<FHashedTile>& Rows)