wip(L17, side branch): FloatingIslands seal-cap fix + owner/Core chunk-scale change (breaks SurfaceWorld)
Not for assembler/world: the 8 m -> 4 m strate chunk change moves every stratum, so the SurfaceWorld spawn camera floats in a void and the L1 mesh export shrank 58.7 -> 31.7 MB. Kept for its diagnostics, the boundarySeal finding and the readable capture shading. See Linux17/REPORT.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
9a7c87e47b
commit
34ae1d7187
30 files changed
+1353
-70
No files matched your search
@@ -25,6 +25,8 @@ namespace
|
||||
float Position[3];
|
||||
float Normal[3];
|
||||
float Height;
|
||||
float WorldPosition[3];
|
||||
float TileData[4];
|
||||
};
|
||||
|
||||
struct FScene
|
||||
@@ -32,6 +34,8 @@ namespace
|
||||
std::uint32_t VoxelSizeMicrons=0;
|
||||
std::array<double,3> CameraMeters{};
|
||||
double YawDegrees=0.0,PitchDegrees=0.0;
|
||||
float MinimumHeight=std::numeric_limits<float>::infinity();
|
||||
float MaximumHeight=-std::numeric_limits<float>::infinity();
|
||||
std::vector<FVertex> Vertices;
|
||||
std::vector<std::uint32_t> Indices;
|
||||
std::uint64_t Triangles=0,SkirtTriangles=0;
|
||||
@@ -70,7 +74,8 @@ namespace
|
||||
if(!Read(File,SurfaceVertices)||!Read(File,SkirtCount)||!Read(File,VertexCount)
|
||||
||!Read(File,IndexCount)||!Read(File,MaskCount)
|
||||
||VertexCount>10000000||IndexCount>60000000||MaskCount>20000000
|
||||
||IndexCount%3!=0||(MaskCount!=0&&MaskCount!=IndexCount/3))
|
||||
||IndexCount%3!=0||(MaskCount!=0&&MaskCount!=IndexCount/3)
|
||||
||Key[3]<0||Key[3]>8)
|
||||
{Error="tile mesh header is malformed";return false;}
|
||||
if(TotalVertices+VertexCount>std::numeric_limits<std::uint32_t>::max()
|
||||
||TotalIndices+IndexCount>std::numeric_limits<std::size_t>::max())
|
||||
@@ -86,6 +91,25 @@ namespace
|
||||
for(float& Value:Scene.Vertices[I].Normal)if(!Read(File,Value))
|
||||
{Error="tile normals are truncated";return false;}
|
||||
Scene.Vertices[I].Height=Scene.Vertices[I].Position[2];
|
||||
Scene.MinimumHeight=std::min(Scene.MinimumHeight,Scene.Vertices[I].Height);
|
||||
Scene.MaximumHeight=std::max(Scene.MaximumHeight,Scene.Vertices[I].Height);
|
||||
}
|
||||
const double TileVoxels=static_cast<double>(32u<<Key[3]);
|
||||
const float TileExtentMeters=static_cast<float>(TileVoxels
|
||||
*static_cast<double>(Scene.VoxelSizeMicrons)/1000000.0);
|
||||
const float TileOriginX=static_cast<float>(static_cast<double>(Key[0])
|
||||
*TileExtentMeters);
|
||||
const float TileOriginY=static_cast<float>(static_cast<double>(Key[1])
|
||||
*TileExtentMeters);
|
||||
for(std::size_t I=Base;I<Base+VertexCount;++I)
|
||||
{
|
||||
FVertex& Vertex=Scene.Vertices[I];
|
||||
std::copy(std::begin(Vertex.Position),std::end(Vertex.Position),
|
||||
std::begin(Vertex.WorldPosition));
|
||||
Vertex.TileData[0]=TileOriginX;
|
||||
Vertex.TileData[1]=TileOriginY;
|
||||
Vertex.TileData[2]=TileExtentMeters;
|
||||
Vertex.TileData[3]=static_cast<float>(Key[3]);
|
||||
}
|
||||
const std::size_t IndexOffset=Scene.Indices.size();
|
||||
Scene.Indices.resize(IndexOffset+IndexCount);
|
||||
@@ -151,8 +175,12 @@ precision highp float;
|
||||
layout(location=0) in vec3 inCameraPosition;
|
||||
layout(location=1) in vec3 inNormal;
|
||||
layout(location=2) in float inHeight;
|
||||
layout(location=3) in vec3 inWorldPosition;
|
||||
layout(location=4) in vec4 inTileData;
|
||||
out vec3 vNormal;
|
||||
out float vHeight;
|
||||
out vec3 vWorldPosition;
|
||||
out vec4 vTileData;
|
||||
uniform float uTanHalfHorizontal;
|
||||
uniform float uTanHalfVertical;
|
||||
uniform float uNear;
|
||||
@@ -165,19 +193,54 @@ void main()
|
||||
inCameraPosition.y/uTanHalfVertical,clipZ,z);
|
||||
vNormal=normalize(inNormal);
|
||||
vHeight=inHeight;
|
||||
vWorldPosition=inWorldPosition;
|
||||
vTileData=inTileData;
|
||||
})GLSL";
|
||||
static constexpr char FragmentSource[]=R"GLSL(#version 300 es
|
||||
precision highp float;
|
||||
in vec3 vNormal;
|
||||
in float vHeight;
|
||||
in vec3 vWorldPosition;
|
||||
in vec4 vTileData;
|
||||
out vec4 outColor;
|
||||
uniform int uReadableMode;
|
||||
uniform int uTileEdges;
|
||||
uniform float uHeightCenter;
|
||||
uniform float uHeightRange;
|
||||
uniform float uTileEdgeWidth;
|
||||
uniform vec3 uLightDirection;
|
||||
void main()
|
||||
{
|
||||
vec3 n=normalize(vNormal);
|
||||
vec3 normalColor=abs(n)*0.78+vec3(0.12);
|
||||
float band=mod(floor((vHeight+10000.0)/80.0),2.0);
|
||||
vec3 bandColor=mix(vec3(0.24,0.31,0.37),vec3(0.39,0.42,0.35),band);
|
||||
outColor=vec4(mix(bandColor,normalColor,0.68),1.0);
|
||||
vec3 color;
|
||||
if(uReadableMode==0)
|
||||
{
|
||||
vec3 normalColor=abs(n)*0.78+vec3(0.12);
|
||||
float band=mod(floor((vHeight+10000.0)/80.0),2.0);
|
||||
vec3 bandColor=mix(vec3(0.24,0.31,0.37),vec3(0.39,0.42,0.35),band);
|
||||
color=mix(bandColor,normalColor,0.68);
|
||||
}
|
||||
else
|
||||
{
|
||||
float heightT=clamp(0.5+(vHeight-uHeightCenter)/max(uHeightRange,0.001),0.0,1.0);
|
||||
vec3 heightTint=mix(vec3(0.80,0.91,1.0),vec3(1.0,0.91,0.77),heightT);
|
||||
float diffuse=max(dot(n,normalize(uLightDirection)),0.0);
|
||||
float illumination=0.62+0.38*diffuse;
|
||||
color=vec3(0.64,0.62,0.56)*heightTint*illumination;
|
||||
}
|
||||
if(uTileEdges!=0&&vTileData.z>0.0)
|
||||
{
|
||||
vec2 local=mod(vWorldPosition.xy-vTileData.xy,vTileData.z);
|
||||
vec2 edge=min(local,vec2(vTileData.z)-local);
|
||||
float distanceToTileEdge=min(edge.x,edge.y);
|
||||
float antialias=max(fwidth(distanceToTileEdge),0.005);
|
||||
float line=1.0-smoothstep(uTileEdgeWidth-antialias,
|
||||
uTileEdgeWidth+antialias,distanceToTileEdge);
|
||||
vec3 edgeColor=mix(vec3(0.16,0.22,0.25),vec3(0.30,0.23,0.14),
|
||||
clamp(vTileData.w/8.0,0.0,1.0));
|
||||
color=mix(color,edgeColor,0.32*line);
|
||||
}
|
||||
outColor=vec4(color,1.0);
|
||||
})GLSL";
|
||||
const GLuint VS=CompileShader(GL_VERTEX_SHADER,VertexSource);
|
||||
const GLuint FS=CompileShader(GL_FRAGMENT_SHADER,FragmentSource);
|
||||
@@ -224,7 +287,8 @@ void main()
|
||||
}
|
||||
|
||||
bool Render(FScene& Scene,const std::filesystem::path& Output,int Width,int Height,
|
||||
double HorizontalFovDegrees)
|
||||
double HorizontalFovDegrees,bool ReadableMode,bool TileEdges,
|
||||
double TileEdgeWidthMeters)
|
||||
{
|
||||
EGLDisplay Display=MakeDisplay();
|
||||
EGLint Major=0,Minor=0;
|
||||
@@ -304,6 +368,10 @@ void main()
|
||||
reinterpret_cast<void*>(offsetof(FVertex,Normal)));
|
||||
glEnableVertexAttribArray(2);glVertexAttribPointer(2,1,GL_FLOAT,GL_FALSE,sizeof(FVertex),
|
||||
reinterpret_cast<void*>(offsetof(FVertex,Height)));
|
||||
glEnableVertexAttribArray(3);glVertexAttribPointer(3,3,GL_FLOAT,GL_FALSE,sizeof(FVertex),
|
||||
reinterpret_cast<void*>(offsetof(FVertex,WorldPosition)));
|
||||
glEnableVertexAttribArray(4);glVertexAttribPointer(4,4,GL_FLOAT,GL_FALSE,sizeof(FVertex),
|
||||
reinterpret_cast<void*>(offsetof(FVertex,TileData)));
|
||||
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);
|
||||
@@ -312,6 +380,14 @@ void main()
|
||||
glUniform1f(glGetUniformLocation(Program,"uTanHalfVertical"),static_cast<float>(TanHalfVertical));
|
||||
glUniform1f(glGetUniformLocation(Program,"uNear"),static_cast<float>(Near));
|
||||
glUniform1f(glGetUniformLocation(Program,"uFar"),static_cast<float>(Far));
|
||||
glUniform1i(glGetUniformLocation(Program,"uReadableMode"),ReadableMode?1:0);
|
||||
glUniform1i(glGetUniformLocation(Program,"uTileEdges"),TileEdges?1:0);
|
||||
glUniform1f(glGetUniformLocation(Program,"uHeightCenter"),
|
||||
static_cast<float>(Scene.CameraMeters[2]));
|
||||
glUniform1f(glGetUniformLocation(Program,"uHeightRange"),64.0f);
|
||||
glUniform1f(glGetUniformLocation(Program,"uTileEdgeWidth"),
|
||||
static_cast<float>(TileEdgeWidthMeters));
|
||||
glUniform3f(glGetUniformLocation(Program,"uLightDirection"),-0.42f,-0.58f,0.70f);
|
||||
glDrawElements(GL_TRIANGLES,static_cast<GLsizei>(Scene.Indices.size()),GL_UNSIGNED_INT,nullptr);
|
||||
glFinish();
|
||||
std::vector<std::uint8_t> Pixels(static_cast<std::size_t>(Width)*Height*4);
|
||||
@@ -323,9 +399,10 @@ void main()
|
||||
{
|
||||
std::error_code SizeError;
|
||||
const auto Bytes=std::filesystem::file_size(Output,SizeError);
|
||||
std::printf("[OffscreenCapture] triangles=%llu tiles=%u skirts=%llu png_bytes=%llu status=PASS path=%s\n",
|
||||
std::printf("[OffscreenCapture] triangles=%llu tiles=%u skirts=%llu shading=%s tile_edges=%s edge_width_m=%.3f png_bytes=%llu status=PASS path=%s\n",
|
||||
static_cast<unsigned long long>(Scene.Triangles),Scene.TileCount,
|
||||
static_cast<unsigned long long>(Scene.SkirtTriangles),
|
||||
ReadableMode?"readable":"normal",TileEdges?"on":"off",TileEdgeWidthMeters,
|
||||
static_cast<unsigned long long>(SizeError?0:Bytes),Output.string().c_str());
|
||||
}
|
||||
glDeleteProgram(Program);glDeleteBuffers(1,&Ebo);glDeleteBuffers(1,&Vbo);
|
||||
@@ -341,12 +418,13 @@ int main(int argc,char** argv)
|
||||
{
|
||||
if(argc<3)
|
||||
{
|
||||
std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N]\n",argv[0]);
|
||||
std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N] [--shade=readable|normal] [--tile-edges=on|off] [--tile-edge-width-m=N]\n",argv[0]);
|
||||
return 2;
|
||||
}
|
||||
int Width=2560,Height=1440;double Fov=90.0;
|
||||
bool HasYaw=false,HasPitch=false;double Yaw=0.0,Pitch=0.0;
|
||||
bool HasCamera=false;std::array<double,3> Camera{};
|
||||
bool ReadableMode=true,TileEdges=false;double TileEdgeWidthMeters=0.15;
|
||||
for(int I=3;I<argc;++I)
|
||||
{
|
||||
const std::string_view Arg(argv[I]);
|
||||
@@ -380,6 +458,28 @@ int main(int argc,char** argv)
|
||||
{std::fprintf(stderr,"Invalid camera angle\n");return 2;}
|
||||
if(IsYaw){Yaw=Parsed;HasYaw=true;}else{Pitch=Parsed;HasPitch=true;}
|
||||
}
|
||||
else if(Arg.starts_with("--shade="))
|
||||
{
|
||||
const std::string_view Mode=Arg.substr(8);
|
||||
if(Mode=="readable")ReadableMode=true;
|
||||
else if(Mode=="normal")ReadableMode=false;
|
||||
else {std::fprintf(stderr,"Invalid shading mode\n");return 2;}
|
||||
}
|
||||
else if(Arg.starts_with("--tile-edges="))
|
||||
{
|
||||
const std::string_view Mode=Arg.substr(13);
|
||||
if(Mode=="on")TileEdges=true;
|
||||
else if(Mode=="off")TileEdges=false;
|
||||
else {std::fprintf(stderr,"Invalid tile-edge mode\n");return 2;}
|
||||
}
|
||||
else if(Arg.starts_with("--tile-edge-width-m="))
|
||||
{
|
||||
char* End=nullptr;const std::string Value(Arg.substr(20));
|
||||
TileEdgeWidthMeters=std::strtod(Value.c_str(),&End);
|
||||
if(End==Value.c_str()||*End!='\0'||!std::isfinite(TileEdgeWidthMeters)
|
||||
||TileEdgeWidthMeters<=0.0||TileEdgeWidthMeters>5.0)
|
||||
{std::fprintf(stderr,"Invalid tile-edge width\n");return 2;}
|
||||
}
|
||||
else {std::fprintf(stderr,"Unknown option: %.*s\n",static_cast<int>(Arg.size()),Arg.data());return 2;}
|
||||
}
|
||||
FScene Scene;std::string Error;
|
||||
@@ -388,10 +488,12 @@ int main(int argc,char** argv)
|
||||
if(HasCamera)Scene.CameraMeters=Camera;
|
||||
if(HasYaw)Scene.YawDegrees=Yaw;
|
||||
if(HasPitch)Scene.PitchDegrees=Pitch;
|
||||
std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f vertices=%zu triangles=%llu\n",
|
||||
std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f height_m=%.3f..%.3f shade=%s tile_edges=%s vertices=%zu triangles=%llu\n",
|
||||
1000000.0/Scene.VoxelSizeMicrons,Scene.CameraMeters[0],Scene.CameraMeters[1],Scene.CameraMeters[2],
|
||||
Scene.YawDegrees,Scene.PitchDegrees,Scene.Vertices.size(),
|
||||
Scene.YawDegrees,Scene.PitchDegrees,Scene.MinimumHeight,Scene.MaximumHeight,
|
||||
ReadableMode?"readable":"normal",TileEdges?"on":"off",Scene.Vertices.size(),
|
||||
static_cast<unsigned long long>(Scene.Triangles));
|
||||
return Render(Scene,argv[2],Width,Height,Fov)?0:3;
|
||||
return Render(Scene,argv[2],Width,Height,Fov,ReadableMode,TileEdges,
|
||||
TileEdgeWidthMeters)?0:3;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user