276 lines
7.1 KiB
C++
276 lines
7.1 KiB
C++
#pragma once
|
|
|
|
namespace verus
|
|
{
|
|
namespace Scene
|
|
{
|
|
class Terrain;
|
|
|
|
enum class TerrainTBN : int
|
|
{
|
|
tangent,
|
|
binormal,
|
|
normal
|
|
};
|
|
|
|
class TerrainPhysics
|
|
{
|
|
btHeightfieldTerrainShape* _pShape = nullptr;
|
|
btRigidBody* _pRigidBody = nullptr;
|
|
bool _debugDraw = false;
|
|
|
|
public:
|
|
TerrainPhysics();
|
|
~TerrainPhysics();
|
|
|
|
void Init(Physics::PUserPtr p, int w, int h, const void* pData, float heightScale = 0.01f);
|
|
void Done();
|
|
|
|
void EnableDebugDraw(bool b);
|
|
bool IsDebugDrawEnabled() const { return _debugDraw; }
|
|
};
|
|
VERUS_TYPEDEFS(TerrainPhysics);
|
|
|
|
class TerrainLOD
|
|
{
|
|
public:
|
|
Vector<UINT16> _vIB;
|
|
int _side = 0;
|
|
int _vertCount = 0;
|
|
int _indexCount = 0;
|
|
int _firstIndex = 0;
|
|
|
|
void Init(int sidePoly, int step, bool addEdgeTess);
|
|
void InitGeo(short* pV, UINT16* pI, int vertexOffset, bool addEdgeTess);
|
|
};
|
|
VERUS_TYPEDEFS(TerrainLOD);
|
|
|
|
class TerrainPatch
|
|
{
|
|
public:
|
|
struct TBN
|
|
{
|
|
char _normals0[16 * 16][3];
|
|
char _normals1[8 * 8][3];
|
|
char _normals2[4 * 4][3];
|
|
char _normals3[2 * 2][3];
|
|
char _normals4[1 * 1][3];
|
|
};
|
|
VERUS_TYPEDEFS(TBN);
|
|
|
|
PTBN _pTBN = nullptr;
|
|
UINT16 _ijCoord[2];
|
|
char _layerForChannel[4];
|
|
int _distToCameraSq = 0;
|
|
short _patchHeight = 0;
|
|
char _quadtreeLOD = 0;
|
|
char _usedChannelCount = 1;
|
|
short _height[16 * 16];
|
|
char _mainLayer[16 * 16];
|
|
|
|
TerrainPatch();
|
|
void BindTBN(PTBN p);
|
|
void InitFlat(short height, int mainLayer);
|
|
void UpdateNormals(Terrain* p, int lod);
|
|
int GetSplatChannelForLayer(int layer) const;
|
|
};
|
|
VERUS_TYPEDEFS(TerrainPatch);
|
|
|
|
class Terrain : public Object, public Math::QuadtreeIntegralDelegate, public Physics::UserPtr
|
|
{
|
|
public:
|
|
#include "../Shaders/DS_Terrain.inc.hlsl"
|
|
#include "../Shaders/SimpleTerrain.inc.hlsl"
|
|
|
|
enum SHADER
|
|
{
|
|
SHADER_MAIN,
|
|
SHADER_SIMPLE,
|
|
SHADER_COUNT
|
|
};
|
|
|
|
enum PIPE
|
|
{
|
|
PIPE_LIST,
|
|
PIPE_STRIP,
|
|
PIPE_TESS,
|
|
|
|
PIPE_DEPTH_LIST,
|
|
PIPE_DEPTH_STRIP,
|
|
PIPE_DEPTH_TESS,
|
|
|
|
PIPE_WIREFRAME_LIST,
|
|
PIPE_WIREFRAME_STRIP,
|
|
PIPE_REFLECTION_LIST,
|
|
PIPE_REFLECTION_STRIP,
|
|
PIPE_UNDERWATER_LIST,
|
|
PIPE_UNDERWATER_STRIP,
|
|
PIPE_COUNT
|
|
};
|
|
|
|
enum TEX
|
|
{
|
|
TEX_HEIGHTMAP,
|
|
TEX_NORMALS,
|
|
TEX_BLEND,
|
|
TEX_LAYERS,
|
|
TEX_LAYERS_NM,
|
|
TEX_MAIN_LAYER,
|
|
TEX_COUNT
|
|
};
|
|
|
|
static const int s_maxLayers = 32;
|
|
|
|
struct PerInstanceData
|
|
{
|
|
short _posPatch[4];
|
|
short _layers[4];
|
|
};
|
|
|
|
struct LayerData
|
|
{
|
|
float _specStrength = 1;
|
|
float _detailStrength = 1;
|
|
};
|
|
|
|
protected:
|
|
static CGI::ShaderPwns<SHADER_COUNT> s_shader;
|
|
static UB_TerrainVS s_ubTerrainVS;
|
|
static UB_TerrainFS s_ubTerrainFS;
|
|
static UB_SimpleTerrainVS s_ubSimpleTerrainVS;
|
|
static UB_SimpleTerrainFS s_ubSimpleTerrainFS;
|
|
|
|
CGI::GeometryPwn _geo;
|
|
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
|
CGI::TexturePwns<TEX_COUNT> _tex;
|
|
Vector<TerrainPatch> _vPatches;
|
|
Vector<TerrainPatch::TBN> _vPatchTBNs;
|
|
Vector<UINT16> _vSortedPatchIndices;
|
|
Vector<PerInstanceData> _vInstanceBuffer;
|
|
Vector<String> _vLayerUrls;
|
|
Vector<short> _vHeightBuffer;
|
|
Vector<glm::uint16> _vHeightmapSubresData;
|
|
Vector<UINT32> _vNormalsSubresData;
|
|
Vector<UINT32> _vBlendBuffer;
|
|
Vector<BYTE> _vMainLayerSubresData;
|
|
float _quadtreeFatten = 0.5f;
|
|
int _mapSide = 0;
|
|
int _mapShift = 0;
|
|
int _vertCount = 0;
|
|
int _indexCount = 0;
|
|
int _instanceCount = 0;
|
|
int _visiblePatchCount = 0;
|
|
CGI::CSHandle _cshVS;
|
|
CGI::CSHandle _cshFS;
|
|
CGI::CSHandle _cshSimpleVS;
|
|
CGI::CSHandle _cshSimpleFS;
|
|
TerrainLOD _lods[5]; // Level of detail data for (16x16, 8x8, 4x4, 2x2, 1x1).
|
|
LayerData _layerData[s_maxLayers];
|
|
TerrainPhysics _physics;
|
|
Math::QuadtreeIntegral _quadtree;
|
|
|
|
public:
|
|
float _lamScale = 1.9f;
|
|
float _lamBias = -0.9f;
|
|
|
|
struct Desc
|
|
{
|
|
int _mapSide = 256;
|
|
int _layer = 0;
|
|
short _height = 0;
|
|
short _debugHills = 0;
|
|
|
|
Desc() {}
|
|
};
|
|
VERUS_TYPEDEFS(Desc);
|
|
|
|
struct DrawDesc
|
|
{
|
|
bool _allowTess = false;
|
|
bool _wireframe = false;
|
|
|
|
void Reset()
|
|
{
|
|
*this = DrawDesc();
|
|
}
|
|
};
|
|
VERUS_TYPEDEFS(DrawDesc);
|
|
|
|
Terrain();
|
|
virtual ~Terrain();
|
|
|
|
static void InitStatic();
|
|
static void DoneStatic();
|
|
|
|
void Init(RcDesc desc = Desc());
|
|
void InitByWater();
|
|
void Done();
|
|
|
|
void ResetInstanceCount();
|
|
void Layout();
|
|
void Draw(RcDrawDesc dd = DrawDesc());
|
|
void DrawReflection();
|
|
|
|
void SortVisiblePatches();
|
|
|
|
virtual int UserPtr_GetType() override;
|
|
|
|
int GetMapSide() const { return _mapSide; }
|
|
|
|
RTerrainPatch GetPatch(int index) { return _vPatches[index]; }
|
|
|
|
// Quadtree:
|
|
Math::RQuadtreeIntegral GetQuadtree() { return _quadtree; }
|
|
virtual void QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center) override;
|
|
virtual void QuadtreeIntegral_GetHeights(const short ij[2], float height[2]) override;
|
|
void FattenQuadtreeNodesBy(float x);
|
|
|
|
// Height:
|
|
static constexpr float ConvertHeight(short h) { return h * 0.01f; }
|
|
static constexpr int ConvertHeight(float h) { return static_cast<int>(h * 100); }
|
|
float GetHeightAt(const float xz[2]) const;
|
|
float GetHeightAt(RcPoint3 pos) const;
|
|
float GetHeightAt(const int ij[2], int lod = 0, short* pRaw = nullptr) const;
|
|
void SetHeightAt(const int ij[2], short h);
|
|
void UpdateHeightBuffer();
|
|
|
|
// Normals:
|
|
const char* GetNormalAt(const int ij[2], int lod = 0, TerrainTBN tbn = TerrainTBN::normal) const;
|
|
Matrix3 GetBasisAt(const int ij[2]) const;
|
|
|
|
// Layers:
|
|
void InsertLayerUrl(int layer, CSZ url);
|
|
void DeleteAllLayerUrls();
|
|
void GetLayerUrls(Vector<CSZ>& v);
|
|
void LoadLayersFromFile(CSZ url = nullptr);
|
|
void LoadLayerTextures();
|
|
int GetMainLayerAt(const int ij[2]) const;
|
|
void UpdateMainLayerAt(const int ij[2]);
|
|
|
|
float GetSpecStrength(int layer) const { return _layerData[layer]._specStrength; }
|
|
float GetDetailStrength(int layer) const { return _layerData[layer]._detailStrength; }
|
|
void SetSpecStrength(int layer, float x) { _layerData[layer]._specStrength = x; }
|
|
void SetDetailStrength(int layer, float x) { _layerData[layer]._detailStrength = x; }
|
|
|
|
// Textures:
|
|
void UpdateHeightmapTexture();
|
|
CGI::TexturePtr GetHeightmapTexture() const;
|
|
void UpdateNormalsTexture();
|
|
CGI::TexturePtr GetNormalsTexture() const;
|
|
void UpdateBlendTexture();
|
|
CGI::TexturePtr GetBlendTexture() const;
|
|
void UpdateMainLayerTexture();
|
|
CGI::TexturePtr GetMainLayerTexture() const;
|
|
void OnHeightModified();
|
|
|
|
// Physics:
|
|
void AddNewRigidBody();
|
|
RTerrainPhysics GetPhysics() { return _physics; }
|
|
|
|
void Serialize(IO::RSeekableStream stream);
|
|
void Deserialize(IO::RStream stream);
|
|
};
|
|
VERUS_TYPEDEFS(Terrain);
|
|
}
|
|
}
|