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
@@ -5,6 +5,7 @@
|
||||
#include "VoxelCaveMorphology.h"
|
||||
#include "VoxelNoise.h"
|
||||
#include "VoxelStrateManager.h"
|
||||
#include "VoxelDensityPrimitives.h"
|
||||
#include "VoxelForgeCore/VoxelForgeCore.h"
|
||||
#include "VoxelForgeFieldShared.h"
|
||||
|
||||
@@ -32,6 +33,13 @@
|
||||
class FStandaloneShapeWorld
|
||||
{
|
||||
public:
|
||||
struct FResolvedStratumBounds
|
||||
{
|
||||
double BottomZ=0.0;
|
||||
double TopZ=0.0;
|
||||
double SealThickness=0.0;
|
||||
};
|
||||
|
||||
double GetCoreVoxelSizeCm() const
|
||||
{
|
||||
return Owner == nullptr || Owner->CoreVoxelSizeMicrons == 0
|
||||
@@ -47,6 +55,41 @@ public:
|
||||
return static_cast<double>(CHUNK_SIZE) * OwnerVoxelSizeCm / GetCoreVoxelSizeCm();
|
||||
}
|
||||
|
||||
static bool MakeResolvedStratumBounds(double BottomZ,double TopZ,double SealThickness,
|
||||
FResolvedStratumBounds& Out)
|
||||
{
|
||||
if(!std::isfinite(BottomZ)||!std::isfinite(TopZ)||!std::isfinite(SealThickness)
|
||||
||TopZ<=BottomZ||SealThickness<0.0)return false;
|
||||
Out={BottomZ,TopZ,SealThickness};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetResolvedStratumBounds(const FStrateSlot& Slot,FResolvedStratumBounds& Out) const
|
||||
{
|
||||
if(!Owner||!Owner->Manager)return false;
|
||||
const int32 MidChunkZ=(Slot.TopChunkZ+Slot.BottomChunkZ)/2;
|
||||
if(bUseNativeManifestFields&&WorldAssembly
|
||||
&&Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,MidChunkZ))
|
||||
==ECaveGeneratorType::FloatingIslands)
|
||||
{
|
||||
const auto* Plan=FindWorldAssemblyFloatingIslandStratum(Slot.StrateIndex,MidChunkZ);
|
||||
if(Plan&&Plan->manifest.recipe.geometryVersion>=3)
|
||||
{
|
||||
constexpr double Scale=static_cast<double>(
|
||||
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
return MakeResolvedStratumBounds(
|
||||
static_cast<double>(Plan->manifest.recipe.layoutMinimumZSubvoxels)/Scale,
|
||||
static_cast<double>(Plan->manifest.recipe.layoutMaximumZSubvoxels)/Scale,
|
||||
static_cast<double>(Plan->manifest.recipe.boundarySealSubvoxels)/Scale,Out);
|
||||
}
|
||||
}
|
||||
const FStrateGenerationParams Params=Owner->Manager->GetGenerationParams(
|
||||
FIntVector(0,0,MidChunkZ));
|
||||
return MakeResolvedStratumBounds(static_cast<double>(Slot.BottomChunkZ)*CHUNK_SIZE,
|
||||
static_cast<double>(Slot.TopChunkZ+1)*CHUNK_SIZE,
|
||||
static_cast<double>(Params.BoundarySealThickness),Out);
|
||||
}
|
||||
|
||||
enum class EDetailVariant : uint8 { Coherent, Smooth, PerVoxel };
|
||||
struct FBoxClassification
|
||||
{
|
||||
@@ -714,12 +757,12 @@ public:
|
||||
const double TileZ0=Origin.Z,TileZ1=Origin.Z+static_cast<double>(Cells)*Step;
|
||||
for(const FStrateSlot& Slot:Owner->Manager->GetLayout())
|
||||
{
|
||||
const FStrateGenerationParams Params=Owner->Manager->GetGenerationParams(
|
||||
FIntVector(0,0,(Slot.TopChunkZ+Slot.BottomChunkZ)/2));
|
||||
FResolvedStratumBounds Bounds;
|
||||
if(!GetResolvedStratumBounds(Slot,Bounds))continue;
|
||||
const float HalfWidth=static_cast<float>(std::max(8.0,
|
||||
static_cast<double>(Params.BoundarySealThickness)+8.0));
|
||||
const float Boundaries[2]={static_cast<float>(Slot.BottomChunkZ)*CHUNK_SIZE,
|
||||
static_cast<float>(Slot.TopChunkZ+1)*CHUNK_SIZE};
|
||||
Bounds.SealThickness+8.0));
|
||||
const float Boundaries[2]={static_cast<float>(Bounds.BottomZ),
|
||||
static_cast<float>(Bounds.TopZ)};
|
||||
for(const float Z:Boundaries)
|
||||
if(Z+HalfWidth>=TileZ0&&Z-HalfWidth<=TileZ1)
|
||||
Out.stratumBoundaries.push_back({Z,HalfWidth});
|
||||
@@ -1549,13 +1592,18 @@ public:
|
||||
const std::int64_t Seal=IslandPlan->manifest.recipe.boundarySealSubvoxels;
|
||||
const std::int64_t BoxBottom=static_cast<std::int64_t>(BMin[2])*Scale;
|
||||
const std::int64_t BoxTop=static_cast<std::int64_t>(BMax[2])*Scale;
|
||||
const bool bBottomSealOverlap=BoxBottom<Bottom+Seal&&BoxTop>=Bottom;
|
||||
const bool bTopSealOverlap=BoxBottom<=Top&&BoxTop>Top-Seal;
|
||||
const bool bSharedTopSealEnabled=IslandPlan->manifest.recipe.geometryVersion<3
|
||||
||!VoxelDensityAblation::IsBoundarySealOff();
|
||||
const bool bTopSealOverlap=bSharedTopSealEnabled
|
||||
&&BoxBottom<=Top&&BoxTop>Top-Seal;
|
||||
const bool bBottomSealOverlap=IslandPlan->manifest.recipe.geometryVersion<3
|
||||
&&BoxBottom<Bottom+Seal&&BoxTop>=Bottom;
|
||||
if(bBottomSealOverlap)
|
||||
return Finish(BoxBottom>=Bottom&&BoxTop<=Bottom+Seal
|
||||
?EVoxelTileClass::AllSolid:EVoxelTileClass::Mixed);
|
||||
if(bTopSealOverlap)
|
||||
return Finish(BoxBottom>=Top-Seal&&BoxTop<=Top
|
||||
return Finish((IslandPlan->manifest.recipe.geometryVersion<3
|
||||
?BoxBottom>=Top-Seal:BoxBottom>Top-Seal)&&BoxTop<=Top
|
||||
?EVoxelTileClass::AllSolid:EVoxelTileClass::Mixed);
|
||||
const VoxelForgeCore::FloatingIslandFieldV1 Block(
|
||||
IslandPlan->manifest.recipe,IslandPlan->manifest.plan);
|
||||
@@ -2130,9 +2178,28 @@ private:
|
||||
const std::int64_t Top=Plan->manifest.recipe.layoutMaximumZSubvoxels;
|
||||
const std::int64_t Seal=Plan->manifest.recipe.boundarySealSubvoxels;
|
||||
const std::int64_t Zq=ToFixed(Z);
|
||||
if(Zq>=Bottom&&Zq<Bottom+Seal)Density=std::min(Density,-std::max<std::int64_t>(1,Zq-Bottom));
|
||||
if(Zq<=Top&&Zq>Top-Seal)Density=std::min(Density,-std::max<std::int64_t>(1,Top-Zq));
|
||||
OutDensity=static_cast<float>(static_cast<double>(Density)/Scale);
|
||||
if(Plan->manifest.recipe.geometryVersion<3)
|
||||
{
|
||||
if(Zq>=Bottom&&Zq<Bottom+Seal)
|
||||
Density=std::min(Density,-std::max<std::int64_t>(1,Zq-Bottom));
|
||||
if(Zq<=Top&&Zq>Top-Seal)
|
||||
Density=std::min(Density,-std::max<std::int64_t>(1,Top-Zq));
|
||||
OutDensity=static_cast<float>(static_cast<double>(Density)/Scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutDensity=static_cast<float>(static_cast<double>(Density)/Scale);
|
||||
FResolvedStratumBounds Bounds;
|
||||
if(!MakeResolvedStratumBounds(static_cast<double>(Bottom)/Scale,
|
||||
static_cast<double>(Top)/Scale,static_cast<double>(Seal)/Scale,Bounds))
|
||||
return false;
|
||||
const FFloatingIslandParams Params=Owner->Manager->GetFloatingIslandParamsForChunk(
|
||||
FIntVector(0,0,ChunkZ));
|
||||
float InternalDensity=-OutDensity;
|
||||
VF_ApplyUpperBoundarySeal(InternalDensity,Z,static_cast<float>(Bounds.TopZ),
|
||||
static_cast<float>(Bounds.SealThickness),Params.BaseDensity);
|
||||
OutDensity=-InternalDensity;
|
||||
}
|
||||
return std::isfinite(OutDensity);
|
||||
}
|
||||
|
||||
@@ -2351,19 +2418,23 @@ private:
|
||||
int32 Top=MIN_int32,Bottom=MAX_int32;
|
||||
for(const FStrateSlot& Slot:Layout)
|
||||
{
|
||||
Top=std::max(Top,Slot.TopChunkZ);Bottom=std::min(Bottom,Slot.BottomChunkZ);
|
||||
FResolvedStratumBounds Bounds;
|
||||
if(!GetResolvedStratumBounds(Slot,Bounds))continue;
|
||||
const int32 ResolvedBottom=FMath::FloorToInt(static_cast<float>(Bounds.BottomZ));
|
||||
const int32 ResolvedTop=FMath::CeilToInt(static_cast<float>(Bounds.TopZ));
|
||||
Top=std::max(Top,ResolvedTop);Bottom=std::min(Bottom,ResolvedBottom);
|
||||
if(!Slot.Definition)continue;
|
||||
const int32 MidChunkZ=(Slot.TopChunkZ+Slot.BottomChunkZ)/2;
|
||||
FLayerField Field;
|
||||
Field.Lo=Slot.BottomChunkZ*CHUNK_SIZE;
|
||||
Field.Hi=(Slot.TopChunkZ+1)*CHUNK_SIZE;
|
||||
Field.Lo=ResolvedBottom;
|
||||
Field.Hi=ResolvedTop;
|
||||
Field.StrateIndex=Slot.StrateIndex;
|
||||
Field.Params=Owner->Manager->GetGenerationParams(FIntVector(0,0,MidChunkZ));
|
||||
LayerFields.push_back(std::move(Field));
|
||||
}
|
||||
if(Top>=Bottom)
|
||||
{
|
||||
LayerRanges.push_back({Bottom*CHUNK_SIZE,(Top+1)*CHUNK_SIZE});
|
||||
LayerRanges.push_back({Bottom,Top});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user