1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _GEOPATCH_H
5 #define _GEOPATCH_H
6 
7 #include <SDL_stdinc.h>
8 
9 #include "Color.h"
10 #include "GeoPatchID.h"
11 #include "JobQueue.h"
12 #include "RefCounted.h"
13 #include "matrix4x4.h"
14 #include "vector3.h"
15 #include <deque>
16 #include <memory>
17 
18 //#define DEBUG_BOUNDING_SPHERES
19 
20 #ifdef DEBUG_BOUNDING_SPHERES
21 #include "graphics/Drawables.h"
22 namespace Graphics {
23 	class RenderState;
24 }
25 #endif
26 
27 namespace Graphics {
28 	class Renderer;
29 	class Frustum;
30 	class VertexBuffer;
31 }
32 
33 class GeoPatchContext;
34 class GeoSphere;
35 class BasePatchJob;
36 class SQuadSplitResult;
37 class SSingleSplitResult;
38 
39 class GeoPatch {
40 public:
41 	GeoPatch(const RefCountedPtr<GeoPatchContext> &_ctx, GeoSphere *gs,
42 		const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_,
43 		const int depth, const GeoPatchID &ID_);
44 
45 	~GeoPatch();
46 
NeedToUpdateVBOs()47 	inline void NeedToUpdateVBOs()
48 	{
49 		m_needUpdateVBOs = (nullptr != m_heights);
50 	}
51 
52 	void UpdateVBOs(Graphics::Renderer *renderer);
53 
GetChildIdx(const GeoPatch * child)54 	int GetChildIdx(const GeoPatch *child) const
55 	{
56 		for (int i = 0; i < NUM_KIDS; i++) {
57 			if (m_kids[i].get() == child) return i;
58 		}
59 		abort();
60 		return -1;
61 	}
62 
63 	// in patch surface coords, [0,1]
GetSpherePoint(const double x,const double y)64 	inline vector3d GetSpherePoint(const double x, const double y) const
65 	{
66 		return (m_v0 + x * (1.0 - y) * (m_v1 - m_v0) + x * y * (m_v2 - m_v0) + (1.0 - x) * y * (m_v3 - m_v0)).Normalized();
67 	}
68 
69 	void Render(Graphics::Renderer *r, const vector3d &campos, const matrix4x4d &modelView, const Graphics::Frustum &frustum);
70 
canBeMerged()71 	inline bool canBeMerged() const
72 	{
73 		bool merge = true;
74 		if (m_kids[0]) {
75 			for (int i = 0; i < NUM_KIDS; i++) {
76 				merge &= m_kids[i]->canBeMerged();
77 			}
78 		}
79 		merge &= !(m_HasJobRequest);
80 		return merge;
81 	}
82 
83 	void LODUpdate(const vector3d &campos, const Graphics::Frustum &frustum);
84 
85 	void RequestSinglePatch();
86 	void ReceiveHeightmaps(SQuadSplitResult *psr);
87 	void ReceiveHeightmap(const SSingleSplitResult *psr);
88 	void ReceiveJobHandle(Job::Handle job);
89 
HasHeightData()90 	inline bool HasHeightData() const { return (m_heights.get() != nullptr); }
91 private:
92 	static const int NUM_KIDS = 4;
93 
94 	RefCountedPtr<GeoPatchContext> m_ctx;
95 	const vector3d m_v0, m_v1, m_v2, m_v3;
96 	std::unique_ptr<double[]> m_heights;
97 	std::unique_ptr<vector3f[]> m_normals;
98 	std::unique_ptr<Color3ub[]> m_colors;
99 	std::unique_ptr<Graphics::VertexBuffer> m_vertexBuffer;
100 	std::unique_ptr<GeoPatch> m_kids[NUM_KIDS];
101 	GeoPatch *m_parent;
102 	GeoSphere *m_geosphere;
103 	double m_roughLength;
104 	vector3d m_clipCentroid, m_centroid;
105 	double m_clipRadius;
106 	Sint32 m_depth;
107 	bool m_needUpdateVBOs;
108 
109 	const GeoPatchID m_PatchID;
110 	Job::Handle m_job;
111 	bool m_HasJobRequest;
112 #ifdef DEBUG_BOUNDING_SPHERES
113 	std::unique_ptr<Graphics::Drawables::Sphere3D> m_boundsphere;
114 #endif
115 };
116 
117 #endif /* _GEOPATCH_H */
118