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 ¢erHeightMap[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