wip(assembler): round L18 -- FloatingIslands false floors removed; shared strate ceiling
FI geometry v3 drops the all-XY lower boundary seal that created false floors (3.5/8 m); the ceiling comes from the shared VF_ApplyUpperBoundarySeal and AppendStratumBoundaryCeilings path for every generator, at each strate's own configured upper boundary (owner: every strate has a ceiling). Far-LOD ceiling continuity: 0 gaps at LOD4-8. SurfaceWorld bit-identical to L14 (14 configs + 24 m crossing); FI deterministic (28-row matrix); route parity and proofs pass. Unreal: FI geometryVersion 2->3 and the shared upper-seal helper extracted (UBT compile needed on the owner PC). Open: small ceiling holes; lower-stratum LOD ring steps seen through the FI void. 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
87041290dd
commit
dcf0763ec5
36 files changed
+1690
-54
No files matched your search
@@ -16,6 +16,7 @@
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
@@ -38,10 +39,69 @@ namespace
|
||||
float MaximumHeight=-std::numeric_limits<float>::infinity();
|
||||
std::vector<FVertex> Vertices;
|
||||
std::vector<std::uint32_t> Indices;
|
||||
struct FTileRange
|
||||
{
|
||||
std::array<std::int32_t,4> Key{};
|
||||
std::size_t IndexBegin=0;
|
||||
std::uint32_t IndexCount=0;
|
||||
std::vector<std::uint8_t> FaceMasks;
|
||||
};
|
||||
std::vector<FTileRange> Tiles;
|
||||
std::uint64_t Triangles=0,SkirtTriangles=0;
|
||||
std::uint64_t VisibleSkirtTriangles=0,HiddenSameLodSkirtTriangles=0;
|
||||
std::uint64_t DrawnTriangles=0;
|
||||
std::uint32_t TileCount=0;
|
||||
};
|
||||
|
||||
struct FTileKeyHash
|
||||
{
|
||||
std::size_t operator()(const std::array<std::int32_t,4>& Key) const noexcept
|
||||
{
|
||||
std::size_t Hash=0xcbf29ce484222325ull;
|
||||
for(const std::int32_t Value:Key)
|
||||
{
|
||||
Hash^=static_cast<std::uint32_t>(Value);
|
||||
Hash*=0x100000001b3ull;
|
||||
}
|
||||
return Hash;
|
||||
}
|
||||
};
|
||||
|
||||
std::int32_t FloorDiv(std::int64_t Value,std::int64_t Divisor)
|
||||
{
|
||||
const std::int64_t Quotient=Value/Divisor, Remainder=Value%Divisor;
|
||||
return static_cast<std::int32_t>(Quotient-((Remainder<0)?1:0));
|
||||
}
|
||||
|
||||
std::uint8_t ComputeVisibleSkirtFaceMask(
|
||||
const std::array<std::int32_t,4>& Tile,
|
||||
const std::unordered_set<std::array<std::int32_t,4>,FTileKeyHash>& Desired)
|
||||
{
|
||||
const std::int64_t Extent=static_cast<std::int64_t>(32)<<Tile[3];
|
||||
const std::int64_t Origin[3]={static_cast<std::int64_t>(Tile[0])*Extent,
|
||||
static_cast<std::int64_t>(Tile[1])*Extent,static_cast<std::int64_t>(Tile[2])*Extent};
|
||||
std::uint8_t Mask=0;
|
||||
for(std::int32_t Axis=0;Axis<3;++Axis)for(std::int32_t Side=0;Side<2;++Side)
|
||||
{
|
||||
std::int64_t Probe[3]={Origin[0]+Extent/2,Origin[1]+Extent/2,
|
||||
Origin[2]+Extent/2};
|
||||
Probe[Axis]=Side?Origin[Axis]+Extent:Origin[Axis]-1;
|
||||
std::int32_t NeighborLevel=-1;
|
||||
for(std::int32_t Level=0;Level<=8;++Level)
|
||||
{
|
||||
const std::int64_t NeighborExtent=static_cast<std::int64_t>(32)<<Level;
|
||||
const std::array<std::int32_t,4> Neighbor={
|
||||
FloorDiv(Probe[0],NeighborExtent),FloorDiv(Probe[1],NeighborExtent),
|
||||
FloorDiv(Probe[2],NeighborExtent),Level};
|
||||
if(Desired.contains(Neighbor))
|
||||
{NeighborLevel=Level;break;}
|
||||
}
|
||||
if(NeighborLevel<0||NeighborLevel!=Tile[3])
|
||||
Mask|=static_cast<std::uint8_t>(1u<<(Axis*2+Side));
|
||||
}
|
||||
return Mask;
|
||||
}
|
||||
|
||||
template<typename T> bool Read(std::ifstream& File,T& Value)
|
||||
{
|
||||
File.read(reinterpret_cast<char*>(&Value),sizeof(Value));
|
||||
@@ -126,11 +186,36 @@ namespace
|
||||
}
|
||||
Scene.Triangles+=IndexCount/3;
|
||||
Scene.SkirtTriangles+=SkirtCount;
|
||||
Scene.Tiles.push_back({{Key[0],Key[1],Key[2],Key[3]},IndexOffset,
|
||||
IndexCount,std::move(Masks)});
|
||||
TotalVertices+=VertexCount;TotalIndices+=IndexCount;
|
||||
}
|
||||
if(File.peek()!=std::char_traits<char>::eof())
|
||||
{Error="mesh scene has trailing bytes";return false;}
|
||||
if(Scene.Indices.empty()){Error="mesh scene contains no triangles";return false;}
|
||||
std::unordered_set<std::array<std::int32_t,4>,FTileKeyHash> Desired;
|
||||
Desired.reserve(Scene.Tiles.size());
|
||||
for(const auto& Tile:Scene.Tiles)Desired.insert(Tile.Key);
|
||||
std::vector<std::uint32_t> VisibleIndices;
|
||||
VisibleIndices.reserve(Scene.Indices.size());
|
||||
for(const auto& Tile:Scene.Tiles)
|
||||
{
|
||||
const std::uint8_t VisibleMask=ComputeVisibleSkirtFaceMask(Tile.Key,Desired);
|
||||
for(std::uint32_t Triangle=0;Triangle<Tile.IndexCount/3;++Triangle)
|
||||
{
|
||||
const std::size_t MaskIndex=Triangle;
|
||||
const std::uint8_t FaceMask=MaskIndex<Tile.FaceMasks.size()
|
||||
?Tile.FaceMasks[MaskIndex]:0;
|
||||
if(FaceMask!=0&&(FaceMask&VisibleMask)==0)
|
||||
{++Scene.HiddenSameLodSkirtTriangles;continue;}
|
||||
if(FaceMask!=0)++Scene.VisibleSkirtTriangles;
|
||||
const std::size_t Index=Tile.IndexBegin+static_cast<std::size_t>(Triangle)*3;
|
||||
VisibleIndices.insert(VisibleIndices.end(),Scene.Indices.begin()+Index,
|
||||
Scene.Indices.begin()+Index+3);
|
||||
}
|
||||
}
|
||||
Scene.Indices=std::move(VisibleIndices);
|
||||
Scene.DrawnTriangles=Scene.Indices.size()/3;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -399,9 +484,14 @@ void main()
|
||||
{
|
||||
std::error_code SizeError;
|
||||
const auto Bytes=std::filesystem::file_size(Output,SizeError);
|
||||
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,
|
||||
std::printf("[OffscreenCapture] source_triangles=%llu drawn_triangles=%llu tiles=%u "
|
||||
"skirts=%llu visible_skirt_triangles=%llu hidden_same_lod_skirt_triangles=%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),
|
||||
static_cast<unsigned long long>(Scene.DrawnTriangles),Scene.TileCount,
|
||||
static_cast<unsigned long long>(Scene.SkirtTriangles),
|
||||
static_cast<unsigned long long>(Scene.VisibleSkirtTriangles),
|
||||
static_cast<unsigned long long>(Scene.HiddenSameLodSkirtTriangles),
|
||||
ReadableMode?"readable":"normal",TileEdges?"on":"off",TileEdgeWidthMeters,
|
||||
static_cast<unsigned long long>(SizeError?0:Bytes),Output.string().c_str());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user