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:
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
|
||||
@@ -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.
|
||||
Reference in new issue
Block a user