summaryrefslogtreecommitdiffstats
path: root/src/Generating/HeiGen.h
blob: d40c052c56afd6b1ed01ff4d5a034de0b874078b (plain) (blame)
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

// HeiGen.h

/*
Interfaces to the various height-based terrain shape generators:
	- cHeiGenFlat
	- cHeiGenClassic
	- cHeiGenBiomal

Also implements the heightmap cache
*/





#pragma once

#include "ComposableGenerator.h"
#include "../Noise/Noise.h"





/** A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation */
class cHeiGenCache : public cTerrainHeightGen
{
  public:
	cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, size_t a_CacheSize);

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;

	/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
	bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);

  protected:
	struct sCacheData
	{
		cChunkCoords m_Coords;
		cChunkDef::HeightMap m_HeightMap;

		/** Default constructor: Fill in bogus coords, so that the item is not used until properly calculated. */
		sCacheData() :
			m_Coords(0x7fffffff, 0x7fffffff)
		{
		}
	};

	/** The terrain height generator that is being cached. */
	cTerrainHeightGen & m_HeiGenToCache;

	// To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
	size_t m_CacheSize;
	std::vector<size_t> m_CacheOrder;  // MRU-ized order, indices into m_CacheData array
	std::vector<sCacheData> m_CacheData;  // m_CacheData[m_CacheOrder[0]] is the most recently used

	// Cache statistics
	size_t m_NumHits;
	size_t m_NumMisses;
	size_t m_TotalChain;  // Number of cache items walked to get to a hit (only added for hits)
};





/** Caches heightmaps in multiple underlying caches to improve the distribution and lower the chain length. */
class cHeiGenMultiCache : public cTerrainHeightGen
{
  public:
	cHeiGenMultiCache(
		std::unique_ptr<cTerrainHeightGen> a_HeightGenToCache,
		size_t a_SubCacheSize,
		size_t a_NumSubCaches
	);

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;

	/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
	bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);

  protected:
	/** The coefficient used to turn Z coords into index (x + Coeff * z). */
	static const size_t m_CoeffZ = 5;

	/** Number of sub-caches, pulled out of m_SubCaches.size() for performance reasons. */
	size_t m_NumSubCaches;

	/** The individual sub-caches. */
	std::vector<std::unique_ptr<cHeiGenCache>> m_SubCaches;

	/** The underlying height generator. */
	std::unique_ptr<cTerrainHeightGen> m_Underlying;
};





class cHeiGenFlat : public cTerrainHeightGen
{
  public:
	cHeiGenFlat(void) :
		m_Height(5)
	{
	}

  protected:
	HEIGHTTYPE m_Height;

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual void InitializeHeightGen(cIniFile & a_IniFile) override;
};





class cHeiGenClassic : public cTerrainHeightGen
{
  public:
	cHeiGenClassic(int a_Seed);

  protected:
	int m_Seed;
	cNoise m_Noise;
	float m_HeightFreq1, m_HeightAmp1;
	float m_HeightFreq2, m_HeightAmp2;
	float m_HeightFreq3, m_HeightAmp3;

	float GetNoise(float x, float y);

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual void InitializeHeightGen(cIniFile & a_IniFile) override;
};





class cHeiGenMountains : public cTerrainHeightGen
{
  public:
	cHeiGenMountains(int a_Seed);

  protected:
	int m_Seed;
	cRidgedMultiNoise m_MountainNoise;
	cRidgedMultiNoise m_DitchNoise;
	cPerlinNoise m_Perlin;

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual void InitializeHeightGen(cIniFile & a_IniFile) override;
};





class cHeiGenBiomal : public cTerrainHeightGen
{
	using Super = cTerrainHeightGen;

  public:
	cHeiGenBiomal(int a_Seed, cBiomeGen & a_BiomeGen) :
		m_Noise(a_Seed), m_BiomeGen(a_BiomeGen)
	{
	}

	// cTerrainHeightGen overrides:
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override;
	virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ)
		override  // Need to provide this override due to clang's overzealous detection of overloaded virtuals
	{
		return Super::GetHeightAt(a_BlockX, a_BlockZ);
	}
	virtual void InitializeHeightGen(cIniFile & a_IniFile) override;

  protected:
	typedef cChunkDef::BiomeMap BiomeNeighbors[3][3];

	cNoise m_Noise;
	cBiomeGen & m_BiomeGen;

	// Per-biome terrain generator parameters:
	struct sGenParam
	{
		float m_HeightFreq1, m_HeightAmp1;
		float m_HeightFreq2, m_HeightAmp2;
		float m_HeightFreq3, m_HeightAmp3;
		float m_BaseHeight;
	};
	static const sGenParam m_GenParam[256];


	NOISE_DATATYPE GetHeightAt(
		int a_RelX,
		int a_RelZ,
		int a_ChunkX,
		int a_ChunkZ,
		const BiomeNeighbors & a_BiomeNeighbors
	);
};