refactor(dead-code): remove functions, members and types with no caller

Each symbol below had zero references in Source/ (tests included), Tools/,
Config/ and the build files after comment/string stripping.

Functions: EvaluateTunnelCoreSDF, EvaluateSDF (uncached wrapper),
IsTunnelSupportFloorWorldPoint, BuildTunnelSupportFloorColumn,
IsTunnelSupportFloorColumnZ, GetTunnelSupportFloorColumnBand,
VF_TunnelFloorAtSegment, VF_ProjectSweptTunnelFloor, FVoxelWormField
EvaluateExact, ApplyPassageLandingAirMC, ApplyPassageTunnelAirMC,
GetGenerationParamsFingerprint, FVoxelStrateCorpus::LoadFromSettings,
GetSkippedDefinitions, VF_RollStrateParams, VF_ArePlayerFitConnectedWithSampler,
VF_GetVoxelSeasonSelectionReasonName, UVoxelSeasonAsset::GetManifestContentHash,
FVoxelStackSampler::IsRunning, CompareSkippedPostValue,
MakeSurfaceColumnSource, WriteObjTile, ExploreEffectName,
ExploreTileClassName, and the VoxelTypes.h chunk-local helpers
(WorldToLocalCoord, ChunkToWorldPos, LocalToIndex, IndexToLocal,
IsValidLocalCoord, GetFaceDirection, GetFaceNormal, CHUNK_SIZE_SQUARED,
CHUNK_VOLUME).

Members/types: write-only floor flags (FVoxelOpSample::
bProtectedStructuralFloor, StructuralFloorMinimumDensity,
bTunnelCoreSupportFloor; bSupportFloor on the tunnel evaluations;
FTunnelFloorSegmentProfile::NumSteps), UVoxelStrateManager::BlendChunks,
unused FSummary counters in the stack sampler, two unused
FVoxelSeasonCompositionSettings aliases, and a few unused locals/constants.

No UPROPERTY, UFUNCTION, reflected type or enum was touched. Behaviour is
unchanged: removed code was unreachable or only written, never read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01URDGLsu7c4nunqNFPJEFPU
This commit is contained in:
Claude committed 2026-09-28 14:09:05 +00:00
1 parent 4753416d4a
commit 3f629f407a
26 files changed
+8 -1112

No files matched your search

