wip(standalone): speed round -- interrupted by a PC hard reset at 10:16 (Kernel-Power 41)
Verified before the reset (density + full mesh hashes equal at 1/8/16 workers, routes 5642/5642, look audits green): - merged field lookups, parallel mask merge, compact inline spatial bins, line-local relief hash cache, lattice-specific mesher entry, fused sign+magnitude evaluation, far connectors as one capsule each (181,836 -> 16,491 far primitives). - crater edit (sphere+box+capsule, one transaction across LOD0/1): 15-27 ms; player 3x3x3 neighbourhood meshes ready ~18 ms after streaming starts. NOT yet verified (in the tree, unhashed): standalone-only skips of UV/colour arrays and of the ceiling/ground material grouping (best cold whole view 0.958 s @16 workers) and a far-bin reserve tweak. Those skips drop data the plugin's materials may need: not a game-path win as-is. 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
97c0455939
commit
ee5b05b357
16 files changed
+1011
-156
No files matched your search
@@ -144,6 +144,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
// plus de (ré)allocation de hash-map par tuile (chaque worker a son propre exemplaire).
|
||||
static thread_local TMap<FIntVector, int32> VertexMap;
|
||||
VertexMap.Reset();
|
||||
const int32 VertexCapacityHint=FMath::Clamp(InCellsPerAxis,2,CHUNK_SIZE);
|
||||
VertexMap.Reserve(VertexCapacityHint*VertexCapacityHint*2);
|
||||
|
||||
//=========================================================================
|
||||
// F17 — CLASSE DE SURFACE (sol vs plafond sky-cap), par vertex → par triangle
|
||||
@@ -158,8 +160,11 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
// ~zéro sur une tuile de sol pur, borné par lattice² sur une tuile de cap.
|
||||
static thread_local TArray<uint8> VertexClasses; // 0 = sol, 1 = sky-cap
|
||||
static thread_local TMap<FIntVector, FVector2f> SurfColMemo; // (Xq,Yq,chunkZ) → (TerrainZ, CeilSurf) ; X=FLT_MAX ⇒ pas SurfaceWorld
|
||||
VertexClasses.Reset();
|
||||
SurfColMemo.Reset();
|
||||
if (!bStandaloneCompactPayload)
|
||||
{
|
||||
VertexClasses.Reset();
|
||||
SurfColMemo.Reset();
|
||||
}
|
||||
|
||||
// Normale fournie par l'appelant (gradient lu dans la grille de densité, T1.b) —
|
||||
// plus d'échantillonnage de densité par vertex. RawNormal pointe solide→air ; on la
|
||||
@@ -189,65 +194,56 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
}
|
||||
MeshData.Normals.Add(Normal);
|
||||
|
||||
// UVs planaires — le triplanar mapping se fait dans le matériau.
|
||||
MeshData.UVs.Add(FVector2D(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE));
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// VERTEX COLOUR — masques pour le matériau triplanar maître (F6).
|
||||
// R = index de palette du biome DOMINANT (0-255) — re-skin par biome.
|
||||
// G = pente (0 = sol/plafond plat, 1 = paroi verticale) — roche sur falaises.
|
||||
// B = poids de fondu de bordure (0 au cœur d'un biome → ~0.5 à la frontière).
|
||||
// A = index de palette du biome VOISIN — le matériau lerp(R,A) par B → bords sans couture.
|
||||
// La hauteur/snow-line se déduit de WorldPosition.Z dans le matériau (pas besoin de canal).
|
||||
// Coût: une résolution biome par vertex UNIQUE (déduplication) ; nul si la strate n'a pas
|
||||
// de biomes (GetBiomeMaterialAt sort en O(1) → palette 0 partout).
|
||||
int32 PalD = 0, PalN = 0; float BlendW = 0.0f;
|
||||
Generator->GetBiomeMaterialAt(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE,
|
||||
WorldPos.Z / VOXEL_SIZE, PalD, PalN, BlendW);
|
||||
const uint8 R = (uint8)FMath::Clamp(PalD, 0, 255);
|
||||
const uint8 A = (uint8)FMath::Clamp(PalN, 0, 255);
|
||||
const uint8 G = (uint8)FMath::Clamp(FMath::RoundToInt((1.0f - FMath::Abs((float)Normal.Z)) * 255.0f), 0, 255);
|
||||
const uint8 Bc = (uint8)FMath::Clamp(FMath::RoundToInt(BlendW * 255.0f), 0, 255);
|
||||
MeshData.Colors.Add(FColor(R, G, Bc, A));
|
||||
|
||||
// F17 — classe de surface (voir le bloc en tête de fonction). Down-facing seulement :
|
||||
// les vertex de sol/falaise (N.Z ≥ -0.1) sont "sol" sans payer la requête colonne.
|
||||
uint8 SurfClass = 0;
|
||||
if (Normal.Z < -0.1f)
|
||||
if (!bStandaloneCompactPayload)
|
||||
{
|
||||
const float Zv = WorldPos.Z / VOXEL_SIZE;
|
||||
const float StepF = (float)Step;
|
||||
const FIntVector MemoKey(
|
||||
FMath::RoundToInt(WorldPos.X / (VOXEL_SIZE * StepF)),
|
||||
FMath::RoundToInt(WorldPos.Y / (VOXEL_SIZE * StepF)),
|
||||
FMath::FloorToInt(Zv / (float)CHUNK_SIZE));
|
||||
FVector2f* Col = SurfColMemo.Find(MemoKey);
|
||||
if (!Col)
|
||||
// UVs planaires — le triplanar mapping se fait dans le matériau.
|
||||
MeshData.UVs.Add(FVector2D(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE));
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// VERTEX COLOUR — masks for biome palette, slope and border blend.
|
||||
int32 PalD = 0, PalN = 0; float BlendW = 0.0f;
|
||||
Generator->GetBiomeMaterialAt(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE,
|
||||
WorldPos.Z / VOXEL_SIZE, PalD, PalN, BlendW);
|
||||
const uint8 R = (uint8)FMath::Clamp(PalD, 0, 255);
|
||||
const uint8 A = (uint8)FMath::Clamp(PalN, 0, 255);
|
||||
const uint8 G = (uint8)FMath::Clamp(FMath::RoundToInt((1.0f - FMath::Abs((float)Normal.Z)) * 255.0f), 0, 255);
|
||||
const uint8 Bc = (uint8)FMath::Clamp(FMath::RoundToInt(BlendW * 255.0f), 0, 255);
|
||||
MeshData.Colors.Add(FColor(R, G, Bc, A));
|
||||
}
|
||||
|
||||
if (!bStandaloneCompactPayload)
|
||||
{
|
||||
// F17 — classify down-facing vertices for material-only ceiling grouping.
|
||||
uint8 SurfClass = 0;
|
||||
if (Normal.Z < -0.1f)
|
||||
{
|
||||
float TerrainZ = 0.0f, CeilSurf = 0.0f;
|
||||
// Un vertex du cap vit à la FRONTIÈRE HAUTE de la strate : arrondi/interpolation
|
||||
// peuvent le faire flotter dans le chunk gap/seal juste AU-DESSUS (hors
|
||||
// SurfaceWorld ⇒ sonde ratée ⇒ faux "sol"). On retente un chunk plus bas.
|
||||
const bool bSurf = Generator->GetSurfaceHeightAt(
|
||||
(float)(MemoKey.X * Step), (float)(MemoKey.Y * Step), MemoKey.Z,
|
||||
TerrainZ, CeilSurf)
|
||||
|| Generator->GetSurfaceHeightAt(
|
||||
(float)(MemoKey.X * Step), (float)(MemoKey.Y * Step), MemoKey.Z - 1,
|
||||
TerrainZ, CeilSurf);
|
||||
Col = &SurfColMemo.Add(MemoKey, bSurf ? FVector2f(TerrainZ, CeilSurf)
|
||||
: FVector2f(FLT_MAX, -FLT_MAX));
|
||||
const float Zv = WorldPos.Z / VOXEL_SIZE;
|
||||
const float StepF = (float)Step;
|
||||
const FIntVector MemoKey(
|
||||
FMath::RoundToInt(WorldPos.X / (VOXEL_SIZE * StepF)),
|
||||
FMath::RoundToInt(WorldPos.Y / (VOXEL_SIZE * StepF)),
|
||||
FMath::FloorToInt(Zv / (float)CHUNK_SIZE));
|
||||
FVector2f* Col = SurfColMemo.Find(MemoKey);
|
||||
if (!Col)
|
||||
{
|
||||
float TerrainZ = 0.0f, CeilSurf = 0.0f;
|
||||
const bool bSurf = Generator->GetSurfaceHeightAt(
|
||||
(float)(MemoKey.X * Step), (float)(MemoKey.Y * Step), MemoKey.Z,
|
||||
TerrainZ, CeilSurf)
|
||||
|| Generator->GetSurfaceHeightAt(
|
||||
(float)(MemoKey.X * Step), (float)(MemoKey.Y * Step), MemoKey.Z - 1,
|
||||
TerrainZ, CeilSurf);
|
||||
Col = &SurfColMemo.Add(MemoKey, bSurf ? FVector2f(TerrainZ, CeilSurf)
|
||||
: FVector2f(FLT_MAX, -FLT_MAX));
|
||||
}
|
||||
if (Col->X != FLT_MAX && FMath::Abs(Zv - Col->Y) < FMath::Abs(Zv - Col->X)
|
||||
&& Zv <= Col->Y + 2.0f * StepF)
|
||||
{
|
||||
SurfClass = 1;
|
||||
}
|
||||
}
|
||||
// Plus proche du plafond que du terrain ⇒ sky-cap. (Hors SurfaceWorld : sol.)
|
||||
// + garde : un vrai vertex de cap est AU niveau du cap (± slop d'interpolation) ;
|
||||
// loin AU-DESSUS = plancher/toit de la strate d'à côté atteint via le retry chunkZ-1
|
||||
// (strates contiguës) → reste sol.
|
||||
if (Col->X != FLT_MAX && FMath::Abs(Zv - Col->Y) < FMath::Abs(Zv - Col->X)
|
||||
&& Zv <= Col->Y + 2.0f * StepF)
|
||||
{
|
||||
SurfClass = 1;
|
||||
}
|
||||
VertexClasses.Add(SurfClass);
|
||||
}
|
||||
VertexClasses.Add(SurfClass);
|
||||
|
||||
return NewIndex;
|
||||
};
|
||||
@@ -919,7 +915,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
((ReachBlockZ * ReachBlocksPerAxis) + ReachBlockY)
|
||||
* ReachBlocksPerAxis + ReachBlockX;
|
||||
float PreEditDensity = 0.0f;
|
||||
DensityGrid[LocalIndex] = Generator->GetDensityAt(
|
||||
DensityGrid[LocalIndex] = Generator->GetDensityAtLattice(
|
||||
OriginVoxels.X + gx * Step,
|
||||
OriginVoxels.Y + gy * Step,
|
||||
OriginVoxels.Z + gz * Step,
|
||||
@@ -1244,14 +1240,18 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
const int32 Idx1 = GetOrCreateVertex(EdgeVertices[E1], EdgeNormals[E1]);
|
||||
const int32 Idx2 = GetOrCreateVertex(EdgeVertices[E2], EdgeNormals[E2]);
|
||||
|
||||
// F17 — vote majoritaire (≥ 2 vertex sky-cap ⇒ triangle sky-cap).
|
||||
const int32 CapVotes = (int32)VertexClasses[Idx0]
|
||||
+ (int32)VertexClasses[Idx1]
|
||||
+ (int32)VertexClasses[Idx2];
|
||||
TArray<int32>& Dst = (CapVotes >= 2) ? CapTris : GroundTris;
|
||||
Dst.Add(Idx0);
|
||||
Dst.Add(Idx2);
|
||||
Dst.Add(Idx1);
|
||||
TArray<int32>* Dst = &GroundTris;
|
||||
if (!bStandaloneCompactPayload)
|
||||
{
|
||||
// F17 — majority vote (at least two ceiling vertices => ceiling triangle).
|
||||
const int32 CapVotes = (int32)VertexClasses[Idx0]
|
||||
+ (int32)VertexClasses[Idx1]
|
||||
+ (int32)VertexClasses[Idx2];
|
||||
Dst = (CapVotes >= 2) ? &CapTris : &GroundTris;
|
||||
}
|
||||
Dst->Add(Idx0);
|
||||
Dst->Add(Idx2);
|
||||
Dst->Add(Idx1);
|
||||
}
|
||||
if (bSampleCell)
|
||||
{
|
||||
@@ -1314,8 +1314,11 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
const int32 Idx = MeshData.Vertices.Num();
|
||||
MeshData.Vertices.Add(Pos);
|
||||
MeshData.Normals.Add(Nrm);
|
||||
MeshData.UVs.Add(FVector2D(Pos.X / VOXEL_SIZE, Pos.Y / VOXEL_SIZE));
|
||||
MeshData.Colors.Add(Col); // hérite la couleur du vertex source (parallèle aux autres tableaux)
|
||||
if (!bStandaloneCompactPayload)
|
||||
{
|
||||
MeshData.UVs.Add(FVector2D(Pos.X / VOXEL_SIZE, Pos.Y / VOXEL_SIZE));
|
||||
MeshData.Colors.Add(Col); // parallel with the other vertex arrays
|
||||
}
|
||||
return Idx;
|
||||
};
|
||||
|
||||
@@ -1339,8 +1342,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
|
||||
const FVector NA = MeshData.Normals[iA];
|
||||
const FVector NB = MeshData.Normals[iB];
|
||||
const FColor CA = MeshData.Colors[iA];
|
||||
const FColor CB = MeshData.Colors[iB];
|
||||
const FColor CA = bStandaloneCompactPayload ? FColor::White : MeshData.Colors[iA];
|
||||
const FColor CB = bStandaloneCompactPayload ? FColor::White : MeshData.Colors[iB];
|
||||
const int32 iA2 = AddSkirtVert(PA - NA * SkirtDepth, NA, CA);
|
||||
const int32 iB2 = AddSkirtVert(PB - NB * SkirtDepth, NB, CB);
|
||||
|
||||
|
||||
Reference in new issue
Block a user