summaryrefslogtreecommitdiff
path: root/Runtime/Terrain/TerrainRenderer.h
blob: d9bf68389f398e74f46295986fb40dc06800f4ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#pragma once
#include "Configuration/UnityConfigure.h"

#if ENABLE_TERRAIN

#include "Runtime/Math/Vector3.h"
#include "Runtime/Geometry/AABB.h"
#include "TerrainData.h"
#include "Runtime/Filters/Mesh/LodMesh.h"
#include "Runtime/Shaders/Material.h"
#include "SplatMaterials.h"

#define TERRAIN_PREFER_VBO_OVER_MESH

class Camera;

enum
{
	kVisibilityLoddedAway = 0,
	kVisibilityDrawChild = 1,
	kVisibilityDrawSelf = 2
};

struct QuadTreeNode
{
#ifdef TERRAIN_PREFER_VBO_OVER_MESH
	VBO         *vbo;
	SubMesh     subMesh;
#else
	Mesh        *mesh;
#endif
	int         edgeMask;
	float       maxHeightError;
	
	int  visibility;
	int  oldVisibility;
		
	int x;
	int y;
	int level;
	AABB bounds;
	bool useSplatmap		: 1;

#ifdef TERRAIN_PREFER_VBO_OVER_MESH
	bool updateMesh			: 1;
	bool updateIndices		: 1;
#endif
	
	QuadTreeNode()
	{ 
		edgeMask = -1; 
		maxHeightError = 1; 
		visibility = kVisibilityLoddedAway; 
		oldVisibility = kVisibilityLoddedAway;
#ifdef TERRAIN_PREFER_VBO_OVER_MESH
		vbo = NULL;
		updateMesh = false;
		updateIndices = false;
#else
		mesh = NULL;
#endif
	}
	
	~QuadTreeNode()
	{
#ifdef TERRAIN_PREFER_VBO_OVER_MESH
		AssertIf(vbo != NULL);
#else
		DestroySingleObject(mesh);
#endif
	}
};

class TerrainRenderer
{
public:
	TerrainRenderer              *m_TopNeighbor;
	TerrainRenderer              *m_RightNeighbor;
	TerrainRenderer              *m_BottomNeighbor;
	TerrainRenderer              *m_LeftNeighbor;
	
	Vector3f					m_Scale;
	std::vector<QuadTreeNode>	m_Quadtree;
	int                         m_Levels;
	SplatMaterials				*m_SplatMaterials;
	Vector3f					m_Position;
	bool						m_CastShadows;
	
	Vector3f m_CachedCameraPosition;
	int m_CachedMaxLodLevel;
	float m_CachedkC;
	float m_CachedSqrSplatDistance;
	
	TerrainRenderer (SInt32 instanceID, PPtr<TerrainData> terrainData, const Vector3f &position, int lightmapIndex);
	~TerrainRenderer ();
	void RenderStep1 (Camera *camera, int maxLodLevel, float tau, float splatDistance);
	void RenderStep2 ();
	void RenderStep3 (Camera *camera, int layer, bool castShadow, Material* mat);
	void ReloadAll ();
	void Cleanup ();
	void UnloadVBOFromGfxDevice ();
	void ReloadVBOToGfxDevice ();
	void ReloadPrecomputedError ();	
	void ReloadBounds ();
	void RecursiveCalculateLod (QuadTreeNode &node);
	void SetNeighbors (TerrainRenderer *left, TerrainRenderer *top, TerrainRenderer *right, TerrainRenderer *bottom);
	
	PPtr<TerrainData> GetTerrainData() const { return m_TerrainData; }
	void SetTerrainData(PPtr<TerrainData> value);

	int GetLightmapIndex() { return m_LightmapIndex; }
	void SetLightmapIndex(int value) { m_LightmapIndex = value; }

	std::vector<Mesh*> GetMeshPatches();
	
	#if UNITY_EDITOR
	void SetLightmapSize(int lightmapSize) { m_LightmapSize = lightmapSize; }
	#endif

private:
	
	int m_CurrentLayer;
	Camera *m_CurrentCamera;
	Material *m_CurrentBaseMaterial;
	int m_CurrentMaterialCount;
	Material **m_CurrentMaterials;
	PPtr<TerrainData> m_TerrainData;
	int m_LightmapIndex;
	#if UNITY_EDITOR
	SInt32 m_InstanceID;
	int m_LightmapSize;
	#endif

	std::list<VBO*> m_FreeVBOPool;
	VBO* CreateVBO();
	void ReclaimVBO(VBO* vbo);

	QuadTreeNode &GetRootNode() { return m_Quadtree.back(); }
	bool IsRootNode (const QuadTreeNode& node) { return (node.level == GetRootNode().level); }


	int GetIndex (int x, int y, int level);
	QuadTreeNode *GetNode (int x, int y, int level);
	QuadTreeNode *GetNodeAndRenderer (int x, int y, int level, TerrainRenderer *&renderer);
	int GetPatchCountX (int level);
	int GetPatchCountY (int level);
	void RebuildNodes ();
	Vector3f GetNodePosition (QuadTreeNode &node);
	int CalculateEdgeMask (QuadTreeNode &node);
	QuadTreeNode *FindNeighbor (QuadTreeNode &node, int direction);
	QuadTreeNode *FindNeighborAndRenderer (QuadTreeNode &node, int direction, TerrainRenderer *&renderer);
	QuadTreeNode *FindChild (QuadTreeNode &node, int direction);
	QuadTreeNode *FindParent (QuadTreeNode &node);
	void CleanupMeshes ();
	static float CalculateSqrDistance (Vector3f &rkPoint, AABB &rkBox);
	void MarkChildVisibilityRecurse (QuadTreeNode &node, int newVisibility);		
	void ForceSplitParent (QuadTreeNode &node);
	void EnforceLodTransitions (QuadTreeNode &node);
	void RemoveMesh (QuadTreeNode &node);
	void RecursiveRemoveMeshes (QuadTreeNode &node);
	void RenderNode (QuadTreeNode &node);
	void BuildRenderer (QuadTreeNode &node, int edgeMask);
	void RecursiveRenderMeshes (QuadTreeNode &node, Heightmap &heightmap);

	friend class QuadTreeNodeRenderer;
};

#endif // ENABLE_TERRAIN