File: ReadMap.h

package info (click to toggle)
spring 88.0%2Bdfsg1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 41,524 kB
  • sloc: cpp: 343,114; ansic: 38,414; python: 12,257; java: 12,203; awk: 5,748; sh: 1,204; xml: 997; perl: 405; objc: 192; makefile: 181; php: 134; sed: 2
file content (299 lines) | stat: -rwxr-xr-x 10,437 bytes parent folder | download
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef READ_MAP_H
#define READ_MAP_H

#include <list>

#include "System/creg/creg_cond.h"
#include "System/float3.h"
#include "Sim/Misc/GlobalConstants.h"
#include "Sim/Misc/GlobalSynced.h"

#define USE_UNSYNCED_HEIGHTMAP

class CMetalMap;
class CCamera;
class CFileHandler;
class CUnit;
class CSolidObject;
class CFileHandler;
class CLoadSaveInterface;
class CBaseGroundDrawer;


struct MapFeatureInfo
{
	float3 pos;
	/// index to one of the strings above
	int featureType;
	float rotation;
};


struct MapBitmapInfo
{
	MapBitmapInfo() : width(0), height(0) {}
	MapBitmapInfo(int w, int h) : width(w), height(h) {}

	int width;
	int height;
};

struct HeightMapUpdate {
	HeightMapUpdate(int tlx, int brx,  int tly, int bry, bool inLOS = false): x1(tlx), x2(brx), y1(tly), y2(bry), los(inLOS) {
	}

	int x1, x2;
	int y1, y2;
	bool los;
};


class CReadMap
{
protected:
	CReadMap();

	/// called by implementations of CReadMap
	void Initialize();
	void CalcHeightmapChecksum();

	virtual void UpdateHeightMapUnsynced(const HeightMapUpdate&) = 0;

public:
	CR_DECLARE(CReadMap);

	static CReadMap* LoadMap(const std::string& mapname);
	static inline unsigned char EncodeHeight(const float h) {
		return std::max(0, 255 + int(10.0f * h));
	}

	/// creg serialize callback
	void Serialize(creg::ISerializer& s);


	/**
	 * calculates derived heightmap information
	 * such as normals, centerheightmap and slopemap
	 */
	void UpdateHeightMapSynced(int x1, int z1, int x2, int z2);
	void PushVisibleHeightMapUpdate(int x1, int z1, int x2, int z2, bool);
	void UpdateDraw();

	virtual ~CReadMap();

	virtual void Update() {}
	virtual void UpdateShadingTexture() {}

	virtual void NewGroundDrawer() = 0;
	virtual CBaseGroundDrawer* GetGroundDrawer() { return 0; }

	virtual unsigned int GetGrassShadingTexture() const { return 0; }
	/**
	 * a texture with RGB for shading and A for height
	 * (0 := above water; 1-255 := under water = 255+height*10)
	 */
	virtual unsigned int GetShadingTexture() const = 0;

	/// Draws the minimap in a quad (with extends: (0,0)-(1,1))
	virtual void DrawMinimap() const = 0;

	/// Feature creation
	virtual int GetNumFeatures() = 0;
	virtual int GetNumFeatureTypes() = 0;
	/// Returns MapFeatureInfo[GetNumFeatures()]
	virtual void GetFeatureInfo(MapFeatureInfo* f) = 0;
	virtual const char* GetFeatureTypeName(int typeID) = 0;

	/**
	 * Infomaps (such as metal map, grass map, ...),
	 * handling them with a string as type seems flexible...
	 * Some map types:
	 *   "metal"  -  metalmap
	 *   "grass"  -  grassmap
	 */
	virtual unsigned char* GetInfoMap(const std::string& name, MapBitmapInfo* bm) = 0;
	virtual void FreeInfoMap(const std::string& name, unsigned char* data) = 0;

	/// Determine visibility for a rectangular grid
	struct IQuadDrawer
	{
		virtual ~IQuadDrawer() {}
		virtual void DrawQuad (int x,int y) = 0;
	};
	virtual void GridVisibility(CCamera* cam, int quadSize, float maxdist, IQuadDrawer* cb, int extraSize = 0) = 0;


