Files
VoxelForge/Standalone/UNREAL_INTEGRATION_REPORT.md
T
Fr0zkaandClaude Opus 5.5 29ca99af7f wip(unreal): VoxelForgeCore UBT module + asset adapter reproduce the standalone world
Luna, integration round 1 (BuildHost only; owner's project and assets untouched):
- New runtime module VoxelForgeCore: one shim per Standalone/Core/core_sources.txt row
  (sources stay canonical under Standalone/), NoPCH/no unity, manifest check; VoxelForge
  links it (no runtime routing yet). UE link-safety audit: 18 shims, 83,843 symbol lines
  vs 399 Unreal-style names, 0 clashes.
- Adapter (editor commandlet path) turns staged copies of the owner's DA_* assets into
  schema-v1 JSON; with clip_radius=3/max_clip_level=8 it reproduces all four Core hashes
  (0xdb2991c73215af4c, 0x8236c5edd7fc8e4f, 0x4c48fa75a543d58e, 0xbea22e76b34a4dfc) and
  walkability 5,642/5,642 at worker limits 1, 8 and 16.
- Noted: the owner's settings asset says max clip level 6 (standalone used 8); Core uses
  25 cm voxels vs the plugin runtime's 12.5 cm.
Not done yet: AVoxelWorld switch and Core runtime route (round 2).
Docs: CODEMAP, ARCHITECTURE, SHARED_CPP_LIBRARY_PLAN, UNREAL_INTEGRATION_REPORT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
2026-10-08 19:38:18 +02:00

9.2 KiB
Raw Blame History

Unreal Core integration report — round 1

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.

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.

Files and architecture

  • Source/VoxelForgeCore/VoxelForgeCore.Build.cs defines the runtime module. It validates the canonical manifest and shim inventory, uses C++20/precise FP with no PCH or unity, and exposes only Standalone/Core/include publicly.
  • Source/VoxelForgeCore/Private/Manifest/ contains one include shim for each of the 18 rows in Standalone/Core/core_sources.txt. Canonical source files remain under Standalone/.
  • Source/VoxelForgeCore/Private/ModuleEntry/ supplies the Unreal module entry and the isolated include of the engine CoreMinimal.h.
  • 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.

BuildHost evidence

Tools/BuildVoxelForgeCoreHost.ps1 stages plugin source and copied owner assets only under Saved/BuildHost/HostProject. The final UBT run completed successfully:

  • UnrealEditor-VoxelForgeCore.dll and UnrealEditor-VoxelForge.dll linked in UnrealEditor Win64 Development.
  • All 18 expected Core shim objects were found and audited.
  • CheckCoreSymbols.ps1 reported CORE_LINK_SAFETY_PASS: 83,843 dumpbin symbol lines checked against 399 copied Unreal-style type names, with no conflicts.
  • Five staged asset copies matched their source SHA-256 values:
Asset SHA-256
DA_Settings 5D2977F57E75A63B6B73499CD6E0AA7FBBF3718CE7F70318107BF922F0819AB7
DA_Strate1 CDA1F985E589F28CA6E93A068FECC3CA92487E4AD5700F2C301C4B563E40E5F9
DA_Strate2 02F56A18CED991BAF93DFB2F69438152275E8353B5E279C1CB7DD6E079E352E2
DA_Strate3 F47437F8D156C608AA06E40C5B76716ED4A19FA0F057688E7FECC04DC976428C
DA_Strate4 279570AE3CBA7B3507269C8209A7C931EEB7A15CC3241CE07B50120996B1C656

The final logs are Saved/BuildHost/UBT-CoreIntegration.log and Saved/BuildHost/VoxelForgeCore_ue_link_safety.log.

Headless adapter evidence

Tools/TestVoxelForgeCoreAdapterHost.ps1 launches the isolated BuildHost Unreal commandlet at Normal priority. It sampled about 4.30 GiB private memory, below the 8 GiB limit. The generated JSON is retained at Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreAdapterValidation/Output/owner_world.json; the commandlet log is beside it under Logs/CoreAdapterValidation.log.

For Core compile worker limits 1, 8, and 16, the validator then generated and hashed the 2,226 desired tiles serially. Each pass matched:

Hash Expected / actual
Density 0xdb2991c73215af4c
Mesh 0x8236c5edd7fc8e4f
Payload 0x4c48fa75a543d58e
Topology 0xbea22e76b34a4dfc
Passage walkability 5,642 / 5,642

The adapter first parses the unmodified asset-derived export. The test then reparses a validation 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

  • 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.

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.

The run history, including corrected failures, is:

Run Outcome
Early UBT validation/build attempts 1–7 Failed in sequence on a shim-preamble regex, stale staged Build.cs, duplicated UHT source tree, missing API export/incorrect CoreMinimal and forwarding-header paths, malformed macro quoting, canonical C4456/C4668 warnings-as-errors, and editor-only FFilePath compat fields. Each was corrected; no source Binaries/, Intermediate/, or generated header was edited.
Initial successful BuildHost UBT runs Passed after defining the module export macro, isolating the actual engine CoreMinimal include, and setting WITH_EDITORONLY_DATA=0. They established module links and the first symbol audit.
Adapter commandlet: first launch Failed the commandlet's output-path guard because -out was outside the staged plugin Saved directory. The path was moved under BuildHost.
Adapter commandlet: DDC path Exited 3 with a fatal error because the DDC path exceeded Unreal's 119-character limit. The staged DDC was moved to the shorter Saved/BuildHost/VFCoreAdapterDDC; no new UECC folder appeared.
Adapter commandlet: scale Failed schema resolution with voxel_size_cm=12.5; the adapter was corrected to emit Core's standalone 25 cm scale.
Adapter commandlet: clip bounds The original radius 6 exceeded the validation compiler's 160-million-node bound. The harness now applies the documented radius 3 override to a copy only.
Adapter commandlet: hash comparison Generated 6,498 tiles and walkability 5,642/5,642, but hashes differed because the staged asset max level is 6 and the standalone reference is 8. The validation copy now applies max level 8.
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.

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.

Owner hand-off

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.