standalone: VoxelForgeCore library -- the fast generator behind a clean C++20 API, output unchanged

- Standalone/Core: public header VoxelForgeCore.h (no Unreal types), static library target,
  ResolvedWorldSnapshot (from the schema-v1 JSON), World (compile, generateTile, density/sign,
  point/segment solid, classifyBox), host-supplied JobScheduler (the core starts no threads),
  sequenced, idempotent EditTransaction returning affected tiles per LOD.
- The viewer, benchmarks, edits and audits run on Core; StreamingWorld stays host code.
- Same as round 11: 11 hash rows at W1 and W8, routes 5642/5642, look/passage/far audits pass,
  bad-shell control fails, six fixed captures byte-identical; cold W8 1.025 s vs 1.041 s reference.
- SHARED_CPP_LIBRARY_PLAN.md rewritten for a UBT module compiling the same sources via shims.
Open issue before Unreal: Core's implementation still compiles the Compat stand-ins named like
Unreal types (TArray, FVector...); inside a UE binary that is an ODR clash. Must be namespaced.

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-05 11:39:02 +02:00
1 parent 631dd57eb4
commit 557f6aac30
22 files changed
+6185 -5063

No files matched your search

@@ -6,7 +6,6 @@
#include "VoxelGenerator.h"
#include "StandaloneResearchTunnels.h"
#include "StandaloneShapeWorld.h"
#include "VoxelSettings.h"
#include "VoxelStrateManager.h"
#include "VoxelStrateDefinition.h"
@@ -2850,12 +2849,6 @@ bool UVoxelGenerator::EvaluateDensityChunk(
float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ,
float* OutPreEditDensity) const
{
if (const FStandaloneShapeWorld* ShapeWorld=FStandaloneShapeWorldAccess::GetActive())
{
const float ShapeDensity=ShapeWorld->DensityAt(WorldX,WorldY,WorldZ);
if (OutPreEditDensity) *OutPreEditDensity=ShapeDensity;
return ShapeDensity;
}
#if WITH_EDITOR
// Step 2e and step 2d are separate editor-only, default-off side paths. The owner field stays
// authoritative unless a research commandlet or automation test explicitly selects one.
@@ -4076,19 +4069,14 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ,
bFinalFieldDifferent);
}
Result = FStandaloneResearchTunnels::Apply(
Result,WorldX,WorldY,WorldZ,static_cast<uint32>(Seed));
Result,WorldX,WorldY,WorldZ,static_cast<uint32>(Seed),
bStandaloneResearchRoundTunnels,bStandaloneResearchEnhancedWalls);
return Result;
}
float UVoxelGenerator::GetDensityAtLattice(int32 WorldX, int32 WorldY, int32 WorldZ,
float* OutPreEditDensity) const
{
if (const FStandaloneShapeWorld* ShapeWorld=FStandaloneShapeWorldAccess::GetActive())
{
const float ShapeDensity=ShapeWorld->DensityAtLattice(WorldX,WorldY,WorldZ);
if (OutPreEditDensity) *OutPreEditDensity=ShapeDensity;
return ShapeDensity;
}
return GetDensityAt(static_cast<float>(WorldX),static_cast<float>(WorldY),
static_cast<float>(WorldZ),OutPreEditDensity);
}
@@ -6501,19 +6489,6 @@ EVoxelTileClass UVoxelGenerator::ClassifyTile(const FIntVector& OriginVoxels, in
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileClassifyCalls);
if (const FStandaloneShapeWorld* ShapeWorld=FStandaloneShapeWorldAccess::GetActive())
{
const EVoxelTileClass ShapeVerdict=ShapeWorld->ClassifyBox(
OriginVoxels,NormalizedStep,NormalizedCellsPerAxis);
if (ShapeVerdict==EVoxelTileClass::AllSolid)
VoxelDensityProfile::AddCounter(VoxelDensityProfile::ECounter::TileClassifyAllSolid);
else if (ShapeVerdict==EVoxelTileClass::AllAir)
VoxelDensityProfile::AddCounter(VoxelDensityProfile::ECounter::TileClassifyAllAir);
else
VoxelDensityProfile::AddCounter(VoxelDensityProfile::ECounter::TileClassifyMixed);
return ShapeVerdict;
}
#if WITH_EDITOR
// The ordinary tile classifier proves the live field's interval bounds. While the separate
// research field is selected, decline those proofs until its own complete final-field interval
@@ -563,9 +563,19 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
{
VoxelDensityProfile::RecordClassifierCall(bSampleClassifier);
}
const EVoxelTileClass Verdict = Generator->ClassifyTile(
BlockOrigin, Step, BlockCells,
bSampleClassifier ? &ClassifierStats : nullptr);
EVoxelTileClass Verdict;
if(ShapeWorldContext)
{
const auto ShapeVerdict=ShapeWorldContext->ClassifyBox(
BlockOrigin,Step,BlockCells);
Verdict=ShapeVerdict==EVoxelTileClass::AllSolid
?EVoxelTileClass::AllSolid
:ShapeVerdict==EVoxelTileClass::AllAir
?EVoxelTileClass::AllAir:EVoxelTileClass::Mixed;
}
else
Verdict=Generator->ClassifyTile(BlockOrigin,Step,BlockCells,
bSampleClassifier ? &ClassifierStats : nullptr);
if (bSampleClassifier)
{
VoxelDensityProfile::AddSampledMeasurement(
@@ -700,10 +710,13 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
{
for (int32 X = 0; X <= BlockCells; ++X)
{
const float Density = Generator->GetDensityAt(
BlockOrigin.X + X * Step,
BlockOrigin.Y + Y * Step,
BlockOrigin.Z + Z * Step);
const float Density = ShapeWorldContext
?ShapeWorldContext->DensityAt(
static_cast<float>(BlockOrigin.X+X*Step),
static_cast<float>(BlockOrigin.Y+Y*Step),
static_cast<float>(BlockOrigin.Z+Z*Step))
:Generator->GetDensityAt(BlockOrigin.X+X*Step,
BlockOrigin.Y+Y*Step,BlockOrigin.Z+Z*Step);
if (!VoxelMath::IsFinite(Density) || Density == 0.0f)
{
bAllSolid = false;
@@ -1003,11 +1016,13 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
((ReachBlockZ * ReachBlocksPerAxis) + ReachBlockY)
* ReachBlocksPerAxis + ReachBlockX;
float PreEditDensity = 0.0f;
DensityGrid[LocalIndex] = Generator->GetDensityAtLattice(
OriginVoxels.X + gx * Step,
OriginVoxels.Y + gy * Step,
OriginVoxels.Z + gz * Step,
bCapturePreEditGrid ? &PreEditDensity : nullptr);
const int32 SampleX=OriginVoxels.X+gx*Step;
const int32 SampleY=OriginVoxels.Y+gy*Step;
const int32 SampleZ=OriginVoxels.Z+gz*Step;
DensityGrid[LocalIndex] = ShapeWorldContext
?ShapeWorldContext->DensityAtLattice(SampleX,SampleY,SampleZ)
:Generator->GetDensityAtLattice(SampleX,SampleY,SampleZ,
bCapturePreEditGrid ? &PreEditDensity : nullptr);
if (bCapturePreEditGrid)
{
OutPreEditDensityGrid->Samples[LocalIndex] = PreEditDensity;
@@ -1024,7 +1039,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
// lower overhead when a tile spans only one room-graph region.
const int64 TileExtentVoxels = static_cast<int64>(Step) * CellsPerAxis;
const bool bUseVerticalCacheTraversal = TileExtentVoxels > CHUNK_SIZE * 16;
const FStandaloneShapeWorld* ActiveShapeWorld=FStandaloneShapeWorldAccess::GetActive();
const FStandaloneShapeWorld* ActiveShapeWorld=ShapeWorldContext;
const bool bUseShapeWorldXBatch=ActiveShapeWorld!=nullptr
&&!bUseSharedDensityGrid&&!bCapturePreEditGrid;
if (bUseVerticalCacheTraversal)
@@ -118,6 +118,11 @@ public:
// Les formes créatives viennent ensuite des params de strate.
int32 Seed = 0;
// Standalone host options are carried on this generator instance; the density result never
// depends on a module-wide switch or which worker happens to evaluate the sample.
bool bStandaloneResearchRoundTunnels = false;
bool bStandaloneResearchEnhancedWalls = true;
// Authored radius (voxels) of the guaranteed flat-floored landing room at world XY (0,0) in
// every strate — the old “spine” setting now sizes a room and never creates a vertical bore.
// 0 disables the origin landing rooms. Copied from VoxelSettings.
@@ -18,6 +18,8 @@
#include "VoxelGenerator.h"
#include "VoxelMarchingCubesMesher.generated.h"
class FStandaloneShapeWorld;
// A run-scoped, read-only density lattice. The explorer owns the storage and installs the
// pointer only while its canonical tiles are being meshed. The lattice includes the one-point
// halo needed by every tile, so each world sample is generated once and copied into both adjacent
@@ -101,6 +103,10 @@ public:
// the canonical generator path rather than changing geometry.
void SetSharedDensityGrid(const FVoxelSharedDensityGrid* InGrid) { SharedDensityGrid = InGrid; }
// Standalone's interval world is an explicit immutable sampling context. Game builds do not
// set this pointer and continue through Generator.
void SetStandaloneShapeWorld(const FStandaloneShapeWorld* InWorld) { ShapeWorldContext = InWorld; }
private:
FORCEINLINE bool ShouldAbortWork() const
{
@@ -109,6 +115,7 @@ private:
const std::atomic<bool>* ShutdownFlag = nullptr;
const FVoxelSharedDensityGrid* SharedDensityGrid = nullptr;
const FStandaloneShapeWorld* ShapeWorldContext = nullptr;
public: