# Shared C++ library plan This round keeps the standalone copy in place. The next extraction should make one implementation serve both hosts; it should not turn the compatibility layer into a second public API. ## Library contents Move the deterministic CPU pipeline into `VoxelForgeCore`: - Plain voxel, tile, vector, bounds, and resolved-world input types. - Deterministic math, noise, density operations, cave and passage fields, strate composition, and the room/SDF caches they use. - Marching-cubes tables and meshing, including the density-lattice gradient normals. - Clipmap desired-set calculation and the shared density evaluation entry points. Keep JSON and Unreal asset loading, material/actor creation, D3D11 and Unreal rendering, collision, worker scheduling, cancellation policy, and per-frame mesh upload budgets in the host applications. The cache-region traversal found in this round belongs with the density/meshing implementation. The worker-local room graph cache is keyed by exact XY bounds and stratum. Grouping samples by the legacy cache regions reduced a profiled LOD3 tile from 1,084 graph builds to 229. At coarser sizes, plane-first traversal still thrashes the same XY windows across a tall Z run, so tiles wider than 16 chunks keep each XY column's Z samples contiguous. The profiled 64-tile LOD6 case fell from 36,480 graph builds (13.189 s in graph construction) to 12,160 (5.210 s), with the same density hash. Cache capacity is also scale-dependent: a 32-chunk LOD5 tile benefits from two cached stratum windows (26,926 to 9,700 builds across 64 tiles), while a 64-chunk LOD6 tile regresses with two slots (12,160 to 23,104), so the current generator selects two only for 32-chunk tile contexts and one otherwise. Replacing the room-graph `std::function` recursion then reduced profiled LOD5 RoomGraphBuild from 4.531 to 4.417 s and LOD6 from 5.210 to 5.038 s across the same 64 tiles, without changing graph build counts or density hashes. These timings are profiling evidence, not a cross-host benchmark. The shared API should own the traversal and cache policy, with parity tests covering both traversal paths while writing the same original density-grid indices. The compatibility-map and allocator change did not move the original LOD0 run; those changes remove known linear-lookup and heap-growth gaps, but stage profiling put the cost in density evaluation and room-graph cache churn. The hot room-graph walks also used an owning `std::function` compatibility alias for recursion; replacing them with generic self-recursive lambdas kept the same depth-first order and removed repeated type-erasure/allocation overhead. Keep that code in the core rather than carrying the UE-style callback alias into it. Viewer lighting and its palette remain host renderer choices and stay outside the shared generator. ## Compatibility boundary The core should expose standard C++ value types, explicit immutable resolved inputs, and owned mesh results. No Unreal headers, reflection macros, `UObject`, Unreal containers, renderer types, or host allocator should cross the boundary. The plugin adapter converts settings and loaded assets into the resolved input snapshot, then converts the returned vertices, indices, and normals into Unreal mesh types. The standalone JSON loader maps its exported snapshot into the same input snapshot. Do not move scheduling into the library. Each host should pass an immutable generation context to a worker and receive an owned result; this lets the plugin retain its task admission and game-thread rules while the viewer retains its worker pool and bounded D3D11 upload pump. ## Plugin integration Add a `VoxelForgeCore` C++20 target and make both builds compile or link that target from the same source files. For Unreal, first prototype the Unreal Build Tool integration: either a small core module that compiles the library sources or a platform-built static library with explicit build rules. Prefer source integration if packaging a binary per Unreal platform would add maintenance. The plugin then replaces its copied evaluator and mesher calls with the core API behind a thin adapter. Preserve plugin-owned UObject resolution, task cancellation, collision, game-thread mesh application, and upload budgets. The standalone keeps its JSON loader and D3D11 renderer. ## Preventing drift before extraction Until the common target exists, keep a manifest of mirrored files and a sync/check script that names the canonical source for each file, compares hashes, and refuses when both copies have changed. Avoid hand-editing only one copy without recording that the edit is pending synchronization. After each density or meshing change, run the 3,436-sample bitwise corpus and the selected-tile density hash check. Keep `/fp:precise`; do not accept evaluator changes that alter density bits as a speed shortcut. A standalone-only optimization must be marked as pending synchronization until it is ported or explicitly rejected for the canonical core. Delete the duplicate standalone source only after both host builds use the common target and the parity corpus passes through each adapter.