@@ -81,7 +81,6 @@ namespace
struct FVFTunnelShapeEvaluation
{
float SDF = FLT_MAX;
bool bSupportFloor = false;
bool bHasSweptFloor = false;
float SweptFloorZ = -FLT_MAX;
float SweptFloorRadius = 0.0f;
@@ -548,7 +547,6 @@ namespace
Profile.NaturalStartFloorZ = FloorA;
Profile.NaturalEndFloorZ = FloorB;
Profile.bLedgeTransition = false;
Profile.NumSteps = 0;
if (bHasLedgeLevels)
{
@@ -934,27 +932,6 @@ namespace
return FloorZ;
}
FORCEINLINE float VF_TunnelFloorAtSegment(
const FVector& A, float RadiusA,
const FVector& B, float RadiusB,
float T, int32 SegmentIndex, int32 NumSegments,
const FVector& Position,
const FCachedTunnel& Tunnel,
const void* CacheIdentity, int32 TunnelIndex,
bool bEvaluateRelief,
const FVFFloorReliefColumnKey& Column,
const FTunnelFloorSegmentProfile* FloorProfile,
const FVFRoomFloorOwnership* RoomFloorOwnership)
{
const FVFTunnelFloorTerms Terms = VF_TunnelFloorTerms(
A, RadiusA, B, RadiusB,
T, SegmentIndex, NumSegments, Tunnel, FloorProfile,
RoomFloorOwnership);
return VF_TunnelFloorFromTerms(
Position, Tunnel, Terms,
CacheIdentity, TunnelIndex, bEvaluateRelief, Column);
}
FORCEINLINE bool VF_ProjectTunnelSegmentXY(
const FVector& Position, const FVector& A, const FVector& B,
float& OutT, float& OutDistanceSquared)
@@ -1229,76 +1206,6 @@ namespace
RoomFloorOwnership);
}
static bool VF_ProjectSweptTunnelFloor(
const FVector& Position,
const FCachedTunnel& Tunnel,
bool bWorldChain,
float& OutFloorZ,
float& OutSupportRadius,
const void* CacheIdentity, int32 TunnelIndex,
const FVFRoomFloorOwnership* RoomFloorOwnership = nullptr)
{
const FVFFloorReliefColumnKey ReliefColumn =
VF_MakeFloorReliefColumnKey(
static_cast<float>(Position.X), static_cast<float>(Position.Y));
const TArray<FVector>& ControlPoints = bWorldChain
? Tunnel.WorldControlPoints : Tunnel.ControlPoints;
const TArray<float>& ControlRadii = bWorldChain
? Tunnel.WorldControlRadii : Tunnel.ControlRadii;
if (ControlPoints.Num() < 2
|| ControlRadii.Num() != ControlPoints.Num())
{
return false;
}
const int32 ControlPointCount = ControlPoints.Num();
const int32 NumSegments = ControlPointCount - 1;
const FVector* ControlPointData = ControlPoints.GetData();
const float* ControlRadiusData = ControlRadii.GetData();
const TArray<FTunnelFloorSegmentProfile>* FloorProfiles = bWorldChain
? &Tunnel.WorldFloorProfiles : &Tunnel.FloorProfiles;
const FTunnelFloorSegmentProfile* FloorProfileData =
FloorProfiles->Num() == NumSegments ? FloorProfiles->GetData() : nullptr;
float BestDistanceSquared = FLT_MAX;
bool bFound = false;
for (int32 SegmentIndex = 0;
SegmentIndex < NumSegments;
++SegmentIndex)
{
float T = 0.0f;
float DistanceSquared = FLT_MAX;
if (!VF_ProjectTunnelSegmentXY(
Position,
ControlPointData[SegmentIndex], ControlPointData[SegmentIndex + 1],
T, DistanceSquared)
|| DistanceSquared >= BestDistanceSquared)
{
continue;
}
const float RadiusA = ControlRadiusData[SegmentIndex];
const float RadiusB = ControlRadiusData[SegmentIndex + 1];
OutFloorZ = VF_TunnelFloorAtSegment(
ControlPointData[SegmentIndex], RadiusA,
ControlPointData[SegmentIndex + 1], RadiusB,
T, SegmentIndex, NumSegments, Position, Tunnel,
CacheIdentity, TunnelIndex, /*bEvaluateRelief=*/true,
ReliefColumn,
FloorProfileData != nullptr ? FloorProfileData + SegmentIndex : nullptr,
RoomFloorOwnership);
OutSupportRadius = FMath::Max(
FMath::Min(FMath::Abs(RadiusA), FMath::Abs(RadiusB)) - 0.5f,
VoxelPassageGeometry::PlayerRadiusVoxels);
BestDistanceSquared = DistanceSquared;
bFound = true;
}
return bFound
&& VoxelMath::IsFinite(OutFloorZ)
&& VoxelMath::IsFinite(OutSupportRadius)
&& BestDistanceSquared <= FMath::Square(OutSupportRadius);
}
}
void FChunkSDFSpatialIndex::Reset()
@@ -8960,50 +8867,6 @@ float VoxelCaveMorphology::EvaluateSDFCached(
return MinSDF;
}
float VoxelCaveMorphology::EvaluateTunnelCoreSDF(
float WorldX, float WorldY, float WorldZ,
const FChunkSDFCache& Cache,
bool bUseSpatialIndex)
{
if (VoxelDensityAblation::IsTunnelCoreOff())
{
return FLT_MAX;
}
const FVector Pos(WorldX, WorldY, WorldZ);
float MinSDF = FLT_MAX;
const FCachedTunnel* TunnelData = Cache.Tunnels.GetData();
auto EvaluateTunnel = [&](int32 TunnelIdx)
{
const FCachedTunnel& Tunnel = TunnelData[TunnelIdx];
if (Tunnel.SDFInfluenceRadius > 0.0f
&& VF_DistanceSquaredToAabb(
WorldX, WorldY, WorldZ,
Tunnel.SDFCenterlineMin, Tunnel.SDFCenterlineMax)
> FMath::Square(Tunnel.SDFInfluenceRadius))
{
return;
}
if (VF_FloatDistSquared(WorldX, WorldY, WorldZ, Tunnel.BoundCenter)
> Tunnel.BoundRadiusSq)
{
return;
}
MinSDF = FMath::Min(
MinSDF,
VF_EvaluateSweptTunnel(
Pos, Tunnel, /*bWorldChain=*/false, Cache.SDFBlendRadius,
/*bApplyFloorCut=*/false, &Cache, TunnelIdx).SDF);
};
VF_ForEachSpatialCandidate(
Cache.TunnelSpatialIndex, Cache.Tunnels.Num(), WorldX, WorldY, EvaluateTunnel,
bUseSpatialIndex);
return MinSDF;
}
FTunnelCoreWorldEvaluation VoxelCaveMorphology::EvaluateTunnelCoreWorld(
float WorldX, float WorldY, float WorldZ,
const FChunkSDFCache& Cache,
@@ -9454,7 +9317,7 @@ bool VoxelCaveMorphology::AnyTunnelCoreWorldNearLattice(
// The broad sphere already encloses the swept radius and finite floor band. Add the
// vertical relief and room-mouth ownership envelopes before asking whether the lattice
// box can touch it. A miss is therefore an identity proof for the core evaluator and
// its support/room-floor tail; its only field writes are bSupportFloor, bRoomFloor, or
// its support/room-floor tail; its only field writes are bRoomFloor or
// CoreSDF < -inset, all of which are inside this envelope.
const float Reach = (
FMath::Sqrt(FMath::Max(BoundRadiusSq, 0.0f))
@@ -9477,254 +9340,6 @@ float VoxelCaveMorphology::EvaluateTunnelCoreWorldSDF(
WorldX, WorldY, WorldZ, Cache, nullptr, bUseSpatialIndex).SDF;
}
bool VoxelCaveMorphology::IsTunnelSupportFloorWorldPoint(
float WorldX, float WorldY, float WorldZ,
const FChunkSDFCache& Cache,
bool bUseSpatialIndex)
{
if (VoxelDensityAblation::IsTunnelCoreOff())
{
return false;
}
const FVector Pos(WorldX, WorldY, WorldZ);
const FCachedTunnel* TunnelData = Cache.Tunnels.GetData();
auto TestTunnel = [&](int32 TunnelIdx) -> bool
{
const FCachedTunnel& Tunnel = TunnelData[TunnelIdx];
const bool bHasWorldChain = Tunnel.WorldControlPoints.Num() >= 2
&& Tunnel.WorldControlRadii.Num() == Tunnel.WorldControlPoints.Num();
const FVector& CenterlineMin = bHasWorldChain
? Tunnel.WorldCenterlineMin : Tunnel.SDFCenterlineMin;
const FVector& CenterlineMax = bHasWorldChain
? Tunnel.WorldCenterlineMax : Tunnel.SDFCenterlineMax;
const float InfluenceRadius = bHasWorldChain
? Tunnel.WorldInfluenceRadius : Tunnel.SDFInfluenceRadius;
if (InfluenceRadius > 0.0f
&& VF_DistanceSquaredToAabb(
WorldX, WorldY, WorldZ, CenterlineMin, CenterlineMax)
> FMath::Square(InfluenceRadius))
{
return false;
}
const FVector& BoundCenter = bHasWorldChain
? Tunnel.WorldBoundCenter : Tunnel.BoundCenter;
const float BoundRadiusSq = bHasWorldChain
? Tunnel.WorldBoundRadiusSq : Tunnel.BoundRadiusSq;
if (BoundRadiusSq > 0.0f
&& VF_FloatDistSquared(WorldX, WorldY, WorldZ, BoundCenter) > BoundRadiusSq)
{
return false;
}
const FVFRoomFloorOwnership RoomMouthOwnership =
VF_FindWorldTunnelMouthOwnership(Pos, Tunnel, Cache.SDFBlendRadius);
if (RoomMouthOwnership.bValid)
{
float ProjectedFloorZ = 0.0f;
float SupportRadius = 0.0f;
if (VF_ProjectSweptTunnelFloor(
Pos, Tunnel, bHasWorldChain, ProjectedFloorZ, SupportRadius,
&Cache, TunnelIdx, &RoomMouthOwnership)
&& ProjectedFloorZ > RoomMouthOwnership.FloorZ + KINDA_SMALL_NUMBER)
{
// Only a raised tunnel apron is clipped. If the tunnel is lower, the room's
// SmoothMax floor already wins naturally and retaining this support band is
// capability-safe for legacy callers.
return false;
}
}
return VF_EvaluateSweptTunnel(
Pos, Tunnel, bHasWorldChain, Cache.SDFBlendRadius,
/*bApplyFloorCut=*/true, &Cache, TunnelIdx,
&RoomMouthOwnership).bSupportFloor;
};
bool bSupport = false;
int32 CandidateCount = 0;
auto TestRange = [&](int32 Begin, int32 End)
{
const int32* ItemIndexData = Cache.TunnelSpatialIndex.ItemIndices.GetData();
for (int32 Cursor = Begin; Cursor < End; ++Cursor)
{
const int32 TunnelIdx = ItemIndexData[Cursor];
if (!Cache.Tunnels.IsValidIndex(TunnelIdx))
{
continue;
}
++CandidateCount;
if (TestTunnel(TunnelIdx))
{
bSupport = true;
if (VoxelDensityProfile::AreCountersEnabled())
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TunnelCoreEvaluated);
}
break;
}
}
};
int32 Begin = 0;
int32 End = 0;
if (bUseSpatialIndex && Cache.TunnelSpatialIndex.GetRange(WorldX, WorldY, Begin, End))
{
TestRange(Begin, End);
}
else
{
for (int32 TunnelIdx = 0; TunnelIdx < Cache.Tunnels.Num() && !bSupport; ++TunnelIdx)
{
++CandidateCount;
if (TestTunnel(TunnelIdx))
{
bSupport = true;
if (VoxelDensityProfile::AreCountersEnabled())
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TunnelCoreEvaluated);
}
}
}
}
if (VoxelDensityProfile::AreCountersEnabled())
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TunnelCoreCandidates,
static_cast<uint64>(CandidateCount));
}
return bSupport;
}
void VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
float WorldX, float WorldY,
const FChunkSDFCache& Cache,
FTunnelSupportFloorColumn& OutColumn,
bool bUseSpatialIndex)
{
if (VoxelDensityAblation::IsTunnelCoreOff())
{
OutColumn.Reset();
return;
}
VoxelDensityProfile::FScopedTimer ProfileTimer(
VoxelDensityProfile::EBucket::TunnelCoreSupport);
OutColumn.Reset();
if (VoxelDensityProfile::AreCountersEnabled())
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TunnelSupportColumnBuilds);
}
const FVector ColumnPosition(WorldX, WorldY, 0.0f);
const FCachedTunnel* TunnelData = Cache.Tunnels.GetData();
auto EvaluateTunnel = [&](int32 TunnelIdx)
{
const FCachedTunnel& Tunnel = TunnelData[TunnelIdx];
const FVFRoomFloorOwnership RoomMouthOwnership =
VF_FindWorldTunnelMouthOwnership(ColumnPosition, Tunnel, Cache.SDFBlendRadius);
float FloorZ = 0.0f;
float SupportRadius = 0.0f;
if (!VF_ProjectSweptTunnelFloor(
ColumnPosition, Tunnel, /*bWorldChain=*/true,
FloorZ, SupportRadius, &Cache, TunnelIdx, &RoomMouthOwnership))
{
return;
}
float MinZ = FloorZ - VoxelPassageGeometry::LandingFloorThicknessVoxels;
float MaxZ = FloorZ + VoxelPassageGeometry::WalkableTunnelFloorAirClearanceVoxels;
// Preserve the public point predicate's world bounding sphere exactly, while resolving
// its Z interval once. The XY projection already proves the support-radius condition.
if (Tunnel.WorldBoundRadiusSq > 0.0f)
{
const float DX = WorldX - static_cast<float>(Tunnel.WorldBoundCenter.X);
const float DY = WorldY - static_cast<float>(Tunnel.WorldBoundCenter.Y);
const float Remaining = Tunnel.WorldBoundRadiusSq - (DX * DX + DY * DY);
if (Remaining < 0.0f)
{
return;
}
const float HalfZ = FMath::Sqrt(Remaining);
MinZ = FMath::Max(MinZ, static_cast<float>(Tunnel.WorldBoundCenter.Z) - HalfZ);
MaxZ = FMath::Min(MaxZ, static_cast<float>(Tunnel.WorldBoundCenter.Z) + HalfZ);
}
if (MinZ <= MaxZ)
{
FTunnelSupportFloorInterval& Interval =
OutColumn.Intervals.Emplace_GetRef();
Interval.TunnelIndex = TunnelIdx;
Interval.FloorZ = FloorZ;
Interval.MinZ = MinZ;
Interval.MaxZ = MaxZ;
}
};
const int32 CandidateCount = VF_ForEachSpatialCandidate(
Cache.TunnelSpatialIndex, Cache.Tunnels.Num(), WorldX, WorldY, EvaluateTunnel,
bUseSpatialIndex);
if (VoxelDensityProfile::AreCountersEnabled())
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TunnelSupportColumnCandidates,
static_cast<uint64>(CandidateCount));
}
// Candidate IDs are deterministic and allow the world evaluator to find a
// tunnel's own band without re-running the XY projection. The public union
// query below simply tests every band; graph columns normally contain only a
// handful of candidates.
OutColumn.Intervals.Sort(
[](const FTunnelSupportFloorInterval& A,
const FTunnelSupportFloorInterval& B)
{
return A.TunnelIndex < B.TunnelIndex;
});
}
bool VoxelCaveMorphology::IsTunnelSupportFloorColumnZ(
float WorldZ,
const FTunnelSupportFloorColumn& Column)
{
for (const FTunnelSupportFloorInterval& Interval : Column.Intervals)
{
if (WorldZ <= Interval.MaxZ)
{
if (WorldZ >= Interval.MinZ)
{
return true;
}
}
}
return false;
}
bool VoxelCaveMorphology::GetTunnelSupportFloorColumnBand(
int32 TunnelIndex,
const FTunnelSupportFloorColumn& Column,
float& OutFloorZ,
float& OutMinZ,
float& OutMaxZ)
{
for (const FTunnelSupportFloorInterval& Interval : Column.Intervals)
{
if (Interval.TunnelIndex == TunnelIndex)
{
OutFloorZ = Interval.FloorZ;
OutMinZ = Interval.MinZ;
OutMaxZ = Interval.MaxZ;
return true;
}
}
return false;
}
//=============================================================================
// CONVENIENCE WRAPPER (backward compatible)
//=============================================================================
@@ -9734,35 +9349,3 @@ bool VoxelCaveMorphology::GetTunnelSupportFloorColumnBand(
// internally widens the COLLECT region to (2*MaxTunnelLength + MaxInfluence) so the
// graph it builds is the same one the chunk path would build at this point.
float VoxelCaveMorphology::EvaluateSDF(
float WorldX, float WorldY, float WorldZ,
const FStrateGenerationParams& Params,
uint32 Seed, int32 StrateIndex)
{
const float RoomRadiusEnvelope = FMath::Max(
FMath::Abs(Params.MinRoomRadius), FMath::Abs(Params.MaxRoomRadius));
const float TunnelRadiusEnvelope = FMath::Max(
0.5f,
FMath::Max(FMath::Abs(Params.TunnelMinRadius), FMath::Abs(Params.TunnelMaxRadius))
* 1.18f);
const float FloorReliefEnvelope = FMath::Abs(Params.FloorReliefStrength)
* VOXEL_NOISE_SCALE * 1.5f;
const float BlendEnvelope = FMath::Max(Params.SDFBlendRadius, 0.0f);
const float Margin = FMath::Max(
RoomRadiusEnvelope + FloorReliefEnvelope,
FMath::Abs(Params.TunnelWarpStrength) + TunnelRadiusEnvelope
) + BlendEnvelope * 3.0f;
FChunkSDFCache TempCache;
BuildChunkCache(
TempCache,
WorldX - Margin, WorldY - Margin,
WorldX + Margin, WorldY + Margin,
Params, Seed, StrateIndex
);
return EvaluateSDFCached(
WorldX, WorldY, WorldZ,
TempCache, Params.SDFBlendRadius
);
}
@@ -361,33 +361,6 @@ namespace
// STAGE B5 DECISION: repeated early-out in each op, NOT a scoping container — the stack is a flat
// list that ClassifyBox folds op by op, and an op that only exists inside a container is not
// composable. Cost stated honestly: twelve predictable compares instead of one branch.
/** Distance d'un point à un SEGMENT (pas à une droite). Écrite ici plutôt que prise dans
* `FMath` : cinq lignes, aucune ambiguïté d'API, et elle sert une borne de correction — le
* genre d'endroit où « je crois que cette fonction fait ça » n'est pas suffisant. */
FORCEINLINE float VF_DistPointSegment(const FVector& P, const FVector& A, const FVector& B)
{
const FVector AB = B - A;
const double LenSq = FVector::DotProduct(AB, AB);
const double T = (LenSq > KINDA_SMALL_NUMBER)
? FMath::Clamp(FVector::DotProduct(P - A, AB) / LenSq, 0.0, 1.0)
: 0.0;
return (float)FVector::Dist(P, A + AB * T);
}
/** La même chose en 2D, pour les connecteurs de puits : ce sont des capsules HORIZONTALES, donc
* Z se teste exactement et seul XY demande une distance point-segment. */
FORCEINLINE float VF_DistPointSegment2D(const FVector2D& P, const FVector2D& A, const FVector2D& B)
{
const FVector2D AB = B - A;
const double LenSq = (double)AB.X * AB.X + (double)AB.Y * AB.Y;
const double T = (LenSq > KINDA_SMALL_NUMBER)
? FMath::Clamp(((double)(P.X - A.X) * AB.X + (double)(P.Y - A.Y) * AB.Y) / LenSq, 0.0, 1.0)
: 0.0;
const double DX = (double)P.X - ((double)A.X + AB.X * T);
const double DY = (double)P.Y - ((double)A.Y + AB.Y * T);
return (float)FMath::Sqrt(DX * DX + DY * DY);
}
FORCEINLINE bool VF_NearCaveSurface(float Sdf, float SDFBlendRadius)
{
// Transcrit tel quel, ordre des comparaisons compris :
@@ -795,16 +768,6 @@ namespace
return FVector((X + 0.5f) * CellSize, (Y + 0.5f) * CellSize, (Z + 0.5f) * CellSize);
}
// Sur-approximation volontaire : boîte englobante du segment contre la boîte élargie.
// Un test capsule/AABB exact serait plus serré ; il coûterait plus cher pour un gain nul
// ici, car la réponse ne sert qu'à un rejet grossier par tuile.
static bool SegmentHitsBox(const FVector& A, const FVector& B, const FVector& Min, const FVector& Max)
{
return FMath::Min(A.X, B.X) <= Max.X && FMath::Max(A.X, B.X) >= Min.X
&& FMath::Min(A.Y, B.Y) <= Max.Y && FMath::Max(A.Y, B.Y) >= Min.Y
&& FMath::Min(A.Z, B.Z) <= Max.Z && FMath::Max(A.Z, B.Z) >= Min.Z;
}
/**
* Le cache par CELLULE, partagé avec le même contrat que GetMazeDensity. Il est `thread_local` et non
* membre parce que la pile est PARTAGÉE entre workers en lecture — un membre mutable serait
@@ -1120,12 +1083,6 @@ namespace
}
}
/** Sans biomes — délègue, pour qu'il n'existe qu'UN corps de construction et UN compteur
* d'identité. Deux constructeurs qui s'initialisent chacun de leur côté, c'est deux
* endroits où oublier un membre. */
FSurfaceColumnSource(const FSurfaceGenerationParams& InP, int32 Seed)
: FSurfaceColumnSource(InP, Seed, TArray<FSurfaceGenerationParams>(), nullptr) {}
void BuildSingleBiome(const FSurfaceGenerationParams& InP, int32 Seed)
{
// Construite à la main (pas via BuildSurfaceHeightStack) pour GARDER le pointeur vers la
@@ -1342,8 +1299,6 @@ namespace
return S.Height;
}
const FSurfaceGenerationParams& GetParams() const { return P; }
EVoxelOpRole GetRole() const override { return EVoxelOpRole::FieldSource; }
EVoxelOpChannelMask ChannelReads() const override { return VoxelOpChannels::None; }
EVoxelOpChannelMask ChannelWrites() const override { return VoxelOpChannels::Density; }
@@ -4313,7 +4268,6 @@ namespace
// room's own volume.
InOut.bHasTunnelCoreWorldEvaluation = true;
InOut.TunnelCoreWorldSDF = S.LastTunnelCoreWorldEvaluation.SDF;
InOut.bTunnelCoreSupportFloor = false;
InOut.bTunnelCoreRoomFloor =
S.LastTunnelCoreWorldEvaluation.bRoomFloor;
InOut.bHasTunnelCoreSweptFloor =
@@ -4322,8 +4276,6 @@ namespace
S.LastTunnelCoreWorldEvaluation.SweptFloorZ;
InOut.TunnelCoreSweptFloorRadius =
S.LastTunnelCoreWorldEvaluation.SweptFloorRadius;
InOut.bProtectedStructuralFloor = false;
InOut.StructuralFloorMinimumDensity = 0.0f;
}
// These cache hand-offs remain valid when tunnel core is off; detail operators still
@@ -4445,7 +4397,6 @@ namespace
bool bMayHaveTunnelCoreTail = false;
uint32 ExactTailQueries = 0;
uint32 ExactTailEvaluated = 0;
uint32 ExactTailCacheHits = 0;
uint64 ExactTailCycles = 0;
uint64 PropagateCycles = 0;
uint64 ExactPrimitiveCycles = 0;
@@ -4534,12 +4485,6 @@ namespace
return false;
}
bool HasRoomColumnsForLastBox() const
{
const FBoxState& B = BoxState();
return !B.bValid || GetBoxCache().Columns.Num() > 0;
}
float RoomColumnFillSupremumForLastBox() const
{
const FBoxState& B = BoxState();
@@ -5623,18 +5568,6 @@ namespace
}
};
auto EffectiveZRangeToWorld = [&](float MinEffectiveZ,
float MaxEffectiveZ) -> FVector2D
{
if (P.VerticalScale > 0.0f && P.VerticalScale != 1.0f)
{
const float WorldA = MinEffectiveZ * P.VerticalScale;
const float WorldB = MaxEffectiveZ * P.VerticalScale;
return FVector2D(FMath::Min(WorldA, WorldB), FMath::Max(WorldA, WorldB));
}
return FVector2D(MinEffectiveZ, MaxEffectiveZ);
};
auto DistanceBlockToInfiniteLineLower = [&](const FExactLatticeBlock& Block,
const FVector& A,
const FVector& BPoint) -> float
@@ -9463,11 +9396,6 @@ namespace VoxelDensityOps
return MakeUnique<FGridColumnMod>(P, Seed);
}
TUniquePtr<IVoxelDensityOp> MakeSurfaceColumnSource(const FSurfaceGenerationParams& P, int32 Seed)
{
return MakeUnique<FSurfaceColumnSource>(P, Seed);
}
void BuildSurfaceStack(FVoxelOpStack& OutStack, const FSurfaceGenerationParams& P,
int32 Seed, float SpineRadius, const UVoxelStrateManager* StrateManager,
const TArray<FSurfaceGenerationParams>& PerBiomeParams,
@@ -218,11 +218,6 @@ namespace VoxelDensityProfile
}
}
void SetEnabled(bool bEnabled)
{
SetMode(bEnabled ? EMode::Sampled : EMode::Disabled, DefaultSampleInterval);
}
void SetMode(EMode Mode, uint32 SampleInterval)
{
if (SampleInterval == 0)
@@ -3287,7 +3287,6 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
float BlockDensity = 0.f;
bool bBlockHasTunnelCore = false;
float BlockTunnelCoreSDF = FLT_MAX;
bool bBlockTunnelCoreSupportFloor = false;
bool bBlockTunnelCoreRoomFloor = false;
bool bBlockHasTunnelCoreSweptFloor = false;
float BlockTunnelCoreSweptFloorZ = -FLT_MAX;
@@ -3362,7 +3361,6 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
BlockDensity = BlockCoreSample.Density;
bBlockHasTunnelCore = BlockCoreSample.bHasTunnelCoreWorldEvaluation;
BlockTunnelCoreSDF = BlockCoreSample.TunnelCoreWorldSDF;
bBlockTunnelCoreSupportFloor = BlockCoreSample.bTunnelCoreSupportFloor;
bBlockTunnelCoreRoomFloor = BlockCoreSample.bTunnelCoreRoomFloor;
bBlockHasTunnelCoreSweptFloor =
BlockCoreSample.bHasTunnelCoreSweptFloor;
@@ -3466,7 +3464,6 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
else if (bUsedOpBlockSample && bBlockHasTunnelCore)
{
PreDisturbanceTunnelCore.SDF = BlockTunnelCoreSDF;
PreDisturbanceTunnelCore.bSupportFloor = bBlockTunnelCoreSupportFloor;
PreDisturbanceTunnelCore.bRoomFloor = bBlockTunnelCoreRoomFloor;
PreDisturbanceTunnelCore.bHasSweptFloor =
bBlockHasTunnelCoreSweptFloor;
@@ -1410,59 +1410,6 @@ namespace VoxelSeasonManifestPrivate
return bValid;
}
bool SaveJson(const FString& FilePath, const TSharedPtr<FJsonObject>& Root,
FString& OutReport)
{
const FString Directory = FPaths::GetPath(FilePath);
if (!Directory.IsEmpty() && !IFileManager::Get().MakeDirectory(*Directory, true))
{
OutReport = FString::Printf(TEXT("could not create manifest directory %s"), *Directory);
return false;
}
FString JsonText;
TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> Writer =
TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&JsonText);
if (!FJsonSerializer::Serialize(Root.ToSharedRef(), Writer) || !Writer->Close()
|| !FFileHelper::SaveStringToFile(JsonText, *FilePath))
{
OutReport = FString::Printf(TEXT("could not write season manifest %s"), *FilePath);
return false;
}
return true;
}
bool LoadJson(const FString& FilePath, TSharedPtr<FJsonObject>& OutRoot,
FString& OutReport, FString* OutJsonText = nullptr)
{
FString JsonText;
if (!FFileHelper::LoadFileToString(JsonText, *FilePath))
{
OutReport = FString::Printf(TEXT("could not read season manifest %s"), *FilePath);
return false;
}
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonText);
if (!FJsonSerializer::Deserialize(Reader, OutRoot) || !OutRoot.IsValid())
{
OutReport = FString::Printf(TEXT("invalid JSON in season manifest %s"), *FilePath);
return false;
}
if (OutJsonText != nullptr)
{
*OutJsonText = MoveTemp(JsonText);
}
return true;
}
}
const TCHAR* VF_GetVoxelSeasonSelectionReasonName(EVoxelSeasonSelectionReason Reason)
{
switch (Reason)
{
case EVoxelSeasonSelectionReason::Grounded: return TEXT("grounded");
case EVoxelSeasonSelectionReason::Outlier: return TEXT("outlier");
case EVoxelSeasonSelectionReason::Fixed: return TEXT("fixed");
}
return TEXT("unknown");
}
namespace
@@ -863,12 +863,6 @@ void FVoxelStackSampler::Shutdown()
StopAndWrite();
}
bool FVoxelStackSampler::IsRunning() const
{
FScopeLock LifecycleLock(&LifecycleMutex);
return Impl != nullptr;
}
bool FVoxelStackSampler::RegisterCurrentThread(int32 LODLevel)
{
// Keep this as the first and only operation in the disabled fast path. In particular, do not
@@ -3800,55 +3800,6 @@ bool FVoxelStrateCorpus::LoadFromAssetRegistry(
return bLoaded && NumUnresolved == 0 && bPromotedLoaded;
}
bool FVoxelStrateCorpus::LoadFromSettings(const UVoxelSettings* Settings, FString& OutReport)
{
// Compatibility/audit entry point. It intentionally does not load any soft reference: the
// Asset Registry is the corpus source, while the settings pool is reported as the reason the
// first Tier 4a run saw only one vector.
TArray<FString> SettingsPaths;
if (Settings != nullptr)
{
TSet<FString> UniquePaths;
for (const TPair<int32, TSoftObjectPtr<UVoxelStrateDefinition>>& Pair : Settings->FixedStrates)
{
const FString Path = Pair.Value.ToSoftObjectPath().ToString();
if (!Path.IsEmpty())
{
UniquePaths.Add(Path);
}
}
for (const TSoftObjectPtr<UVoxelStrateDefinition>& Reference : Settings->StratePool)
{
const FString Path = Reference.ToSoftObjectPath().ToString();
if (!Path.IsEmpty())
{
UniquePaths.Add(Path);
}
}
for (const FString& Path : UniquePaths)
{
SettingsPaths.Add(Path);
}
SettingsPaths.Sort();
}
FString RegistryReport;
const bool bLoaded = LoadFromAssetRegistry(RegistryReport);
OutReport = FString::Printf(
TEXT("Settings audit: %d unique fixed/pool soft paths"), SettingsPaths.Num());
for (const FString& Path : SettingsPaths)
{
OutReport += FString::Printf(TEXT(" [%s]"), *Path);
}
if (Settings == nullptr)
{
OutReport += TEXT(" [settings object was null]");
}
OutReport += TEXT("; settings references are diagnostic only. ");
OutReport += RegistryReport;
return bLoaded;
}
int32 FVoxelStrateCorpus::NumForArchetype(ECaveGeneratorType Archetype) const
{
int32 Count = 0;
@@ -5301,12 +5252,6 @@ bool VF_ValidateStrateCorpusFreeConstraints(
return false;
}
FStrateGenerationParams VF_RollStrateParams(const FVoxelStrateCorpus& Corpus,
int32 Seed, int32 Index)
{
return VF_RollStrateParamsDetailed(Corpus, Seed, Index).Params;
}
namespace
{
const TCHAR* VF_RecipeOpCode(EVoxelStrateOpClass OpClass)
@@ -5532,15 +5477,6 @@ FVoxelStrateRegionManifest VF_RollStrateRegionManifest(
ECaveGeneratorType::VerticalShafts,
ECaveGeneratorType::FloatingIslands,
};
static const EVoxelStrateParamBlock BlockIds[] =
{
EVoxelStrateParamBlock::TunnelNetwork,
EVoxelStrateParamBlock::Slab,
EVoxelStrateParamBlock::Maze,
EVoxelStrateParamBlock::Surface,
EVoxelStrateParamBlock::VerticalShaft,
EVoxelStrateParamBlock::FloatingIsland,
};
static const uint32 BlockSalts[] = { 0x1001u, 0x1003u, 0x1005u,
0x1007u, 0x1009u, 0x100Bu };
@@ -3023,20 +3023,6 @@ void UVoxelStrateManager::ApplyPassageLandingAir(
VF_ApplyPassageLandingCarving(Density, MinLandingSDF, BaseDensity, SealThickness);
}
void UVoxelStrateManager::ApplyPassageLandingAirMC(
float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const
{
// ApplyDisturbances is deliberately an MC-space post-process and can add a bridge or ridge
// on top of the structural passage. Reassert only landing air here; the support slab is
// restored by ApplyPassageLandingFloorMC immediately afterwards. This stays on the same
// thread-local passage shortlist as the hot voxel path and performs no source/topology work.
float InternalDensity = -Density;
ApplyPassageLandingAir(
InternalDensity, WorldX, WorldY, WorldZ, BaseDensity, SealThickness);
Density = -InternalDensity;
}
void UVoxelStrateManager::ApplyPassageTunnelAir(
float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const
@@ -3070,18 +3056,6 @@ void UVoxelStrateManager::ApplyPassageTunnelAir(
}
}
void UVoxelStrateManager::ApplyPassageTunnelAirMC(
float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const
{
// The disturbance layer uses MC polarity (negative = solid), so reuse the exact internal
// tunnel-air operation rather than maintaining a second polarity-specific formula.
float InternalDensity = -Density;
ApplyPassageTunnelAir(
InternalDensity, WorldX, WorldY, WorldZ, BaseDensity, SealThickness);
Density = -InternalDensity;
}
void UVoxelStrateManager::ApplyPassageLandingFloorMC(
float& Density, float WorldX, float WorldY, float WorldZ, float BaseDensity) const
{
@@ -6712,7 +6686,7 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
// Three transition styles:
//
// GRADIENT (default):
// Classic linear lerp of all params across BlendChunks. Smooth,
// Classic linear lerp of all params across TransitionBlendChunks. Smooth,
// invisible boundary. Cave shape morphs gradually from one strate
// to the next over several chunks.
//
@@ -6720,7 +6694,7 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
// No blending at all — params switch instantly at the boundary.
// The abrupt change in density, room size, roughness, etc. creates
// a natural cliff, ledge, or visible material discontinuity.
// BlendChunks is ignored (effectively 0).
// TransitionBlendChunks is ignored (effectively 0).
//
// INTERLEAVED:
// 3D Perlin noise warps the effective boundary Z position per XY column.
@@ -6740,7 +6714,7 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
// CHECK BOTTOM BOUNDARY (transitioning to strate below)
//---------------------------------------------------------------------
// DistFromBottom = how many chunks above the bottom edge of this strate.
// When 0, we're right at the boundary. When == BlendChunks, we're at
// When 0, we're right at the boundary. When == TransitionBlendChunks, we're at
// the outer edge of the transition zone.
int32 DistFromBottom = ChunkCoord.Z - Slot.BottomChunkZ;
@@ -6749,7 +6723,7 @@ FStrateGenerationParams UVoxelStrateManager::GetGenerationParams(const FIntVecto
// The upper strate (this one) controls the transition type at its lower edge
const EVoxelStrateTransition TransType = Slot.Definition->TransitionType;
// Per-definition blend distance (overrides the manager's default BlendChunks)
// Per-definition blend distance.
const int32 EffectiveBlend = Slot.Definition->TransitionBlendChunks;
// Prepare the neighbor's params (only used for Gradient and Interleaved)
@@ -6952,93 +6926,3 @@ FStrateGenerationParams UVoxelStrateManager::BuildParamsFromDefinition(const UVo
return Result;
}
uint64 UVoxelStrateManager::GetGenerationParamsFingerprint() const
{
// The diagnostic command-line override changes density inputs without changing an asset. Do
// not let a verdict from the unoverridden layout survive into an overridden session (or vice
// versa); a zero fingerprint conservatively disables persistence for that session.
const FRuntimeRoughnessOverrides& RoughnessOverrides = VF_GetRuntimeRoughnessOverrides();
if (RoughnessOverrides.bSurfaceRoughness
|| RoughnessOverrides.bFrequency
|| RoughnessOverrides.bNoiseType)
{
return 0;
}
// The session cache is deliberately conservative. These inputs are valid density inputs but
// are not represented by the fixed-size hash below, so returning zero disables verdict reuse
// instead of pretending that a partial key is complete.
if (IsUsingSeason())
{
return 0;
}
#if WITH_EDITOR
if (ComposerOverrides.Num() > 0)
{
return 0;
}
#endif
uint32 A = 0x9E3779B9u;
uint32 B = 0x85EBCA6Bu;
auto HashBytes = [&A, &B](const void* Data, int32 Size)
{
A = FCrc::MemCrc32(Data, Size, A);
B = FCrc::MemCrc32(Data, Size, B ^ 0xA511E9B3u);
};
auto HashValue = [&HashBytes](const auto& Value)
{
HashBytes(&Value, sizeof(Value));
};
HashValue(CachedSeed);
HashValue(bOpenSurfaceEntry);
HashValue(OriginSpineRadius);
HashValue(InterStrateGapChunks);
const int32 LayoutCount = StrateLayout.Num();
HashValue(LayoutCount);
for (const FStrateSlot& Slot : StrateLayout)
{
if (Slot.Definition == nullptr)
{
return 0;
}
// BuildChunkCache resolves these arrays into the room cache. Hashing UObject pointers or
// asset names would not prove the asset contents, so dynamic operation/biome layouts
// conservatively opt out. The normal synthetic/runtime profile has neither array.
if (Slot.Definition->TerrainOperations.Num() > 0
|| Slot.Definition->Biomes.Num() > 0)
{
return 0;
}
HashValue(Slot.StrateIndex);
HashValue(Slot.TopChunkZ);
HashValue(Slot.BottomChunkZ);
HashValue(Slot.HeightInChunks);
HashValue(Slot.Definition->GeneratorType);
HashValue(Slot.Definition->bUseOperatorStack);
HashValue(Slot.Definition->bEnableWorms);
HashValue(VF_WormsForceOff());
// Development-only stage ablations change the field and therefore belong in every
// persistent/verdict key even though they are not authored generation parameters.
HashValue(VoxelDensityAblation::GetResolvedMask());
HashValue(Slot.Definition->StrateHeightInChunks);
HashValue(Slot.Definition->TransitionType);
HashValue(Slot.Definition->TransitionBlendChunks);
HashValue(Slot.Definition->GenerationParams);
HashValue(Slot.Definition->SlabParams);
HashValue(Slot.Definition->MazeParams);
HashValue(Slot.Definition->SurfaceParams);
HashValue(Slot.Definition->VerticalShaftParams);
HashValue(Slot.Definition->FloatingIslandParams);
HashValue(Slot.Definition->PassageConfig);
HashValue(Slot.Definition->bHasWater);
HashValue(Slot.Definition->BiomeMapParams);
}
const uint64 Result = (static_cast<uint64>(B) << 32) | static_cast<uint64>(A);
return Result != 0 ? Result : 1;
}
@@ -2973,24 +2973,6 @@ namespace VoxelStrateMeasurePrivate
return Result;
}
int32 GetSixNeighbour(const FSampleGrid& Grid, int32 Cell, int32 Direction)
{
int32 X = 0;
int32 Y = 0;
int32 Z = 0;
DecodeIndex(Grid, Cell, X, Y, Z);
switch (Direction)
{
case 0: return X + 1 < Grid.NumX ? Grid.Index(X + 1, Y, Z) : INDEX_NONE;
case 1: return X > 0 ? Grid.Index(X - 1, Y, Z) : INDEX_NONE;
case 2: return Y + 1 < Grid.NumY ? Grid.Index(X, Y + 1, Z) : INDEX_NONE;
case 3: return Y > 0 ? Grid.Index(X, Y - 1, Z) : INDEX_NONE;
case 4: return Z + 1 < Grid.NumZ ? Grid.Index(X, Y, Z + 1) : INDEX_NONE;
case 5: return Z > 0 ? Grid.Index(X, Y, Z - 1) : INDEX_NONE;
default: return INDEX_NONE;
}
}
int32 CountPlayerFitNeighbours(
const FSampleGrid& Grid,
const TArray<uint8>& PlayerFitMask,
@@ -3458,26 +3440,6 @@ FVoxelConnectivityDiagnostics VF_DiagnoseConnectivityWithSampler(
return Result;
}
EVoxelConnectivityResult VF_ArePlayerFitConnectedWithSampler(
const IVoxelStrateDensitySampler& Sampler,
int32 StrateBottomWorldZ,
int32 StrateTopWorldZ,
float BoundarySealThickness,
const FVector& AVoxel,
const FVector& BVoxel,
const FVoxelStrateMeasureSettings& Settings,
bool& bOutStartSnapped,
bool& bOutGoalSnapped,
FVoxelConnectivityDiagnostics* OutDiagnostics)
{
int32 NumRouteRetries = 0;
return VoxelStrateMeasurePrivate::QueryConnectivity(
nullptr, nullptr, &Sampler, INDEX_NONE,
StrateBottomWorldZ, StrateTopWorldZ, BoundarySealThickness, true,
AVoxel, BVoxel, Settings, bOutStartSnapped, bOutGoalSnapped,
NumRouteRetries, OutDiagnostics, true, nullptr);
}
FVoxelConnectivityDiagnostics VF_DiagnosePlayerFitConnectivityWithSampler(
const IVoxelStrateDensitySampler& Sampler,
int32 StrateBottomWorldZ,
@@ -76,16 +76,6 @@ namespace
namespace VoxelWormField
{
float EvaluateExact(
float WorldX,
float WorldY,
float WorldZ,
float Threshold,
const FParameters& Parameters)
{
return EvaluateExactField(WorldX, WorldY, WorldZ, Threshold, Parameters);
}
float Evaluate(
float WorldX,
float WorldY,
+2 -57
View File
@@ -637,9 +637,8 @@ struct FCachedRoomFloorJoin
// One immutable floor segment authored while the tunnel chain is built. The floor is continuous
// unless bLedgeTransition is set; that marker means the segment terminates at a deliberate
// dramatic ledge and the vertical riser is placed at the next control-point boundary. NumSteps is
// retained as a compatibility/diagnostic field and is always zero for newly authored tunnels: a
// steep floor is never quantised into a staircase. ReliefScale is baked with a derivative bound,
// dramatic ledge and the vertical riser is placed at the next control-point boundary. A steep
// floor is never quantised into a staircase. ReliefScale is baked with a derivative bound,
// so evaluation only reads this profile and never decides a floor shape per voxel.
struct FTunnelFloorSegmentProfile
{
@@ -652,9 +651,6 @@ struct FTunnelFloorSegmentProfile
float NaturalEndFloorZ = 0.0f;
float ReliefScale = 0.0f;
bool bLedgeTransition = false;
// Deprecated staircase count. New profiles leave this at zero; keep the member so old
// diagnostic consumers can still compile while the authored representation has one meaning.
int32 NumSteps = 0;
};
// A pre-computed wandering tunnel chain — all connection decisions and hash-derived properties
@@ -938,8 +934,6 @@ struct FChunkSDFCache
struct FTunnelCoreWorldEvaluation
{
float SDF = FLT_MAX;
// Deprecated compatibility output. The separate graph-tunnel support slab was removed.
bool bSupportFloor = false;
// Room geometry owns the lower side while the world-space tunnel is inside a room. The
// tunnel SDF may still reopen air there, but its swept bottom must not turn that room air back
// into a shelf or wall.
@@ -1065,15 +1059,6 @@ namespace VoxelCaveMorphology
bool* OutRoomOwnsBottom = nullptr
);
// Evaluate the raw union of cached graph-tunnel capsules. This is intentionally separate from
// the SmoothMin morphology: the generator uses it after terrain/passage posts to reassert the
// tunnel's walkable air core without reintroducing a connector or changing room ownership.
VOXELFORGE_API float EvaluateTunnelCoreSDF(
float WorldX, float WorldY, float WorldZ,
const FChunkSDFCache& Cache,
bool bUseSpatialIndex = true
);
// Evaluate the final structural air contract against the world-space wandering chain. Room
// SDFs remain evaluated in warped coordinates; only this post uses world coordinates so its
// walkable floor follows the authored chain exactly.
@@ -1106,46 +1091,6 @@ namespace VoxelCaveMorphology
float ReachScale = 1.0f
);
// Deprecated compatibility query for the removed graph-tunnel support slab. Production
// generation does not call this predicate; the tunnel's own swept shape owns its floor.
VOXELFORGE_API bool IsTunnelSupportFloorWorldPoint(
float WorldX, float WorldY, float WorldZ,
const FChunkSDFCache& Cache,
bool bUseSpatialIndex = true
);
// Deprecated compatibility helper for callers that still inspect the old support-band
// diagnostic. It is detached from production density generation.
VOXELFORGE_API void BuildTunnelSupportFloorColumn(
float WorldX, float WorldY,
const FChunkSDFCache& Cache,
FTunnelSupportFloorColumn& OutColumn,
bool bUseSpatialIndex = true
);
VOXELFORGE_API bool IsTunnelSupportFloorColumnZ(
float WorldZ,
const FTunnelSupportFloorColumn& Column
);
// Returns the legacy projected band for one tunnel at this XY column. The world evaluator no
// longer uses it to write a support slab.
VOXELFORGE_API bool GetTunnelSupportFloorColumnBand(
int32 TunnelIndex,
const FTunnelSupportFloorColumn& Column,
float& OutFloorZ,
float& OutMinZ,
float& OutMaxZ
);
// CONVENIENCE WRAPPER: builds a temporary cache and evaluates in one call.
// Use this for one-off queries (debug visualization, single-point sampling).
// For chunk generation, use BuildChunkCache + EvaluateSDFCached instead.
float EvaluateSDF(
float WorldX, float WorldY, float WorldZ,
const FStrateGenerationParams& Params,
uint32 Seed, int32 StrateIndex
);
}
/**
@@ -337,11 +337,6 @@ struct FVoxelOpSample
// FLT_MAX = "no surface nearby" — the initial state, and the early-out placed sources use.
float Sdf = FLT_MAX;
// Deprecated structural-floor compatibility fields. Graph tunnels now carry their floor in
// the swept shape itself; the production stack does not use these fields to write a slab.
bool bProtectedStructuralFloor = false;
float StructuralFloorMinimumDensity = 0.0f;
// Block evaluation keeps the room source's per-sample selection explicit. The scalar path
// still uses the source's worker-local state, but a later block-capable modifier must never
// observe the state belonging to the last sample of the preceding operator.
@@ -353,7 +348,6 @@ struct FVoxelOpSample
// consulting a last-sample TLS value after an op-major evaluation.
bool bHasTunnelCoreWorldEvaluation = false;
float TunnelCoreWorldSDF = FLT_MAX;
bool bTunnelCoreSupportFloor = false;
bool bTunnelCoreRoomFloor = false;
bool bHasTunnelCoreSweptFloor = false;
float TunnelCoreSweptFloorZ = -FLT_MAX;
@@ -568,12 +568,6 @@ namespace VoxelDensityOps
* `FillOnly` quand une colonne atteint la boîte, `Identity` (le cas courant) sinon. */
VOXELFORGE_API TUniquePtr<IVoxelDensityOp> MakeGridColumnMod(const FSlabGenerationParams& P, int32 Seed);
/** Rôle 1 — le pont entre les deux espaces : consomme les piles de HAUTEUR (sol + voûte,
* `VoxelHeightOp.h`) et en fait une densité. `IsXYPure()` est **false** — les hauteurs sont
* pures en XY, la densité est une distance à celles-ci et ne peut pas l'être. */
VOXELFORGE_API TUniquePtr<IVoxelDensityOp> MakeSurfaceColumnSource(const FSurfaceGenerationParams& P,
int32 Seed);
/**
* SurfaceWorld, COMPLET : colonne (sol + voûte) → densité, overhang 3D, post structurel, et le
* mélange de biomes quand `PerBiomeParams` est non vide.
@@ -300,7 +300,6 @@ FORCEINLINE void VF_ApplyXYEdgeSealMC(float& Density, float WorldX, float WorldY
// mathematical inner edge the helper is a true no-op, so claiming AllSolid there would be false.
namespace VoxelDensityReach
{
constexpr float SpineBlend = 3.0f;
constexpr float PassageBlend = 4.0f;
constexpr float EdgeProofMargin = 1.0f;
}
@@ -312,7 +312,6 @@ namespace VoxelDensityProfile
FCacheMemoryBreakdown RoomGraphCacheBreakdown;
};
VOXELFORGE_API void SetEnabled(bool bEnabled);
VOXELFORGE_API void SetMode(EMode Mode, uint32 SampleInterval = DefaultSampleInterval);
// Counters are collected only while a diagnostic mode is enabled. In the ordinary clean
// path this is a single relaxed load, so the measurement hooks stay dormant.
@@ -45,10 +45,6 @@ namespace VoxelPassageGeometry
// ownership band: the floor writer owns the plane, while the air writer owns the capsule
// volume above it even when two overlapping passage projections differ by a fraction.
constexpr float WalkableTunnelFloorAirClearanceVoxels = 0.5f;
// The graph-tunnel post owns the interior above its floor after terrain and passage-floor
// writers have run. The support-floor predicate is also an exclusion mask for the air post,
// so overlapping graph tubes cannot erase one another's walkable support band.
constexpr float CaveTunnelAirCoreInsetVoxels = 0.5f;
// A 15 degree ramp is comfortably below the 44 degree engine walkability ceiling. The
// latter is a scramble limit, not a sensible default for a tunnel the player walks through.
@@ -32,7 +32,6 @@ public:
int32 GetSeasonSeed() const { return SeasonSeed; }
float GetOriginSpineRadius() const { return OriginSpineRadius; }
float GetWorldRadiusVoxels() const { return WorldRadiusVoxels; }
const FString& GetManifestContentHash() const { return ManifestContentHash; }
/** Create the asset in Content Browser, choose a JSON file, then press this button. */
UFUNCTION(CallInEditor, Category = "Season")
@@ -134,10 +134,6 @@ struct VOXELFORGE_API FVoxelSeasonCompositionSettings
}
};
// Friendly aliases for callers that use the task's shorter naming.
using FVoxelSeasonComposerSettings = FVoxelSeasonCompositionSettings;
using FVoxelSeasonComposeSettings = FVoxelSeasonCompositionSettings;
/** Compact audit row; the full vectors live only for selected strates. */
struct VOXELFORGE_API FVoxelSeasonCandidateAudit
{
@@ -260,10 +256,6 @@ struct VOXELFORGE_API FVoxelSeasonManifest
}
};
/** Human-readable enum names used by JSON and the review page. */
VOXELFORGE_API const TCHAR* VF_GetVoxelSeasonSelectionReasonName(
EVoxelSeasonSelectionReason Reason);
/** Compose, validate, select, serialize, and (by default) write one season. Editor/build-box only. */
#if WITH_EDITOR
VOXELFORGE_API FVoxelSeasonManifest VF_ComposeSeason(
@@ -48,15 +48,6 @@ public:
uint64 RetainedSamples = 0;
uint64 DroppedSamples = 0;
uint64 TotalFrames = 0;
// Kept for source compatibility with the earlier in-process summary. Raw sessions leave
// these zero; the offline summary owns all resolved-frame counts and tables.
uint64 ResolvedFrames = 0;
uint64 UnknownFrames = 0;
uint64 WaitLikeFrames = 0;
uint64 SamplesWithResolvedLeaf = 0;
uint64 SamplesWithWaitLikeFrame = 0;
uint64 UniqueProgramCounters = 0;
uint64 InlineSymbols = 0;
uint64 MaxActiveRegisteredThreads = 0;
uint64 ModuleCount = 0;
double RunSeconds = 0.0;
@@ -78,8 +69,6 @@ public:
/** Used by the module shutdown path as a final lifecycle backstop. */
void Shutdown();
bool IsRunning() const;
/** Called only by FScopedVoxelStackRegistration; cheap when disabled. */
static bool RegisterCurrentThread(int32 LODLevel = INDEX_NONE);
static void DeregisterCurrentThread();
@@ -594,11 +594,6 @@ public:
const FString& PromotedStorePath = FString(),
const IVoxelStratePromotionVerifier* PromotionVerifier = nullptr);
/**
* Compatibility alias retained for callers compiled against the first Tier 4a pass. The
* settings argument is audited only for diagnostics; it is not a corpus input.
*/
bool LoadFromSettings(const UVoxelSettings* Settings, FString& OutReport);
bool LoadFromDefinitions(const TArray<UVoxelStrateDefinition*>& Definitions, FString& OutReport);
/** Add an already-resolved vector, primarily for offline tools and focused tests. */
@@ -625,7 +620,6 @@ public:
int32 Num() const { return Entries.Num(); }
const TArray<FVoxelStrateCorpusEntry>& GetEntries() const { return Entries; }
const TArray<FVoxelStrateFieldSpread>& GetFieldSpreads() const { return FieldSpreads; }
const TArray<FString>& GetSkippedDefinitions() const { return SkippedDefinitions; }
int32 NumForArchetype(ECaveGeneratorType Archetype) const;
int32 NumForProvenance(EVoxelStrateCorpusProvenance Provenance) const;
@@ -804,10 +798,6 @@ VOXELFORGE_API uint32 VF_HashStrateStructureRecipe(const FVoxelOpStackRecipe& Re
VOXELFORGE_API bool VF_AreStrateStructureRecipesIdentical(
const FVoxelOpStackRecipe& A, const FVoxelOpStackRecipe& B);
/** The compact API requested by the composer design. */
VOXELFORGE_API FStrateGenerationParams VF_RollStrateParams(
const FVoxelStrateCorpus& Corpus, int32 Seed, int32 Index);
/** Bitwise comparison over exactly the fields in FStrateGenerationParams::Lerp. */
VOXELFORGE_API bool VF_AreStrateParamsBitIdentical(
const FStrateGenerationParams& A, const FStrateGenerationParams& B);
+1 -21
View File
@@ -249,15 +249,6 @@ public:
* live edit) can never serve a stale strate index or passage shortlist. */
uint32 GetLayoutVersion() const { return PassagesVersion; }
/**
* Fingerprint of the immutable density inputs used by the generator.
*
* Returns zero when the manager has dynamic inputs that this compact cache key intentionally
* does not serialize (seasons, composer recipes, biome maps, or terrain-op assets). Zero is a
* fail-closed answer: callers must skip verdict reuse rather than risk an old all-air proof.
*/
uint64 GetGenerationParamsFingerprint() const;
/** Diagnostic-only switch for isolating the inter-strate support writer. */
void SetPassageSupportFloorWritesEnabledForDiagnostics(bool bEnabled)
{
@@ -289,7 +280,7 @@ public:
* Get generation params for a chunk, with boundary blending.
*
* BLENDING CONCEPT:
* When a chunk is near a strate boundary (within BlendChunks of the edge),
* When a chunk is near a strate boundary (within the definition's TransitionBlendChunks of the edge),
* the params are lerped between the two adjacent strates. This prevents
* hard visual seams where one strate ends and another begins.
*
@@ -419,14 +410,6 @@ public:
void ApplyPassageTunnelAir(float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const;
/** Re-assert landing air after MC-space disturbances, still before the final XY seal. */
void ApplyPassageLandingAirMC(float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const;
/** Re-assert walkable tunnel air after MC-space disturbances, still before the final XY seal. */
void ApplyPassageTunnelAirMC(float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const;
/** Apply the landing/tunnel MC post in one cached passage scan after disturbances. */
void ApplyPassageStructuralPostsMC(float& Density, float WorldX, float WorldY, float WorldZ,
float BaseDensity, float SealThickness) const;
@@ -530,9 +513,6 @@ protected:
// allocator address reuse must not make a stale worker-local stack look current.
uint64 CacheLifetimeId = 0;
// How many chunks at strate boundaries are blended (transition zone)
int32 BlendChunks = 2;
// World seed (stored for passage generation)
int32 CachedSeed = 0;
@@ -510,23 +510,6 @@ VOXELFORGE_API FVoxelConnectivityDiagnostics VF_DiagnoseConnectivityWithSampler(
const FVector& BVoxel,
const FVoxelStrateMeasureSettings& Settings);
/**
* Player-fit connectivity over a custom stack. This is deliberately a separate API from the
* legacy air route: it refuses unless Settings.SampleStep == 1, resolves endpoints against the
* direct capsule-occupancy/floor mask, and flood-fills/routes only through player-fit cells.
*/
VOXELFORGE_API EVoxelConnectivityResult VF_ArePlayerFitConnectedWithSampler(
const IVoxelStrateDensitySampler& Sampler,
int32 StrateBottomWorldZ,
int32 StrateTopWorldZ,
float BoundarySealThickness,
const FVector& AVoxel,
const FVector& BVoxel,
const FVoxelStrateMeasureSettings& Settings,
bool& bOutStartSnapped,
bool& bOutGoalSnapped,
FVoxelConnectivityDiagnostics* OutDiagnostics = nullptr);
/** Full diagnostics variant for the player-fit custom-stack route. */
VOXELFORGE_API FVoxelConnectivityDiagnostics VF_DiagnosePlayerFitConnectivityWithSampler(
const IVoxelStrateDensitySampler& Sampler,
@@ -411,14 +411,4 @@ namespace VoxelGenLOD
Density = Before;
}
/** Compare a scalar proof input such as EvaluateModifierSDF without changing the field. */
FORCEINLINE void CompareSkippedPostValue(
float Candidate, float Canonical,
ETilePostComparisonKind Kind = ETilePostComparisonKind::Other)
{
if (bTilePostReachDebug && !bTilePostReachBypass)
{
RecordSkippedPostComparison(Kind, !SameFloatBits(Candidate, Canonical));
}
}
}
-69
View File
@@ -210,8 +210,6 @@ namespace VoxelMath
// taille de chunk. La taille de chunk reste le levier streaming-vs-draws si besoin.
constexpr int32 CHUNK_SIZE = 32;
constexpr int32 CHUNK_SIZE_SQUARED = CHUNK_SIZE * CHUNK_SIZE; // 1024
constexpr int32 CHUNK_VOLUME = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; // 32768
constexpr float VOXEL_SIZE = 25.0f;
@@ -276,26 +274,6 @@ enum class EVoxelFace : uint8
NegativeZ, // Down (-Z)
};
inline FIntVector GetFaceDirection(EVoxelFace Face)
{
switch (Face)
{
case EVoxelFace::PositiveX: return FIntVector( 1, 0, 0);
case EVoxelFace::NegativeX: return FIntVector(-1, 0, 0);
case EVoxelFace::PositiveY: return FIntVector( 0, 1, 0);
case EVoxelFace::NegativeY: return FIntVector( 0, -1, 0);
case EVoxelFace::PositiveZ: return FIntVector( 0, 0, 1);
case EVoxelFace::NegativeZ: return FIntVector( 0, 0, -1);
default: return FIntVector( 0, 0, 0);
}
}
inline FVector GetFaceNormal(EVoxelFace Face)
{
const FIntVector Dir = GetFaceDirection(Face);
return FVector(Dir.X, Dir.Y, Dir.Z);
}
//=============================================================================
// COORDINATE CONVERSION
//=============================================================================
@@ -319,53 +297,6 @@ inline FIntVector WorldToChunkCoord(const FVector& WorldPos)
);
}
inline FIntVector WorldToLocalCoord(const FVector& WorldPos)
{
// ((x % n) + n) % n → modulo positif même pour x négatif.
// (-5 % 32) = -5 en C++, mais on veut 27.
return FIntVector(
((FMath::FloorToInt(WorldPos.X / VOXEL_SIZE) % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE,
((FMath::FloorToInt(WorldPos.Y / VOXEL_SIZE) % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE,
((FMath::FloorToInt(WorldPos.Z / VOXEL_SIZE) % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE
);
}
inline FVector ChunkToWorldPos(const FIntVector& ChunkCoord)
{
return FVector(
ChunkCoord.X * CHUNK_SIZE * VOXEL_SIZE,
ChunkCoord.Y * CHUNK_SIZE * VOXEL_SIZE,
ChunkCoord.Z * CHUNK_SIZE * VOXEL_SIZE
);
}
// Index 3D → 1D pour un tableau plat (voir doc CLAUDE.md: "x + y*SizeX + z*SizeX*SizeY").
inline int32 LocalToIndex(int32 X, int32 Y, int32 Z)
{
return X + (Y * CHUNK_SIZE) + (Z * CHUNK_SIZE_SQUARED);
}
inline FIntVector IndexToLocal(int32 Index)
{
return FIntVector(
Index % CHUNK_SIZE,
(Index / CHUNK_SIZE) % CHUNK_SIZE,
Index / CHUNK_SIZE_SQUARED
);
}
inline bool IsValidLocalCoord(int32 X, int32 Y, int32 Z)
{
return X >= 0 && X < CHUNK_SIZE
&& Y >= 0 && Y < CHUNK_SIZE
&& Z >= 0 && Z < CHUNK_SIZE;
}
inline bool IsValidLocalCoord(const FIntVector& Coord)
{
return IsValidLocalCoord(Coord.X, Coord.Y, Coord.Z);
}
//=============================================================================
// MATH HELPERS (partagés entre générateur, morphologie, manager)
//=============================================================================
@@ -17,14 +17,6 @@ namespace VoxelWormField
};
/** Evaluate the exact two-noise field, retaining the N1 threshold short-circuit. */
VOXELFORGE_API float EvaluateExact(
float WorldX,
float WorldY,
float WorldZ,
float Threshold,
const FParameters& Parameters);
/** Evaluate the exact two-noise field. */
VOXELFORGE_API float Evaluate(
float WorldX,
float WorldY,
@@ -4243,76 +4243,6 @@ bool WriteObjHeader(FArchive& Archive)
return bOk && !Archive.IsError();
}
bool WriteObjTile(
FArchive& Archive,
const FVoxelMeshData& MeshData,
int32 VertexOffset,
FString& OutError)
{
if (!ValidateCanonicalTile(MeshData, OutError))
{
return false;
}
bool bOk = true;
for (const FVector& Vertex : MeshData.Vertices)
{
bOk = bOk && WriteUtf8(Archive, FString::Printf(
TEXT("v %.9f %.9f %.9f\n"),
Vertex.X / 100.0,
Vertex.Y / 100.0,
Vertex.Z / 100.0));
}
for (const FVector2D& UV : MeshData.UVs)
{
bOk = bOk && WriteUtf8(Archive, FString::Printf(
TEXT("vt %.9f %.9f\n"), UV.X, UV.Y));
}
for (const FVector& Normal : MeshData.Normals)
{
bOk = bOk && WriteUtf8(Archive, FString::Printf(
TEXT("vn %.9f %.9f %.9f\n"), Normal.X, Normal.Y, Normal.Z));
}
const int32 NumTriangles = MeshData.Triangles.Num() / 3;
const int32 FirstCeilingTriangle = FMath::Clamp(
NumTriangles - MeshData.NumCeilingTriangles, 0, NumTriangles);
if (NumTriangles > 0)
{
bOk = bOk && WriteUtf8(Archive, TEXT("usemtl VoxelGround\n"));
}
for (int32 Triangle = 0; Triangle < NumTriangles; ++Triangle)
{
if (Triangle == FirstCeilingTriangle)
{
bOk = bOk && WriteUtf8(Archive, TEXT("usemtl VoxelCeiling\n"));
}
const int32 Base = Triangle * 3;
const int32 SourceA = MeshData.Triangles[Base];
const int32 SourceB = MeshData.Triangles[Base + 1];
const int32 SourceC = MeshData.Triangles[Base + 2];
if (SourceA < 0 || SourceB < 0 || SourceC < 0
|| SourceA >= MeshData.Vertices.Num()
|| SourceB >= MeshData.Vertices.Num()
|| SourceC >= MeshData.Vertices.Num())
{
OutError = TEXT("Canonical mesher returned an out-of-range triangle index.");
return false;
}
const int32 A = SourceA + 1 + VertexOffset;
const int32 B = SourceB + 1 + VertexOffset;
const int32 C = SourceC + 1 + VertexOffset;
bOk = bOk && WriteUtf8(Archive, FString::Printf(
TEXT("f %d/%d/%d %d/%d/%d %d/%d/%d\n"),
A, A, A, B, B, B, C, C, C));
}
if (!bOk || Archive.IsError())
{
OutError = TEXT("Could not write a canonical OBJ tile.");
return false;
}
return true;
}
bool WriteObjMesh(
FArchive& Archive,
const FVoxelMeshData& MeshData,
@@ -7091,29 +7021,6 @@ FString BuildExploreJson(
return Writer->Close() ? Json : FString();
}
const TCHAR* ExploreEffectName(EVoxelOpEffect Effect)
{
switch (Effect)
{
case EVoxelOpEffect::Identity: return TEXT("Identity");
case EVoxelOpEffect::CarveOnly: return TEXT("CarveOnly");
case EVoxelOpEffect::FillOnly: return TEXT("FillOnly");
case EVoxelOpEffect::Both: return TEXT("Both");
default: return TEXT("Unknown");
}
}
const TCHAR* ExploreTileClassName(EVoxelTileClass Class)
{
switch (Class)
{
case EVoxelTileClass::AllSolid: return TEXT("AllSolid");
case EVoxelTileClass::AllAir: return TEXT("AllAir");
case EVoxelTileClass::Mixed: return TEXT("Mixed");
default: return TEXT("Unknown");
}
}
// Density-bound APIs use FLT_MAX as the documented "unknown/unbounded" sentinel. It is finite
// according to IEEE-754, so FMath::IsFinite alone would misreport the very failure this audit is
// intended to expose as a real numeric envelope.