wip(assembler): round S1 -- one Core voxel-size source; per-tile feature lists (islands)
AVoxelWorld::CoreVoxelSizeCm (default 25, 32 voxels/tile) flows through plan, field, mesher, content, water, atmosphere, edits and collision. Staged-owner BuildHost passes at 20 cm (SurfaceWorld + islands, W1/W8/W16, anchors, BP edits, collision) with a fixed-25cm negative control; default-size hashes match round 4; Core off stays legacy 12.5 cm. Reusable BuildWorldAssemblyFeatureTileListV1; wired into FloatingIslands only so far. 256-island stress: tile p95 112.5 -> 2.0 ms, 0 mismatches, dropped-feature control fails. Content placement measured (no populated cells): island ground search 7.25 ms/cell vs legacy 0.29 ms -- open. Outside-review evaluation in Round5/REPORT.md. 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
111cf3d262
commit
d6e69420e8
25 files changed
+2136
-250
No files matched your search
@@ -32,6 +32,58 @@
|
||||
class FStandaloneShapeWorld
|
||||
{
|
||||
public:
|
||||
struct FNativeIslandTileFeatureContext
|
||||
{
|
||||
const VoxelForgeCore::FloatingIslandPlanV1* Plan = nullptr;
|
||||
const VoxelForgeCore::FloatingIslandTileFeatureListV1* FeatureList = nullptr;
|
||||
};
|
||||
class FScopedNativeIslandTileFeatureContext
|
||||
{
|
||||
public:
|
||||
FScopedNativeIslandTileFeatureContext(const VoxelForgeCore::FloatingIslandPlanV1* plan,
|
||||
const VoxelForgeCore::FloatingIslandTileFeatureListV1* featureList)
|
||||
{
|
||||
Context.Plan = plan;
|
||||
Context.FeatureList = featureList;
|
||||
Previous = SetNativeIslandTileFeatureContext(plan && featureList ? &Context : nullptr);
|
||||
}
|
||||
~FScopedNativeIslandTileFeatureContext()
|
||||
{ RestoreNativeIslandTileFeatureContext(Previous); }
|
||||
FScopedNativeIslandTileFeatureContext(const FScopedNativeIslandTileFeatureContext&) = delete;
|
||||
FScopedNativeIslandTileFeatureContext& operator=(const FScopedNativeIslandTileFeatureContext&) = delete;
|
||||
|
||||
private:
|
||||
FNativeIslandTileFeatureContext Context{};
|
||||
const FNativeIslandTileFeatureContext* Previous = nullptr;
|
||||
};
|
||||
static const FNativeIslandTileFeatureContext* SetNativeIslandTileFeatureContext(
|
||||
const FNativeIslandTileFeatureContext* context)
|
||||
{
|
||||
auto& active = ActiveNativeIslandTileFeatureContext();
|
||||
const auto* previous = active;
|
||||
active = context;
|
||||
return previous;
|
||||
}
|
||||
static void RestoreNativeIslandTileFeatureContext(const FNativeIslandTileFeatureContext* context)
|
||||
{ ActiveNativeIslandTileFeatureContext() = context; }
|
||||
static const FNativeIslandTileFeatureContext* GetNativeIslandTileFeatureContext()
|
||||
{ return ActiveNativeIslandTileFeatureContext(); }
|
||||
|
||||
double GetCoreVoxelSizeCm() const
|
||||
{
|
||||
return Owner == nullptr || Owner->CoreVoxelSizeMicrons == 0
|
||||
? static_cast<double>(VOXEL_SIZE)
|
||||
: static_cast<double>(Owner->CoreVoxelSizeMicrons) / 10000.0;
|
||||
}
|
||||
|
||||
double GetCoreVoxelsPerOwnerChunk() const
|
||||
{
|
||||
const double OwnerVoxelSizeCm = Owner == nullptr || Owner->OwnerVoxelSizeMicrons == 0
|
||||
? 0.5 * static_cast<double>(VOXEL_SIZE)
|
||||
: static_cast<double>(Owner->OwnerVoxelSizeMicrons) / 10000.0;
|
||||
return static_cast<double>(CHUNK_SIZE) * OwnerVoxelSizeCm / GetCoreVoxelSizeCm();
|
||||
}
|
||||
|
||||
enum class EDetailVariant : uint8 { Coherent, Smooth, PerVoxel };
|
||||
struct FBoxClassification
|
||||
{
|
||||
@@ -1088,6 +1140,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static const FNativeIslandTileFeatureContext*& ActiveNativeIslandTileFeatureContext()
|
||||
{
|
||||
static thread_local const FNativeIslandTileFeatureContext* Context = nullptr;
|
||||
return Context;
|
||||
}
|
||||
|
||||
static uint64 PackLatticeKey(int32 X,int32 Y,int32 Z)
|
||||
{
|
||||
constexpr uint64 Mask=0x1FFFFFull;
|
||||
@@ -1249,10 +1307,9 @@ public:
|
||||
bOtherStrateOverlap=true;
|
||||
}
|
||||
|
||||
// Floating islands use the explicit 12.5 cm owner to 25 cm Core mapping:
|
||||
// one legacy 4 m chunk occupies 16 Core voxels.
|
||||
// Les iles flottantes suivent l'echelle explicite proprietaire/Core: 16 voxels Core.
|
||||
constexpr int32 CoreVoxelsPerIslandChunk=CHUNK_SIZE/2;
|
||||
// Island strata preserve owner-authored physical bounds through the resolved scale ratio.
|
||||
// Les strates d'iles conservent les bornes physiques owner via le rapport de resolution.
|
||||
const double CoreVoxelsPerIslandChunk=GetCoreVoxelsPerOwnerChunk();
|
||||
const int32 FirstIslandChunk=FMath::FloorToInt(static_cast<float>(BMin[2])
|
||||
/static_cast<float>(CoreVoxelsPerIslandChunk));
|
||||
const int32 LastIslandChunk=FMath::FloorToInt(static_cast<float>(BMax[2])
|
||||
@@ -1340,11 +1397,8 @@ public:
|
||||
{
|
||||
if(!IslandPlan)return Finish(EVoxelTileClass::Mixed,true);
|
||||
constexpr std::int64_t Scale=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
constexpr std::int64_t CoreVoxelsPerLegacyChunk=CHUNK_SIZE/2;
|
||||
const std::int64_t Bottom=static_cast<std::int64_t>(IslandPlan->bottomChunkZ)
|
||||
*CoreVoxelsPerLegacyChunk*Scale;
|
||||
const std::int64_t Top=(static_cast<std::int64_t>(IslandPlan->topChunkZ)+1)
|
||||
*CoreVoxelsPerLegacyChunk*Scale;
|
||||
const std::int64_t Bottom=IslandPlan->manifest.recipe.layoutMinimumZSubvoxels;
|
||||
const std::int64_t Top=IslandPlan->manifest.recipe.layoutMaximumZSubvoxels;
|
||||
const std::int64_t Seal=IslandPlan->manifest.recipe.boundarySealSubvoxels;
|
||||
const std::int64_t BoxBottom=static_cast<std::int64_t>(BMin[2])*Scale;
|
||||
const std::int64_t BoxTop=static_cast<std::int64_t>(BMax[2])*Scale;
|
||||
@@ -1889,7 +1943,7 @@ private:
|
||||
||!std::isfinite(X)||!std::isfinite(Y)||!std::isfinite(Z))return false;
|
||||
// Convert Core query Z back to the owner's legacy chunk coordinate.
|
||||
// Convertir Z du Core vers la coordonnee de chunk legacy du proprietaire.
|
||||
constexpr int32 CoreVoxelsPerLegacyChunk=CHUNK_SIZE/2;
|
||||
const double CoreVoxelsPerLegacyChunk=GetCoreVoxelsPerOwnerChunk();
|
||||
const int32 ChunkZ=FMath::FloorToInt(Z/static_cast<float>(CoreVoxelsPerLegacyChunk));
|
||||
if(Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,ChunkZ))
|
||||
!=ECaveGeneratorType::FloatingIslands)return false;
|
||||
@@ -1907,13 +1961,15 @@ private:
|
||||
const VoxelForgeCore::FloatingIslandFieldV1 Field(
|
||||
Plan->manifest.recipe,Plan->manifest.plan);
|
||||
if(!Field.isValid())return false;
|
||||
std::int64_t Density=Field.densitySubvoxels(ToFixed(X),ToFixed(Y),ToFixed(Z));
|
||||
// A legacy 4 m chunk is 16 Core voxels at the published 12.5 cm to 25 cm scale.
|
||||
// Un chunk legacy de 4 m represente 16 voxels Core avec l'echelle publiee.
|
||||
const std::int64_t Bottom=static_cast<std::int64_t>(Plan->bottomChunkZ)
|
||||
*CoreVoxelsPerLegacyChunk*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t Top=(static_cast<std::int64_t>(Plan->topChunkZ)+1)
|
||||
*CoreVoxelsPerLegacyChunk*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
std::int64_t Density=0;
|
||||
const auto* TileContext=GetNativeIslandTileFeatureContext();
|
||||
if(TileContext&&TileContext->Plan==&Plan->manifest.plan&&TileContext->FeatureList)
|
||||
Density=Field.densitySubvoxelsForTile(ToFixed(X),ToFixed(Y),ToFixed(Z),
|
||||
*TileContext->FeatureList);
|
||||
else
|
||||
Density=Field.densitySubvoxels(ToFixed(X),ToFixed(Y),ToFixed(Z));
|
||||
const std::int64_t Bottom=Plan->manifest.recipe.layoutMinimumZSubvoxels;
|
||||
const std::int64_t Top=Plan->manifest.recipe.layoutMaximumZSubvoxels;
|
||||
const std::int64_t Seal=Plan->manifest.recipe.boundarySealSubvoxels;
|
||||
const std::int64_t Zq=ToFixed(Z);
|
||||
if(Zq>=Bottom&&Zq<Bottom+Seal)Density=std::min(Density,-std::max<std::int64_t>(1,Zq-Bottom));
|
||||
|
||||
Reference in new issue
Block a user