	/// synced only
	const float* GetOriginalHeightMapSynced() const { return &originalHeightMap[0]; }
	const float* GetCenterHeightMapSynced() const { return &centerHeightMap[0]; }
	const float* GetMIPHeightMapSynced(unsigned int mip) const { return mipPointerHeightMaps[mip]; }
	const float* GetSlopeMapSynced() const { return &slopeMap[0]; }
	const unsigned char* GetTypeMapSynced() const { return &typeMap[0]; }
	      unsigned char* GetTypeMapSynced()       { return &typeMap[0]; }

	/// unsynced only
	const float3* GetVisVertexNormalsUnsynced() const { return &visVertexNormals[0]; }

	/// both
	/// synced versions
	const float* GetCornerHeightMapSynced() const { return &(*heightMapSynced)[0]; }
	const float3* GetFaceNormalsSynced()    const { return &faceNormalsSynced[0]; }
	const float3* GetCenterNormalsSynced()  const { return &centerNormalsSynced[0]; }
	/// unsynced versions
#ifdef USE_UNSYNCED_HEIGHTMAP
	const float* GetCornerHeightMapUnsynced() const { return &(*heightMapUnsynced)[0]; }
	const float3* GetFaceNormalsUnsynced()   const { return &faceNormalsUnsynced[0]; }
	const float3* GetCenterNormalsUnsynced() const { return &centerNormalsUnsynced[0]; }
#else
	const float* GetCornerHeightMapUnsynced() const { return GetCornerHeightMapSynced(); }
	const float3* GetFaceNormalsUnsynced()    const { return GetFaceNormalsSynced(); }
	const float3* GetCenterNormalsUnsynced()  const { return GetCenterNormalsSynced(); }
#endif

	// shared interface
	// Use when code is shared between synced & unsynced, in such cases these functions will have a better branch-prediciton behavior.
	static const float* GetCornerHeightMap(const bool& synced);
	static const float* GetCenterHeightMap(const bool& synced);
	static const float3* GetFaceNormals(const bool& synced);
	static const float3* GetCenterNormals(const bool& synced);
	static const float* GetSlopeMap(const bool& synced);

	/// if you modify the heightmap through these, call UpdateHeightMapSynced
	float SetHeight(const int& idx, const float& h);
	float AddHeight(const int& idx, const float& a);

public:
	/// number of heightmap mipmaps, including full resolution
	static const int numHeightMipMaps = 7;

	/// Metal-density/height-map
	CMetalMap* metalMap;

	int width, height;
	float initMinHeight, initMaxHeight; //! initial minimum- and maximum-height (before any deformations)
	float currMinHeight, currMaxHeight; //! current minimum- and maximum-height 

	unsigned int mapChecksum;

private:
	void UpdateCenterHeightmap(const int x1, const int z1, const int x2, const int z2);
	void UpdateMipHeightmaps(const int x1, const int z1, const int x2, const int z2);
	void UpdateFaceNormals(int x1, int z1, int x2, int z2);
	void UpdateSlopemap(const int x1, const int z1, const int x2, const int z2);

protected:
	std::vector<float>* heightMapSynced;      /// size: (mapx+1)*(mapy+1) (per vertex) [SYNCED, updates on terrain deformation]
	std::vector<float>* heightMapUnsynced;    /// size: (mapx+1)*(mapy+1) (per vertex) [UNSYNCED]
	std::vector<float> originalHeightMap;    /// size: (mapx+1)*(mapy+1) (per vertex) [SYNCED, does NOT update on terrain deformation]
	std::vector<float> centerHeightMap;      /// size: (mapx  )*(mapy  ) (per face) [SYNCED, updates on terrain deformation]
	std::vector< std::vector<float> > mipCenterHeightMaps;

	/**
	 * array of pointers to heightmaps in different resolutions,
	 * mipPointerHeightMaps[0  ] is full resolution (centerHeightMap),
	 * mipPointerHeightMaps[n+1] is half resolution of mipPointerHeightMaps[n] (mipCenterHeightMaps[n - 1])
	 */
	std::vector< float* > mipPointerHeightMaps;

