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

+47 -3
View File
@@ -34,6 +34,7 @@ namespace
float Height;
float WorldPosition[3];
float TileData[4];
float Material[4]{};
};
struct FScene
@@ -121,11 +122,12 @@ namespace
if(!File){Error="cannot open mesh scene";return false;}
char Magic[8]{};
File.read(Magic,sizeof(Magic));
if(!File||std::memcmp(Magic,"VFMSH001",8)!=0)
const bool HasMaterials=File&&std::memcmp(Magic,"VFMSH002",8)==0;
if(!File||(!HasMaterials&&std::memcmp(Magic,"VFMSH001",8)!=0))
{Error="mesh scene magic is invalid";return false;}
std::uint32_t Version=0,ExpectedTiles=0;
if(!Read(File,Version)||!Read(File,Scene.VoxelSizeMicrons)||!Read(File,ExpectedTiles)
||Version!=1||Scene.VoxelSizeMicrons==0||ExpectedTiles>1000000)
||Version!=(HasMaterials?2u:1u)||Scene.VoxelSizeMicrons==0||ExpectedTiles>1000000)
{Error="mesh scene header is malformed";return false;}
for(double& Value:Scene.CameraMeters)if(!Read(File,Value))
{Error="mesh scene camera is truncated";return false;}
@@ -161,6 +163,19 @@ namespace
Scene.MinimumHeight=std::min(Scene.MinimumHeight,Scene.Vertices[I].Height);
Scene.MaximumHeight=std::max(Scene.MaximumHeight,Scene.Vertices[I].Height);
}
if(HasMaterials)
for(std::size_t I=Base;I<Base+VertexCount;++I)
{
std::uint16_t Host=0,Ids[2]{},Weights[2]{};
if(!Read(File,Host)||!Read(File,Ids[0])||!Read(File,Ids[1])
||!Read(File,Weights[0])||!Read(File,Weights[1]))
{Error="tile material attributes are truncated";return false;}
Scene.Vertices[I].Material[0]=static_cast<float>(Ids[0]);
Scene.Vertices[I].Material[1]=static_cast<float>(Weights[0])/65535.0f;
Scene.Vertices[I].Material[2]=static_cast<float>(Ids[1]);
Scene.Vertices[I].Material[3]=static_cast<float>(Weights[1])/65535.0f;
(void)Host;
}
const double TileVoxels=static_cast<double>(32u<<Key[3]);
const float TileExtentMeters=static_cast<float>(TileVoxels
*static_cast<double>(Scene.VoxelSizeMicrons)/1000000.0);
@@ -540,10 +555,12 @@ layout(location=1) in vec3 inNormal;
layout(location=2) in float inHeight;
layout(location=3) in vec3 inWorldPosition;
layout(location=4) in vec4 inTileData;
layout(location=5) in vec4 inMaterial;
out vec3 vNormal;
out float vHeight;
out vec3 vWorldPosition;
out vec4 vTileData;
out vec4 vMaterial;
uniform float uTanHalfHorizontal;
uniform float uTanHalfVertical;
uniform float uNear;
@@ -558,6 +575,7 @@ void main()
vHeight=inHeight;
vWorldPosition=inWorldPosition;
vTileData=inTileData;
vMaterial=inMaterial;
})GLSL";
static constexpr char FragmentSource[]=R"GLSL(#version 300 es
precision highp float;
@@ -565,6 +583,7 @@ in vec3 vNormal;
in float vHeight;
in vec3 vWorldPosition;
in vec4 vTileData;
in vec4 vMaterial;
out vec4 outColor;
uniform int uReadableMode;
uniform int uTileEdges;
@@ -582,6 +601,7 @@ void main()
if(uClipEnabled!=0&&dot(vec4(vWorldPosition,1.0),uClipPlane)<0.0)discard;
vec3 n=normalize(vNormal);
vec3 color;
float illumination=1.0;
if(uReadableMode==0)
{
vec3 normalColor=abs(n)*0.78+vec3(0.12);
@@ -597,10 +617,32 @@ void main()
?mix(vec3(0.62,0.78,1.0),vec3(1.0,0.82,0.62),smoothHeightT)
:vec3(1.0);
float diffuse=max(dot(n,normalize(uLightDirection)),0.0);
float illumination=uGrazingLight!=0?0.32+1.20*diffuse:
illumination=uGrazingLight!=0?0.32+1.20*diffuse:
uHeadlamp!=0?0.78+0.34*diffuse:0.62+0.38*diffuse;
color=vec3(0.64,0.62,0.56)*heightTint*illumination;
}
if(uReadableMode!=0)
{
vec3 resourceColor=vec3(0.0);
float resourceWeight=0.0;
if(vMaterial.x>0.5)
{
float w=clamp(vMaterial.y,0.0,1.0);
vec3 oreColor=vMaterial.x<1.5?vec3(0.94,0.36,0.12):
vMaterial.x<2.5?vec3(0.20,0.48,0.92):vec3(0.25,0.88,0.84);
resourceColor+=oreColor*w;resourceWeight+=w;
}
if(vMaterial.z>0.5)
{
float w=clamp(vMaterial.w,0.0,1.0);
vec3 oreColor=vMaterial.z<1.5?vec3(0.94,0.36,0.12):
vMaterial.z<2.5?vec3(0.20,0.48,0.92):vec3(0.25,0.88,0.84);
resourceColor+=oreColor*w;resourceWeight+=w;
}
if(resourceWeight>0.0)
color=mix(color,resourceColor/max(resourceWeight,0.001),
clamp(resourceWeight,0.0,0.95))*illumination;
}
if(uTileEdges!=0&&vTileData.z>0.0)
{
vec2 local=mod(vWorldPosition.xy-vTileData.xy,vTileData.z);
@@ -749,6 +791,8 @@ void main()
reinterpret_cast<void*>(offsetof(FVertex,WorldPosition)));
glEnableVertexAttribArray(4);glVertexAttribPointer(4,4,GL_FLOAT,GL_FALSE,sizeof(FVertex),
reinterpret_cast<void*>(offsetof(FVertex,TileData)));
glEnableVertexAttribArray(5);glVertexAttribPointer(5,4,GL_FLOAT,GL_FALSE,sizeof(FVertex),
reinterpret_cast<void*>(offsetof(FVertex,Material)));
glViewport(0,0,Width,Height);glDisable(GL_CULL_FACE);glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);glClearColor(0.035f,0.055f,0.075f,1.0f);
glClearDepthf(1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);