HydroTile.h
1 #pragma once
2 
3 #include "VoxelLayer.h"
4 #include "TileSet.h"
5 #include "Biome.h"
6 #include "ExternalMutex.h"
7 #include <map>
8 #include <set>
9 #include <vector>
10 
11 namespace VoxelFarm
12 {
14  {
15  public:
16  virtual void getHeights(double xo, double zo, double xsize, double zsize, double* heights, bool* ocean, int size, int pageX, int pageZ, int pageSize) = 0;
17  };
18 
20  class CHydroTile
21  {
22  public:
23  CHydroTile(
25  int size,
27  int pageSize,
29  IHydroHeightmapPage* heightmap,
31  double xo, double zo,
33  double xsize, double zsize,
35  double seaLevel,
37  double springLevel
38  );
39  ~CHydroTile();
40  public:
42  void generate(CellId masterCell);
43  public:
44  int size;
45  IHydroHeightmapPage* heightmap;
46  double xo;
47  double zo;
48  double xsize;
49  double zsize;
50  double seaLevel;
51  double springLevel;
52  unsigned char* data;
53  double* waterHeight;
54  bool* riverMap;
55  bool* lakeMap;
56  public:
57  double* heights;
58  bool* oceanMap;
61  double getHeight(int x, int z)
62  {
63  int pageX = x/pageScale;
64  int pageZ = z/pageScale;
65  bool& pageLoaded = pageIndex[pageZ*pageIndexSize + pageX];
66  if (!pageLoaded)
67  {
68  heightmap->getHeights(xo, zo, xsize, zsize, heights, oceanMap, size, pageX*pageScale, pageZ*pageScale, pageSize);
69  pageLoaded = true;
70  }
71  double height = heights[z*size + x];
72  return height;
73  };
75  bool isOcean(int x, int z)
76  {
77  int pageX = x/pageScale;
78  int pageZ = z/pageScale;
79  bool& pageLoaded = pageIndex[pageZ*pageIndexSize + pageX];
80  if (!pageLoaded)
81  {
82  heightmap->getHeights(xo, zo, xsize, zsize, heights, oceanMap, size, pageX*pageScale, pageZ*pageScale, pageSize);
83  pageLoaded = true;
84  }
85  bool ocean = oceanMap[z*size + x];
86  return ocean;
87  }
88  static inline double biLinearInterpolate(double p[2][2], double x, double y)
89  {
90  double h0 = p[0][0] + x*(p[1][0] - p[0][0]);
91  double h1 = p[0][1] + x*(p[1][1] - p[0][1]);
92  return h0 + y*(h1 - h0);
93  }
95  inline double getWaterHeight(double x, double z, int pageXc, int pageZc, double pageSize)
96  {
97  double tileXd = (x - pageXc*pageSize)*this->size/pageSize;
98  double tileZd = (z - pageZc*pageSize)*this->size/pageSize;
99  int tileX = (int)tileXd;
100  int tileZ = (int)tileZd;
101  if (tileX < 0 || tileX >= this->size || tileZ < 0 || tileZ >= this->size)
102  {
103  return 0.0;
104  }
105 
106  int tileIdx = tileZ*this->size + tileX;
107  double waterHeight = this->waterHeight[tileIdx];
108 
109  bool hasValue = waterHeight > 0.0;
110  double k[2][2];
111  for (int iTileZ = 0; iTileZ < 2; iTileZ++)
112  for (int iTileX = 0; iTileX < 2; iTileX++)
113  {
114  if (tileX + iTileX < 0 || tileX + iTileX >= this->size ||
115  tileZ + iTileZ < 0 || tileZ + iTileZ >= this->size)
116  {
117  k[iTileX][iTileZ] = waterHeight;
118  }
119  else
120  {
121  int idx = (tileZ + iTileZ)*this->size + tileX + iTileX;
122  double h = this->waterHeight[idx];
123  k[iTileX][iTileZ] = h;
124  hasValue |= (h > 0.0);
125  }
126  }
127 
128  if (!hasValue)
129  {
130  return 0.0;
131  }
132 
133  waterHeight = biLinearInterpolate(k, tileXd - tileX, tileZd - tileZ);
134  return waterHeight;
135  }
136  inline double getRiverDensity(double x, double z, int pageXc, int pageZc, double pageSize)
137  {
138  double tileXd = (x - pageXc*pageSize)*this->size/pageSize;
139  double tileZd = (z - pageZc*pageSize)*this->size/pageSize;
140  int tileX = (int)tileXd;
141  int tileZ = (int)tileZd;
142  if (tileX < 0 || tileX >= this->size || tileZ < 0 || tileZ >= this->size)
143  {
144  return 0.0;
145  }
146 
147  int tileIdx = tileZ*this->size + tileX;
148  double waterHeight = (this->riverMap[tileIdx])? 1.0 : 0;
149 
150  double k[2][2];
151  for (int iTileZ = 0; iTileZ < 2; iTileZ++)
152  for (int iTileX = 0; iTileX < 2; iTileX++)
153  {
154  if (tileX + iTileX < 0 || tileX + iTileX >= this->size ||
155  tileZ + iTileZ < 0 || tileZ + iTileZ >= this->size)
156  {
157  k[iTileX][iTileZ] = waterHeight;
158  }
159  else
160  {
161  int idx = (tileZ + iTileZ)*this->size + tileX + iTileX;
162  k[iTileX][iTileZ] = (this->riverMap[idx])? 1.0 : 0;
163  }
164  }
165 
166  waterHeight = biLinearInterpolate(k, tileXd - tileX, tileZd - tileZ);
167  return waterHeight;
168  }
169  public:
170  bool* pageIndex;
171  int pageSize;
172  int pageIndexSize;
173  int pageScale;
175  bool& getPage(int x, int z)
176  {
177  x /= pageScale;
178  z /= pageScale;
179  return pageIndex[z*pageIndexSize + x];
180  }
181  };
182 
183  // This is an implementation of IHydroHeightmapPage that reads heights from a CHeightmap object
185  {
186  public:
187  CHeightmapTerrainPage(CHeightmap* heightmap);
188  public:
189  CHeightmap* heightmap;
190  virtual void getHeights(double xo, double zo, double xsize, double zsize, double* heights, bool* ocean, int size, int pageX, int pageZ, int pageSize);
191  };
192 
193  // This is an implementation of IHydroHeightmapPage that reads heights from a CSimplexWorld object
195  {
196  public:
198  public:
199  CSimplexWorld* simplexWorld;
200  virtual void getHeights(double xo, double zo, double xsize, double zsize, double* heights, bool* ocean, int size, int pageX, int pageZ, int pageSize);
201  };
202 
203  // This implements a voxel layer for the water bodies
204  class CHeightmapWaterLayer : public IVoxelLayer, public IMask
205  {
206  public:
207  // Each hydro tile will cover one TILE_LOD cell
208  static const int TILE_LOD = 14;
209  // Resolution for each tile
210  static const int TILE_SIZE = 512;
211  // Page size within tile. The hydro system only request data for the pages that are likely to be
212  // involved in the simulation. The system will request pages of PAGE_SIZExPAGE_SIZE elements.
213  static const int PAGE_SIZE = 32;
214  public:
215  CHeightmapWaterLayer(IHydroHeightmapPage* heightmap, MaterialId waterMaterial, double seaLevel, double springLevel);
216  virtual ~CHeightmapWaterLayer();
217  public:
218  IHydroHeightmapPage* heightmap;
219  TMap<CellId, CHydroTile*> pages;
221  TSet<CellId> pendingCells;
222  TVector<CellId> pendingQueue;
223  MaterialId waterMaterial;
224  double seaLevel;
225  double springLevel;
226  public:
227  CHydroTile* getTile(CellId cell);
228  CHydroTile* getTile(int level, int xc, int yc, int zc);
229  public:
231  virtual void getContourData(
233  CellId cell,
235  ContourVoxelData* data,
237  bool& empty,
238  void* threadContext) override;
240  virtual void planJobs(Scene* scene) override;
242  virtual void runJobs() override;
243  virtual int getStatsContourId() override
244  {
245  return STAT_WATER;
246  }
247  public:
248  // IMask
249  virtual double getMaskValue(
251  double x,
253  double y,
255  double z);
256  };
257 
258  class IOceanMap
259  {
260  public:
261  virtual void getOceanHeight(CellId cell, double* heights, int size, bool& empty, bool& full) = 0;
262  };
263 
264  class COceanLayer : public IVoxelLayer
265  {
266  public:
267  static const int OCEAN_PAGE_SIZE = BLOCK_SIZE;
268  COceanLayer(IOceanMap* oceanMap, MaterialId waterMaterial);
269  public:
270  IOceanMap* oceanMap;
271  MaterialId waterMaterial;
272  public:
274  virtual void getContourData(
276  CellId cell,
278  ContourVoxelData* data,
280  bool& empty,
281  void* threadContext) override;
282  virtual int getStatsContourId() override
283  {
284  return STAT_WATER;
285  }
286  virtual void* createThreadContext();
287  virtual void disposeThreadContext(void* threadContext);
288  public:
290  {
291  double* heights;
292  };
293  };
294 
297  {
298  public:
299  virtual void getExtents(
300  // extents in world coordinates
301  double& x0, double& z0, double& x1, double& z1,
302  // heightmap extents
303  int& xsize, int& zsize,
304  // sea level
305  double& seaLevel) = 0;
306  };
307 
310  {
311  public:
312  virtual void getExtents(
313  // extents in world coordinates
314  double& x0, double& z0, double& x1, double& z1,
315  // heightmap extents
316  int& size,
317  // sea level
318  double& seaLevel,
319  // sea level
320  double& springLevel) = 0;
321  };
322 
323 
327  void computeOceanHeightmap(IOceanDataExtents* source, int margin, bool* oceanMask, unsigned short* heights);
328 
331  void computeOceanMask(IOceanDataExtents* source, double* heights, bool* mask);
332 
335  void computeStaticWater(IStaticWaterDataExtents* source, bool* oceanMask, IHydroHeightmapPage* heightmap, double* heights, bool* lakeMask);
336 
338  {
339  public:
340  virtual void getWaterHeight(CellId cell, double* heights, int size, bool& empty, bool& full) = 0;
341  };
342 
343  // This implements a voxel layer for the static water bodies like lakes.
345  {
346  public:
347  static const int WATER_PAGE_SIZE = BLOCK_SIZE;
348  CStaticWaterLayer(IStaticWaterMap* waterMap, MaterialId waterMaterial);
349  public:
350  IStaticWaterMap* waterMap;
351  MaterialId waterMaterial;
352  public:
354  virtual void getContourData(
356  CellId cell,
358  ContourVoxelData* data,
360  bool& empty,
361  void* threadContext) override;
362  virtual int getStatsContourId() override
363  {
364  return STAT_WATER;
365  }
366  virtual void* createThreadContext();
367  virtual void disposeThreadContext(void* threadContext);
368  public:
370  {
371  double* heights;
372  };
373  };
374 
375 }
void computeStaticWater(IStaticWaterDataExtents *source, bool *oceanMask, IHydroHeightmapPage *heightmap, double *heights, bool *lakeMask)
CHydroTile(int size, int pageSize, IHydroHeightmapPage *heightmap, double xo, double zo, double xsize, double zsize, double seaLevel, double springLevel)
virtual void runJobs() override
Processes pending generation requests. This is called by the contouring loop. Pending cells will be g...
virtual void disposeThreadContext(void *threadContext)
Destroys the specified thread context.
Contains all classes and functions for the VoxelFarm engine.
virtual void getContourData(CellId cell, ContourVoxelData *data, bool &empty, void *threadContext) override
Returns voxel data for the specified cell (IVoxelLayer)
An interface for a 3D mask. A mask can be used to control the application of other features...
Definition: VoxelLayer.h:581
const int BLOCK_SIZE
Actual number of voxels in one Cell Dim once the margin is considered.
Definition: VoxelLayer.h:38
void computeOceanMask(IOceanDataExtents *source, double *heights, bool *mask)
double getWaterHeight(double x, double z, int pageXc, int pageZc, double pageSize)
Returns the water level in any point inside the tile.
Definition: HydroTile.h:95
virtual void * createThreadContext()
The voxel layer can use this method to return a structure that will be unique for each calling thread...
This class is used to request the ocean mask for a given area (in world coordinates) ...
Definition: HydroTile.h:296
unsigned __int64 CellId
A 64bit integer that identifies a single world octree Cell.
Definition: mapindex.h:23
Cells Scene
A Scene is a set of cells.
Definition: scene.h:12
virtual void planJobs(Scene *scene) override
Processes a scene to get new entities from it. This is called by the scene creation loop...
An interface for a voxel layer. By implementing this interface, very different modules can contribute...
Definition: VoxelLayer.h:535
virtual void * createThreadContext()
The voxel layer can use this method to return a structure that will be unique for each calling thread...
virtual void disposeThreadContext(void *threadContext)
Destroys the specified thread context.
This class is used to request the static water mask for a given area (in world coordinates) ...
Definition: HydroTile.h:309
It generates the water information for an area.
Definition: HydroTile.h:20
virtual double getMaskValue(double x, double y, double z)
Returns the mask strength value for the specified 3D point. The value must be between 0 and 1...
virtual void getContourData(CellId cell, ContourVoxelData *data, bool &empty, void *threadContext) override
Returns voxel data for the specified cell (IVoxelLayer)
Defines the world elevation at any XZ point. Contains a collection of biomes.
Definition: Biome.h:254
bool & getPage(int x, int z)
Calculates the page index for a given cell coordinates.
Definition: HydroTile.h:175
bool isOcean(int x, int z)
Returns if a cell in the tile is in the ocean.
Definition: HydroTile.h:75
virtual int getStatsContourId() override
Returns the stats ID to be used for measuring performance of the getContourData() method...
Definition: HydroTile.h:362
virtual int getStatsContourId() override
Returns the stats ID to be used for measuring performance of the getContourData() method...
Definition: HydroTile.h:282
virtual int getStatsContourId() override
Returns the stats ID to be used for measuring performance of the getContourData() method...
Definition: HydroTile.h:243
double getHeight(int x, int z)
Definition: HydroTile.h:61
virtual void getContourData(CellId cell, ContourVoxelData *data, bool &empty, void *threadContext) override
Returns voxel data for the specified cell (IVoxelLayer)
void generate(CellId masterCell)
Generates the water information for the tile.
void computeOceanHeightmap(IOceanDataExtents *source, int margin, bool *oceanMask, unsigned short *heights)