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