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 _GEOSPHERE_H
5 #define _GEOSPHERE_H
6 
7 #include <SDL_stdinc.h>
8 
9 #include "BaseSphere.h"
10 #include "Camera.h"
11 #include "vector3.h"
12 
13 #include <deque>
14 
15 namespace Graphics {
16 	class Renderer;
17 	class Texture;
18 }
19 
20 class SystemBody;
21 class GeoPatch;
22 class GeoPatchContext;
23 class SQuadSplitRequest;
24 class SQuadSplitResult;
25 class SSingleSplitResult;
26 
27 #define NUM_PATCHES 6
28 
29 class GeoSphere : public BaseSphere {
30 public:
31 	GeoSphere(const SystemBody *body);
32 	virtual ~GeoSphere();
33 
34 	virtual void Update() override;
35 	virtual void Render(Graphics::Renderer *renderer, const matrix4x4d &modelView, vector3d campos, const float radius, const std::vector<Camera::Shadow> &shadows) override;
36 
GetHeight(const vector3d & p)37 	virtual double GetHeight(const vector3d &p) const override final
38 	{
39 		const double h = m_terrain->GetHeight(p);
40 #ifdef DEBUG
41 		// XXX don't remove this. Fix your fractals instead
42 		// Fractals absolutely MUST return heights >= 0.0 (one planet radius)
43 		// otherwise atmosphere and other things break.
44 		if (h < 0.0) {
45 			Output("GetHeight({ %f, %f, %f }) returned %f\n", p.x, p.y, p.z, h);
46 			m_terrain->DebugDump();
47 			assert(h >= 0.0);
48 		}
49 #endif /* DEBUG */
50 		return h;
51 	}
52 
53 	static void Init();
54 	static void Uninit();
55 	static void UpdateAllGeoSpheres();
56 	static void OnChangeDetailLevel();
57 	static bool OnAddQuadSplitResult(const SystemPath &path, SQuadSplitResult *res);
58 	static bool OnAddSingleSplitResult(const SystemPath &path, SSingleSplitResult *res);
59 	// in sbody radii
GetMaxFeatureHeight()60 	virtual double GetMaxFeatureHeight() const override final { return m_terrain->GetMaxHeight(); }
61 
62 	bool AddQuadSplitResult(SQuadSplitResult *res);
63 	bool AddSingleSplitResult(SSingleSplitResult *res);
64 	void ProcessSplitResults();
65 
66 	virtual void Reset() override;
67 
GetMaxDepth()68 	inline Sint32 GetMaxDepth() const { return m_maxDepth; }
69 
70 	void AddQuadSplitRequest(double, SQuadSplitRequest *, GeoPatch *);
71 
72 private:
73 	void BuildFirstPatches();
74 	void CalculateMaxPatchDepth();
GetColor(const vector3d & p,double height,const vector3d & norm)75 	inline vector3d GetColor(const vector3d &p, double height, const vector3d &norm) const
76 	{
77 		return m_terrain->GetColor(p, height, norm);
78 	}
79 	void ProcessQuadSplitRequests();
80 
81 	std::unique_ptr<GeoPatch> m_patches[6];
82 	struct TDistanceRequest {
TDistanceRequestTDistanceRequest83 		TDistanceRequest(double dist, SQuadSplitRequest *pRequest, GeoPatch *pRequester) :
84 			mDistance(dist),
85 			mpRequest(pRequest),
86 			mpRequester(pRequester) {}
87 		double mDistance;
88 		SQuadSplitRequest *mpRequest;
89 		GeoPatch *mpRequester;
90 	};
91 	std::deque<TDistanceRequest> mQuadSplitRequests;
92 
93 	static const uint32_t MAX_SPLIT_OPERATIONS = 128;
94 	std::deque<SQuadSplitResult *> mQuadSplitResults;
95 	std::deque<SSingleSplitResult *> mSingleSplitResults;
96 
97 	bool m_hasTempCampos;
98 	vector3d m_tempCampos;
99 	Graphics::Frustum m_tempFrustum;
100 
101 	static RefCountedPtr<GeoPatchContext> s_patchContext;
102 
103 	virtual void SetUpMaterials() override;
104 
105 	RefCountedPtr<Graphics::Texture> m_texHi;
106 	RefCountedPtr<Graphics::Texture> m_texLo;
107 
108 	enum EGSInitialisationStage {
109 		eBuildFirstPatches = 0,
110 		eRequestedFirstPatches,
111 		eReceivedFirstPatches,
112 		eDefaultUpdateState
113 	};
114 	EGSInitialisationStage m_initStage;
115 
116 	Sint32 m_maxDepth;
117 };
118 
119 #endif /* _GEOSPHERE_H */
120