wip(assembler): M2 round 3 -- opt-in hybrid sharp mesher (WorldAssemblerHybridV1) in the Unreal Core route

Default MarchingCubesV1 unchanged (W1/W8/W16 = round-6 hashes). Hybrid DC only in LOD0 interior cells
with tagged features; tile-border cells and LOD1+ stay MC. BuildHost: fixtures repeat exactly, cooked
collision bounds = render bounds, same-LOD borders pass, sampled SurfaceWorld cliff bit-identical to MC.
Open: tagged tiles cost 5.7-6.7x MC; corner-top field contact error 20 cm; 5 MC doorway LOD cases.

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-10 09:53:04 +02:00
1 parent a3b7d2015e
commit 22a6b30494
21 files changed
+3009 -23

No files matched your search

+27 -4
View File
@@ -8725,6 +8725,7 @@ void AVoxelWorld::HandleTileCollisionCookComplete(
const int32 NumVertices = Pending->NumVertices;
const int32 NumTriangles = Pending->NumTriangles;
const int32 NumSkirtTriangles = Pending->NumSkirtTriangles;
const bool bPooledComponent = Pending->bPooledComponent;
const int32 PendingCooksAtSubmit = Pending->PendingCooksAtSubmit;
const bool bUseAsyncCook = Pending->bUseAsyncCook;
const bool bUseComplexAsSimpleCollision = Pending->bUseComplexAsSimpleCollision;
@@ -8745,6 +8746,15 @@ void AVoxelWorld::HandleTileCollisionCookComplete(
CollisionSuppressedAtCycles.Remove(Tile);
if (URealtimeMeshComponent* Comp = TileComponents.FindRef(Tile))
{
// RMC caches local bounds on pooled components; rebinding after the async cook
// invalidates that cache and rebuilds scene-query bounds from the installed mesh.
// RMC met les bornes locales en cache sur les composants reutilises ; le rebranchement
// apres la cuisson invalide ce cache et recalcule les bornes des traces.
if (bPooledComponent && Comp->GetRealtimeMesh() == CompletedMesh)
{
Comp->SetRealtimeMesh(nullptr);
Comp->SetRealtimeMesh(CompletedMesh);
}
Comp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
}
CollisionReadyTiles.Add(Tile);
@@ -11439,6 +11449,9 @@ void AVoxelWorld::LoadCoreTile(const FVoxelTileKey& Tile, EVoxelTileWorkPriority
const VoxelForgeCore::TileKey CoreKey{{Tile.Coord.X, Tile.Coord.Y, Tile.Coord.Z}, Tile.Level};
VoxelForgeCore::TileGenerationOptions Options;
Options.mesherRecipe = CoreMesherRecipe == EVoxelForgeCoreMesherRecipe::WorldAssemblerHybridV1
? VoxelForgeCore::MesherRecipe::worldAssemblerHybridV1
: VoxelForgeCore::MesherRecipe::marchingCubesV1;
Options.hashDensity = bCaptureHashes;
std::string CoreError;
std::optional<VoxelForgeCore::TileMesh> CoreMesh;
@@ -12248,7 +12261,7 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
MeshComp = AcquireTileComponent(
bProfileApply ? &ComponentCreationSeconds : nullptr,
bProfileApply ? &ComponentRegistrationSeconds : nullptr,
bProfileApply ? &bComponentCreated : nullptr);
&bComponentCreated);
TileComponents.Add(Tile, MeshComp);
}
if (!IsValid(MeshComp))
@@ -12263,6 +12276,7 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
}
return false;
}
const bool bWasPooledComponent = !bComponentAlreadyPresent && !bComponentCreated;
const double ComponentSeconds = bProfileApply
? FPlatformTime::ToSeconds64(FPlatformTime::Cycles64() - ComponentStartCycles)
: 0.0;
@@ -12407,6 +12421,7 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
Pending.NumTriangles = Result.NumTriangles;
Pending.NumSkirtTriangles = Result.NumSkirtTriangles;
Pending.PendingCooksAtSubmit = PendingCollisionCooks.Num();
Pending.bPooledComponent = bWasPooledComponent;
Pending.bUseAsyncCook = CollisionConfig.bUseAsyncCook;
Pending.bUseComplexAsSimpleCollision = CollisionConfig.bUseComplexAsSimpleCollision;
Pending.bShouldFastCookMeshes = CollisionConfig.bShouldFastCookMeshes;
@@ -13275,7 +13290,8 @@ FString AVoxelWorld::GetCurrentSeasonContentHash() const
{
return FString();
}
if (AssemblyHash.IsEmpty())
const bool bHybridMesher = CoreMesherRecipe == EVoxelForgeCoreMesherRecipe::WorldAssemblerHybridV1;
if (AssemblyHash.IsEmpty() && !bHybridMesher)
{
return SeasonHash;
}
@@ -13295,8 +13311,15 @@ FString AVoxelWorld::GetCurrentSeasonContentHash() const
}
}
}
Payload += TEXT("|world_assembly=");
Payload += AssemblyHash;
if (!AssemblyHash.IsEmpty())
{
Payload += TEXT("|world_assembly=");
Payload += AssemblyHash;
}
if (bHybridMesher)
{
Payload += TEXT("|core_mesher=WorldAssemblerHybridV1");
}
FTCHARToUTF8 Utf8Payload(*Payload);
uint8 Digest[FSHA1::DigestSize];
FSHA1::HashBuffer(Utf8Payload.Get(), Utf8Payload.Length(), Digest);