1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef READ_MAP_H
4 #define READ_MAP_H
5 
6 #include <list>
7 
8 #include "Sim/Misc/GlobalConstants.h"
9 #include "Sim/Misc/GlobalSynced.h"
10 #include "System/float3.h"
11 #include "System/type2.h"
12 #include "System/creg/creg_cond.h"
13 #include "System/Misc/RectangleOptimizer.h"
14 
15 #define USE_UNSYNCED_HEIGHTMAP
16 
17 class CMetalMap;
18 class CCamera;
19 class CUnit;
20 class CSolidObject;
21 class CBaseGroundDrawer;
22 
23 
24 struct MapFeatureInfo
25 {
26 	float3 pos;
27 	/// index to one of the strings above
28 	int featureType;
29 	float rotation;
30 };
31 
32 
33 struct MapBitmapInfo
34 {
MapBitmapInfoMapBitmapInfo35 	MapBitmapInfo() : width(0), height(0) {}
MapBitmapInfoMapBitmapInfo36 	MapBitmapInfo(int w, int h) : width(w), height(h) {}
37 
38 	int width;
39 	int height;
40 };
41 
42 
43 
44 class CReadMap
45 {
46 protected:
47 	CReadMap();
48 
49 	/// called by implementations of CReadMap
50 	void Initialize();
51 	void CalcHeightmapChecksum();
52 
53 	virtual void UpdateHeightMapUnsynced(const SRectangle&) = 0;
54 
55 public:
56 	CR_DECLARE(CReadMap)
57 
58 	static CReadMap* LoadMap(const std::string& mapname);
EncodeHeight(const float h)59 	static inline unsigned char EncodeHeight(const float h) {
60 		return std::max(0, 255 + int(10.0f * h));
61 	}
62 
63 	/// creg serialize callback
64 	void Serialize(creg::ISerializer& s);
65 
66 
67 	/**
68 	 * calculates derived heightmap information
69 	 * such as normals, centerheightmap and slopemap
70 	 */
71 	void UpdateHeightMapSynced(SRectangle rect, bool initialize = false);
72 	void UpdateLOS(const SRectangle& rect);
73 	void BecomeSpectator();
74 	void UpdateDraw();
75 
76 	virtual ~CReadMap();
77 
Update()78 	virtual void Update() {}
UpdateShadingTexture()79 	virtual void UpdateShadingTexture() {}
80 
81 	virtual void NewGroundDrawer() = 0;
GetGroundDrawer()82 	virtual CBaseGroundDrawer* GetGroundDrawer() { return 0; }
83 
GetMiniMapTexture()84 	virtual unsigned int GetMiniMapTexture() const { return 0; }
GetMiniMapTextureSize()85 	virtual int2 GetMiniMapTextureSize() const { return int2(0,0); }
GetGrassShadingTexture()86 	virtual unsigned int GetGrassShadingTexture() const { return 0; }
87 	/**
88 	 * a texture with RGB for shading and A for height
89 	 * (0 := above water; 1-255 := under water = 255+height*10)
90 	 */
91 	virtual unsigned int GetShadingTexture() const = 0;
92 
93 	/// Draws the minimap in a quad (with extends: (0,0)-(1,1))
94 	virtual void DrawMinimap() const = 0;
95 
96 	/// Feature creation
97 	virtual int GetNumFeatures() = 0;
98 	virtual int GetNumFeatureTypes() = 0;
99 	/// Returns MapFeatureInfo[GetNumFeatures()]
100 	virtual void GetFeatureInfo(MapFeatureInfo* f) = 0;
101 	virtual const char* GetFeatureTypeName(int typeID) = 0;
102 
103 	/**
104 	 * Infomaps (such as metal map, grass map, ...),
105 	 * handling them with a string as type seems flexible...
106 	 * Some map types:
107 	 *   "metal"  -  metalmap
108 	 *   "grass"  -  grassmap
109 	 */
110 	virtual unsigned char* GetInfoMap(const std::string& name, MapBitmapInfo* bm) = 0;
111 	virtual void FreeInfoMap(const std::string& name, unsigned char* data) = 0;
112 
113 	/// Determine visibility for a rectangular grid
114 	struct IQuadDrawer
115 	{
~IQuadDrawerIQuadDrawer116 		virtual ~IQuadDrawer() {}
117 		virtual void DrawQuad (int x,int y) = 0;
118 	};
119 	virtual void GridVisibility(CCamera* cam, int quadSize, float maxdist, IQuadDrawer* cb, int extraSize = 0) = 0;
120 
121 
122 	/// synced only
GetOriginalHeightMapSynced()123 	const float* GetOriginalHeightMapSynced() const { return &originalHeightMap[0]; }
GetCenterHeightMapSynced()124 	const float* GetCenterHeightMapSynced() const { return &centerHeightMap[0]; }
GetMIPHeightMapSynced(unsigned int mip)125 	const float* GetMIPHeightMapSynced(unsigned int mip) const { return mipPointerHeightMaps[mip]; }
GetSlopeMapSynced()126 	const float* GetSlopeMapSynced() const { return &slopeMap[0]; }
GetTypeMapSynced()127 	const unsigned char* GetTypeMapSynced() const { return &typeMap[0]; }
GetTypeMapSynced()128 	      unsigned char* GetTypeMapSynced()       { return &typeMap[0]; }
129 
130 	/// unsynced only
GetVisVertexNormalsUnsynced()131 	const float3* GetVisVertexNormalsUnsynced() const { return &visVertexNormals[0]; }
132 
133 	/// synced versions
GetCornerHeightMapSynced()134 	const float* GetCornerHeightMapSynced() const { return sharedCornerHeightMaps[true]; }
GetFaceNormalsSynced()135 	const float3* GetFaceNormalsSynced()    const { return sharedFaceNormals[true]; }
GetCenterNormalsSynced()136 	const float3* GetCenterNormalsSynced()  const { return sharedCenterNormals[true]; }
137 	/// unsynced versions
GetCornerHeightMapUnsynced()138 	const float* GetCornerHeightMapUnsynced() const { return sharedCornerHeightMaps[false]; }
GetFaceNormalsUnsynced()139 	const float3* GetFaceNormalsUnsynced()    const { return sharedFaceNormals[false]; }
GetCenterNormalsUnsynced()140 	const float3* GetCenterNormalsUnsynced()  const { return sharedCenterNormals[false]; }
141 
142 
143 	/// shared interface
GetSharedCornerHeightMap(bool synced)144 	const float* GetSharedCornerHeightMap(bool synced) const { return sharedCornerHeightMaps[synced]; }
GetSharedCenterHeightMap(bool synced)145 	const float* GetSharedCenterHeightMap(bool synced) const { return sharedCenterHeightMaps[synced]; }
GetSharedFaceNormals(bool synced)146 	const float3* GetSharedFaceNormals(bool synced) const { return sharedFaceNormals[synced]; }
GetSharedCenterNormals(bool synced)147 	const float3* GetSharedCenterNormals(bool synced) const { return sharedCenterNormals[synced]; }
GetSharedSlopeMap(bool synced)148 	const float* GetSharedSlopeMap(bool synced) const { return sharedSlopeMaps[synced]; }
149 
150 	/// if you modify the heightmap through these, call UpdateHeightMapSynced
151 	float SetHeight(const int idx, const float h, const int add = 0);
152 	float AddHeight(const int idx, const float a);
153 
154 
GetInitMinHeight()155 	float GetInitMinHeight() const { return initMinHeight; }
GetCurrMinHeight()156 	float GetCurrMinHeight() const { return currMinHeight; }
GetInitMaxHeight()157 	float GetInitMaxHeight() const { return initMaxHeight; }
GetCurrMaxHeight()158 	float GetCurrMaxHeight() const { return currMaxHeight; }
159 
IsUnderWater()160 	bool IsUnderWater() const { return (currMaxHeight <  0.0f); }
IsAboveWater()161 	bool IsAboveWater() const { return (currMinHeight >= 0.0f); }
162 
163 	bool HasVisibleWater() const;
164 	bool HasOnlyVoidWater() const;
165 
GetMapChecksum()166 	unsigned int GetMapChecksum() const { return mapChecksum; }
167 
168 private:
169 	void UpdateCenterHeightmap(const SRectangle& rect, bool initialize);
170 	void UpdateMipHeightmaps(const SRectangle& rect, bool initialize);
171 	void UpdateFaceNormals(const SRectangle& rect, bool initialize);
172 	void UpdateSlopemap(const SRectangle& rect, bool initialize);
173 
174 	inline void HeightMapUpdateLOSCheck(const SRectangle& rect);
175 	inline bool HasHeightMapChanged(const int lmx, const int lmy);
176 	inline void InitHeightMapDigestsVectors();
177 
178 public:
179 	/// number of heightmap mipmaps, including full resolution
180 	static const int numHeightMipMaps = 7;
181 
182 	/// Metal-density/height-map
183 	CMetalMap* metalMap;
184 
185 protected:
186 	// these point to the actual heightmap data
187 	// which is allocated by subclass instances
188 	std::vector<float>* heightMapSyncedPtr;      //< size: (mapx+1)*(mapy+1) (per vertex) [SYNCED, updates on terrain deformation]
189 	std::vector<float>* heightMapUnsyncedPtr;    //< size: (mapx+1)*(mapy+1) (per vertex) [UNSYNCED]
190 
191 	std::vector<float> originalHeightMap;        //< size: (mapx+1)*(mapy+1) (per vertex) [SYNCED, does NOT update on terrain deformation]
192 	std::vector<float> centerHeightMap;          //< size: (mapx  )*(mapy  ) (per face) [SYNCED, updates on terrain deformation]
193 	std::vector< std::vector<float> > mipCenterHeightMaps;
194 
195 	/**
196 	 * array of pointers to heightmaps in different resolutions,
197 	 * mipPointerHeightMaps[0  ] is full resolution (centerHeightMap),
198 	 * mipPointerHeightMaps[n+1] is half resolution of mipPointerHeightMaps[n] (mipCenterHeightMaps[n - 1])
199 	 */
200 	std::vector< float* > mipPointerHeightMaps;
201 
202 	std::vector<float3> visVertexNormals;      //< size:  (mapx + 1) * (mapy + 1), contains one vertex normal per corner-heightmap pixel [UNSYNCED]
203 	std::vector<float3> faceNormalsSynced;     //< size: 2*mapx      *  mapy     , contains 2 normals per quad -> triangle strip [SYNCED]
204 	std::vector<float3> faceNormalsUnsynced;   //< size: 2*mapx      *  mapy     , contains 2 normals per quad -> triangle strip [UNSYNCED]
205 	std::vector<float3> centerNormalsSynced;   //< size:   mapx      *  mapy     , contains 1 interpolated normal per quad, same as (facenormal0+facenormal1).Normalize()) [SYNCED]
206 	std::vector<float3> centerNormalsUnsynced;
207 
208 	std::vector<float> slopeMap;               //< size: (mapx/2)    * (mapy/2)  , same as 1.0 - interpolate(centernomal[i]).y [SYNCED]
209 	std::vector<unsigned char> typeMap;
210 
211 	CRectangleOptimizer unsyncedHeightMapUpdates;
212 	CRectangleOptimizer unsyncedHeightMapUpdatesTemp;
213 
214 private:
215 	// these combine the various synced and unsynced arrays
216 	// for branch-less access: [0] = !synced, [1] = synced
217 	const float* sharedCornerHeightMaps[2];
218 	const float* sharedCenterHeightMaps[2];
219 	const float3* sharedFaceNormals[2];
220 	const float3* sharedCenterNormals[2];
221 	const float* sharedSlopeMaps[2];
222 
223 #ifdef USE_UNSYNCED_HEIGHTMAP
224 	/// used to filer LOS updates (so only update UHM on LOS updates when the heightmap was changed beforehand)
225 	/// size: in LOS resolution
226 	std::vector<unsigned char>   syncedHeightMapDigests;
227 	std::vector<unsigned char> unsyncedHeightMapDigests;
228 #endif
229 
230 	unsigned int mapChecksum;
231 
232 	float initMinHeight, initMaxHeight; //< initial minimum- and maximum-height (before any deformations)
233 	float currMinHeight, currMaxHeight; //< current minimum- and maximum-height
234 };
235 
236 extern CReadMap* readMap;
237 
238 
239 
SetHeight(const int idx,const float h,const int add)240 inline float CReadMap::SetHeight(const int idx, const float h, const int add) {
241 	float& x = (*heightMapSyncedPtr)[idx];
242 
243 	// add=0 <--> x = x*0 + h =   h
244 	// add=1 <--> x = x*1 + h = x+h
245 	x = x * add + h;
246 
247 	currMinHeight = std::min(x, currMinHeight);
248 	currMaxHeight = std::max(x, currMaxHeight);
249 
250 	return x;
251 }
252 
AddHeight(const int idx,const float a)253 inline float CReadMap::AddHeight(const int idx, const float a) {
254 	return SetHeight(idx, a, 1);
255 }
256 
257 
258 
259 
260 
261 /// Converts a map-square into a float3-position.
SquareToFloat3(int xSquare,int zSquare)262 inline float3 SquareToFloat3(int xSquare, int zSquare) {
263 	const float* hm = readMap->GetCenterHeightMapSynced();
264 	const float h = hm[(zSquare * gs->mapx) + xSquare];
265 	return float3(xSquare * SQUARE_SIZE, h, zSquare * SQUARE_SIZE);
266 }
267 
268 /// TODO: use in SM3 renderer also
GetVisibleVertexHeight(int idx)269 inline float GetVisibleVertexHeight(int idx) {
270 	const float* hm = readMap->GetCornerHeightMapUnsynced();
271 	return hm[idx];
272 }
273 
274 
275 #endif /* READ_MAP_H */
276