fix(streaming): no false gate on digs, no see-through at tile handoffs; density volume off

- Dig near the pawn: a same-tile collision recook withdrew readiness although the old body was
  still installed, so the gate held a standing pawn (957 of 1,931 frames over 8 near digs).
  A tile now stays ready during a recook while collision is still wanted and its existing body is
  valid. After: 0 gate frames, 0 falling frames over 2,604 frames. Dig directly under the pawn
  still falls (~127 cm, max ~502 cm/s). The reported "accelerating toward the ground" was not
  reproduced; the false hold is the measured part.
- See-through: the retire logic only waited for replacements that overlapped the old tile in
  volume and missed desired neighbours touching at a face/edge/corner. Handoff now includes
  contact. New surface-witness gap audit (24 surface points per tile, skirts excluded, catches an
  injected early hide). 6000 cm/s walk, 75 s: 3 gaps / 51 frames / longest 603 ms -> 0.
  Dig session: 0 -> 0. Overlap audit and edit ghost stay at 0.
- bEnableDensityVolume defaults to false; when off: no volume, no fill thread, uploads or tick
  work, no volume-dependent proof bypass; terrain MIDs get VolP5.z = 0 (enable off), other VolP*
  black, VolTex* null, so M_Test1's volume nodes return their neutral result.

Gate: deep gate-on passes (79.9 m, 3 holds, -0.101 cm), gate-off penetrates (-5.1 cm).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-09-29 04:53:57 +02:00
1 parent 0bcd67a016
commit ce6812dbeb
7 files changed
+1111 -76

No files matched your search

+14 -6
View File
@@ -152,6 +152,10 @@ struct FChunkResult
// Exact pre-edit level-0 lattice for the bounded local-player dig cache. Sampled on the worker
// with the tile's normal generator context and moved through the result queue.
FVoxelSharedDensityGrid PreEditDensityGrid;
// Sparse points on the prior surface, used only by the explicit rendered-coverage audit.
// Captured from the mesher output and kept out of normal streaming results.
bool bCaptureSurfaceWitnesses = false;
TArray<FVector> SurfaceWitnesses;
};
/** One worker-produced mesh identity emitted only by the explicit parity harness. */
@@ -223,17 +227,16 @@ public:
UPROPERTY()
UVoxelAtmosphereManager* AtmosphereManager;
/** Player-centred density CLIPMAP streamed onto the GPU for the mini-sun raymarched shadow
* system (forward rendering). Created in BeginPlay when Settings->bEnableDensityVolume is on.
* Filled on worker threads (re-evaluating GetDensityAt), recentred toroidally as the player
* moves, refilled locally on carve. See UVoxelDensityVolume. */
/** Optional player-centred density CLIPMAP for mini-sun raymarched shadows. It is absent when
* Settings->bEnableDensityVolume is false, so no fill thread or texture uploads run. */
UPROPERTY()
UVoxelDensityVolume* DensityVolume;
/** Shared Material Instance Dynamics that bind the density-volume textures + per-frame shadow params
* (clipmap transform + nearest orb) onto the terrain material(s). Keyed by BASE material so every
* tile of a given base shares ONE MID (no batching cost). Created lazily in ApplyMeshToTile,
* refreshed each Tick by UpdateTerrainMaterialParams. */
* tile of a given base shares ONE MID (no batching cost). Created lazily in ApplyMeshToTile;
* refreshed each Tick only while DensityVolume exists. When disabled, each MID receives neutral
* VolP* values and null VolTex* bindings at creation. */
UPROPERTY()
TMap<TObjectPtr<UMaterialInterface>, TObjectPtr<UMaterialInstanceDynamic>> TerrainMIDs;
@@ -541,10 +544,15 @@ private:
/** Apply the current TVP0..4 + level-0 volume texture to one MID (also used on MID creation). */
void SetVolumeParamsOnMID(UMaterialInstanceDynamic* MID) const;
/** Put all terrain MIDs into the material's neutral, volume-disabled state. */
void SetDensityVolumeMaterialParamsDisabled();
/** Explicitly opt-in headless streaming validation. This is a command-line-only harness path;
* normal gameplay never moves the pawn here. It supplies a repeatable moving session and lets
* -nullrhi request a graceful EndPlay so the clean latency summary is flushed. */
void ConfigureHeadlessStreamingTest();
void AdvanceHeadlessDigMotionTest(FVector& InOutPlayerPosition, APawn* Pawn);
void RecordHeadlessDigMotionFrame(APawn* Pawn, const FVector& PlayerPosition, float DeltaTime);
void AdvanceHeadlessStreamingTest(FVector& InOutPlayerPosition,
FVector& InOutPlayerHeading, APawn* PlayerPawn);
void AdvanceHeadlessCollisionGateStressTest(FVector& InOutPlayerPosition,