wip(unreal): AVoxelWorld Core mode -- streaming, collision and carving through VoxelForgeCore

Luna, integration round 2 (BuildHost only): AVoxelWorld::bUseVoxelForgeCore (default
false) routes desired tiles, generation, upload/collision and carving through Core.
Core-only CoreClipRadius=3 / CoreMaxClipLevel=8 (owner's asset untouched); 25 cm Core
voxels in every cm<->voxel conversion; legacy brush sizes scaled to keep physical size;
UE-task JobScheduler, epoch-checked Mpsc results, existing RMC upload + collision cook;
carving via sequenced applyEditTransaction. Switch off: BuildDesiredTiles takes the old
path unchanged.
BuildHost proof (actor commandlet, staged copies of the owner's assets): all 2,226
initial tiles hash-match standalone Core; collision bodies as expected; anchor move
requests 1 / releases 1 tile; carved tile hash matches standalone; peak ~2.68 GiB.
Legacy CrossPlatformDigest automation: 115,000 samples pass (wrapper flagged an
analytics write outside isolation).

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-10-08 20:33:46 +02:00
1 parent 29ca99af7f
commit 075e58187e
7 files changed
+2069 -118

No files matched your search

+74 -8
View File
@@ -34,6 +34,18 @@ class UMaterialInstanceDynamic;
class FScopedGenerationPause;
class ACameraActor;
namespace RealtimeMesh { struct FRealtimeMeshStreamSet; } // T1.f — worker-built geometry buffers
class FVoxelForgeCoreRuntimeState;
struct FVoxelForgeCoreTileHashRecord
{
uint64 Density = 0;
uint64 Mesh = 0;
uint64 Payload = 0;
uint64 Topology = 0;
int32 Triangles = 0;
bool bEmpty = true;
bool bHasHashes = false;
};
/** Per-request cancellation state. The game thread flips the flag when a pending tile leaves the
* desired set; workers only read it and return an aborted result through the normal MPSC queue. */
@@ -141,6 +153,11 @@ struct FChunkResult
// section for a non-empty polygroup — configuring a missing one is invalid).
bool bHasGroundTris = false;
bool bHasCeilingTris = false;
uint64 CoreDensityHash = 0;
uint64 CoreMeshHash = 0;
uint64 CorePayloadHash = 0;
uint64 CoreTopologyHash = 0;
bool bHasCoreHashes = false;
// STRATE CONTENT CUT — the chunk-Z band this tile was MESHED with (MIN/MAX = uncut). The
// apply path clamps its strate/material lookups into it (a coarse tile's raw min corner can
// sit in a strate whose content was cut out of the mesh entirely).
@@ -248,6 +265,25 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel World")
bool bManageAtmosphere = true;
/** Route terrain generation, streaming and edits through Standalone Core (opt-in). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel World|Core", meta = (DisplayName = "Use VoxelForge Core"))
bool bUseVoxelForgeCore = false;
/** Core-only clipmap radius, in level-0 Core tiles. Does not read Settings->ClipRadius. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel World|Core", meta = (ClampMin = "1", ClampMax = "64"))
int32 CoreClipRadius = 3;
/** Core-only maximum clip level. Does not read Settings->MaxClipLevel. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel World|Core", meta = (ClampMin = "0", ClampMax = "8"))
int32 CoreMaxClipLevel = 8;
/** Commandlet-only identity capture; normal Core streaming leaves Core's hash path disabled. */
bool bCaptureVoxelForgeCoreHashesForValidation = false;
TMap<FVoxelTileKey, FVoxelForgeCoreTileHashRecord> VoxelForgeCoreTileHashes;
uint64 LastVoxelForgeCoreEditDigest = 0;
uint64 LastVoxelForgeCoreEditSequence = 0;
TArray<FVoxelTileKey> LastVoxelForgeCoreAffectedTiles;
//=========================================================================
// CHUNK STORAGE
//=========================================================================
@@ -388,7 +424,8 @@ public:
* Applies a spherical brush that subtracts density.
*
* @param Position - World-space center of the carve brush
* @param Radius - Brush radius in voxels (default 6 voxels / 0.75 m at 12.5 cm per voxel)
* @param Radius - Brush radius in legacy Runtime voxels (12.5 cm); Core converts it to
* 25 cm voxels to preserve the physical brush size.
* @param Strength - How aggressively to carve (default 10, higher = deeper)
*/
UFUNCTION(BlueprintCallable, Category = "Voxel World|Modification")
@@ -399,7 +436,8 @@ public:
* Applies a spherical brush that adds density.
*
* @param Position - World-space center of the fill brush
* @param Radius - Brush radius in voxels (default 6 voxels / 0.75 m at 12.5 cm per voxel)
* @param Radius - Brush radius in legacy Runtime voxels (12.5 cm); Core converts it to
* 25 cm voxels to preserve the physical brush size.
* @param Strength - How aggressively to fill (default 10, higher = more solid)
*/
UFUNCTION(BlueprintCallable, Category = "Voxel World|Modification")
@@ -407,7 +445,8 @@ public:
/**
* Box brush carve/fill. Position is world-space (Unreal units); ExtentVoxels is the
* box half-size in voxels. Strength magnitude controls aggressiveness (sign forced).
* box half-size in legacy Runtime voxels (12.5 cm). Core converts it to 25 cm voxels.
* Strength magnitude controls aggressiveness (sign forced).
*/
UFUNCTION(BlueprintCallable, Category = "Voxel World|Modification")
void CarveBox(FVector Position, FVector ExtentVoxels, float Strength = 12.0f);
@@ -416,8 +455,9 @@ public:
void FillBox(FVector Position, FVector ExtentVoxels, float Strength = 12.0f);
/**
* Capsule brush carve/fill between two world-space points (Unreal units), with a
* tube radius in voxels. Great for boring tunnels or laying solid pillars/walls.
* Capsule brush carve/fill between two world-space points (Unreal units), with a tube radius
* in legacy Runtime voxels (12.5 cm). Core converts it to 25 cm voxels.
* Great for boring tunnels or laying solid pillars/walls.
*/
UFUNCTION(BlueprintCallable, Category = "Voxel World|Modification")
void CarveCapsule(FVector WorldA, FVector WorldB, float RadiusVoxels = 6.0f, float Strength = 12.0f);
@@ -426,8 +466,9 @@ public:
void FillCapsule(FVector WorldA, FVector WorldB, float RadiusVoxels = 6.0f, float Strength = 12.0f);
/**
* Apply a fully-specified modification (any shape). Centers/endpoints are expected
* in VOXEL coordinates here (this is the low-level entry the helpers build on).
* Apply a fully-specified modification (any shape). Centers/endpoints and brush dimensions
* are expected in active voxel coordinates here (12.5 cm legacy, 25 cm Core); high-level
* helpers convert legacy brush sizes to preserve physical dimensions.
* Returns nothing; re-meshes affected chunks.
*/
UFUNCTION(BlueprintCallable, Category = "Voxel World|Modification")
@@ -523,6 +564,11 @@ public:
UFUNCTION(BlueprintPure, Category = "Voxel World|Space")
FVector LocalVoxelToWorld(FVector VoxelPos) const;
/** Core-route state accessors used by the isolated BuildHost commandlet. */
bool IsVoxelForgeCoreReady() const;
FVector GetVoxelForgeCoreDefaultCenterWorld() const;
bool QueryVoxelForgeCoreDensityAt(FVector WorldLocation, float& OutDensity) const;
UFUNCTION(BlueprintPure, Category = "Voxel World|Strate")
int32 GetStrateAtPosition(FVector WorldPosition) const;
@@ -601,6 +647,20 @@ private:
/** Put all terrain MIDs into the material's neutral, volume-disabled state. */
void SetDensityVolumeMaterialParamsDisabled();
/** Runtime Core snapshot, world lifetime, and worker-side streaming bridge. */
bool InitializeVoxelForgeCoreWorld();
void BuildCoreDesiredTiles(const FIntVector& Center, const FVector& PlayerPosition,
APawn* PlayerPawn, const FVector& PlayerHeading,
TArray<FVoxelTileKey>& OutLeavers);
void StartPendingCoreRegionCompile();
void LoadCoreTile(const FVoxelTileKey& Tile, EVoxelTileWorkPriority WorkPriority);
void ApplyCoreModification(const FVoxelModification& Modification);
void BuildDesiredTransitionIndex();
float GetActiveVoxelSizeCm() const;
float GetLegacyVoxelToActiveVoxelScale() const;
FIntVector GetTileCoordAtLocalCm(const FVector& LocalPositionCm) const;
FIntVector GetTileCoordAtVoxelPosition(const FVector& VoxelPosition) const;
/** 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. */
@@ -652,6 +712,12 @@ private:
// UpdateOrbLightMPC, which deliberately rewrites every frame).
TWeakObjectPtr<UVolumeTexture> LastBoundVolTex0; // re-push MIDs if the L0 texture was recreated
TSharedPtr<FVoxelForgeCoreRuntimeState, ESPMode::ThreadSafe> VoxelForgeCoreState;
FVector CoreFallbackCenterLocalCm = FVector::ZeroVector;
bool bCoreRegionCompilePending = false;
TArray<FVoxelTileKey> PendingCoreRegionTiles;
TArray<FVoxelTileKey> PendingCoreRetainedTiles;
public:
//=========================================================================
@@ -717,7 +783,7 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Editor Brush")
FVector EditorBrushCenter = FVector::ZeroVector;
/** Brush radius in voxels for the editor buttons. */
/** Brush radius in legacy Runtime voxels; Core helpers preserve the same physical radius. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Editor Brush", meta = (ClampMin = "0.5"))
float EditorBrushRadius = 1.5f * 100.0f / VOXEL_SIZE;