	std::vector<float3> visVertexNormals;      /// size:  (mapx + 1) * (mapy + 1), contains one vertex normal per corner-heightmap pixel [UNSYNCED]
	std::vector<float3> faceNormalsSynced;     /// size: 2*mapx      *  mapy     , contains 2 normals per quad -> triangle strip [SYNCED]
	std::vector<float3> faceNormalsUnsynced;   /// size: 2*mapx      *  mapy     , contains 2 normals per quad -> triangle strip [UNSYNCED]
	std::vector<float3> centerNormalsSynced;   /// size:   mapx      *  mapy     , contains 1 interpolated normal per quad, same as (facenormal0+facenormal1).Normalize()) [SYNCED]
	std::vector<float3> centerNormalsUnsynced;

	std::vector<float> slopeMap;               /// size: (mapx/2)    * (mapy/2)  , same as 1.0 - interpolate(centernomal[i]).y [SYNCED]
	std::vector<unsigned char> typeMap;

	std::list<HeightMapUpdate> unsyncedHeightMapUpdates;

#ifdef USE_UNSYNCED_HEIGHTMAP
	struct HeightMapUpdateFilter {
		HeightMapUpdateFilter(bool upd = false) : minx(0), maxx(0), miny(0), maxy(0), update(upd) {}
		HeightMapUpdateFilter(int mnx, int mxx, int mny, int mxy, bool upd = false) : minx(mnx), maxx(mxx), miny(mny), maxy(mxy), update(upd) {}

		void Expand(const HeightMapUpdateFilter& fnew) {
			minx = std::min(minx, fnew.minx);
			maxx = std::max(maxx, fnew.maxx);
			miny = std::min(miny, fnew.miny);
			maxy = std::max(maxy, fnew.maxy);
			update = fnew.update;
		}

		int minx;
		int maxx;
		int miny;
		int maxy;
		bool update;
	};
#endif
};

extern CReadMap* readmap;



/**
 * Inlined functions
 */
inline const float* CReadMap::GetCornerHeightMap(const bool& synced) {
	// Note, this doesn't save a branch compared to `(synced) ? SHM : UHM`. Cause static vars always check if they were already initialized.
	//  But they are only initialized once, so this branch will always fail. And so branch-prediction will have easier going.
	assert(readmap && readmap->mapChecksum);
	return synced ? readmap->GetCornerHeightMapSynced() : readmap->GetCornerHeightMapUnsynced();
}
inline const float* CReadMap::GetCenterHeightMap(const bool& synced) {
	assert(readmap && readmap->mapChecksum);
	// TODO: add unsynced variant
	return synced ? readmap->GetCenterHeightMapSynced() : readmap->GetCenterHeightMapSynced();
}
inline const float3* CReadMap::GetFaceNormals(const bool& synced) {
	assert(readmap && readmap->mapChecksum);
	return synced ? readmap->GetFaceNormalsSynced() : readmap->GetFaceNormalsUnsynced();
}
inline const float3* CReadMap::GetCenterNormals(const bool& synced) {
	assert(readmap && readmap->mapChecksum);
	return synced ? readmap->GetCenterNormalsSynced() : readmap->GetCenterNormalsUnsynced();
}
inline const float* CReadMap::GetSlopeMap(const bool& synced) {
	assert(readmap && readmap->mapChecksum);
	// TODO: add unsynced variant (or add a LOS check foreach square access?)
	return synced ? readmap->GetSlopeMapSynced() : readmap->GetSlopeMapSynced();
}






/// if you modify the heightmap through these, call UpdateHeightMapSynced
inline float CReadMap::SetHeight(const int& idx, const float& h) {
	currMinHeight = std::min(h, currMinHeight);
	currMaxHeight = std::max(h, currMaxHeight);
	return ((*heightMapSynced)[idx] = h);
}

inline float CReadMap::AddHeight(const int& idx, const float& a) {
	return SetHeight(idx, (*heightMapSynced)[idx] + a);
}





/// Converts a map-square into a float3-position.
inline float3 SquareToFloat3(int xSquare, int zSquare) {
	const float* hm = readmap->GetCenterHeightMapSynced();
	const float& h = hm[(zSquare * gs->mapx) + xSquare];
	return float3(xSquare * SQUARE_SIZE, h, zSquare * SQUARE_SIZE);
}

/// TODO: use in SM3 renderer also
inline float GetVisibleVertexHeight(int idx) {
	const float* hm = readmap->GetCornerHeightMapUnsynced();
	return hm[idx];
}


#endif /* READ_MAP_H */