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

+215 -114
View File
@@ -1,7 +1,7 @@
#include "OwnerWorldLoader.h"
#include "StreamingWorld.h"
#include "StandaloneResearchTunnels.h"
#include "StandaloneShapeWorld.h"
#include "StandaloneCoreScheduler.h"
#include "../Core/src/StandaloneSnapshotAdapter.h"
#include "VoxelDensityProfile.h"
#ifdef TEXT
@@ -313,13 +313,14 @@ namespace
// Keep the owner's walkable rooms, tunnels, and strate passages intact. The research
// round field composes as additional air after the owner field, so it can widen/connect
// spaces but cannot remove the authored entrance-to-exit route.
FStandaloneResearchTunnels::Set(bRoundTunnels,bEnhancedWalls);
World.Manager=std::make_unique<UVoxelStrateManager>();
if(!World.Manager->Initialize(World.Settings.get(),Seed))
{Error="standalone copied strate manager failed while applying viewer settings";return false;}
World.Generator=std::make_unique<UVoxelGenerator>();
World.Generator->InitializeSettings(World.Settings.get());
World.Generator->SetStrateManager(World.Manager.get());
World.Generator->bStandaloneResearchRoundTunnels=bRoundTunnels;
World.Generator->bStandaloneResearchEnhancedWalls=bEnhancedWalls;
return true;
}
@@ -337,9 +338,11 @@ namespace
ID3D11Buffer* Constants=nullptr;
ID3D11RasterizerState* SolidRasterizer=nullptr;
ID3D11RasterizerState* WireRasterizer=nullptr;
std::unique_ptr<FStandaloneOwnerWorld> World;
std::unique_ptr<FStandaloneShapeWorld> ShapeWorld;
std::unique_ptr<FStandaloneShapeWorld> PendingFullShapeWorld;
std::shared_ptr<FStandaloneOwnerWorld> World;
VoxelForgeCore::ResolvedWorldSnapshot Snapshot;
std::unique_ptr<VoxelForgeCore::World> ShapeWorld;
std::unique_ptr<VoxelForgeCore::World> PendingFullShapeWorld;
FStandaloneCoreScheduler CoreScheduler;
std::unique_ptr<FStandaloneStreamingGenerator> Streamer;
std::thread FullShapeBuildThread;
std::atomic<bool> bFullShapeBuildFinished{false};
@@ -376,13 +379,14 @@ namespace
bool bShapeAuditOnly=false;
bool bShapeCompare=false;
bool bFarShapeStagePending=false;
FStandaloneShapeWorld::EDetailVariant ShapeDetailVariant=FStandaloneShapeWorld::EDetailVariant::Coherent;
VoxelForgeCore::DetailVariant ShapeDetailVariant=VoxelForgeCore::DetailVariant::coherent;
bool bWireframe=false;
bool bCaptured=false;
bool bAutoCaptureWritten=false;
bool bFullDetailReported=false;
bool bInitialClipmapReported=false;
bool bProfileAttribution=false;
bool bProfileDetailBand=false;
bool bCompareEvaluators=false;
bool bParityOnly=false;
bool bDensityHash=false;
@@ -649,9 +653,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
bool ConfigureWorld(std::string& Error)
{
FStandaloneShapeWorldAccess::SetActive(nullptr);
ShapeWorld.reset();
World=std::make_unique<FStandaloneOwnerWorld>();
Snapshot={};
World=std::make_shared<FStandaloneOwnerWorld>();
if(!StandaloneOwnerLoader::Load(DataPath,*World,Error))return false;
if(!bParityChecked&&Seed==World->Seed&&!bRoundTunnels)PrintParity();
const int32 ExportClipRadius=World->ClipRadius;
@@ -718,15 +722,23 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
Min.X-=NearBuildPad;Min.Y-=NearBuildPad;Min.Z-=NearBuildPad;
Max.X+=NearBuildPad;Max.Y+=NearBuildPad;Max.Z+=NearBuildPad;
}
ShapeWorld=std::make_unique<FStandaloneShapeWorld>();
Snapshot=VoxelForgeCore::MakeStandaloneSnapshot(World);
if(!Snapshot){Error="the standalone adapter could not make a resolved core snapshot";return false;}
ShapeWorld=std::make_unique<VoxelForgeCore::World>(Snapshot);
const int32 ShapeWorkers=bNeighborhoodOnly?(WorkerCount>=8?2:1):WorkerCount;
if(!ShapeWorld->Build(*World,Min,Max,ClipMin,ClipMax,ShapeWorkers,
ShapeDetailVariant,bIncludeFarWorld,Error))
VoxelForgeCore::ShapeBuildRequest Request;
Request.minVoxel={Min.X,Min.Y,Min.Z};Request.maxVoxel={Max.X,Max.Y,Max.Z};
Request.clipMinVoxel={ClipMin.X,ClipMin.Y,ClipMin.Z};
Request.clipMaxVoxel={ClipMax.X,ClipMax.Y,ClipMax.Z};
Request.workerLimit=static_cast<uint32>(ShapeWorkers);Request.detail=ShapeDetailVariant;
Request.includeFarWorld=bIncludeFarWorld;Request.roundTunnels=bRoundTunnels;
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
Request.profileDetailBand=bProfileDetailBand;
if(!ShapeWorld->compile(Request,CoreScheduler,Error))
{ShapeWorld.reset();return false;}
FStandaloneShapeWorldAccess::SetActive(ShapeWorld.get());
bShapePipelineActive=bNeighborhoodOnly;
bNeighborhoodReadyReported=false;
bFarShapeStagePending=bShapeWorld&&!bNeighborhoodOnly&&!ShapeWorld->HasFarWorld();
bFarShapeStagePending=bShapeWorld&&!bNeighborhoodOnly&&!ShapeWorld->hasFarWorld();
std::printf("[ShapeRegion] fine_tiles=%llu bounds=(%d,%d,%d)..(%d,%d,%d) clip=(%d,%d,%d)..(%d,%d,%d)\n",
static_cast<unsigned long long>(FineTiles),Min.X,Min.Y,Min.Z,Max.X,Max.Y,Max.Z,
ClipMin.X,ClipMin.Y,ClipMin.Z,ClipMax.X,ClipMax.Y,ClipMax.Z);
@@ -748,15 +760,24 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
if(FineMin.X==INT32_MAX||ClipMin.X==INT32_MAX)
{Error="the full shape build has no desired detail or clipmap tiles";return false;}
PendingFullShapeWorld=std::make_unique<FStandaloneShapeWorld>();
PendingFullShapeWorld=std::make_unique<VoxelForgeCore::World>(Snapshot);
FullShapeBuildError.clear();bFullShapeBuildSucceeded=false;
bFullShapeBuildFinished.store(false,std::memory_order_relaxed);
const int32 FullWorkers=WorkerCount>=8?6:WorkerCount;
FullShapeBuildStart=std::chrono::steady_clock::now();
FullShapeBuildThread=std::thread([this,FineMin,FineMax,ClipMin,ClipMax,FullWorkers]()
{
bFullShapeBuildSucceeded=PendingFullShapeWorld->Build(*World,FineMin,FineMax,
ClipMin,ClipMax,FullWorkers,ShapeDetailVariant,true,FullShapeBuildError);
VoxelForgeCore::ShapeBuildRequest Request;
Request.minVoxel={FineMin.X,FineMin.Y,FineMin.Z};
Request.maxVoxel={FineMax.X,FineMax.Y,FineMax.Z};
Request.clipMinVoxel={ClipMin.X,ClipMin.Y,ClipMin.Z};
Request.clipMaxVoxel={ClipMax.X,ClipMax.Y,ClipMax.Z};
Request.workerLimit=static_cast<uint32>(FullWorkers);Request.detail=ShapeDetailVariant;
Request.includeFarWorld=true;Request.roundTunnels=bRoundTunnels;
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
Request.profileDetailBand=bProfileDetailBand;
bFullShapeBuildSucceeded=PendingFullShapeWorld->compile(
Request,CoreScheduler,FullShapeBuildError);
bFullShapeBuildFinished.store(true,std::memory_order_release);
});
std::printf("[ShapePipelineBuildStart] neighborhood_tiles=%zu near_mesh_workers=%d full_shape_workers=%d\n",
@@ -826,12 +847,20 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(*World,CameraVoxels);
DesiredTiles=Desired.Tiles;
if(ShapeWorld)
{
const auto CoreTiles=ShapeWorld->desiredTiles({CameraVoxels.X,CameraVoxels.Y,CameraVoxels.Z});
DesiredTiles.clear();DesiredTiles.reserve(CoreTiles.size());
for(const auto& Key:CoreTiles)
DesiredTiles.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
}
for(int32 I=0;I<=MaxLevels;++I)DesiredByLevel[I]=0;
for(const FVoxelTileKey& Tile:DesiredTiles)++DesiredByLevel[Tile.Level];
const int32 StreamWorkers=bShapePipelineActive?(WorkerCount>=8?2:1):WorkerCount;
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,StreamWorkers,false,
(!bShapeWorld&&MeshCache.IsLoaded())?&MeshCache:nullptr,
bFarShapeStagePending?World->FullResClipLevels-1:-1);
bFarShapeStagePending?World->FullResClipLevels-1:-1,
false,false,false,false,ShapeWorld.get());
if(bShapePipelineActive)Streamer->SetDesiredTileFilter(InitialNeighborhoodTiles);
const FStandaloneStreamingUpdate Update=Streamer->Start(CameraVoxels,{},CrossingIndex);
if(bShapePipelineActive&&Update.DesiredTiles!=static_cast<int32>(InitialNeighborhoodTiles.size()))
@@ -872,14 +901,15 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
void StartFarShapeGeneration()
{
if(!bFarShapeStagePending||!ShapeWorld||ShapeWorld->HasFarWorld()||!Streamer)return;
ShapeWorld->BuildFarWorld();
if(!bFarShapeStagePending||!ShapeWorld||ShapeWorld->hasFarWorld()||!Streamer)return;
ShapeWorld->buildFarWorld();
bFarShapeStagePending=false;
Streamer->Stop();
std::vector<FVoxelTileKey> ResidentKeys;ResidentKeys.reserve(ResidentTiles.size());
for(const auto& Pair:ResidentTiles)ResidentKeys.push_back(Pair.first);
Streamer.reset();
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,WorkerCount,false,nullptr,-1);
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,WorkerCount,false,nullptr,-1,
false,false,false,false,ShapeWorld.get());
const FVector CameraVoxels(Position.X*4.0,Position.Y*4.0,Position.Z*4.0);
++CrossingIndex;
const FStandaloneStreamingUpdate Update=Streamer->Start(CameraVoxels,ResidentKeys,CrossingIndex);
@@ -929,11 +959,11 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(Streamer)Streamer->Stop();
Streamer.reset();
ShapeWorld=std::move(PendingFullShapeWorld);
FStandaloneShapeWorldAccess::SetActive(ShapeWorld.get());
bFarShapeStagePending=false;bShapePipelineActive=false;
const FVector CameraVoxels(Position.X*4.0,Position.Y*4.0,Position.Z*4.0);
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,WorkerCount,false,nullptr,-1);
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,WorkerCount,false,nullptr,-1,
false,false,false,false,ShapeWorld.get());
++CrossingIndex;
const FStandaloneStreamingUpdate Update=Streamer->Start(CameraVoxels,ResidentKeys,CrossingIndex);
if(Update.DesiredTiles!=static_cast<int32>(DesiredTiles.size()))
@@ -1370,13 +1400,24 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
int RunTileBenchmark(FStandaloneOwnerWorld& World,V3 CameraPosition,int32 Level,
int32 Count,bool bProfile,bool bCompareEvaluators,bool bDensityHash)
int32 Count,bool bProfile,bool bCompareEvaluators,bool bDensityHash,
VoxelForgeCore::World* CoreWorld)
{
const FVector CameraVoxels(CameraPosition.X*4.0,CameraPosition.Y*4.0,CameraPosition.Z*4.0);
const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraVoxels);
std::vector<FVoxelTileKey> Tiles;Tiles.reserve(static_cast<size_t>(std::max(Count,1)));
for(const FVoxelTileKey& Tile:Desired.Tiles)
if(Tile.Level==Level&&static_cast<int32>(Tiles.size())<Count)Tiles.push_back(Tile);
if(CoreWorld)
{
const auto CoreTiles=CoreWorld->desiredTiles({CameraVoxels.X,CameraVoxels.Y,CameraVoxels.Z});
for(const auto& Key:CoreTiles)
if(Key.lod==Level&&static_cast<int32>(Tiles.size())<Count)
Tiles.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
}
else
{
for(const FVoxelTileKey& Tile:Desired.Tiles)
if(Tile.Level==Level&&static_cast<int32>(Tiles.size())<Count)Tiles.push_back(Tile);
}
if(Tiles.empty())
{std::fprintf(stderr,"No LOD %d tiles are in the current desired set.\n",Level);return 4;}
@@ -1386,8 +1427,10 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
FParse::Value(FCommandLine::Get(),"voxel.TileCacheWindow=",TileCacheWindow);
FParse::Value(FCommandLine::Get(),"voxel.TileCacheWindowMinLOD=",TileCacheWindowMinLOD);
FParse::Value(FCommandLine::Get(),"voxel.RoomGraphCacheSlots=",RoomGraphCacheSlots);
std::printf("[BenchmarkConfig] tile_cache_window=%d fused_min_lod=%d room_graph_cache_slots=%d command='%s'\n",
TileCacheWindow,TileCacheWindowMinLOD,RoomGraphCacheSlots,FCommandLine::Get());
std::printf("[BenchmarkConfig] tile_cache_window=%d fused_min_lod=%d room_graph_cache_slots=%d generator=%s command='%s'\n",
TileCacheWindow,TileCacheWindowMinLOD,RoomGraphCacheSlots,
CoreWorld&&!bCompareEvaluators?"VoxelForgeCore":"compatibility-diagnostic",
FCommandLine::Get());
VoxelDensityProfile::SetMode(bProfile?VoxelDensityProfile::EMode::Attribution
:VoxelDensityProfile::EMode::Disabled,128);
if(bProfile)VoxelDensityProfile::CalibrateTimer();
@@ -1458,12 +1501,35 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const int32 Step=FMath::Max(1,Tile.ExtentVoxels()/Cells);
int64 TileSamples=0;
std::vector<float> DebugDensitySamples;
FVoxelMeshData Mesh=Mesher.GenerateMesh(Tile.OriginVoxels(),Step,Cells,nullptr,
BandMin,BandMax,&TileSamples,nullptr,nullptr,
bDensityHash?&DebugDensitySamples:nullptr);
uint64 TileVertices=0,TileIndices=0;
if(CoreWorld&&!bCompareEvaluators)
{
VoxelForgeCore::TileGenerationOptions Options;
Options.bandMinZVoxel=BandMin;Options.bandMaxZVoxel=BandMax;
Options.captureDensitySamples=bDensityHash;
std::string CoreError;
auto Mesh=CoreWorld->generateTile(
{{Tile.Coord.X,Tile.Coord.Y,Tile.Coord.Z},Tile.Level},Options,CoreError);
if(!Mesh)
{
std::fprintf(stderr,"[VoxelForgeCore] benchmark tile generation failed: %s\n",CoreError.c_str());
return 8;
}
TileSamples=static_cast<int64>(Mesh->densitySampleCount);
TileVertices=Mesh->vertices.size();TileIndices=Mesh->indices.size();
if(bDensityHash)DebugDensitySamples=std::move(Mesh->debugDensitySamples);
}
else
{
FVoxelMeshData Mesh=Mesher.GenerateMesh(Tile.OriginVoxels(),Step,Cells,nullptr,
BandMin,BandMax,&TileSamples,nullptr,nullptr,
bDensityHash?&DebugDensitySamples:nullptr);
TileVertices=static_cast<uint64>(Mesh.Vertices.Num());
TileIndices=static_cast<uint64>(Mesh.Triangles.Num());
}
Samples+=static_cast<uint64>(FMath::Max<int64>(0,TileSamples));
Vertices+=static_cast<uint64>(Mesh.Vertices.Num());
Indices+=static_cast<uint64>(Mesh.Triangles.Num());
Vertices+=TileVertices;
Indices+=TileIndices;
if(bDensityHash)
{
for(const float Density:DebugDensitySamples)
@@ -1607,17 +1673,15 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
return Result;
}
int RunOwnerShapeComparison(FStandaloneOwnerWorld& World,const FStandaloneShapeWorld& Shape,
int RunOwnerShapeComparison(FStandaloneOwnerWorld& World,VoxelForgeCore::World& Shape,
V3 CameraPosition,float CameraYaw,float CameraPitch,
int32 Workers,int32 LevelFilter,int32 TileLimit)
{
if(FStandaloneShapeWorldAccess::GetActive()!=&Shape)
{std::fprintf(stderr,"Shape comparison requires the compiled interval world to be active.\n");return 11;}
if(LevelFilter>=World.FullResClipLevels&&!Shape.HasFarWorld())
const_cast<FStandaloneShapeWorld&>(Shape).BuildFarWorld();
if(!Shape.isCompiled())
{std::fprintf(stderr,"Shape comparison requires a compiled core world.\n");return 11;}
if(LevelFilter>=World.FullResClipLevels&&!Shape.hasFarWorld())Shape.buildFarWorld();
const FVector CameraVoxels(CameraPosition.X*4.0,CameraPosition.Y*4.0,CameraPosition.Z*4.0);
Shape.AuditViewSurface(CameraPosition.X,CameraPosition.Y,CameraPosition.Z,
CameraYaw,CameraPitch);
Shape.auditViewSurface({CameraVoxels.X,CameraVoxels.Y,CameraVoxels.Z},CameraYaw,CameraPitch);
{
const int32 Offsets[][3]={{0,0,0},{4,0,0},{-4,0,0},{0,4,0},{0,-4,0},{0,0,4},{0,0,-4}};
for(const auto& Offset:Offsets)
@@ -1626,17 +1690,18 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const float Y=static_cast<float>(CameraVoxels.Y+Offset[1]);
const float Z=static_cast<float>(CameraVoxels.Z+Offset[2]);
float OwnerDensity=0.0f;
{FStandaloneShapeWorldAccess::FScopedBypass Bypass;
OwnerDensity=World.Generator->GetDensityAt(X,Y,Z);}
const float ShapeDensity=Shape.DensityAt(X,Y,Z);
OwnerDensity=World.Generator->GetDensityAt(X,Y,Z);
const float ShapeDensity=Shape.densityAt({X,Y,Z});
std::printf("[ShapeProbe] voxels=(%.1f,%.1f,%.1f) owner=%.5f shape=%.5f owner_air=%d shape_air=%d protected_air=%d solid_overlay=%d\n",
X,Y,Z,OwnerDensity,ShapeDensity,OwnerDensity>=0.0f?1:0,ShapeDensity>=0.0f?1:0,
Shape.DebugCriticalAirAt(X,Y,Z)?1:0,Shape.DebugSolidOverlayAt(X,Y,Z)?1:0);
Shape.debugCriticalAirAt({X,Y,Z})?1:0,Shape.debugSolidOverlayAt({X,Y,Z})?1:0);
}
}
const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraVoxels);
std::vector<FVoxelTileKey> CoreDesired;
for(const auto& Key:Shape.desiredTiles({CameraVoxels.X,CameraVoxels.Y,CameraVoxels.Z}))
CoreDesired.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
std::vector<FVoxelTileKey> Tiles;
for(const FVoxelTileKey& Tile:Desired.Tiles)
for(const FVoxelTileKey& Tile:CoreDesired)
if(LevelFilter<0?Tile.Level<World.FullResClipLevels:Tile.Level==LevelFilter)
Tiles.push_back(Tile);
if(TileLimit>0&&Tiles.size()>static_cast<size_t>(TileLimit))
@@ -1670,7 +1735,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
std::atomic<size_t> Next{0};
std::vector<std::thread> Threads;
const int32 ThreadCount=std::clamp(Workers,1,16);
const int32 ThreadCount=std::clamp(Workers,1,8);
Threads.reserve(ThreadCount);
for(int32 Worker=0;Worker<ThreadCount;++Worker)
{
@@ -1688,15 +1753,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const FVoxelTileKey& Tile=Tiles[Index];
const int32 Cells=Tile.Level<World.FullResClipLevels?CHUNK_SIZE:World.CoarseTileCells;
const int32 Step=std::max(1,Tile.ExtentVoxels()/Cells);
std::vector<float> NewDensities,OldDensities;
FVoxelMeshData NewMesh=Mesher.GenerateMesh(Tile.OriginVoxels(),Step,Cells,nullptr,
MinChunkZ,MaxChunkZ,nullptr,nullptr,nullptr,&NewDensities);
VoxelForgeCore::TileGenerationOptions ShapeOptions;
ShapeOptions.bandMinZVoxel=MinChunkZ;ShapeOptions.bandMaxZVoxel=MaxChunkZ;
ShapeOptions.captureDensitySamples=true;
std::string CoreError;
auto NewMesh=Shape.generateTile({{Tile.Coord.X,Tile.Coord.Y,Tile.Coord.Z},Tile.Level},
ShapeOptions,CoreError);
std::vector<float> NewDensities=NewMesh?std::move(NewMesh->debugDensitySamples):std::vector<float>{};
std::vector<float> OldDensities;
FVoxelMeshData OldMesh;
{
FStandaloneShapeWorldAccess::FScopedBypass Bypass;
OldMesh=Mesher.GenerateMesh(Tile.OriginVoxels(),Step,Cells,nullptr,
MinChunkZ,MaxChunkZ,nullptr,nullptr,nullptr,&OldDensities);
}
OldMesh=Mesher.GenerateMesh(Tile.OriginVoxels(),Step,Cells,nullptr,
MinChunkZ,MaxChunkZ,nullptr,nullptr,nullptr,&OldDensities);
FTileComparison& R=Results[Index];
const size_t Shared=std::min(NewDensities.size(),OldDensities.size());
R.Samples=Shared;
@@ -1708,9 +1775,12 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
R.OldHash^=std::bit_cast<uint32>(OldDensities[I]);R.OldHash*=1099511628211ull;
}
constexpr size_t VertexStride=4;
R.NewSurface.reserve(static_cast<size_t>(NewMesh.Vertices.Num())/VertexStride+1);
for(int32 I=0;I<NewMesh.Vertices.Num();I+=static_cast<int32>(VertexStride))
{const FVector& P=NewMesh.Vertices[I];R.NewSurface.push_back({P.X*0.01,P.Y*0.01,P.Z*0.01});}
if(NewMesh)
{
R.NewSurface.reserve(NewMesh->vertices.size()/VertexStride+1);
for(size_t I=0;I<NewMesh->vertices.size();I+=VertexStride)
{const auto& P=NewMesh->vertices[I].position;R.NewSurface.push_back({P.x*0.01,P.y*0.01,P.z*0.01});}
}
R.OldSurface.reserve(static_cast<size_t>(OldMesh.Vertices.Num())/VertexStride+1);
for(int32 I=0;I<OldMesh.Vertices.Num();I+=static_cast<int32>(VertexStride))
{const FVector& P=OldMesh.Vertices[I];R.OldSurface.push_back({P.X*0.01,P.Y*0.01,P.Z*0.01});}
@@ -1779,9 +1849,12 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
uint64 TotalSamples=0,ChangedSigns=0;
uint64 LegacyHash=14695981039346656037ull,DetailedHash=14695981039346656037ull;
const bool PreviousRoundTunnels=World.Generator->bStandaloneResearchRoundTunnels;
const bool PreviousEnhancedWalls=World.Generator->bStandaloneResearchEnhancedWalls;
const auto Evaluate=[&](bool bEnhanced,std::vector<FComparisonTile>& Out)
{
FStandaloneResearchTunnels::Set(true,bEnhanced);
World.Generator->bStandaloneResearchRoundTunnels=true;
World.Generator->bStandaloneResearchEnhancedWalls=bEnhanced;
for(size_t I=0;I<Tiles.size();++I)
{
const FVoxelTileKey& Tile=Tiles[I];
@@ -1795,6 +1868,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
};
Evaluate(false,Legacy);
Evaluate(true,Detailed);
World.Generator->bStandaloneResearchRoundTunnels=PreviousRoundTunnels;
World.Generator->bStandaloneResearchEnhancedWalls=PreviousEnhancedWalls;
FDirectedSurfaceDistance LegacyToDetailed,DetailedToLegacy;
std::vector<FComparePoint> AllLegacySurface,AllDetailedSurface;
for(size_t TileIndex=0;TileIndex<Tiles.size();++TileIndex)
@@ -1823,7 +1898,6 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
static_cast<unsigned long long>(LegacyHash),static_cast<unsigned long long>(DetailedHash),
AllLegacySurface.size(),AllDetailedSurface.size(),MeanDistance,Hausdorff,
static_cast<unsigned long long>(LegacyToDetailed.Unmatched+DetailedToLegacy.Unmatched));
FStandaloneResearchTunnels::Set(true,true);
return TotalSamples>0&&LegacyToDetailed.Unmatched+DetailedToLegacy.Unmatched==0?0:10;
}
@@ -1866,12 +1940,14 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
return Hash;
}
int RunPipelinedStreamingBenchmark(FStandaloneOwnerWorld& World,const FVector& CameraPositionVoxels,
int32 WorkerCount,int32 MaxLevel,FStandaloneShapeWorld::EDetailVariant DetailVariant,
int RunPipelinedStreamingBenchmark(std::shared_ptr<FStandaloneOwnerWorld> OwnerWorld,
const FVector& CameraPositionVoxels,int32 WorkerCount,int32 MaxLevel,
VoxelForgeCore::DetailVariant DetailVariant,const VoxelForgeCore::JobScheduler& Scheduler,
bool bHashDensity,bool bSkipUvAndColors,bool bSkipMaterialGroups,bool bSkipUV,bool bSkipColors,
std::chrono::steady_clock::time_point ColdStart)
{
using Clock=std::chrono::steady_clock;
FStandaloneOwnerWorld& World=*OwnerWorld;
FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraPositionVoxels);
if(MaxLevel>=0)
Desired.Tiles.erase(std::remove_if(Desired.Tiles.begin(),Desired.Tiles.end(),
@@ -1902,24 +1978,30 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(Neighborhood.size()!=27)
{std::fprintf(stderr,"[StreamPipeline] expected 27 player-neighborhood tiles, found %zu.\n",Neighborhood.size());return 7;}
FStandaloneShapeWorld Shape;
VoxelForgeCore::World Shape(VoxelForgeCore::MakeStandaloneSnapshot(OwnerWorld));
std::string BuildError;
const bool bIncludeFarWorld=MaxLevel<0||MaxLevel>=World.FullResClipLevels;
const auto ShapeBuildStart=Clock::now();
if(!Shape.Build(World,FineMin,FineMax,ClipMin,ClipMax,WorkerCount,
DetailVariant,bIncludeFarWorld,BuildError))
VoxelForgeCore::ShapeBuildRequest ShapeRequest;
ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z};
ShapeRequest.maxVoxel={FineMax.X,FineMax.Y,FineMax.Z};
ShapeRequest.clipMinVoxel={ClipMin.X,ClipMin.Y,ClipMin.Z};
ShapeRequest.clipMaxVoxel={ClipMax.X,ClipMax.Y,ClipMax.Z};
ShapeRequest.workerLimit=static_cast<uint32>(std::clamp(WorkerCount,1,8));
ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld;
ShapeRequest.roundTunnels=World.Generator->bStandaloneResearchRoundTunnels;
ShapeRequest.enhancedTunnelWalls=World.Generator->bStandaloneResearchEnhancedWalls;
if(!Shape.compile(ShapeRequest,Scheduler,BuildError))
{std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;}
const auto ShapeReady=Clock::now();
const double ShapeSeconds=std::chrono::duration<double>(ShapeReady-ShapeBuildStart).count();
FStandaloneShapeWorldAccess::SetActive(&Shape);
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors);
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape);
const auto StreamStart=Clock::now();
const FStandaloneStreamingUpdate Update=Streamer.Start(CameraPositionVoxels);
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
{
Streamer.Stop();FStandaloneShapeWorldAccess::SetActive(nullptr);
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] expected %zu tiles but queued %d.\n",
Desired.Tiles.size(),Update.DesiredTiles);return 7;
}
@@ -2005,11 +2087,11 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
static_cast<unsigned long long>(HashTileRows(PayloadRows)),
static_cast<unsigned long long>(HashTileRows(TopologyRows)));
}
FStandaloneShapeWorldAccess::SetActive(nullptr);
return NeighborhoodFinished==static_cast<int32>(Neighborhood.size())
&&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing?0:6;
}
int RunStreamingBenchmark(FStandaloneOwnerWorld& World,const FVector& CameraPositionVoxels,
int RunStreamingBenchmark(FStandaloneOwnerWorld& World,VoxelForgeCore::World* CoreWorld,
const FVector& CameraPositionVoxels,
int32 WorkerCount,int32 MaxLevel,bool bRoundTunnels,
bool bEnhancedWalls,const FStandaloneMeshCache* Cache,
bool bHashDensity,bool bSkipUvAndColors,bool bSkipMaterialGroups,
@@ -2020,6 +2102,14 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const FStandaloneMeshCacheMetadata& CacheMetadata)
{
FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraPositionVoxels);
if(CoreWorld)
{
const auto CoreTiles=CoreWorld->desiredTiles(
{CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z});
Desired.Tiles.clear();Desired.Tiles.reserve(CoreTiles.size());
for(const auto& Key:CoreTiles)
Desired.Tiles.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
}
if(MaxLevel>=0)
Desired.Tiles.erase(std::remove_if(Desired.Tiles.begin(),Desired.Tiles.end(),
[&](const FVoxelTileKey& Tile){return Tile.Level>MaxLevel;}),Desired.Tiles.end());
@@ -2035,10 +2125,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
std::unique_ptr<FFarSurvivalAudit> FarAudit;
if(bFarSurvivalAudit)
{
const FStandaloneShapeWorld* Shape=FStandaloneShapeWorldAccess::GetActive();
if(!Shape||!Shape->HasFarWorld())
{std::fprintf(stderr,"Far survival audit requires an active shape world with far-parent data.\n");return 15;}
FarAudit=std::make_unique<FFarSurvivalAudit>(World,*Shape,Desired.Tiles,bFarAuditBadShell);
if(!CoreWorld||!CoreWorld->hasFarWorld())
{std::fprintf(stderr,"Far survival audit requires a compiled core world with far-parent data.\n");return 15;}
FarAudit=std::make_unique<FFarSurvivalAudit>(World,*CoreWorld,Desired.Tiles,bFarAuditBadShell);
}
std::array<std::vector<FHashedTile>,MaxLevels+1> HashRows;
std::array<std::vector<FHashedTile>,MaxLevels+1> MeshHashRows;
@@ -2067,7 +2156,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const auto Start=std::chrono::steady_clock::now();
FStandaloneStreamingGenerator Streamer(World,WorkerCount,
bHashDensity||!BakeCachePath.empty(),Cache,MaxLevel,
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors);
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,CoreWorld);
const FStandaloneStreamingUpdate Update=Streamer.Start(CameraPositionVoxels);
const double LOD0Width=static_cast<double>(2*World.ClipRadius+2)
*CHUNK_SIZE*VOXEL_SIZE/100.0;
@@ -2279,47 +2368,58 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
return 0;
}
int RunEditTransactionBenchmark(FStandaloneOwnerWorld& World,FStandaloneShapeWorld& Shape,
const FVector& CameraPositionVoxels,int32 WorkerCount)
int RunEditTransactionBenchmark(FStandaloneOwnerWorld& World,VoxelForgeCore::World& Shape,
const FVector& CameraPositionVoxels,int32 WorkerCount)
{
using Clock=std::chrono::steady_clock;
// Place the spell across the LOD0/LOD1 clipmap seam so one edit exercises every visible
// level it intersects, instead of timing only the center LOD0 tiles.
const double X=CameraPositionVoxels.X+3.0*CHUNK_SIZE;
const double Y=CameraPositionVoxels.Y,Z=CameraPositionVoxels.Z;
std::vector<FStandaloneShapeWorld::FEditBrush> Brushes(3);
Brushes[0].Shape=FStandaloneShapeWorld::FEditBrush::EShape::Sphere;
Brushes[0].Operation=FStandaloneShapeWorld::FEditBrush::EOperation::Carve;
Brushes[0].A={X,Y,Z};Brushes[0].Radius=20.0;
Brushes[1].Shape=FStandaloneShapeWorld::FEditBrush::EShape::RoundedBox;
Brushes[1].Operation=FStandaloneShapeWorld::FEditBrush::EOperation::Carve;
Brushes[1].A={X,Y,Z+12.0};Brushes[1].HalfExtent={11.0,11.0,4.0};Brushes[1].Rounding=3.0;
Brushes[2].Shape=FStandaloneShapeWorld::FEditBrush::EShape::Capsule;
Brushes[2].Operation=FStandaloneShapeWorld::FEditBrush::EOperation::AddRock;
Brushes[2].A={X-22.0,Y,Z-8.0};Brushes[2].B={X+22.0,Y,Z-8.0};Brushes[2].Radius=3.0;
const auto EditStart=Clock::now();
Shape.SetEditTransaction(std::move(Brushes));
FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraPositionVoxels);
const FIntVector EditMin=Shape.GetEditBoundsMin(),EditMax=Shape.GetEditBoundsMax();
const auto CoreDesired=Shape.desiredTiles(
{CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z});
Desired.Tiles.clear();Desired.Tiles.reserve(CoreDesired.size());
std::vector<VoxelForgeCore::TileKey> CoreKeys;CoreKeys.reserve(CoreDesired.size());
for(const auto& Key:CoreDesired)
{
Desired.Tiles.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
CoreKeys.push_back(Key);
}
VoxelForgeCore::EditTransaction Transaction;Transaction.sequence=1;Transaction.brushes.resize(3);
Transaction.brushes[0].shape=VoxelForgeCore::EditBrush::Shape::sphere;
Transaction.brushes[0].operation=VoxelForgeCore::EditBrush::Operation::carve;
Transaction.brushes[0].a={X,Y,Z};Transaction.brushes[0].radius=20.0;
Transaction.brushes[1].shape=VoxelForgeCore::EditBrush::Shape::roundedBox;
Transaction.brushes[1].operation=VoxelForgeCore::EditBrush::Operation::carve;
Transaction.brushes[1].a={X,Y,Z+12.0};Transaction.brushes[1].halfExtent={11.0,11.0,4.0};
Transaction.brushes[1].rounding=3.0;
Transaction.brushes[2].shape=VoxelForgeCore::EditBrush::Shape::capsule;
Transaction.brushes[2].operation=VoxelForgeCore::EditBrush::Operation::addRock;
Transaction.brushes[2].a={X-22.0,Y,Z-8.0};Transaction.brushes[2].b={X+22.0,Y,Z-8.0};
Transaction.brushes[2].radius=3.0;
const auto EditStart=Clock::now();
std::string EditError;
const auto Edit=Shape.applyEditTransaction(Transaction,CoreKeys,EditError);
if(!Edit){std::fprintf(stderr,"[EditTransaction] rejected: %s\n",EditError.c_str());return 9;}
std::vector<FVoxelTileKey> Affected;Affected.reserve(128);
std::array<uint64,MaxLevels+1> AffectedByLevel{},FinishedByLevel{};
for(const FVoxelTileKey& Tile:Desired.Tiles)
for(const auto& LodTiles:Edit->affectedByLod)
{
const FIntVector Origin=Tile.OriginVoxels();const int32 Extent=Tile.ExtentVoxels();
const int32 Pad=std::max(2,Tile.StepVoxels());
if(Origin.X-Pad>EditMax.X||Origin.X+Extent+Pad<EditMin.X
||Origin.Y-Pad>EditMax.Y||Origin.Y+Extent+Pad<EditMin.Y
||Origin.Z-Pad>EditMax.Z||Origin.Z+Extent+Pad<EditMin.Z)continue;
Affected.push_back(Tile);
if(Tile.Level>=0&&Tile.Level<=MaxLevels)++AffectedByLevel[Tile.Level];
for(const auto& Key:LodTiles)
{
const FVoxelTileKey Tile(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
Affected.push_back(Tile);
if(Tile.Level>=0&&Tile.Level<=MaxLevels)++AffectedByLevel[Tile.Level];
}
}
if(Affected.empty())
{
std::fprintf(stderr,"[EditTransaction] failed: no desired tiles intersect the edit bounds.\n");
return 9;
}
FStandaloneStreamingGenerator Streamer(World,WorkerCount,false,nullptr,-1);
FStandaloneStreamingGenerator Streamer(World,WorkerCount,false,nullptr,-1,
false,false,false,false,&Shape);
Streamer.SetDesiredTileFilter(Affected);
const auto Start=Clock::now();
const FStandaloneStreamingUpdate Update=Streamer.Start(CameraPositionVoxels);
@@ -2400,8 +2500,8 @@ int main(int Argc,char** Argv)
else if(Arg.starts_with("--shape-detail="))
{
const std::string_view Value=Arg.substr(15);
if(Value=="smooth")App.ShapeDetailVariant=FStandaloneShapeWorld::EDetailVariant::Smooth;
else if(Value=="per-voxel")App.ShapeDetailVariant=FStandaloneShapeWorld::EDetailVariant::PerVoxel;
if(Value=="smooth")App.ShapeDetailVariant=VoxelForgeCore::DetailVariant::smooth;
else if(Value=="per-voxel")App.ShapeDetailVariant=VoxelForgeCore::DetailVariant::perVoxel;
else if(Value!="coherent"){std::fprintf(stderr,"Invalid --shape-detail value: %.*s\n",static_cast<int>(Value.size()),Value.data());return 2;}
}
else if(Arg=="--round-tunnels")App.bRoundTunnels=true;
@@ -2439,7 +2539,7 @@ int main(int Argc,char** Argv)
else if(Arg.starts_with("--workers="))
{
const int32 Parsed=std::atoi(std::string(Arg.substr(10)).c_str());
App.WorkerCount=std::clamp(Parsed,1,16);
App.WorkerCount=std::clamp(Parsed,1,8);
}
else if(Arg.starts_with("--clip-radius="))
App.ClipRadius=std::clamp(std::atoi(std::string(Arg.substr(14)).c_str()),1,64);
@@ -2461,9 +2561,9 @@ int main(int Argc,char** Argv)
}
else if(!Arg.empty()&&Arg.front()!='-')App.DataPath=std::string(Arg);
}
FStandaloneShapeWorld::SetDetailProfileEnabled(bProfileDetailBand);
App.bProfileDetailBand=bProfileDetailBand;
std::string Error;
App.World=std::make_unique<FStandaloneOwnerWorld>();
App.World=std::make_shared<FStandaloneOwnerWorld>();
if(!StandaloneOwnerLoader::Load(App.DataPath,*App.World,Error)){std::fprintf(stderr,"Owner data load failed: %s\n",Error.c_str());return 2;}
App.Seed=App.World->Seed;
if(App.bParityOnly)
@@ -2500,10 +2600,11 @@ int main(int Argc,char** Argv)
if(App.bShapeAuditOnly)
{
if(bPassageDetailAuditOnly)
return App.ShapeWorld->AuditSurfaceBandFamilies(true)?0:8;
const bool bSurfacePassing=App.ShapeWorld->AuditViewSurface(App.Position.X,App.Position.Y,
App.Position.Z,App.Yaw,App.Pitch);
return App.ShapeWorld->IsDetailAuditPassing()&&bSurfacePassing?0:7;
return App.ShapeWorld->auditSurfaceFamilies(true)?0:8;
const bool bSurfacePassing=App.ShapeWorld->auditViewSurface(
{App.Position.X*4.0,App.Position.Y*4.0,App.Position.Z*4.0},
App.Yaw,App.Pitch);
return App.ShapeWorld->auditDetailPassing()&&bSurfacePassing?0:7;
}
if(App.bShapeCompare)
return RunOwnerShapeComparison(*App.World,*App.ShapeWorld,App.Position,App.Yaw,App.Pitch,App.WorkerCount,
@@ -2513,9 +2614,9 @@ int main(int Argc,char** Argv)
if(bStreamBenchmark)
{
if(bStreamPipeline)
return RunPipelinedStreamingBenchmark(*App.World,
return RunPipelinedStreamingBenchmark(App.World,
FVector(App.Position.X*4.0,App.Position.Y*4.0,App.Position.Z*4.0),
App.WorkerCount,StreamBenchmarkMaxLevel,App.ShapeDetailVariant,
App.WorkerCount,StreamBenchmarkMaxLevel,App.ShapeDetailVariant,App.CoreScheduler,
bStreamHash||!BakeMeshCachePath.empty(),bSkipUvAndColors,bSkipMaterialGroups,
bSkipUV,bSkipColors,ColdProcessStart);
if(bEditBenchmark)
@@ -2526,7 +2627,7 @@ int main(int Argc,char** Argv)
std::printf("Standalone clip override: exported radius=%d (112 m cube) -> radius=%d (%.0f m LOD0 cube), voxel size=25 cm.\n",
ExportClipRadius,App.ClipRadius,FullDetailWidth);
if(!App.bForceGenerate&&!App.bShapeWorld)App.LoadMeshCache();
return RunStreamingBenchmark(*App.World,
return RunStreamingBenchmark(*App.World,App.ShapeWorld.get(),
FVector(App.Position.X*4.0,App.Position.Y*4.0,App.Position.Z*4.0),
App.WorkerCount,StreamBenchmarkMaxLevel,App.bRoundTunnels,
App.bRoundTunnelEnhanced,(!App.bShapeWorld&&App.MeshCache.IsLoaded())?&App.MeshCache:nullptr,
@@ -2536,7 +2637,7 @@ int main(int Argc,char** Argv)
}
if(BenchmarkLevel>=0)
return RunTileBenchmark(*App.World,App.Position,BenchmarkLevel,BenchmarkCount,
App.bProfileAttribution,App.bCompareEvaluators,App.bDensityHash);
App.bProfileAttribution,App.bCompareEvaluators,App.bDensityHash,App.ShapeWorld.get());
App.World.reset();
WNDCLASSA Class{};Class.lpfnWndProc=WindowProc;Class.hInstance=GetModuleHandleA(nullptr);Class.lpszClassName="VoxelForgeStandaloneWorld";