# VoxelForgeCore API reference Public header: `Core/include/VoxelForgeCore/VoxelForgeCore.h` (C++20, standard library only). Build the static library and viewer with `Build.ps1 -Target All`, or only the library with `Build.ps1 -Target Core`. The public header uses only standard C++ types and can be included after Unreal's `CoreMinimal.h`. `Core/verification/UnrealHeaderCoexistence.cpp` is the compile smoke check against the installed Unreal 5.7 headers. Copied generator and compatibility declarations stay in the private `vfcore::detail` implementation and do not appear in this API. ## Units and ownership - `Vec3d` query positions and `Vec3i` voxel coordinates are in **voxels**. - `TileKey.coordinate` is a tile coordinate; one coordinate step spans `32 << lod` voxels. - Mesh vertex positions are **centimetres**. UVs, RGBA8 colors, normals and 32-bit indices are returned per vertex / triangle in owned `std::vector`s. - `MeshGroups::groundTriangleCount` and `ceilingTriangleCount` describe the contiguous index runs emitted by the mesher. Ceiling is the final run. `skirtTriangleCount` is a subset of the ground and ceiling runs. `surfaceVertexCount` ends before skirt vertices. - A `World` owns its compiled field and edit log. The snapshot can be shared as immutable input. Serialize compile/edit changes against query and tile-generation calls on that same `World`. ## Load and compile `ResolvedWorldSnapshot::FromJson` accepts the normalized UTF-8 schema-v1 owner export used by the standalone loader. It returns `std::nullopt` and fills `error` when parsing or asset resolution fails. Read `configuration()` for the resolved scalar settings. Implement `JobScheduler::parallel_for` in the host. It must run each index from zero to `count - 1` exactly once and return only after all submitted work is complete. The library creates no threads. `ShapeBuildRequest` supplies the detail and clip bounds in voxels, worker limit, detail variant, far-world inclusion, and optional tunnel/detail profiles. ```cpp std::string error; auto snapshot = VoxelForgeCore::ResolvedWorldSnapshot::FromJson(json, error); if (!snapshot) { /* report error */ } VoxelForgeCore::World world(std::move(*snapshot)); VoxelForgeCore::ShapeBuildRequest build; build.minVoxel = {-256, -768, -384}; build.maxVoxel = { 256, -256, 128}; build.clipMinVoxel = {-57344, -57344, -8192}; build.clipMaxVoxel = { 49152, 49152, 8192}; build.workerLimit = 8; build.includeFarWorld = true; if (!world.compile(build, hostScheduler, error)) { /* report error */ } ``` For a streamed shape world, compile the initial camera region once, then add deterministic detail pages before generating any newly desired fine tile outside that region: ```cpp const auto entering = world.desiredTiles(newCameraVoxels); VoxelForgeCore::TileGenerationOptions options; std::size_t pageCoveredTiles = 0; if (!world.compileTileRegion(entering, 8, hostScheduler, error, &pageCoveredTiles)) { /* report error */ } for (const auto& key : entering) { if (auto mesh = world.generateTile(key, options, error)) { /* upload and retain */ } } world.retainTileRegions(entering); ``` By default, the Core groups missing keys by LOD and builds one analytic primitive/bin region for each entering LOD slab. The region bounds come from the requested absolute tile coordinates, with an 8-voxel sampling apron; no dense lattice is allocated for unused parts of the slab. A tile's samples therefore depend on its world coordinates and the world snapshot, not the camera path or the order in which tiles arrive. `compileTileRegion` skips LODs at or above `fullResolutionLodCount`, keys covered by the initial `ShapeBuildRequest`, and keys already resident. Its optional output counts requested keys that received a new region. After the regions needed by the next desired set compile, call `retainTileRegions` with that set to release regions that are no longer needed. The Core owns region lifetime and mesh data; the host keeps still-visible meshes resident until replacement tiles are generated and uploaded. Pass `analyticOnly = false` to retain the reference packed-page compiler. Packed pages use absolute parent-cell coordinates and an 8-voxel apron; each covers a 128-voxel cube or one larger coarse tile. This path remains available for parity checks and workloads that need the packed lattice. ## Queries and tiles `densityAt(position)` returns signed density; negative is solid and nonnegative is air. `isSolidAt` wraps that sign test. `isSolidAlongSegment(start, end, spacing)` samples evenly along the segment with no interval wider than `spacing` voxels; it returns true if any sample is solid. `classifyBox(origin, step, cells)` returns `allSolid`, `allAir` or `mixed` for mesher tile classification. `desiredTiles(cameraVoxels)` returns the snapshot's clipmap set. Pass it to `prioritizeTiles(tiles, centerChunk)` when submitting work. Generate independent keys concurrently on host workers: ```cpp VoxelForgeCore::TileGenerationOptions options; auto mesh = world.generateTile(key, options, error); if (!mesh) { /* report error */ } // mesh->vertices, mesh->indices and mesh->groups are owned by this result. ``` The optional `hashDensity` flag fills deterministic density, viewer-mesh, payload and topology hashes. `captureDensitySamples` is a diagnostic option and retains the sampled lattice values. ## Deterministic edits Build an `EditTransaction` with a monotonically increasing authority sequence and an ordered brush array (`sphere`, `capsule`, `roundedBox`; `carve`, `addRock`, `densityOffset`). `carve` and `addRock` apply hard signed-distance CSG. `densityOffset` applies `strength` inside a sphere or inside/around a capsule or box with its `falloff` band; negative strength carves and positive strength adds rock. This operation maps the plugin's soft `FVoxelModification` brushes into the shared field. Apply the transaction against the currently desired keys: ```cpp VoxelForgeCore::EditTransaction edit; edit.sequence = 12; VoxelForgeCore::EditBrush brush; brush.shape = VoxelForgeCore::EditBrush::Shape::capsule; brush.operation = VoxelForgeCore::EditBrush::Operation::densityOffset; brush.a = {0.0, 0.0, 0.0}; brush.b = {12.0, 0.0, 0.0}; brush.radius = 3.0; brush.strength = -10.0f; brush.falloff = 2.0f; edit.brushes.push_back(brush); const auto affected = world.applyEditTransaction(edit, currentTiles, error); if (affected) { for (const auto& lodTiles : affected->affectedByLod) for (const auto& key : lodTiles) submitHostJob([&, key] { std::string tileError; return world.generateTile(key, options, tileError); }); } ``` The transaction digest covers the sequence and each brush field in order. Replaying the same sequence and values returns the original result; reusing a sequence with different values or applying an older sequence is rejected. Each client must deserialize identical brush values and apply transactions in the same sequence. `affectedByLod` is limited to the desired keys passed to the call. ## Other outputs `farConnectorSegments()` returns owned connector geometry, while `farConnectorCandidates(min,max)` returns candidate indices overlapping a voxel-space box. The audit methods expose shape detail, surface-family and camera-look checks for host diagnostics. All returned values are standard C++; the host owns conversion to engine mesh, collision or renderer objects.