115 lines
7.2 KiB
C++
115 lines
7.2 KiB
C++
// VoxelMarchingCubesMesher.h
|
||
// Mesh lisse à partir du champ de densité du générateur.
|
||
//
|
||
// Principe:
|
||
// 1. Chaque cellule du chunk (cube 2x2x2 voxels) lit la densité aux 8 coins.
|
||
// 2. Un index 8 bits indique quels coins sont au-dessus du IsoLevel.
|
||
// 3. Les tables MC (EdgeTable + TriTable) donnent les triangles à générer.
|
||
// 4. On interpole la position du vertex le long de chaque arête traversée.
|
||
//
|
||
// LOD: Step > 1 échantillonne moins souvent → moins de triangles à distance.
|
||
|
||
#pragma once
|
||
|
||
#include "CoreMinimal.h"
|
||
#include "VoxelTypes.h" // Pour FVoxelMeshData, CHUNK_SIZE, VOXEL_SIZE, etc.
|
||
#include "VoxelGenerator.h"
|
||
#include "VoxelMarchingCubesMesher.generated.h"
|
||
|
||
UCLASS(BlueprintType)
|
||
class VOXELFORGE_API UVoxelMarchingCubesMesher : public UObject
|
||
{
|
||
GENERATED_BODY()
|
||
|
||
public:
|
||
/**
|
||
* Génère le mesh d'une TUILE de clipmap (voir FVoxelTileKey).
|
||
*
|
||
* @param OriginVoxels - Coin min de la tuile en coords VOXEL (= Tile.OriginVoxels()).
|
||
* @param Step - Taille de cellule en voxels. La tuile couvre CellsPerAxis*Step voxels.
|
||
* @param CellsPerAxis - Nombre de cellules par axe. Les tuiles GROSSIÈRES en utilisent MOINS
|
||
* (gen moins chère, maillage plus grossier au loin) tout en couvrant la
|
||
* même étendue (extent = CellsPerAxis*Step). Niveau 0 = CHUNK_SIZE.
|
||
* @param OutCaptureGrid - CAPTURE-DURING-MESHING (optionnel). Si non-null ET CellsPerAxis==CHUNK_SIZE
|
||
* (tuile pleine résolution, Step==1<<Level, donc 1:1 avec une cellule du clipmap
|
||
* de densité), on y recopie les CHUNK_SIZE³ points intérieurs de la grille de
|
||
* densité déjà échantillonnée, quantifiés via VF_QuantizeDensity. Cela évite à
|
||
* UVoxelDensityVolume de re-sampler GetDensityAt pour ces cellules (le mesher
|
||
* les a déjà calculées). Vidé puis rempli ; reste vide si non éligible.
|
||
* @param BandZMinVox / BandZMaxVox - COUPE DE CONTENU PAR STRATE (optionnel, voxels Z INCLUSIFS,
|
||
* cf. UVoxelSettings::StrateContentCutMinLevel) : seules les cellules dont
|
||
* l'intervalle Z chevauche la bande sont maillées. Une tuile grossière qui
|
||
* chevauche une frontière de strate ne maille que la strate du joueur —
|
||
* supprime les trous d'aliasing (le bouchon seal/gap plus fin que Step
|
||
* tombait entre deux points du treillis) et le mélange de matériaux entre
|
||
* strates. Les cellules maillées restent identiques au bit près (mêmes
|
||
* échantillons monde purs). Jamais combiné avec OutCaptureGrid.
|
||
*/
|
||
FVoxelMeshData GenerateMesh(FIntVector OriginVoxels, int32 Step = 1, int32 CellsPerAxis = CHUNK_SIZE,
|
||
TArray<uint8>* OutCaptureGrid = nullptr,
|
||
int32 BandZMinVox = INT32_MIN, int32 BandZMaxVox = INT32_MAX);
|
||
|
||
/**
|
||
* F18 — FEUILLE de champ lointain (anneau render-distance, cf. UVoxelSettings::bFarSheetRing).
|
||
* Dans une strate ouverte (SurfaceWorld) le champ lointain est exactement DEUX heightfields —
|
||
* TerrainZ (sol) et CeilSurf (plafond sky-cap), déjà calculés par colonne par l'oracle
|
||
* GetSurfaceHeightAt. On construit donc deux grilles déplacées régulières au lieu d'un marching
|
||
* cubes 3D : sol = polygroup 0, cap = polygroup 1 (classes vraies PAR CONSTRUCTION — pas de vote,
|
||
* pas de sonde de classification), mêmes conventions que GenerateMesh (positions monde cm, UVs
|
||
* planaires, masques couleur F6 biome/pente/fondu, normales du gradient de hauteur, jupes
|
||
* périmètre par seau, run d'indices sol‖cap + NumCeilingTriangles).
|
||
*
|
||
* @param OriginVoxels - Coin min de la tuile (voxels). Seul XY est utilisé (les hauteurs sont absolues).
|
||
* @param StepXY - Pas d'échantillonnage XY en voxels (aligné sur l'anneau MC pour la continuité).
|
||
* @param CellsXY - Cellules par axe XY (extent = CellsXY × StepXY).
|
||
* @param StrateChunkZ - Chunk Z DANS la strate de référence (le cœur de la bande) — identifie la
|
||
* strate dont on maille sol+cap. Hors SurfaceWorld ⇒ mesh vide.
|
||
* @param HoleMin/MaxX/YVox - TROU XY (voxels, Max EXCLUSIF ; sentinelles MAX/MIN = pas de trou) :
|
||
* les cellules ENTIÈREMENT dans ce rectangle (la zone couverte par les
|
||
* coquilles MC autour du joueur) sont sautées — sinon la feuille recouvre
|
||
* le terrain proche avec son échantillonnage grossier. Les cellules à
|
||
* cheval restent (anneau de recouvrement au raccord) ; pas de jupe sur
|
||
* les bords du trou (le terrain MC remplit derrière).
|
||
* Non couvert (accepté, cf. fable-idea F18) : passages/spine/chasms creusés (le heightfield pur ne
|
||
* les contient pas), diff layer — invisibles à distance de feuille, l'anneau MC proche les garde.
|
||
*/
|
||
FVoxelMeshData GenerateSheetMesh(FIntVector OriginVoxels, int32 StepXY, int32 CellsXY,
|
||
int32 StrateChunkZ,
|
||
int32 HoleMinXVox = INT32_MAX, int32 HoleMinYVox = INT32_MAX,
|
||
int32 HoleMaxXVox = INT32_MIN, int32 HoleMaxYVox = INT32_MIN);
|
||
|
||
//=========================================================================
|
||
// SERVICES (injectés par AVoxelWorld)
|
||
//=========================================================================
|
||
|
||
// Le générateur fournit la densité par voxel.
|
||
UPROPERTY()
|
||
const UVoxelGenerator* Generator = nullptr;
|
||
|
||
void SetGenerator(const UVoxelGenerator* InGenerator) { Generator = InGenerator; }
|
||
|
||
//=========================================================================
|
||
// SETTINGS
|
||
//=========================================================================
|
||
|
||
// Seuil de l'isosurface dans le champ de densité.
|
||
// Convention MC: densité < IsoLevel = solide, >= = air.
|
||
float IsoLevel = 0.0f;
|
||
|
||
// SKIRTS — bouchent les fissures aux frontières de tuiles entre niveaux de clipmap voisins
|
||
// (résolutions différentes → les iso-surfaces ne se rejoignent pas exactement). Une jupe
|
||
// (mur court) est extrudée vers le solide depuis chaque arête de surface posée sur une des 6
|
||
// faces externes de la tuile. Voir GenerateMesh.
|
||
bool bGenerateSkirts = true;
|
||
// Profondeur de la jupe, en CELLULES de la tuile (× Step × VOXEL_SIZE). ~2 cellules couvrent
|
||
// l'écart vers un voisin un niveau plus grossier (cellule 2×). Monter si des fissures persistent.
|
||
float SkirtCells = 2.0f;
|
||
|
||
// T2.b — LOD-aware octave reduction (opt-in, copied from UVoxelSettings::LODOctaveDrop).
|
||
// Octaves dropped from per-voxel volumetric noise PER Step doubling: a tile at Step=S
|
||
// drops LODOctaveDrop * log2(S) octaves (see VoxelGenLOD in VoxelGenerator.h).
|
||
// 0 (default) = off — every LOD samples full octaves, byte-identical to before.
|
||
// Réduction d'octaves sur les tuiles grossières ; 0 = désactivé.
|
||
int32 LODOctaveDrop = 0;
|
||
};
|