perf(apply): stutter is NOT the game thread -- and the flat floor cannot be relaxed
Two things the owner reported from playing412a7ad. One is answered, one is a null result that Codex flagged itself rather than dressing up. THE FLATTENED TUNNEL FLOORS -- capability-safe, and worth almost nothing He has now flagged these twice: every tunnel carries a smooth flat strip running in and out through otherwise craggy rock. The idea was to make the floor CONDITIONAL -- assert it only where the natural rock fails walkability, leave the rock alone elsewhere. Cheaper and better looking, in theory. The floor is now skipped only when the exact no-floor field passes the same player-fit validator at foot offsets 0, -1, +1. Unknown or failed keeps the slab. natural-floor skips accepted 1,539 of 1,529,241 tests = 0.10% player-fit cells 20,153 -> 20,153 reachable cells 10,483 -> 10,483 arrival -> departure connected, both dihedral p50/p90 2.5429 / 33.8499 deg, IDENTICAL mesh time (their batch) 1.757135 -> 1.757140 s Capability preserved exactly. Visual complaint NOT solved, and no speed gained. ⭐ The useful part is what it PROVED by trying to go further. Every broader policy lost walkable space: analytic-only fit -217, reachable -195 tightened analytic fit -76, reachable -76 exact +/-4 foot fit -16, reachable -16 ⇒ The floor cannot be relaxed without changing the walkability contract or adding a route-aware global proof. That is a real constraint, now measured rather than assumed. Codex's own words, and it was right to lead with them: "the conservative floor change is capability-safe, but it does not visibly solve the flattened-strip complaint." THE STUTTER -- measured, and it is not where we thought Game-thread apply, meshed tiles, under -nullrhi: total apply p50 0.107 ms p95 0.153 ms max 0.273 ms stream upload/RMC p50 0.040 p95 0.088 max 0.124 component creation p50 0.019 p95 0.021 max 0.035 registration p50 0.010 p95 0.011 max 0.020 collision config p50 0.005 p95 0.007 max 0.019 A quarter of a millisecond at worst. The game-thread drain is NOT the hitch. ⇒ Remaining visible stutter is most likely render-thread/RHI work or asynchronous collision cooking behind RealtimeMeshComponent, which is off-limits for edits. Added anyway as a cheap safety valve: MaxMeshApplyMilliseconds, default 2 ms of drain budget per frame. Over 729 apply frames: drain p50/p95/max 0.111/0.182/0.313 ms, budget hits 0, at most 2 visible applies in a frame. It costs nothing today and caps a future burst. Request-to-ready, now timed after game-thread application: all p50 57.1 ms p95 432.9 ms max 919.4 ms -> 2.60 m at 6 m/s meshed p50 134.1 ms p95 457.4 ms max 919.4 ms ⚠️ My own verification: 1.197 / 1.131 / 1.118 s vs 1.088-1.102 s on412a7ad. Mean +4.7% -- below the 17% noise floor, but slower in all three runs, and the validator runs 1.5M times to accept 1,539 skips. Geometry moved by 4 triangles (153,740 -> 153,744), which is allowed. If the next round cannot make that validator earn its place, it should come out. Build 0 errors. Peak RSS 1.67 GB export / 1.90 GB game. Nothing outside Plugins/VoxelForge; RealtimeMeshComponent untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
1 parent
412a7ad219
commit
383ec86c37
11 files changed
+508
-43
No files matched your search
@@ -35,6 +35,17 @@
|
||||
#include "VoxelStrateTypes.h"
|
||||
namespace
|
||||
{
|
||||
using FVFPlayerDensitySampler = FTunnelSupportFloorDensitySampler;
|
||||
|
||||
bool VF_ValidatePlayerFitPose(
|
||||
const FVoxelStrateMeasureSettings& Settings,
|
||||
const FVector& CandidateFeetPoint,
|
||||
float StrateTopZ,
|
||||
float StrateBottomZ,
|
||||
float BoundarySealThickness,
|
||||
FVFPlayerDensitySampler SampleDensity,
|
||||
FVector& OutPoint);
|
||||
|
||||
}
|
||||
#include "VoxelNoise.h" // Pure FBM used by the slab landing query
|
||||
#include "VoxelPassageGeometry.h"
|
||||
@@ -72,6 +83,173 @@ namespace
|
||||
return DX * DX + DY * DY + DZ * DZ;
|
||||
}
|
||||
|
||||
// A graph tunnel's rounded capsule is a candidate natural floor only in the part of the tube
|
||||
// where the player's complete support footprint remains inside a sufficiently wide,
|
||||
// sufficiently flat cross-section. This analytic prefilter only saves density probes; it is
|
||||
// never the decision by itself. The exact no-floor field is passed through the same player-fit
|
||||
// validator used by the capability measurement, and failure retains the old support slab.
|
||||
bool VF_IsNaturalTunnelFloorWalkable(
|
||||
const FCachedTunnel& Tunnel,
|
||||
float WorldX,
|
||||
float WorldY,
|
||||
float FloorZ,
|
||||
float SupportRadius,
|
||||
int32 SegmentIndex,
|
||||
const FTunnelSupportFloorDensitySampler* NaturalSampler,
|
||||
float StrateTopZ,
|
||||
float StrateBottomZ,
|
||||
float BoundarySealThickness)
|
||||
{
|
||||
if (SegmentIndex < 0
|
||||
|| SegmentIndex + 1 >= Tunnel.WorldControlPoints.Num()
|
||||
|| Tunnel.WorldControlRadii.Num() != Tunnel.WorldControlPoints.Num())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FVector& Start = Tunnel.WorldControlPoints[SegmentIndex];
|
||||
const FVector& End = Tunnel.WorldControlPoints[SegmentIndex + 1];
|
||||
const float StartRadius = FMath::Abs(Tunnel.WorldControlRadii[SegmentIndex]);
|
||||
const float EndRadius = FMath::Abs(Tunnel.WorldControlRadii[SegmentIndex + 1]);
|
||||
const FVector2D Delta(End.X - Start.X, End.Y - Start.Y);
|
||||
const float LengthSquared = Delta.SizeSquared();
|
||||
if (!(LengthSquared > KINDA_SMALL_NUMBER)
|
||||
|| !FMath::IsFinite(StartRadius)
|
||||
|| !FMath::IsFinite(EndRadius)
|
||||
|| !FMath::IsFinite(FloorZ)
|
||||
|| !FMath::IsFinite(SupportRadius))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FVector2D Query(WorldX, WorldY);
|
||||
const float T = FMath::Clamp(
|
||||
FVector2D::DotProduct(Query - FVector2D(Start.X, Start.Y), Delta)
|
||||
/ LengthSquared,
|
||||
0.0f, 1.0f);
|
||||
const FVector2D Closest = FVector2D(Start.X, Start.Y) + Delta * T;
|
||||
const float CentrelineDistance = (Query - Closest).Size();
|
||||
const float TubeRadius = FMath::Lerp(StartRadius, EndRadius, T);
|
||||
constexpr float CapsuleSafetyMargin = 0.25f;
|
||||
// The first candidate was still too permissive: the analytic tube was walkable, but
|
||||
// roughness outside the structural core could remove the last supporting voxels. Only
|
||||
// the broad, nearly-centreline part of the widest tubes is a certificate strong enough to
|
||||
// replace the authored floor; all marginal geometry keeps the slab.
|
||||
constexpr float NaturalMinimumTubeRadius = 7.5f;
|
||||
constexpr float NaturalCentrelineTolerance = 0.5f;
|
||||
constexpr float NaturalWallMargin = 2.0f;
|
||||
constexpr float NaturalMaximumAxialGradient = 0.12f;
|
||||
const float PlayerRadius = VoxelPassageGeometry::PlayerRadiusVoxels;
|
||||
const float FootprintRadius = PlayerRadius + CapsuleSafetyMargin;
|
||||
if (TubeRadius < NaturalMinimumTubeRadius
|
||||
|| CentrelineDistance > NaturalCentrelineTolerance
|
||||
|| !(TubeRadius > 0.0f)
|
||||
|| CentrelineDistance + FootprintRadius
|
||||
> TubeRadius - NaturalWallMargin
|
||||
|| SupportRadius + KINDA_SMALL_NUMBER < PlayerRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const float FarthestSupportRadius = CentrelineDistance + FootprintRadius;
|
||||
const float CrossSectionHalfWidth = FMath::Sqrt(FMath::Max(
|
||||
TubeRadius * TubeRadius
|
||||
- FarthestSupportRadius * FarthestSupportRadius,
|
||||
0.0f));
|
||||
if (2.0f * CrossSectionHalfWidth
|
||||
< VoxelPassageGeometry::PlayerHeightVoxels
|
||||
+ 2.0f * CapsuleSafetyMargin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// The round floor's steepest support-patch slope is attained at its outer edge. Keep it
|
||||
// no steeper than the authored 15-degree tunnel contract, rather than using a generous
|
||||
// engine walkability ceiling merely to make the optimization fire more often.
|
||||
const float RadialDenominator = FMath::Sqrt(FMath::Max(
|
||||
TubeRadius * TubeRadius
|
||||
- FarthestSupportRadius * FarthestSupportRadius,
|
||||
KINDA_SMALL_NUMBER));
|
||||
const float RadialGradient = FarthestSupportRadius / RadialDenominator;
|
||||
const float AxialGradient = VoxelPassageGeometry::TunnelFloorGradient(
|
||||
Start, StartRadius, End, EndRadius);
|
||||
if (!FMath::IsFinite(RadialGradient)
|
||||
|| !FMath::IsFinite(AxialGradient)
|
||||
|| RadialGradient > VoxelPassageGeometry::WalkableTunnelMaxGradient
|
||||
|| AxialGradient > NaturalMaximumAxialGradient)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reject bends and segment endpoints where the projected support plane changes abruptly.
|
||||
// The flat-floor path remains responsible for those transition columns.
|
||||
constexpr float ProbeDistance = 1.0f;
|
||||
const FVector ProbePositions[] = {
|
||||
FVector(WorldX - ProbeDistance, WorldY, 0.0f),
|
||||
FVector(WorldX + ProbeDistance, WorldY, 0.0f),
|
||||
FVector(WorldX, WorldY - ProbeDistance, 0.0f),
|
||||
FVector(WorldX, WorldY + ProbeDistance, 0.0f)
|
||||
};
|
||||
for (const FVector& Probe : ProbePositions)
|
||||
{
|
||||
float ProbeFloorZ = 0.0f;
|
||||
float ProbeSupportRadius = 0.0f;
|
||||
int32 ProbeSegmentIndex = INDEX_NONE;
|
||||
if (!VoxelPassageGeometry::ProjectWalkableTunnelFloor(
|
||||
Tunnel.WorldControlPoints,
|
||||
Tunnel.WorldControlRadii,
|
||||
Probe,
|
||||
ProbeFloorZ,
|
||||
ProbeSupportRadius,
|
||||
&ProbeSegmentIndex)
|
||||
|| ProbeSegmentIndex != SegmentIndex
|
||||
|| FMath::Abs(ProbeFloorZ - FloorZ)
|
||||
> VoxelPassageGeometry::WalkableTunnelMaxGradient
|
||||
* ProbeDistance + CapsuleSafetyMargin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (NaturalSampler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FVoxelStrateMeasureSettings FitSettings;
|
||||
const float MaxStepHeightVoxels =
|
||||
FVoxelPlayerCapsuleConstants::MaxStepHeightMeters
|
||||
/ FVoxelPlayerCapsuleConstants::VoxelSizeMeters;
|
||||
// The projected graph floor is the centreline's authored support level, but natural rock
|
||||
// may leave a legal footing a little above or below it. Search a small fixed offset set so
|
||||
// that the conditional path does not mistake a vertically displaced natural ledge for a
|
||||
// failed walkability test. The validator still enforces the actual max-step and capsule
|
||||
// clearance rules for every trial; no geometry is accepted by this search alone.
|
||||
constexpr int32 FeetOffsetCount = 3;
|
||||
const float FeetOffsets[FeetOffsetCount] = {
|
||||
0.0f, -1.0f, 1.0f
|
||||
};
|
||||
for (int32 OffsetIndex = 0; OffsetIndex < FeetOffsetCount; ++OffsetIndex)
|
||||
{
|
||||
const FVector CandidateFeet(
|
||||
WorldX, WorldY,
|
||||
FloorZ + MaxStepHeightVoxels + 0.5f + FeetOffsets[OffsetIndex]);
|
||||
FVector FitPoint = FVector::ZeroVector;
|
||||
if (VF_ValidatePlayerFitPose(
|
||||
FitSettings,
|
||||
CandidateFeet,
|
||||
StrateTopZ,
|
||||
StrateBottomZ,
|
||||
BoundarySealThickness,
|
||||
*NaturalSampler,
|
||||
FitPoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FChunkSDFCache::Reset()
|
||||
@@ -903,8 +1081,6 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
using FVFPlayerDensitySampler = TFunctionRef<float(float, float, float)>;
|
||||
|
||||
bool VF_GetPlayerFitInteriorBounds(
|
||||
const FVoxelStrateMeasureSettings& Settings,
|
||||
float StrateTopZ,
|
||||
@@ -5114,7 +5290,8 @@ bool VoxelCaveMorphology::IsTunnelSupportFloorWorldPoint(
|
||||
Tunnel.WorldControlRadii,
|
||||
Pos,
|
||||
FloorZ,
|
||||
SupportRadius)
|
||||
SupportRadius,
|
||||
nullptr)
|
||||
|| WorldZ > FloorZ + VoxelPassageGeometry::WalkableTunnelFloorAirClearanceVoxels
|
||||
|| WorldZ < FloorZ - VoxelPassageGeometry::LandingFloorThicknessVoxels)
|
||||
{
|
||||
@@ -5150,7 +5327,11 @@ bool VoxelCaveMorphology::IsTunnelSupportFloorWorldPoint(
|
||||
void VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
|
||||
float WorldX, float WorldY,
|
||||
const FChunkSDFCache& Cache,
|
||||
FTunnelSupportFloorColumn& OutColumn)
|
||||
FTunnelSupportFloorColumn& OutColumn,
|
||||
const FTunnelSupportFloorDensitySampler* NaturalSampler,
|
||||
float NaturalStrateTopZ,
|
||||
float NaturalStrateBottomZ,
|
||||
float NaturalBoundarySealThickness)
|
||||
{
|
||||
OutColumn.Reset();
|
||||
|
||||
@@ -5183,16 +5364,36 @@ void VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
|
||||
const FVector ColumnPosition(WorldX, WorldY, 0.0f);
|
||||
float FloorZ = 0.0f;
|
||||
float SupportRadius = 0.0f;
|
||||
int32 SegmentIndex = INDEX_NONE;
|
||||
if (!VoxelPassageGeometry::ProjectWalkableTunnelFloor(
|
||||
Tunnel.WorldControlPoints,
|
||||
Tunnel.WorldControlRadii,
|
||||
ColumnPosition,
|
||||
FloorZ,
|
||||
SupportRadius))
|
||||
SupportRadius,
|
||||
&SegmentIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NaturalSampler != nullptr && VoxelDensityProfile::AreCountersEnabled())
|
||||
{
|
||||
VoxelDensityProfile::AddCounter(
|
||||
VoxelDensityProfile::ECounter::TunnelSupportFloorNaturalTests);
|
||||
}
|
||||
if (VF_IsNaturalTunnelFloorWalkable(
|
||||
Tunnel, WorldX, WorldY, FloorZ, SupportRadius, SegmentIndex,
|
||||
NaturalSampler, NaturalStrateTopZ, NaturalStrateBottomZ,
|
||||
NaturalBoundarySealThickness))
|
||||
{
|
||||
if (VoxelDensityProfile::AreCountersEnabled())
|
||||
{
|
||||
VoxelDensityProfile::AddCounter(
|
||||
VoxelDensityProfile::ECounter::TunnelSupportFloorNaturalSkips);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
float MinZ = FloorZ - VoxelPassageGeometry::LandingFloorThicknessVoxels;
|
||||
float MaxZ = FloorZ + VoxelPassageGeometry::WalkableTunnelFloorAirClearanceVoxels;
|
||||
|
||||
|
||||
Reference in new issue
Block a user