wip(assembler): round L22 -- one 8 m layout chunk for every strate; real ceiling -> content -> bedrock
StrateLayoutChunkSizeMeters (world setting, default 8 m; owner decision) is resolved once in the director/adapter and standalone loader; every generator reads the resolved width (no CHUNK_SIZE / Core-tile inference). Every strate gets solid ceiling and bedrock bands from its BoundarySealThickness in the shared composition path (diggable by default); faces come from the shared boundary path. Owner world: FloatingIslands +8..-120 m (128 m, now with a bedrock floor), SurfaceWorld -120..-632 m (unchanged; full-detail and exact-query hashes equal L21); the 60 m gap is gone. The strict layout validator passes on the real world, with 0 endpoint dispatch disagreements. Spawn/benchmark camera derived from route.front. Ledges under the islands gone (reviewer capture). Evaluator 7, recipe schema 2, layout snapshot 2, FI geometry 4. Open: SW cap profiles exceed the ceiling band (owner call); transitions still Hard; Unreal setting/manager/adapter edits uncompiled here. 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
8753f6dbe4
commit
55c26a05a7
28 files changed
+1432
-579
No files matched your search
@@ -32,6 +32,38 @@ namespace
|
||||
using FCoreJsonWriter = TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>;
|
||||
constexpr double OwnerVoxelSizeCm = VOXEL_SIZE;
|
||||
|
||||
float StrateBoundarySealThickness(const UVoxelStrateDefinition& Definition)
|
||||
{
|
||||
switch(Definition.GeneratorType)
|
||||
{
|
||||
case ECaveGeneratorType::SurfaceWorld:return Definition.SurfaceParams.BoundarySealThickness;
|
||||
case ECaveGeneratorType::FloatingIslands:return Definition.FloatingIslandParams.BoundarySealThickness;
|
||||
case ECaveGeneratorType::Maze:return Definition.MazeParams.BoundarySealThickness;
|
||||
case ECaveGeneratorType::VerticalShafts:return Definition.VerticalShaftParams.BoundarySealThickness;
|
||||
case ECaveGeneratorType::TunnelNetwork:
|
||||
case ECaveGeneratorType::FlatPlain:
|
||||
case ECaveGeneratorType::CrystalChamber:
|
||||
case ECaveGeneratorType::Underwater:return Definition.GenerationParams.BoundarySealThickness;
|
||||
}
|
||||
return Definition.GenerationParams.BoundarySealThickness;
|
||||
}
|
||||
|
||||
float StrateBoundarySolidDensity(const UVoxelStrateDefinition& Definition)
|
||||
{
|
||||
switch(Definition.GeneratorType)
|
||||
{
|
||||
case ECaveGeneratorType::SurfaceWorld:return Definition.SurfaceParams.BaseDensity;
|
||||
case ECaveGeneratorType::FloatingIslands:return Definition.FloatingIslandParams.BaseDensity;
|
||||
case ECaveGeneratorType::Maze:return Definition.MazeParams.BaseDensity;
|
||||
case ECaveGeneratorType::VerticalShafts:return Definition.VerticalShaftParams.BaseDensity;
|
||||
case ECaveGeneratorType::TunnelNetwork:
|
||||
case ECaveGeneratorType::FlatPlain:
|
||||
case ECaveGeneratorType::CrystalChamber:
|
||||
case ECaveGeneratorType::Underwater:return Definition.GenerationParams.BaseDensity;
|
||||
}
|
||||
return Definition.GenerationParams.BaseDensity;
|
||||
}
|
||||
|
||||
std::int64_t WorldAssemblyFixed(double Voxels)
|
||||
{
|
||||
return static_cast<std::int64_t>(std::llround(
|
||||
@@ -287,8 +319,10 @@ bool BuildSurfaceStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
const FSurfaceGenerationParams Surface = StrateManager->GetSurfaceParamsForChunk(Chunk);
|
||||
const FBiomeContext BiomeContext = StrateManager->GetBiomeContextForChunk(Chunk);
|
||||
const UVoxelStrateDefinition* Definition = Slot.Definition;
|
||||
const double BottomVoxel = static_cast<double>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const double HeightVoxels = static_cast<double>(Slot.TopChunkZ - Slot.BottomChunkZ + 1) * CHUNK_SIZE;
|
||||
const double LayoutChunkVoxels = static_cast<double>(Recipe.layoutChunkWidthSubvoxels)
|
||||
/ WorldAssemblySubvoxelsPerVoxel;
|
||||
const double BottomVoxel = static_cast<double>(Slot.BottomChunkZ) * LayoutChunkVoxels;
|
||||
const double HeightVoxels = static_cast<double>(Slot.TopChunkZ - Slot.BottomChunkZ + 1) * LayoutChunkVoxels;
|
||||
const FBiomeMapParams& Map = BiomeContext.Map;
|
||||
Recipe.seed = static_cast<std::uint32_t>(StrateManager->GetWorldSeed());
|
||||
Recipe.biomeCellSizeSubvoxels = WorldAssemblyFixed(Map.CellSize);
|
||||
@@ -422,7 +456,7 @@ bool BuildSurfaceStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
Shelf.minimumSubvoxels = {WorldAssemblyFixed(MinX), WorldAssemblyFixed(MinY),
|
||||
std::max(WorldAssemblyFixed(BottomVoxel), LowestGround - WorldAssemblyFixed(4.0))};
|
||||
Shelf.maximumSubvoxels = {WorldAssemblyFixed(MaxX), WorldAssemblyFixed(MaxY),
|
||||
std::min(WorldAssemblyFixed((Slot.TopChunkZ + 1) * CHUNK_SIZE),
|
||||
std::min(WorldAssemblyFixed((Slot.TopChunkZ + 1) * LayoutChunkVoxels),
|
||||
HighestGround + WorldAssemblyFixed(ShelfHeight + 4.0))};
|
||||
Shelf.parametersSubvoxels = {WorldAssemblyFixed(DirX), WorldAssemblyFixed(DirY),
|
||||
WorldAssemblyFixed(ShelfHeight), WorldAssemblyFixed(Reach)};
|
||||
@@ -440,7 +474,7 @@ bool BuildSurfaceStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
|
||||
bool BuildFloatingIslandStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
const FStrateSlot& Slot, VoxelForgeCore::WorldAssemblyManifest& Manifest,
|
||||
double CoreVoxelSizeCm, FString& OutError)
|
||||
double CoreVoxelSizeCm, std::int64_t LayoutChunkWidthSubvoxels, FString& OutError)
|
||||
{
|
||||
using namespace VoxelForgeCore;
|
||||
const FIntVector Chunk(0, 0, Slot.TopChunkZ);
|
||||
@@ -450,7 +484,8 @@ bool BuildFloatingIslandStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
IslandPlan.topChunkZ = Slot.TopChunkZ;
|
||||
IslandPlan.bottomChunkZ = Slot.BottomChunkZ;
|
||||
auto& Recipe = IslandPlan.manifest.recipe;
|
||||
Recipe.geometryVersion = 3;
|
||||
Recipe.geometryVersion = 4;
|
||||
Recipe.layoutChunkWidthSubvoxels = LayoutChunkWidthSubvoxels;
|
||||
Recipe.seed = static_cast<std::uint32_t>(StrateManager->GetWorldSeed());
|
||||
Recipe.ownerVoxelSizeMicrons = static_cast<std::uint32_t>(std::llround(OwnerVoxelSizeCm * 10000.0));
|
||||
Recipe.coreVoxelSizeMicrons = static_cast<std::uint32_t>(std::llround(CoreVoxelSizeCm * 10000.0));
|
||||
@@ -463,12 +498,10 @@ bool BuildFloatingIslandStratumPlan(const UVoxelStrateManager* StrateManager,
|
||||
}
|
||||
Recipe.ownerToCoreScaleNumerator = Recipe.ownerVoxelSizeMicrons / ScaleGcd;
|
||||
Recipe.ownerToCoreScaleDenominator = Recipe.coreVoxelSizeMicrons / ScaleGcd;
|
||||
const double CoreVoxelsPerOwnerChunk = static_cast<double>(CHUNK_SIZE)
|
||||
* Recipe.ownerToCoreScaleNumerator / Recipe.ownerToCoreScaleDenominator;
|
||||
Recipe.layoutMinimumZSubvoxels = WorldAssemblyFixed(
|
||||
static_cast<double>(Slot.BottomChunkZ) * CoreVoxelsPerOwnerChunk);
|
||||
Recipe.layoutMaximumZSubvoxels = WorldAssemblyFixed(
|
||||
static_cast<double>(Slot.TopChunkZ + 1) * CoreVoxelsPerOwnerChunk);
|
||||
Recipe.layoutMinimumZSubvoxels = static_cast<std::int64_t>(Slot.BottomChunkZ)
|
||||
* LayoutChunkWidthSubvoxels;
|
||||
Recipe.layoutMaximumZSubvoxels = static_cast<std::int64_t>(Slot.TopChunkZ + 1)
|
||||
* LayoutChunkWidthSubvoxels;
|
||||
Recipe.layoutCenterTopZSubvoxels = (Recipe.layoutMinimumZSubvoxels
|
||||
+ Recipe.layoutMaximumZSubvoxels) / 2;
|
||||
Recipe.islandDensityQ16 = WorldAssemblyQ16(FMath::Clamp(Params.IslandDensity, 0.0f, 1.0f));
|
||||
@@ -758,6 +791,12 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
const TSharedRef<FJsonObject>& Root,
|
||||
FString& OutError)
|
||||
{
|
||||
const std::uint32_t LayoutChunkSizeMicrometres=StrateManager->GetStrateLayoutChunkSizeMicrometres();
|
||||
const std::uint32_t CoreVoxelMicrometres=static_cast<std::uint32_t>(std::llround(CoreVoxelSizeCm*10000.0));
|
||||
const std::int64_t LayoutChunkWidthSubvoxels=static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(LayoutChunkSizeMicrometres)*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
/std::max<std::uint32_t>(1,CoreVoxelMicrometres)));
|
||||
StrateManager->SetHardTransitionFallbackForAssembly(true);
|
||||
FString ManifestJson;
|
||||
FString ManifestHash;
|
||||
if (!Settings->GetWorldAssemblyManifestJson(ManifestJson, ManifestHash, OutError))
|
||||
@@ -783,6 +822,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
{
|
||||
VoxelForgeCore::WorldAssemblyManifest Generated;
|
||||
Generated.recipe.seed = static_cast<std::uint32_t>(StrateManager->GetWorldSeed());
|
||||
Generated.recipe.layoutChunkWidthSubvoxels=LayoutChunkWidthSubvoxels;
|
||||
int32 SurfaceSlotCount = 0;
|
||||
int32 IslandSlotCount = 0;
|
||||
for (const FStrateSlot& Slot : StrateManager->GetLayout())
|
||||
@@ -815,6 +855,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
{
|
||||
VoxelForgeCore::WorldAssemblyRecipeV1 SlotRecipe;
|
||||
SlotRecipe.seed = static_cast<std::uint32_t>(StrateManager->GetWorldSeed());
|
||||
SlotRecipe.layoutChunkWidthSubvoxels=LayoutChunkWidthSubvoxels;
|
||||
VoxelForgeCore::WorldAssemblyStratumPlanV1 Stratum;
|
||||
if (!BuildSurfaceStratumPlan(StrateManager, Slot,
|
||||
SlotRecipe, Stratum, OutError))
|
||||
@@ -829,7 +870,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
else if (Type == ECaveGeneratorType::FloatingIslands)
|
||||
{
|
||||
if (!BuildFloatingIslandStratumPlan(StrateManager, Slot, Generated,
|
||||
CoreVoxelSizeCm, OutError))
|
||||
CoreVoxelSizeCm, LayoutChunkWidthSubvoxels, OutError))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -873,7 +914,11 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
OutError = TEXT("floating-island override uses a different Core voxel size; regenerate the plan.");
|
||||
return false;
|
||||
}
|
||||
if(Island.manifest.recipe.layoutChunkWidthSubvoxels!=LayoutChunkWidthSubvoxels)
|
||||
{OutError=TEXT("floating-island override uses a different strate-layout chunk width; regenerate the plan.");return false;}
|
||||
}
|
||||
if(Manifest->recipe.layoutChunkWidthSubvoxels!=LayoutChunkWidthSubvoxels)
|
||||
{OutError=TEXT("world assembly manifest uses a different strate-layout chunk width; regenerate the plan.");return false;}
|
||||
|
||||
int32 SurfaceSlotCount = 0;
|
||||
int32 FloatingIslandSlotCount = 0;
|
||||
@@ -946,11 +991,13 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
|
||||
// Keep the inspectable physical-layout export separate from the manifest identity: it is
|
||||
// assembled from the same resolved slots/plans, but adding it must not salt evaluation hashes.
|
||||
VoxelForgeCore::ResolvedLayoutSnapshotV1 Layout;
|
||||
VoxelForgeCore::ResolvedLayoutSnapshotV2 Layout;
|
||||
Layout.worldIdentity = std::string("owner-world/seed/")
|
||||
+ std::to_string(StrateManager->GetWorldSeed());
|
||||
Layout.ownerVoxelSizeMicrometres = static_cast<std::uint32_t>(std::llround(OwnerVoxelSizeCm * 10000.0));
|
||||
Layout.coreVoxelSizeMicrometres = ExpectedCoreVoxelMicrons;
|
||||
Layout.strateLayoutChunkSizeMicrometres=LayoutChunkSizeMicrometres;
|
||||
Layout.strateLayoutChunkWidthSubvoxels=LayoutChunkWidthSubvoxels;
|
||||
const auto generatorName = [](ECaveGeneratorType Type) -> const char*
|
||||
{
|
||||
switch (Type)
|
||||
@@ -987,7 +1034,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const ECaveGeneratorType Type = StrateManager->GetGeneratorTypeForChunk(
|
||||
FIntVector(0, 0, Slot.TopChunkZ));
|
||||
VoxelForgeCore::ResolvedLayoutStratumV1 Item;
|
||||
VoxelForgeCore::ResolvedLayoutStratumV2 Item;
|
||||
Item.strateIndex = Slot.StrateIndex;
|
||||
Item.generatorKind = generatorName(Type);
|
||||
Item.stableId = Layout.worldIdentity + "/strate/" + std::to_string(Slot.StrateIndex)
|
||||
@@ -998,12 +1045,11 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
Item.recipeVersion = Type == ECaveGeneratorType::SurfaceWorld ? Manifest->recipe.schemaVersion : 0;
|
||||
Item.voxelSizeMicrometres = ExpectedCoreVoxelMicrons;
|
||||
Item.interiorBottomMicrometres = static_cast<std::int64_t>(Slot.BottomChunkZ)
|
||||
* CHUNK_SIZE * ExpectedCoreVoxelMicrons;
|
||||
* LayoutChunkSizeMicrometres;
|
||||
Item.interiorTopMicrometres = static_cast<std::int64_t>(Slot.TopChunkZ + 1)
|
||||
* CHUNK_SIZE * ExpectedCoreVoxelMicrons;
|
||||
Item.managerChunkWidthMicrometres = CHUNK_SIZE * OwnerVoxelMicrons;
|
||||
Item.dispatchChunkWidthMicrometres = Type == ECaveGeneratorType::FloatingIslands
|
||||
? CHUNK_SIZE * OwnerVoxelMicrons : CHUNK_SIZE * ExpectedCoreVoxelMicrons;
|
||||
* LayoutChunkSizeMicrometres;
|
||||
Item.managerChunkWidthMicrometres = LayoutChunkSizeMicrometres;
|
||||
Item.dispatchChunkWidthMicrometres = LayoutChunkSizeMicrometres;
|
||||
Item.transitionMode = transitionName(Slot.Definition->TransitionType);
|
||||
Item.transitionBlendChunks = Slot.Definition->TransitionBlendChunks;
|
||||
Item.transitionWidthMicrometres = static_cast<std::int64_t>(Item.transitionBlendChunks)
|
||||
@@ -1011,13 +1057,16 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
Item.transitionWarpAmplitudeMicrometres = Item.transitionMode == "Interleaved"
|
||||
? 2 * Item.managerChunkWidthMicrometres : 0;
|
||||
Item.transitionInterpenetrationMicrometres = 0;
|
||||
Item.transitionHonouredInCore = false;
|
||||
Item.transitionDispatchPath = "upper strate owns lower interface; manager GetGenerationParams can blend legacy vectors, but Core's compiled field selects per-strate/native recipe fields without transition blending";
|
||||
Item.transitionHonouredInCore = Slot.Definition->TransitionType == EVoxelStrateTransition::Hard;
|
||||
Item.transitionFallsBackToHard = Slot.Definition->TransitionType != EVoxelStrateTransition::Hard;
|
||||
Item.transitionDispatchPath = Item.transitionFallsBackToHard
|
||||
? "declared Gradient/Interleaved recorded; Core uses an explicit Hard transition fallback with zero interpenetration"
|
||||
: "declared Hard transition is applied at this interface";
|
||||
Item.managerLookup = "UVoxelStrateManager::GetGeneratorTypeForChunk; transition is controlled by upper strate";
|
||||
if (Type == ECaveGeneratorType::SurfaceWorld)
|
||||
{
|
||||
Item.boundDispatchPath = "BuildSurfaceStratumPlan uses slot chunkZ * 32 Core voxels";
|
||||
Item.queryDispatchPath = "NativeSurfaceDensityAt uses floor(CoreZ / 32), then GetGeneratorTypeForChunk/GetStrateIndex";
|
||||
Item.boundDispatchPath = "BuildSurfaceStratumPlan uses resolved layout chunk width from ResolvedLayoutSnapshotV2";
|
||||
Item.queryDispatchPath = "NativeSurfaceDensityAt selects floor(CoreZ / resolved layout chunk width) from ResolvedLayoutSnapshotV2";
|
||||
const auto Plan = std::find_if(Manifest->plan.strates.begin(), Manifest->plan.strates.end(),
|
||||
[&Slot](const auto& Entry) { return Entry.strateIndex == Slot.StrateIndex; });
|
||||
if (Plan != Manifest->plan.strates.end())
|
||||
@@ -1025,7 +1074,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
for (const auto& Profile : Manifest->recipe.biomes)
|
||||
if (Profile.hasCapProfile)
|
||||
{
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV1 Anchor;
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV2 Anchor;
|
||||
Anchor.kind = "cap_profile";
|
||||
Anchor.stableId = "biome/" + std::to_string(Profile.stableId);
|
||||
Anchor.units = "1/256 Core voxel";
|
||||
@@ -1037,7 +1086,7 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
for (std::size_t RouteIndex = 0; RouteIndex < Plan->route.size(); ++RouteIndex)
|
||||
{
|
||||
const auto& Point = Plan->route[RouteIndex];
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV1 Anchor;
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV2 Anchor;
|
||||
Anchor.kind = "route_point"; Anchor.stableId = "route/" + std::to_string(RouteIndex);
|
||||
Anchor.units = "1/256 Core voxel";
|
||||
Anchor.values = { Point.positionSubvoxels[0], Point.positionSubvoxels[1],
|
||||
@@ -1045,17 +1094,11 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
Item.anchors.push_back(std::move(Anchor));
|
||||
}
|
||||
}
|
||||
Item.ceiling = { "ceiling", Item.interiorTopMicrometres, Item.interiorTopMicrometres,
|
||||
false, true, false, "no separate volumetric boundary band; cap profile remains content",
|
||||
"none", "Heightfield2D cap + AppendStratumBoundaryCeilings fallback mesh" };
|
||||
Item.bedrock = { "bedrock", Item.interiorBottomMicrometres,
|
||||
Item.interiorBottomMicrometres, false, true, false,
|
||||
"no lower bedrock band", "none", "none" };
|
||||
}
|
||||
else if (Type == ECaveGeneratorType::FloatingIslands)
|
||||
{
|
||||
Item.boundDispatchPath = "BuildFloatingIslandStratumPlan uses slot chunkZ * 32 * owner/Core voxel ratio";
|
||||
Item.queryDispatchPath = "NativeFloatingIslandDensityAt uses floor(CoreZ / (32 * owner/Core ratio)), then manager lookup";
|
||||
Item.boundDispatchPath = "BuildFloatingIslandStratumPlan uses resolved layout chunk width from ResolvedLayoutSnapshotV2";
|
||||
Item.queryDispatchPath = "NativeFloatingIslandDensityAt selects floor(CoreZ / resolved layout chunk width) from ResolvedLayoutSnapshotV2";
|
||||
const auto Plan = std::find_if(Manifest->floatingIslands.begin(), Manifest->floatingIslands.end(),
|
||||
[&Slot](const auto& Entry) { return Entry.strateIndex == Slot.StrateIndex; });
|
||||
std::int64_t SealMicrometres = 0;
|
||||
@@ -1063,12 +1106,11 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
{
|
||||
Item.interiorBottomMicrometres = FixedToMicrons(Plan->manifest.recipe.layoutMinimumZSubvoxels);
|
||||
Item.interiorTopMicrometres = FixedToMicrons(Plan->manifest.recipe.layoutMaximumZSubvoxels);
|
||||
SealMicrometres = FixedToMicrons(Plan->manifest.recipe.boundarySealSubvoxels);
|
||||
Item.recipeVersion = Plan->manifest.recipe.geometryVersion;
|
||||
for (std::size_t IslandIndex = 0; IslandIndex < Plan->manifest.plan.islands.size(); ++IslandIndex)
|
||||
{
|
||||
const auto& Island = Plan->manifest.plan.islands[IslandIndex];
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV1 Anchor;
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV2 Anchor;
|
||||
Anchor.kind = "island_anchor"; Anchor.stableId = "island/" + std::to_string(IslandIndex);
|
||||
Anchor.units = "1/256 Core voxel";
|
||||
Anchor.values = { Island.centerSubvoxels[0], Island.centerSubvoxels[1],
|
||||
@@ -1076,38 +1118,35 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
Item.anchors.push_back(std::move(Anchor));
|
||||
}
|
||||
}
|
||||
Item.ceiling = { "ceiling", Item.interiorTopMicrometres - SealMicrometres,
|
||||
Item.interiorTopMicrometres, SealMicrometres > 0, true, false,
|
||||
"v3 shared upper boundary seal; one-sided and inset from upper edge",
|
||||
"upper/interior side", "VF_ApplyUpperBoundarySeal" };
|
||||
Item.bedrock = { "bedrock", Item.interiorBottomMicrometres,
|
||||
Item.interiorBottomMicrometres, false, true, false,
|
||||
"no lower seal in FloatingIsland geometryVersion 3", "none", "none" };
|
||||
}
|
||||
else
|
||||
{
|
||||
Item.boundDispatchPath = "resolved manager slot scaled by Core chunk width";
|
||||
Item.queryDispatchPath = "legacy Core route; manager chunk selected by floor(CoreZ / 32)";
|
||||
const std::int64_t SealMicrometres = static_cast<std::int64_t>(std::llround(
|
||||
std::max(0.0f, Slot.Definition->GenerationParams.BoundarySealThickness)
|
||||
* OwnerVoxelMicrons));
|
||||
Item.ceiling = { "ceiling", Item.interiorTopMicrometres,
|
||||
Item.interiorTopMicrometres + SealMicrometres, false, true, false,
|
||||
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band",
|
||||
"configured upper side", "legacy VF_ApplyBoundarySeal; absent from current Core density path" };
|
||||
Item.bedrock = { "bedrock", Item.interiorBottomMicrometres - SealMicrometres,
|
||||
Item.interiorBottomMicrometres, false, true, false,
|
||||
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band; breakable by default",
|
||||
"configured lower side", "legacy VF_ApplyBoundarySeal; absent from current Core density path" };
|
||||
Item.boundDispatchPath = "resolved manager slot scaled by ResolvedLayoutSnapshotV2 chunk width";
|
||||
Item.queryDispatchPath = "legacy Core route selects manager chunk by floor(CoreZ / resolved layout chunk width)";
|
||||
}
|
||||
const std::int64_t SealMicrometres=static_cast<std::int64_t>(std::llround(
|
||||
std::max(0.0f,StrateBoundarySealThickness(*Slot.Definition))*OwnerVoxelMicrons));
|
||||
if(SealMicrometres<=0)
|
||||
{OutError=FString::Printf(TEXT("Strate %d has no positive BoundarySealThickness for shared ceiling and bedrock bands."),Slot.StrateIndex);return false;}
|
||||
const std::int64_t SolidDensityQ16=std::max<std::int64_t>(1,WorldAssemblyQ16(
|
||||
std::max(0.05f,StrateBoundarySolidDensity(*Slot.Definition))));
|
||||
Item.ceiling={"ceiling",Item.interiorTopMicrometres-SealMicrometres,
|
||||
Item.interiorTopMicrometres,true,true,false,"solid ceiling from strate BoundarySealThickness; breakable by default",
|
||||
"interior-facing lower surface","shared resolved-layout density band",SolidDensityQ16};
|
||||
Item.bedrock={"bedrock",Item.interiorBottomMicrometres,
|
||||
Item.interiorBottomMicrometres+SealMicrometres,true,true,false,
|
||||
"solid bedrock floor from strate BoundarySealThickness; breakable by default",
|
||||
"interior-facing upper surface","shared resolved-layout density band",SolidDensityQ16};
|
||||
Item.content = { "content", Item.interiorBottomMicrometres,
|
||||
Item.interiorTopMicrometres, true, true, false, "resolved generator interior",
|
||||
"none", "none" };
|
||||
Item.content.bottomMicrometres+=SealMicrometres;
|
||||
Item.content.topMicrometres-=SealMicrometres;
|
||||
for (std::size_t PassageIndex = 0; PassageIndex < StrateManager->GetPassages().Num(); ++PassageIndex)
|
||||
{
|
||||
const FVoxelPassage& Passage = StrateManager->GetPassages()[static_cast<int32>(PassageIndex)];
|
||||
if (Passage.UpperStrateIndex != Slot.StrateIndex && Passage.LowerStrateIndex != Slot.StrateIndex) continue;
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV1 Anchor;
|
||||
VoxelForgeCore::ResolvedLayoutAnchorV2 Anchor;
|
||||
Anchor.kind = "passage"; Anchor.stableId = "passage/" + std::to_string(PassageIndex);
|
||||
Anchor.units = "milli owner voxels";
|
||||
Anchor.values = { static_cast<std::int64_t>(std::llround(Passage.UpperPoint.X * 1000.0)),
|
||||
@@ -1127,15 +1166,23 @@ bool AttachValidatedWorldAssembly(const UVoxelSettings* Settings,
|
||||
return false;
|
||||
}
|
||||
const std::string LayoutJson = Layout.ToJson();
|
||||
const FString LayoutText = UTF8_TO_TCHAR(LayoutJson.c_str());
|
||||
TSharedPtr<FJsonObject> LayoutObject;
|
||||
const TSharedRef<TJsonReader<>> LayoutReader = TJsonReaderFactory<>::Create(LayoutText);
|
||||
if (!FJsonSerializer::Deserialize(LayoutReader, LayoutObject) || !LayoutObject.IsValid())
|
||||
Root->SetStringField(TEXT("resolved_layout_json"),UTF8_TO_TCHAR(LayoutJson.c_str()));
|
||||
|
||||
const auto SurfaceSpawnPlan=std::find_if(Manifest->plan.strates.begin(),Manifest->plan.strates.end(),
|
||||
[](const auto& Plan){return !Plan.route.empty();});
|
||||
if(SurfaceSpawnPlan!=Manifest->plan.strates.end())
|
||||
{
|
||||
OutError = TEXT("Core resolved-layout canonical JSON could not be embedded in the resolved snapshot.");
|
||||
return false;
|
||||
const auto& Spawn=SurfaceSpawnPlan->route.front();
|
||||
TSharedRef<FJsonObject> ViewerStart=MakeShared<FJsonObject>();
|
||||
ViewerStart->SetBoolField(TEXT("found_open_space"),true);
|
||||
ViewerStart->SetNumberField(TEXT("x"),static_cast<double>(Spawn.positionSubvoxels[0])
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
ViewerStart->SetNumberField(TEXT("y"),static_cast<double>(Spawn.positionSubvoxels[1])
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
ViewerStart->SetNumberField(TEXT("z"),static_cast<double>(Spawn.positionSubvoxels[2])
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
Root->SetObjectField(TEXT("viewer_start"),ViewerStart);
|
||||
}
|
||||
Root->SetObjectField(TEXT("resolved_layout"), LayoutObject.ToSharedRef());
|
||||
|
||||
const std::string CanonicalJson = Manifest->ToJson();
|
||||
if (CanonicalJson.empty())
|
||||
@@ -1206,6 +1253,8 @@ bool VoxelForgeCoreAdapter::SerializeResolvedWorld(
|
||||
// Override only the temporary schema copy. Clipmap tuning on the owner's asset is preserved.
|
||||
SettingsValue->AsObject()->SetNumberField(TEXT("ClipRadius"), CoreClipRadius);
|
||||
SettingsValue->AsObject()->SetNumberField(TEXT("MaxClipLevel"), CoreMaxClipLevel);
|
||||
SettingsValue->AsObject()->SetNumberField(TEXT("StrateLayoutChunkSizeMeters"),
|
||||
Settings->StrateLayoutChunkSizeMeters);
|
||||
|
||||
TSharedRef<FJsonObject> Root = MakeShared<FJsonObject>();
|
||||
Root->SetNumberField(TEXT("schema_version"), 1);
|
||||
@@ -1225,6 +1274,8 @@ bool VoxelForgeCoreAdapter::SerializeResolvedWorld(
|
||||
Root->SetNumberField(TEXT("edge_seal_thickness"), Settings->EdgeSealThickness);
|
||||
Root->SetNumberField(TEXT("total_strates"), StrateManager->GetNumStrates());
|
||||
Root->SetNumberField(TEXT("inter_strate_gap_chunks"), Settings->InterStrateGapChunks);
|
||||
Root->SetNumberField(TEXT("strate_layout_chunk_size_um"),
|
||||
std::llround(Settings->StrateLayoutChunkSizeMeters*1000000.0));
|
||||
Root->SetNumberField(TEXT("clip_radius"), CoreClipRadius);
|
||||
Root->SetNumberField(TEXT("max_clip_level"), CoreMaxClipLevel);
|
||||
Root->SetNumberField(TEXT("full_res_clip_levels"), Settings->FullResClipLevels);
|
||||
@@ -1292,12 +1343,15 @@ bool VoxelForgeCoreAdapter::SerializeResolvedWorld(
|
||||
return false;
|
||||
}
|
||||
Root->SetArrayField(TEXT("density_samples"), {});
|
||||
TSharedRef<FJsonObject> ViewerStart = MakeShared<FJsonObject>();
|
||||
ViewerStart->SetBoolField(TEXT("found_open_space"), false);
|
||||
ViewerStart->SetNumberField(TEXT("x"), 0.0);
|
||||
ViewerStart->SetNumberField(TEXT("y"), 0.0);
|
||||
ViewerStart->SetNumberField(TEXT("z"), 0.0);
|
||||
Root->SetObjectField(TEXT("viewer_start"), ViewerStart);
|
||||
if(!Root->HasField(TEXT("viewer_start")))
|
||||
{
|
||||
TSharedRef<FJsonObject> ViewerStart = MakeShared<FJsonObject>();
|
||||
ViewerStart->SetBoolField(TEXT("found_open_space"), false);
|
||||
ViewerStart->SetNumberField(TEXT("x"), 0.0);
|
||||
ViewerStart->SetNumberField(TEXT("y"), 0.0);
|
||||
ViewerStart->SetNumberField(TEXT("z"), 0.0);
|
||||
Root->SetObjectField(TEXT("viewer_start"), ViewerStart);
|
||||
}
|
||||
|
||||
FString WriterBuffer;
|
||||
TSharedRef<FCoreJsonWriter> Writer = TJsonWriterFactory<TCHAR,
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace
|
||||
const FVector ChunkCenter(
|
||||
(ChunkCoord.X + 0.5f) * (float)CHUNK_SIZE,
|
||||
(ChunkCoord.Y + 0.5f) * (float)CHUNK_SIZE,
|
||||
(ChunkCoord.Z + 0.5f) * (float)CHUNK_SIZE);
|
||||
(ChunkCoord.Z + 0.5f) * Manager->GetStrateLayoutChunkWidthVoxels());
|
||||
const float ChunkRadius = (float)CHUNK_SIZE * 0.8660254f + 3.0f;
|
||||
const TArray<FVoxelPassage>& Passages = Manager->GetPassages();
|
||||
Cache.FloorProjections.SetNum(Passages.Num());
|
||||
@@ -1103,7 +1103,7 @@ static bool VF_FindWalkableTunnelAir(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(Position.X / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(Position.Y / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(Position.Z / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(Position.Z / Manager->GetStrateLayoutChunkWidthVoxels()));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(Manager, ChunkCoord);
|
||||
const TArray<FVoxelPassage>& Passages = Manager->GetPassages();
|
||||
const FVoxelPassage* PassageData = Passages.GetData();
|
||||
@@ -1138,7 +1138,7 @@ static bool VF_IsAnyPassageFloorAt(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(Position.X / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(Position.Y / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(Position.Z / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(Position.Z / Manager->GetStrateLayoutChunkWidthVoxels()));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(Manager, ChunkCoord);
|
||||
const TArray<FVoxelPassage>& Passages = Manager->GetPassages();
|
||||
const FVoxelPassage* PassageData = Passages.GetData();
|
||||
@@ -1169,6 +1169,17 @@ bool UVoxelStrateManager::Initialize(UVoxelSettings* Settings, int32 WorldSeed)
|
||||
UE_LOG(LogTemp, Error, TEXT("[StrateManager] No settings provided!"));
|
||||
return false;
|
||||
}
|
||||
if (!FMath::IsFinite(Settings->StrateLayoutChunkSizeMeters)
|
||||
|| Settings->StrateLayoutChunkSizeMeters < 0.25f
|
||||
|| Settings->StrateLayoutChunkSizeMeters > 64.0f)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("[StrateManager] StrateLayoutChunkSizeMeters must be in [0.25, 64] m."));
|
||||
return false;
|
||||
}
|
||||
StrateLayoutChunkSizeMicrometres = static_cast<uint32>(std::llround(
|
||||
static_cast<double>(Settings->StrateLayoutChunkSizeMeters) * 1000000.0));
|
||||
StrateLayoutChunkWidthVoxels = static_cast<float>(
|
||||
static_cast<double>(StrateLayoutChunkSizeMicrometres) / (10000.0 * VOXEL_SIZE));
|
||||
|
||||
FVoxelSeasonManifest SeasonManifest;
|
||||
bool bUseSeason = false;
|
||||
@@ -1342,10 +1353,11 @@ bool UVoxelStrateManager::Initialize(UVoxelSettings* Settings, int32 WorldSeed)
|
||||
Slot.Definition->FloatingIslandParams = SeasonStrate.Params.FloatingIslandParams;
|
||||
|
||||
Slot.HeightInChunks = SeasonStrate.HeightInChunks;
|
||||
Slot.TopChunkZ = SeasonStrate.TopWorldZ / CHUNK_SIZE - 1;
|
||||
Slot.BottomChunkZ = SeasonStrate.BottomWorldZ / CHUNK_SIZE;
|
||||
if (SeasonStrate.TopWorldZ % CHUNK_SIZE != 0
|
||||
|| SeasonStrate.BottomWorldZ % CHUNK_SIZE != 0
|
||||
const int32 LayoutChunkVoxels=FMath::RoundToInt(StrateLayoutChunkWidthVoxels);
|
||||
Slot.TopChunkZ = SeasonStrate.TopWorldZ / LayoutChunkVoxels - 1;
|
||||
Slot.BottomChunkZ = SeasonStrate.BottomWorldZ / LayoutChunkVoxels;
|
||||
if (SeasonStrate.TopWorldZ % LayoutChunkVoxels != 0
|
||||
|| SeasonStrate.BottomWorldZ % LayoutChunkVoxels != 0
|
||||
|| Slot.TopChunkZ != CurrentTopZ
|
||||
|| Slot.BottomChunkZ != CurrentTopZ - (Slot.HeightInChunks - 1))
|
||||
{
|
||||
@@ -1525,8 +1537,8 @@ bool UVoxelStrateManager::SetComposerOverrideForStrate(
|
||||
}
|
||||
VF_SetComposerRuntimeBounds(
|
||||
Override->Params,
|
||||
(float)(TargetSlot->TopChunkZ + 1) * CHUNK_SIZE,
|
||||
(float)TargetSlot->BottomChunkZ * CHUNK_SIZE);
|
||||
(float)(TargetSlot->TopChunkZ + 1) * StrateLayoutChunkWidthVoxels,
|
||||
(float)TargetSlot->BottomChunkZ * StrateLayoutChunkWidthVoxels);
|
||||
Override->bUseRecipe = bUseRecipe;
|
||||
if (Recipe != nullptr)
|
||||
{
|
||||
@@ -1545,8 +1557,8 @@ bool UVoxelStrateManager::SetComposerOverrideForStrate(
|
||||
Override->bUseRegions = true;
|
||||
Override->Regions = *InRegions;
|
||||
VF_RekeyStrateRegionManifest(Override->Regions, CandidateSeed, StrateIndex);
|
||||
Override->Regions.StrateTopWorldZ = (float)(TargetSlot->TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Override->Regions.StrateBottomWorldZ = (float)TargetSlot->BottomChunkZ * CHUNK_SIZE;
|
||||
Override->Regions.StrateTopWorldZ = (float)(TargetSlot->TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Override->Regions.StrateBottomWorldZ = (float)TargetSlot->BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
VF_SetStrateArchetypeRuntimeBounds(Override->Params,
|
||||
Override->Regions.StrateTopWorldZ,
|
||||
Override->Regions.StrateBottomWorldZ);
|
||||
@@ -1796,11 +1808,11 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
const FStratePassageConfig& Cfg = UpperDef->PassageConfig;
|
||||
|
||||
// Upper strate floor and lower strate ceiling (differ when there's a bedrock gap).
|
||||
const float UpperTopZ = (float)(Upper.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
const float UpperBottomZ = (float)(Upper.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float LowerTopZ = (float)(Lower.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
const float UpperMax = (float)Upper.HeightInChunks * CHUNK_SIZE * 0.9f;
|
||||
const float LowerMax = (float)Lower.HeightInChunks * CHUNK_SIZE * 0.9f;
|
||||
const float UpperTopZ = (float)(Upper.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
const float UpperBottomZ = (float)(Upper.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float LowerTopZ = (float)(Lower.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
const float UpperMax = (float)Upper.HeightInChunks * StrateLayoutChunkWidthVoxels * 0.9f;
|
||||
const float LowerMax = (float)Lower.HeightInChunks * StrateLayoutChunkWidthVoxels * 0.9f;
|
||||
|
||||
const float DistLo = FMath::Min(Cfg.DistanceMin, Cfg.DistanceMax);
|
||||
const float DistHi = FMath::Max(Cfg.DistanceMin, Cfg.DistanceMax);
|
||||
@@ -1930,7 +1942,7 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
LowerDef->FloatingIslandParams,
|
||||
LowerQuerySeed,
|
||||
LowerTopZ,
|
||||
(float)(Lower.BottomChunkZ) * CHUNK_SIZE,
|
||||
(float)(Lower.BottomChunkZ) * StrateLayoutChunkWidthVoxels,
|
||||
PX,
|
||||
PY,
|
||||
MaxLateralSnap,
|
||||
@@ -1990,7 +2002,7 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
if (bAimedLowerAtPlayerFitPoint)
|
||||
{
|
||||
const float LowerSealThickness = BoundarySealThicknessFor(*LowerDef);
|
||||
const float LowerBottomZ = (float)(Lower.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float LowerBottomZ = (float)(Lower.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float InnerBottomZ = LowerBottomZ + LowerSealThickness;
|
||||
const float InnerTopZ = LowerTopZ - LowerSealThickness;
|
||||
if (VoxelMath::IsFinite(SuggestedLowerPoint.X)
|
||||
@@ -2158,7 +2170,7 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
Cfg.MouthRadius,
|
||||
LowerDoorDirection,
|
||||
LowerTopZ,
|
||||
(float)(Lower.BottomChunkZ) * CHUNK_SIZE,
|
||||
(float)(Lower.BottomChunkZ) * StrateLayoutChunkWidthVoxels,
|
||||
LowerDef ? BoundarySealThicknessFor(*LowerDef) : 0.0f,
|
||||
bAimedLowerAtPlayerFitPoint);
|
||||
Passage.UpperPoint = Passage.UpperLanding.StandingPoint;
|
||||
@@ -2583,8 +2595,8 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
if (bOpenSurfaceEntry && OriginSpineRadius > 0.0f && StrateLayout.Num() > 0)
|
||||
{
|
||||
const FStrateSlot& Top = StrateLayout[0];
|
||||
const float TopZ = (float)(Top.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
const float BottomZ = (float)Top.BottomChunkZ * CHUNK_SIZE;
|
||||
const float TopZ = (float)(Top.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = (float)Top.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
const float TopSeal = Top.Definition
|
||||
? BoundarySealThicknessFor(*Top.Definition) : 0.0f;
|
||||
const VoxelPassageGeometry::FOriginLandingGeometry OriginLanding =
|
||||
@@ -2607,7 +2619,7 @@ void UVoxelStrateManager::GeneratePassages()
|
||||
// the top seal into the finite landing room; lower strate seals remain untouched.
|
||||
Entry.Radius = FMath::Max(OriginSpineRadius,
|
||||
VoxelPassageGeometry::MetersToVoxels(0.25f));
|
||||
Entry.UpperPoint = FVector(0.0f, 0.0f, TopZ + CHUNK_SIZE);
|
||||
Entry.UpperPoint = FVector(0.0f, 0.0f, TopZ + StrateLayoutChunkWidthVoxels);
|
||||
// The capsule's lower tangent meets the room ceiling; it never bores through the
|
||||
// room's floor or creates an origin column in strate 0.
|
||||
Entry.LowerPoint = FVector(
|
||||
@@ -2671,7 +2683,7 @@ float UVoxelStrateManager::EvaluateModifierSDF(float WorldX, float WorldY, float
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
|
||||
// The shortlist is rebuilt once for a (manager, version, chunk) and is shared by the tube,
|
||||
// landing, and floor paths. No source-fit stencil or topology search is allowed below it.
|
||||
@@ -2817,7 +2829,7 @@ void UVoxelStrateManager::ApplyPassageModifier(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
const FVoxelPassage* PassageData = Passages.GetData();
|
||||
const FVector Position(WorldX, WorldY, WorldZ);
|
||||
@@ -2910,7 +2922,7 @@ void UVoxelStrateManager::ApplyPassageLandingAir(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
if (Nearby.Num() == 0) return;
|
||||
|
||||
@@ -3021,7 +3033,7 @@ void UVoxelStrateManager::ApplyPassageLandingFloorMC(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
const FVoxelPassage* PassageData = Passages.GetData();
|
||||
const FVector Position(WorldX, WorldY, WorldZ);
|
||||
@@ -3117,7 +3129,7 @@ void UVoxelStrateManager::ApplyPassageStructuralPostsMC(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
if (Nearby.Num() == 0) return;
|
||||
|
||||
@@ -3244,7 +3256,7 @@ void UVoxelStrateManager::ApplyPassageNativeFloorMC(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
if (Nearby.Num() == 0
|
||||
|| VoxelPassageGeometry::VerticalShaftConnectorAirMarker())
|
||||
@@ -3435,7 +3447,7 @@ void UVoxelStrateManager::ApplyPassageLandingRoomFloorMC(
|
||||
const FIntVector ChunkCoord(
|
||||
FMath::FloorToInt(WorldX / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldY / (float)CHUNK_SIZE),
|
||||
FMath::FloorToInt(WorldZ / (float)CHUNK_SIZE));
|
||||
FMath::FloorToInt(WorldZ / StrateLayoutChunkWidthVoxels));
|
||||
const TArray<int32>& Nearby = VF_GetNearbyPassages(this, ChunkCoord);
|
||||
const FVoxelPassage* PassageData = Passages.GetData();
|
||||
const FVector Position(WorldX, WorldY, WorldZ);
|
||||
@@ -5909,8 +5921,8 @@ bool UVoxelStrateManager::AnyLandingFloorAtLattice(
|
||||
for (const FStrateSlot& Slot : StrateLayout)
|
||||
{
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float Seal = VF_BoundarySealThicknessForDefinition(*Slot.Definition);
|
||||
const VoxelPassageGeometry::FOriginLandingGeometry Geometry =
|
||||
VoxelPassageGeometry::BuildOriginLandingGeometry(
|
||||
@@ -5952,8 +5964,8 @@ bool UVoxelStrateManager::AnyOriginLandingNearBox(
|
||||
for (const FStrateSlot& Slot : StrateLayout)
|
||||
{
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
if (VoxelPassageGeometry::OriginLandingRoomTouchesBox(
|
||||
VoxelBox, TopZ, BottomZ,
|
||||
VF_BoundarySealThicknessForDefinition(*Slot.Definition),
|
||||
@@ -5973,8 +5985,8 @@ bool UVoxelStrateManager::AnyOriginLandingFloorNearBox(
|
||||
for (const FStrateSlot& Slot : StrateLayout)
|
||||
{
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
if (VoxelPassageGeometry::OriginLandingFloorTouchesBox(
|
||||
VoxelBox, TopZ, BottomZ,
|
||||
VF_BoundarySealThicknessForDefinition(*Slot.Definition),
|
||||
@@ -5998,8 +6010,8 @@ bool UVoxelStrateManager::AnyOriginLandingNearLattice(
|
||||
for (const FStrateSlot& Slot : StrateLayout)
|
||||
{
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float Seal = VF_BoundarySealThicknessForDefinition(*Slot.Definition);
|
||||
if (VoxelPassageGeometry::OriginLandingRoomTouchesLattice(
|
||||
VoxelBox, LatticeOrigin, Step, TopZ, BottomZ, Seal, OriginSpineRadius,
|
||||
@@ -6036,8 +6048,8 @@ bool UVoxelStrateManager::AnyOriginLandingAirNearLattice(
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float Seal = VF_BoundarySealThicknessForDefinition(*Slot.Definition);
|
||||
const VoxelPassageGeometry::FOriginLandingGeometry Geometry =
|
||||
VoxelPassageGeometry::BuildOriginLandingGeometry(
|
||||
@@ -6113,8 +6125,8 @@ bool UVoxelStrateManager::AnyOriginLandingFloorNearLattice(
|
||||
for (const FStrateSlot& Slot : StrateLayout)
|
||||
{
|
||||
if (Slot.Definition == nullptr) continue;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * CHUNK_SIZE;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (static_cast<float>(Slot.TopChunkZ) + 1.0f) * StrateLayoutChunkWidthVoxels;
|
||||
const float BottomZ = static_cast<float>(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float Seal = VF_BoundarySealThicknessForDefinition(*Slot.Definition);
|
||||
if (VoxelPassageGeometry::OriginLandingFloorTouchesLattice(
|
||||
VoxelBox, LatticeOrigin, Step, TopZ, BottomZ, Seal, OriginSpineRadius))
|
||||
@@ -6148,7 +6160,7 @@ int32 UVoxelStrateManager::FindSlotIndexForChunkZ(int32 ChunkZ) const
|
||||
UVoxelStrateDefinition* UVoxelStrateManager::GetStrateAt(float WorldZ) const
|
||||
{
|
||||
// Convert world Z to chunk Z coordinate
|
||||
int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / CHUNK_SIZE);
|
||||
int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / StrateLayoutChunkWidthVoxels);
|
||||
int32 SlotIdx = FindSlotIndexForChunkZ(ChunkZ);
|
||||
if (SlotIdx >= 0)
|
||||
{
|
||||
@@ -6159,7 +6171,7 @@ UVoxelStrateDefinition* UVoxelStrateManager::GetStrateAt(float WorldZ) const
|
||||
|
||||
int32 UVoxelStrateManager::GetStrateIndex(float WorldZ) const
|
||||
{
|
||||
int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / CHUNK_SIZE);
|
||||
int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / StrateLayoutChunkWidthVoxels);
|
||||
int32 SlotIdx = FindSlotIndexForChunkZ(ChunkZ);
|
||||
if (SlotIdx >= 0)
|
||||
{
|
||||
@@ -6318,9 +6330,9 @@ FSlabGenerationParams UVoxelStrateManager::GetSlabParamsForChunk(const FIntVecto
|
||||
|
||||
// Fill in the runtime Z bounds (voxel coordinates, same convention as
|
||||
// FStrateGenerationParams::StrateTopWorldZ / StrateBottomWorldZ).
|
||||
// TopChunkZ+1 because the top chunk's CEILING is at (TopChunkZ+1)*CHUNK_SIZE.
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
// TopChunkZ+1 because the top chunk's CEILING is at (TopChunkZ+1)*StrateLayoutChunkWidthVoxels.
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
return Result;
|
||||
}
|
||||
@@ -6353,8 +6365,8 @@ FMazeGenerationParams UVoxelStrateManager::GetMazeParamsForChunk(const FIntVecto
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -6380,8 +6392,8 @@ FSurfaceGenerationParams UVoxelStrateManager::GetSurfaceParamsForChunk(const FIn
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -6407,8 +6419,8 @@ FVerticalShaftParams UVoxelStrateManager::GetVerticalShaftParamsForChunk(const F
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -6434,8 +6446,8 @@ FFloatingIslandParams UVoxelStrateManager::GetFloatingIslandParamsForChunk(const
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -6469,14 +6481,14 @@ FBiomeContext UVoxelStrateManager::GetBiomeContextForChunk(const FIntVector& Chu
|
||||
|
||||
bool UVoxelStrateManager::GetStrateUnrealZRange(float WorldZ, float& OutTopZ, float& OutBottomZ) const
|
||||
{
|
||||
const int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / CHUNK_SIZE);
|
||||
const int32 ChunkZ = FMath::FloorToInt((WorldZ / VOXEL_SIZE) / StrateLayoutChunkWidthVoxels);
|
||||
const int32 SlotIdx = FindSlotIndexForChunkZ(ChunkZ);
|
||||
if (SlotIdx < 0) return false;
|
||||
|
||||
const FStrateSlot& Slot = StrateLayout[SlotIdx];
|
||||
// Voxel-space Z bounds → Unreal units. Ceiling = top chunk's upper edge.
|
||||
OutTopZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE * VOXEL_SIZE;
|
||||
OutBottomZ = (float)(Slot.BottomChunkZ) * CHUNK_SIZE * VOXEL_SIZE;
|
||||
OutTopZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels * VOXEL_SIZE;
|
||||
OutBottomZ = (float)(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels * VOXEL_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6489,8 +6501,8 @@ FStrateDisturbanceParams UVoxelStrateManager::GetDisturbanceParamsForChunk(const
|
||||
}
|
||||
const FStrateSlot& Slot = StrateLayout[SlotIdx];
|
||||
FStrateDisturbanceParams Result = Slot.Definition->Disturbances;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -6522,8 +6534,8 @@ float UVoxelStrateManager::GetWaterLevelWorldZForChunk(const FIntVector& ChunkCo
|
||||
}
|
||||
if (Rel <= 0.0f) return -FLT_MAX;
|
||||
|
||||
const float BottomZ = (float)(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
const float TopZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
const float BottomZ = (float)(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
const float TopZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
return FMath::Lerp(BottomZ, TopZ, FMath::Clamp(Rel, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
@@ -6567,8 +6579,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
FindComposerOverride(Slot.StrateIndex))
|
||||
{
|
||||
FStrateGenerationParams Result = Override->Params.TunnelNetworkParams;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
// A candidate is a hard replacement of this slot. Do not blend its rolled vector with an
|
||||
// authored neighbour at a boundary; this is also how the offline fixture measures it.
|
||||
return ResolveFinalParams(Result);
|
||||
@@ -6578,8 +6590,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
if (SeasonStrates.IsValidIndex(SlotIdx))
|
||||
{
|
||||
FStrateGenerationParams Result = SeasonStrates[SlotIdx].Params.TunnelNetworkParams;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * CHUNK_SIZE;
|
||||
Result.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
Result.StrateBottomWorldZ = (float)Slot.BottomChunkZ * StrateLayoutChunkWidthVoxels;
|
||||
// Season vectors are already final, measured slot records. Vertical structural posts own
|
||||
// their boundary; blending them with another selected recipe would describe neither one.
|
||||
return ResolveFinalParams(Result);
|
||||
@@ -6596,8 +6608,17 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
//
|
||||
// TopChunkZ=0, CHUNK_SIZE=32: top of the strate = chunk 0's top edge = voxel Z=32
|
||||
// BottomChunkZ=-3: bottom of the strate = chunk -3's bottom edge = voxel Z=-3*32 = -96
|
||||
BaseParams.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
BaseParams.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * CHUNK_SIZE;
|
||||
BaseParams.StrateTopWorldZ = (float)(Slot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
BaseParams.StrateBottomWorldZ = (float)(Slot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
// Core currently dispatches one generator field per resolved strate. Gradient and
|
||||
// interleaved metadata therefore use the explicitly declared Hard fallback for every
|
||||
// legacy parameter lookup as well; mixing parameter vectors here would disagree with the
|
||||
// shared ceiling/content/bedrock composition layer.
|
||||
if (bHardTransitionFallbackForAssembly)
|
||||
{
|
||||
return ResolveFinalParams(BaseParams);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// BOUNDARY BLENDING (transition-type aware)
|
||||
@@ -6670,8 +6691,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
if (EffectiveBlend > 0 && DistFromBottom < EffectiveBlend)
|
||||
{
|
||||
FStrateGenerationParams BelowParams = BuildParamsFromDefinition(BelowSlot.Definition);
|
||||
BelowParams.StrateTopWorldZ = (float)(BelowSlot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
BelowParams.StrateBottomWorldZ = (float)(BelowSlot.BottomChunkZ) * CHUNK_SIZE;
|
||||
BelowParams.StrateTopWorldZ = (float)(BelowSlot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
BelowParams.StrateBottomWorldZ = (float)(BelowSlot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
// Linear alpha: 0 at EffectiveBlend chunks away, 1 at the boundary
|
||||
float Alpha = 1.0f - ((float)DistFromBottom / (float)EffectiveBlend);
|
||||
@@ -6708,8 +6729,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
if (DistFromBottom < CheckRange)
|
||||
{
|
||||
FStrateGenerationParams BelowParams = BuildParamsFromDefinition(BelowSlot.Definition);
|
||||
BelowParams.StrateTopWorldZ = (float)(BelowSlot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
BelowParams.StrateBottomWorldZ = (float)(BelowSlot.BottomChunkZ) * CHUNK_SIZE;
|
||||
BelowParams.StrateTopWorldZ = (float)(BelowSlot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
BelowParams.StrateBottomWorldZ = (float)(BelowSlot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
// Sample 3D Perlin noise to warp the boundary position.
|
||||
// XY frequency 0.15 gives medium-scale variation (~6-7 chunks per cycle).
|
||||
@@ -6769,8 +6790,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
if (EffectiveBlend > 0 && DistFromTop < EffectiveBlend)
|
||||
{
|
||||
FStrateGenerationParams AboveParams = BuildParamsFromDefinition(AboveSlot.Definition);
|
||||
AboveParams.StrateTopWorldZ = (float)(AboveSlot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
AboveParams.StrateBottomWorldZ = (float)(AboveSlot.BottomChunkZ) * CHUNK_SIZE;
|
||||
AboveParams.StrateTopWorldZ = (float)(AboveSlot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
AboveParams.StrateBottomWorldZ = (float)(AboveSlot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
float Alpha = 1.0f - ((float)DistFromTop / (float)EffectiveBlend);
|
||||
Alpha = FMath::Clamp(Alpha, 0.0f, 1.0f);
|
||||
@@ -6791,8 +6812,8 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
|
||||
if (DistFromTop < CheckRange)
|
||||
{
|
||||
FStrateGenerationParams AboveParams = BuildParamsFromDefinition(AboveSlot.Definition);
|
||||
AboveParams.StrateTopWorldZ = (float)(AboveSlot.TopChunkZ + 1) * CHUNK_SIZE;
|
||||
AboveParams.StrateBottomWorldZ = (float)(AboveSlot.BottomChunkZ) * CHUNK_SIZE;
|
||||
AboveParams.StrateTopWorldZ = (float)(AboveSlot.TopChunkZ + 1) * StrateLayoutChunkWidthVoxels;
|
||||
AboveParams.StrateBottomWorldZ = (float)(AboveSlot.BottomChunkZ) * StrateLayoutChunkWidthVoxels;
|
||||
|
||||
// Same noise function but with a different seed offset to avoid
|
||||
// symmetry between top and bottom boundaries of adjacent strates
|
||||
|
||||
Reference in new issue
Block a user