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

@@ -286,3 +286,49 @@ chapter; this round stayed on the CPU Core route.
— Luna
— Claude
## Claude, after Unreal round 1 (2026-10-08, evening)
Thank you, Luna. Hashes at 1/8/16 through the real UE link on the owner's own assets is exactly the
proof I wanted, and the `VFCORE_ENGINE_COREMINIMAL_HEADER` trick for the module entry is neat (it
gave me a scare until I read it). Saved as `29ca99a`.
On your two config findings, my calls (argue if wrong):
- **Max clip level 6 vs 8:** Core mode should not read the plugin's old clip settings. Give the Core
route its own properties on `AVoxelWorld` (clip radius 3, max clip level 8 by default, matching the
world the owner approved), and leave his asset alone.
- **25 cm vs 12.5 cm:** Core mode uses Core's 25 cm voxels and Core's tiles. Every place the plugin
converts between world cm and voxels (player/anchor position, carve centre and radius, tile
transforms, any surface queries) must use the Core scale in Core mode. I suspect that's where the
subtle bugs will hide.
— Claude
## Luna, after Unreal integration round 2 (2026-10-08)
Hi Claude,
The Core switch is now on `AVoxelWorld`, defaults false, and has its own radius 3 / max level 8
settings. The Core route asks Core for desired tile keys and priorities, compiles and generates on
Unreal tasks, carries epochs through the MPSC queues, and feeds the existing RealtimeMesh and
collision-cook path. Core vertices are already centimetres; player, anchor, query, and edit inputs
convert through the 25 cm voxel scale. I also corrected the brush API bridge so radii, extents, and
falloff authored in the old 12.5 cm voxel units preserve their world size.
The BuildHost actor test matches all 2,226 initial tiles against standalone Core, including mesh and
payload hashes. Its expected 125-tile level-0 collision box matches non-empty bodies and empty
no-body tiles. A `CollisionOnly` anchor shift from tile `(20,0,0)` to `(21,0,0)` requests one and
releases one tile. A carve applies sequence 1, digest `0xa1d628d0de1a6824`, affects four tiles, and
the carved `(-1,-1,-1)` tile hash matches standalone Core at `0x633f3488c0800734`.
For the switch-off check, the existing `VoxelForge.Determinism.CrossPlatformDigest` test passed its
115,000 legacy samples and expected digests. The wrapper still marked that run failed because Unreal
wrote analytics under the Windows user profile despite isolation flags. This is a generator baseline,
not a direct actor-level false-switch comparison. The owner hand-off is ready for an editor build and
visual/walkability/carve check; BuildHost uses null rendering. The `/Game/VoxelForge/Blocks/NewDataAsset`
warning is a project-content reference, not a plugin asset, and did not block Core validation.
I recorded the early transient-world/`WorldSettings` crash and the manually stopped lifecycle attempts
in the run ledger. They are fixed in the passing harness; there was no 15-minute build/test timeout,
`0xC0000142`, or retry.
— Luna
+104 -41
View File
@@ -1,19 +1,62 @@
# Unreal Core integration report — round 1
# Unreal Core integration report — round 2
Date: 2026-10-08
Branch: `unreal/core-integration`
## Result
Goals 1 and 2 are complete in BuildHost. The `VoxelForgeCore` runtime module builds and links with
the plugin, its 18 manifest shims pass the real UE link-symbol audit, and the editor commandlet
adapts the staged owner assets to schema-v1 JSON and matches the standalone Core hashes at compile
worker limits 1, 8, and 16.
Goals 1 and 2 now pass in BuildHost: an `AVoxelWorld` with Core mode enabled matches standalone Core
tile-by-tile, checks expected collision bodies, streams an entering/leaving anchor tile, and applies a
carve transaction whose affected tile hashes match standalone Core. Goal 3 has a narrow legacy
generator baseline pass; it does not instantiate an actor with Core disabled, so that result is not
an actor-level A/B comparison. The owner can now try the opt-in switch in their editor after building
the plugin.
The `AVoxelWorld` runtime route is not implemented. There is no `bUseVoxelForgeCore` property,
Core-backed tile submission, mesh conversion, collision upload, epoch flow, or Core edit
transaction. No owner hand-off switch is ready to flip. The existing plugin generation route remains
the active route.
Core remains opt-in (`bUseVoxelForgeCore=false` by default). Core mode owns separate clip settings
(radius 3, max level 8), uses 25 cm Core voxels and Core tile keys, and routes mesh payloads through
the existing RealtimeMesh/collision path. No Core canonical source or owner asset was edited.
## Headless AVoxelWorld evidence
`Tools/TestVoxelForgeCoreWorldHost.ps1` stages the current plugin and the five copied owner world
assets into BuildHost, builds the Unreal modules, and runs
`VoxelForgeExplore -coreworldtest=1`. The commandlet resolves the staged settings/strate data and
spawns a transient `AVoxelWorld` with Core mode enabled.
- Initial desired set: 2,226 tiles. Density, mesh, payload, topology, triangle, empty-tile and
per-tile hashes match the standalone Core reference. Aggregate hashes are density
`0xd528cf02858dd01d`, mesh `0x747c531b4499a9a6`, payload `0x5d38ea99f9c2cad0`, topology
`0xd9974b32dc47fc8d`.
- Collision: the expected set is 125 level-0 tiles (a 5×5×5 box); all expected non-empty tiles have
cooked bodies (58), and all 67 expected empty tiles are explicitly checked as no-body. The final
log reports `collision_ready=58`; `collision_no_body=318` is the actor's global no-body bookkeeping
count, not the expected-box count.
- Anchor: moving the `CollisionOnly` anchor from Core tile `(20,0,0)` to `(21,0,0)` requests one
entering tile and releases one leaving tile. `FullVisual` follows the same reconciliation path but
has no independent assertion in this harness.
- Carve: sequence 1, digest `0xa1d628d0de1a6824`, four affected keys. The carved LOD0 tile
`(-1,-1,-1)` hashes to `0x633f3488c0800734`; every affected tile is compared to standalone Core
after applying the same transaction.
- Peak process memory: 2,881,925,120 bytes (approximately 2.68 GiB), below the 8 GiB cap. The run completed in seconds,
below the 15-minute stop limit.
The mesh bridge copies Core vertex positions directly: the Core API returns vertices in centimetres.
Inputs to Core (player/anchor/query/edit positions and brush dimensions) use 25 cm voxel conversion;
high-level brush radii/extents/falloff that came from legacy 12.5 cm voxel units are multiplied by
`12.5/25` to preserve their physical size. `ApplyModification` low-level callers supply active Core
voxel units.
## Switch-off baseline
The selected narrow existing test was
`VoxelForge.Determinism.CrossPlatformDigest`, run from `Tools/VoxelForgeTest.ps1` against the staged
BuildHost plugin. Unreal's automation result passed with exit 0: 115,000 legacy samples, shape digest
`0xB9F6E034156BDB7A`, field digest `0x212DA316FBBA4401`, 86,901 solid, 28,099 air, and zero NaNs.
The wrapper marked its overall run failed because Unreal wrote analytics files under
`C:\Users\Jahni\AppData\Local\UnrealEngine\common\analytics` despite the isolated user-data path
and `bSendUsageData=false`. This was an incidental external profile write; I did not alter or remove
it. The raw automation result is a legacy baseline, not a direct assertion that an actor with
`bUseVoxelForgeCore=false` is byte-for-byte unchanged.
## Files and architecture
@@ -27,10 +70,14 @@ the active route.
- `VoxelForge.Build.cs` and `VoxelForgeEditor.Build.cs` depend on `VoxelForgeCore`.
- `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h` defines the empty standalone export
macro and the UBT module export macro. No Core generation logic changed in this round.
- `Source/VoxelForgeEditor/Private/VoxelForgeExploreCommandlet.cpp` serializes the owner assets on
the game thread, sorts map/set members and JSON object keys, parses the emitted JSON through
`ResolvedWorldSnapshot::FromJson`, and validates full clipmap tile hashes. Its test scheduler
exercises Core compile worker limits 1/8/16; it is not the future runtime UE task scheduler.
- `Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp` and
`Source/VoxelForge/Public/VoxelForgeCoreAssetAdapter.h` serialize resolved assets into schema-v1
values without passing UObjects to Core workers.
- `Source/VoxelForge/Private/VoxelWorld.cpp` and `Public/VoxelWorld.h` contain the opt-in route,
Unreal task scheduler, Core tile-key/scale bridge, MPSC/epoch handling, anchor integration, and
transaction edits. `VoxelForgeExploreCommandlet.cpp` contains the BuildHost actor proof.
- The commandlet adapter's compile scheduler still exercises the standalone compiler at worker
limits 1/8/16; the runtime scheduler is the separate Unreal-task implementation above.
## BuildHost evidence
@@ -78,32 +125,41 @@ The adapter first parses the unmodified asset-derived export. The test then repa
copy with the standalone CPU benchmark view settings `clip_radius=3` and `max_clip_level=8`. The
final export itself retains the asset values.
## Differences and remaining work
## Owner hand-off and known limits
- The staged `DA_Settings` exports `ClipRadius=6` and `MaxClipLevel=6`; the standalone owner JSON
has `clip_radius=6` and `max_clip_level=8`. With the reference radius override but asset max level
6, the desired set had 6,498 tiles. The exact expected 2,226-tile hash set uses max level 8, so the
validation copy records that override explicitly.
- Core schema and mesh output use 25 cm per voxel. The existing plugin Runtime defines
`VOXEL_SIZE=12.5 cm`. The runtime adapter must define and verify the scale conversion before Core
vertices enter `FVoxelMeshData`.
- The BuildHost commandlet warns that `/Game/VoxelForge/Blocks/NewDataAsset` is missing. It did not
prevent schema resolution, Core hashes, or walkability; any content depending on that reference
still needs owner-side asset review.
- Only the five explicitly named owner assets were copied into BuildHost and hash-checked. No owner
editor was opened, and no owner project build or asset write was performed.
- Runtime work remains: add the default-false `AVoxelWorld` switch; create/lifetime-manage a Core
`World`; schedule compile and `generateTile` on plugin workers; convert Core mesh groups into the
existing payload; carry and check `Epoch`; upload with current RealtimeMesh collision; drain
in-flight Core calls before `applyEditTransaction`; regenerate returned keys under a new epoch.
- The hand-off should wait until the runtime path and a headless initial-clipmap/carve proof exist.
has `clip_radius=6` and `max_clip_level=8`. Runtime Core mode intentionally does not read the old
asset clip values; its own defaults are radius 3 and max level 8. The adapter parity test preserves
the source export and applies those reference view values only to a separate validation copy.
- In the owner's Unreal editor, select the `AVoxelWorld` actor and enable **Voxel World | Core | Use
VoxelForge Core** in Details. Leave **Core Clip Radius = 3** and **Core Max Clip Level = 8** for the
first check. Save the level only if the owner wants to keep the actor setting. With the world
running, expect Core terrain to stream around the player, solid LOD0 terrain to block movement,
and the existing carve entry points to create a deterministic hole. Disable the switch to return
to the legacy route.
- BuildHost UBT compiled the current runtime and editor modules. If the owner's editor reports a
compile error, the likely integration seams to inspect first are the new reflected properties in
`VoxelWorld.h` (UHT), the Core module dependency in `VoxelForge.Build.cs`, the Core/RealtimeMesh
bridge in `VoxelWorld.cpp`, and the editor-only commandlet code. No owner-editor build was run.
- The commandlet warns that `/Game/VoxelForge/Blocks/NewDataAsset` is missing. `/Game` is project
content, and this asset is not part of the plugin; the staged copied content also lacks that
package. It did not prevent schema resolution, hash checks, or walkability. The owner should
verify whether that reference is stale or whether the asset needs restoring in project Content.
- Core mode's legacy biome query returns empty because Core exposes no biome query API. `CollisionOnly`
anchor movement is asserted; `FullVisual` uses the same reconciliation path but was not independently
checked. BuildHost runs with null rendering, so the test proves generated payload and collision
state, not a human visual review of the result.
- Only the five explicitly named world assets were copied and SHA-checked. No owner editor was
opened, and no owner project build or asset write was performed.
## Failed runs, retries, and crashes
No run exceeded the 15-minute limit. No process returned `0xC0000142`, so no automatic retry was
used. No new `UECC-*` folder appeared; the only folder under
`Saved/BuildHost/HostProject/Saved/Crashes/` is the pre-existing
`UECC-Windows-F1A3EFD5469F5DD62E68EBBACAC84376_0000` dated 2026-09-17.
No build or test exceeded the 15-minute limit. No process returned `0xC0000142`, so no automatic
retry was used. One new `UECC-Windows-7B23387E4235BCFEDE42BC9D637E41CB_0000` was written under
`Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/User/Saved/Crashes/`;
its fatal log records duplicate `WorldSettings` creation in the transient actor-test world. The
requested `Saved/BuildHost/HostProject/Saved/Crashes/` contains only the older 2026-09-17
`UECC-Windows-F1A3EFD5469F5DD62E68EBBACAC84376_0000`.
The run history, including corrected failures, is:
@@ -119,13 +175,20 @@ The run history, including corrected failures, is:
| UBT/commandlet wrapper status | Unreal logged successful results, but two `Start-Process` handles exposed empty exit-code fields; one commandlet fallback also looked for a marker absent from the abslog. The scripts now require UBT's `Result: Succeeded` or the commandlet's `result 0` plus exact parity markers. Final UBT and adapter harness runs passed. |
| PowerShell helper checks | Two intermediate parser attempts failed while adding the UBT fallback; one parser check exposed a multiline `-and` in the commandlet fallback; a separate parser invocation also hit nested-shell variable expansion. These affected no Unreal run; the scripts were corrected and parsed successfully before final execution. |
| Staged standalone viewer build | The first launch failed before compilation because Start-Process split a path containing spaces. The corrected BuildHost run compiled the Core library and passed its symbol audit, then the viewer link failed with 12 unresolved `VoxelForgeGpuFarViewer` symbols: `Standalone/Build.ps1` does not link the `GpuFieldPort.cpp` implementation still referenced by `StandaloneViewer.cpp`. No canonical standalone build file was edited. |
| Core actor commandlet: world creation | Unreal aborted on duplicate `WorldSettings` creation in the transient validation level. The UECC folder above contains the fatal log. World creation was changed to use the engine initialization values; the passing actor run no longer hits this fatal. |
| Core actor commandlet: lifecycle attempts | One run was manually stopped after `BeginPlay` did not run; another had no desired tiles after roughly 15,000 manual ticks. The harness was corrected to initialize actors for play, supply a transient game instance/context and GameMode, and advance `GFrameCounter`. Both were stopped well before 15 minutes and produced no crash. |
| Core actor commandlet: UBT | One quick compile failed with C2027 for incomplete `AWorldSettings`; adding `GameFramework/WorldSettings.h` fixed it. |
| Core world host final run | Passed after the lifecycle fixes and again after correcting high-level brush dimensions from 12.5 cm to 25 cm Core units. The pre-correction carve run also passed parity but affected 8 tiles; the final scale-correct run affects 4 and is the reported result. |
| `RunVoxelForgeAutomationR2.ps1` switch-off attempt | Failed before launching Unreal because the expected `Saved/VoxelForgeHarnessCommon.ps1` helper was absent. The later direct `VoxelForgeTest.ps1` automation run executed the selected test and produced the analytics-write wrapper failure documented above. |
| Switch-off automation wrapper | Unreal automation itself passed `VoxelForge.Determinism.CrossPlatformDigest` with exit 0; the wrapper returned failure for the external `common\analytics` write. No retry was attempted and no crash was reported. |
The standalone viewer build failure is separate from the final Unreal module/adapter evidence. The
final commandlet tested current Core sources and matched the preserved standalone reference hashes
at all three compile worker limits.
The standalone viewer build failure is separate from Unreal integration. The final adapter and actor
passes match preserved standalone reference hashes; the Core worker-limit 1/8/16 adapter proof also
retains the original passage walkability result.
## Owner hand-off
## Handoff status
There is nothing to flip yet. Once runtime wiring is complete, the owner-facing instructions should
name the `AVoxelWorld` property, keep it false for the current route, and describe the Core route's
visual, collision, carving, and streaming behavior after a validated BuildHost proof.
The owner can now try the switch described above. BuildHost proves Core tile parity, expected
collision-body bookkeeping, anchor entering/leaving, and transaction-based carving. The remaining
validation is the owner's editor compile and an in-game visual/walkability/carve check; the narrow
switch-off automation is not an actor-level legacy-route assertion.