#pragma once #include "CoreMinimal.h" /** Constants of the terrain: chunks, meshing, streaming budgets, carving (World/Descent*Terrain*, DESIGN_UE.md sections 2.3 - 2.6). */ namespace Descent::Tune::Terrain { // ---- chunk geometry (section 2.3, v2) ------------------------------------------------------------------------ constexpr double VoxelM = 1.25; // VS constexpr int32 CoreN = 16; // CN: core samples per axis constexpr double ChunkM = VoxelM * CoreN; // CS = 20 m constexpr int32 Pad = 2; // samples of padding each side constexpr int32 P = CoreN + 2 * Pad; // 20 constexpr int32 P2 = P * P; constexpr int32 P3 = P * P * P; // 8,000 /** Cells the mesher visits per axis (CN + 1) and the vertex slots that gives. */ constexpr int32 SC = CoreN + 1; constexpr int32 SC3 = SC * SC * SC; // ---- classification (section 2.3) ---------------------------------------------------------------------------- /** |GenRaw(centre)| beyond ChunkM * ClassifyFactor + ClassifyBias is a uniform chunk. */ constexpr double ClassifyFactor = 0.87; constexpr double ClassifyBias = 10.0; /** Radius around the chunk centre the fill job gathers primitives for. */ constexpr double GatherRadiusFactor = 0.9; constexpr double GatherRadiusBias = 3.0; /** A chunk that touches a sponge box grown by this is always a candidate (the sponge is not a distance field). */ constexpr double SpongeCandidateGrow = 12.0; // ---- streaming (section 2.6) --------------------------------------------------------------------------------- constexpr double LoadRadiusM = 160.0; // cvar descent.Terrain.StreamRadius constexpr double UnloadExtraM = 40.0; // RU = R + 40 constexpr double LowLoadRadiusM = 120.0; constexpr double LowUnloadExtraM = 30.0; constexpr double PlanIntervalSec = 0.5; constexpr double PlanMoveM = 10.0; constexpr double UnloadIntervalSec = 0.33; constexpr int32 MaxJobsInFlight = 12; constexpr double ApplyBudgetMs = 1.5; // game-thread time per frame for finished jobs constexpr double RemeshBudgetMs = 2.5; // synchronous remesh of carved chunks per frame constexpr int32 RemeshMinFrames = 3; // a chunk is remeshed at most once per this many frames constexpr int32 FilledChunkCap = 4000; // memory cap: 160 MB /** The blocking initial stream at boot (section 1.5 step 4). */ constexpr double InitialRadiusM = 120.0; // ---- carving (section 2.5) ------------------------------------------------------------------------------------ constexpr double CarveBlendK = 1.6; constexpr double CarveCutRadiusExtra = 0.6; // Cut = 200 where dist < Radius + this constexpr uint8 CutValue = 200; constexpr double CarveReachExtra = 2.0; // samples within Radius + this are visited constexpr double CleanupFreedValue = -0.8; constexpr double CleanupMargin = 4.0; // region half-size = ceil((Radius + this) / VS) samples constexpr double RaycastStepFactor = 0.85; constexpr double RaycastMinStep = 0.3; constexpr int32 RaycastBisections = 7; constexpr double GradientH = 0.6; /** Mesher winding: the v2 index order is right-handed; set true if the first screenshot shows rock lit from inside. */ constexpr bool FlipWinding = true; }