Cuberite
A lightweight, fast and extensible game server for Minecraft
Noise3DGenerator.cpp
Go to the documentation of this file.
1 
2 // Nosie3DGenerator.cpp
3 
4 // Generates terrain using 3D noise, rather than composing. Is a test.
5 
6 #include "Globals.h"
7 #include "Noise3DGenerator.h"
8 #include "../IniFile.h"
9 #include "../LinearInterpolation.h"
10 #include "../LinearUpscale.h"
11 
12 
13 
14 
15 
16 /*
17 // Perform an automatic test of upscaling upon program start (use breakpoints to debug):
18 
19 class Test
20 {
21 public:
22  Test(void)
23  {
24  DoTest1();
25  DoTest2();
26  }
27 
28 
29  void DoTest1(void)
30  {
31  float In[3 * 3 * 3];
32  for (size_t i = 0; i < ARRAYCOUNT(In); i++)
33  {
34  In[i] = (float)(i % 5);
35  }
36  Debug3DNoise(In, 3, 3, 3, "Upscale3D in");
37  float Out[17 * 33 * 35];
38  LinearUpscale3DArray(In, 3, 3, 3, Out, 8, 16, 17);
39  Debug3DNoise(Out, 17, 33, 35, "Upscale3D test");
40  }
41 
42 
43  void DoTest2(void)
44  {
45  float In[3 * 3];
46  for (size_t i = 0; i < ARRAYCOUNT(In); i++)
47  {
48  In[i] = (float)(i % 5);
49  }
50  Debug2DNoise(In, 3, 3, "Upscale2D in");
51  float Out[17 * 33];
52  LinearUpscale2DArray(In, 3, 3, Out, 8, 16);
53  Debug2DNoise(Out, 17, 33, "Upscale2D test");
54  }
55 
56 } gTest;
57 //*/
58 
59 
60 
61 
62 
63 #if 0
64 // Perform speed test of the cInterpolNoise class
65 static class cInterpolNoiseSpeedTest
66 {
67 public:
68  cInterpolNoiseSpeedTest(void)
69  {
70  TestSpeed2D();
71  TestSpeed3D();
72  printf("InterpolNoise speed comparison finished.\n");
73  }
74 
75 
77  void TestSpeed3D(void)
78  {
79  printf("Evaluating 3D noise performance...\n");
80  static const int SIZE_X = 128;
81  static const int SIZE_Y = 128;
82  static const int SIZE_Z = 128;
83  static const NOISE_DATATYPE MUL = 80;
84  std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
85  cTimer timer;
86 
87  // Test the cInterpolNoise:
88  cInterpolNoise<Interp5Deg> interpNoise(1);
89  long long start = timer.GetNowTime();
90  for (int i = 0; i < 30; i++)
91  {
92  interpNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL);
93  }
94  long long end = timer.GetNowTime();
95  printf("InterpolNoise took %.02f sec\n", static_cast<float>(end - start) / 1000);
96 
97  // Test the cCubicNoise:
98  cCubicNoise cubicNoise(1);
99  start = timer.GetNowTime();
100  for (int i = 0; i < 30; i++)
101  {
102  cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL);
103  }
104  end = timer.GetNowTime();
105  printf("CubicNoise took %.02f sec\n", static_cast<float>(end - start) / 1000);
106  printf("3D noise performance comparison finished.\n");
107  }
108 
109 
111  void TestSpeed2D(void)
112  {
113  printf("Evaluating 2D noise performance...\n");
114  static const int SIZE_X = 128;
115  static const int SIZE_Y = 128;
116  static const NOISE_DATATYPE MUL = 80;
117  std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y]);
118  cTimer timer;
119 
120  // Test the cInterpolNoise:
121  cInterpolNoise<Interp5Deg> interpNoise(1);
122  long long start = timer.GetNowTime();
123  for (int i = 0; i < 500; i++)
124  {
125  interpNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL);
126  }
127  long long end = timer.GetNowTime();
128  printf("InterpolNoise took %.02f sec\n", static_cast<float>(end - start) / 1000);
129 
130  // Test the cCubicNoise:
131  cCubicNoise cubicNoise(1);
132  start = timer.GetNowTime();
133  for (int i = 0; i < 500; i++)
134  {
135  cubicNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL);
136  }
137  end = timer.GetNowTime();
138  printf("CubicNoise took %.02f sec\n", static_cast<float>(end - start) / 1000);
139  printf("2D noise performance comparison finished.\n");
140  }
141 } g_InterpolNoiseSpeedTest;
142 #endif
143 
144 
145 
146 
147 
149 // cNoise3DGenerator:
150 
152  Super(),
153  m_Perlin(1000),
154  m_Cubic(1000)
155 {
156  m_Perlin.AddOctave(1, 1);
157  m_Perlin.AddOctave(2, 0.5);
158  m_Perlin.AddOctave(4, 0.25);
159  m_Perlin.AddOctave(8, 0.125);
160  m_Perlin.AddOctave(16, 0.0625);
161 
162  m_Cubic.AddOctave(1, 1);
163  m_Cubic.AddOctave(2, 0.5);
164  m_Cubic.AddOctave(4, 0.25);
165  m_Cubic.AddOctave(8, 0.125);
166  m_Cubic.AddOctave(16, 0.0625);
167 }
168 
169 
170 
171 
172 
174 {
175  // Nothing needed yet
176 }
177 
178 
179 
180 
181 
183 {
184  // Params:
185  m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62);
186  m_HeightAmplification = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.1));
187  m_MidPoint = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 68));
188  m_FrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 8));
189  m_FrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 8));
190  m_FrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 8));
191  m_AirThreshold = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0.5));
192 }
193 
194 
195 
196 
197 
199 {
200  UNUSED(a_ChunkCoords);
201  for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++)
202  {
203  a_BiomeMap[i] = biExtremeHills;
204  }
205 }
206 
207 
208 
209 
210 
212 {
213  NOISE_DATATYPE Noise[17 * 257 * 17];
214  GenerateNoiseArray(a_ChunkDesc.GetChunkCoords(), Noise);
215 
216  // Output noise into chunk:
217  for (int z = 0; z < cChunkDef::Width; z++)
218  {
219  for (int y = 0; y < cChunkDef::Height; y++)
220  {
221  int idx = z * 17 * 257 + y * 17;
222  for (int x = 0; x < cChunkDef::Width; x++)
223  {
224  NOISE_DATATYPE n = Noise[idx++];
226  if (n > m_AirThreshold)
227  {
229  }
230  else
231  {
233  }
234  a_ChunkDesc.SetBlockType(x, y, z, BlockType);
235  }
236  }
237  }
238 
239  a_ChunkDesc.UpdateHeightmap();
240  ComposeTerrain (a_ChunkDesc);
241 }
242 
243 
244 
245 
246 
248 {
249  NOISE_DATATYPE NoiseO[DIM_X * DIM_Y * DIM_Z]; // Output for the Perlin noise
250  NOISE_DATATYPE NoiseW[DIM_X * DIM_Y * DIM_Z]; // Workspace that the noise calculation can use and trash
251 
252  // Our noise array has different layout, XZY, instead of regular chunk's XYZ, that's why the coords are "renamed"
253  NOISE_DATATYPE StartX = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkX * cChunkDef::Width) / m_FrequencyX;
254  NOISE_DATATYPE EndX = static_cast<NOISE_DATATYPE>((a_ChunkCoords.m_ChunkX + 1) * cChunkDef::Width) / m_FrequencyX;
255  NOISE_DATATYPE StartZ = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkZ * cChunkDef::Width) / m_FrequencyZ;
256  NOISE_DATATYPE EndZ = static_cast<NOISE_DATATYPE>((a_ChunkCoords.m_ChunkZ + 1) * cChunkDef::Width) / m_FrequencyZ;
257  NOISE_DATATYPE StartY = 0;
258  NOISE_DATATYPE EndY = static_cast<NOISE_DATATYPE>(256) / m_FrequencyY;
259 
260  m_Perlin.Generate3D(NoiseO, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW);
261 
262  // Precalculate a "height" array:
263  NOISE_DATATYPE Height[DIM_X * DIM_Z]; // Output for the cubic noise heightmap ("source")
264  m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 5, EndX / 5, StartZ / 5, EndZ / 5);
265  for (size_t i = 0; i < ARRAYCOUNT(Height); i++)
266  {
267  Height[i] = Height[i] * m_HeightAmplification;
268  }
269 
270  // Modify the noise by height data:
271  for (int y = 0; y < DIM_Y; y++)
272  {
273  NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 30;
274  // AddHeight *= AddHeight * AddHeight;
275  for (int z = 0; z < DIM_Z; z++)
276  {
277  NOISE_DATATYPE * CurRow = &(NoiseO[y * DIM_X + z * DIM_X * DIM_Y]);
278  for (int x = 0; x < DIM_X; x++)
279  {
280  CurRow[x] += AddHeight + Height[x + DIM_X * z];
281  }
282  }
283  }
284 
285  // Upscale the Perlin noise into full-blown chunk dimensions:
287  NoiseO, DIM_X, DIM_Y, DIM_Z,
288  a_OutNoise, UPSCALE_X, UPSCALE_Y, UPSCALE_Z
289  );
290 }
291 
292 
293 
294 
295 
297 {
298  // Make basic terrain composition:
299  for (int z = 0; z < cChunkDef::Width; z++)
300  {
301  for (int x = 0; x < cChunkDef::Width; x++)
302  {
303  int LastAir = a_ChunkDesc.GetHeight(x, z) + 1;
304  bool HasHadWater = false;
305  for (int y = LastAir - 1; y > 0; y--)
306  {
307  switch (a_ChunkDesc.GetBlockType(x, y, z))
308  {
309  case E_BLOCK_AIR:
310  {
311  LastAir = y;
312  break;
313  }
314  case E_BLOCK_STONE:
315  {
316  if (LastAir - y > 3)
317  {
318  break;
319  }
320  if (HasHadWater)
321  {
322  a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND);
323  }
324  else
325  {
326  a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT);
327  }
328  break;
329  }
331  {
332  LastAir = y;
333  HasHadWater = true;
334  break;
335  }
336  } // switch (GetBlockType())
337  } // for y
338  a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK);
339  } // for x
340  } // for z
341 }
342 
343 
344 
345 
346 
348 // cNoise3DComposable:
349 
351  m_ChoiceNoise(a_Seed),
352  m_DensityNoiseA(a_Seed + 1),
353  m_DensityNoiseB(a_Seed + 2),
354  m_BaseNoise(a_Seed + 3),
355  m_HeightAmplification(0.0),
356  m_MidPoint(0.0),
357  m_FrequencyX(0.0),
358  m_FrequencyY(0.0),
359  m_FrequencyZ(0.0),
360  m_BaseFrequencyX(0.0),
361  m_BaseFrequencyZ(0.0),
362  m_ChoiceFrequencyX(0.0),
363  m_ChoiceFrequencyY(0.0),
364  m_ChoiceFrequencyZ(0.0),
365  m_AirThreshold(0.0),
366  m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Use dummy coords that won't ever be used by real chunks
367 {
368 }
369 
370 
371 
372 
373 
375 {
376  // Params:
377  // The defaults generate extreme hills terrain
378  m_HeightAmplification = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045));
379  m_MidPoint = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75));
380  m_FrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40));
381  m_FrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 40));
382  m_FrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 40));
383  m_BaseFrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyX", 40));
384  m_BaseFrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyZ", 40));
385  m_ChoiceFrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyX", 40));
386  m_ChoiceFrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyY", 80));
387  m_ChoiceFrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyZ", 40));
388  m_AirThreshold = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0));
389  int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumChoiceOctaves", 4);
390  int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumDensityOctaves", 6);
391  int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumBaseOctaves", 6);
392  NOISE_DATATYPE BaseNoiseAmplitude = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "Noise3DBaseAmplitude", 1));
393 
394  // Add octaves for the choice noise:
395  NOISE_DATATYPE wavlen = 1, ampl = 0.5;
396  for (int i = 0; i < NumChoiceOctaves; i++)
397  {
398  m_ChoiceNoise.AddOctave(wavlen, ampl);
399  wavlen = wavlen * 2;
400  ampl = ampl / 2;
401  }
402 
403  // Add octaves for the density noises:
404  wavlen = 1; ampl = 1;
405  for (int i = 0; i < NumDensityOctaves; i++)
406  {
407  m_DensityNoiseA.AddOctave(wavlen, ampl);
408  m_DensityNoiseB.AddOctave(wavlen, ampl);
409  wavlen = wavlen * 2;
410  ampl = ampl / 2;
411  }
412 
413  // Add octaves for the base noise:
414  wavlen = 1; ampl = BaseNoiseAmplitude;
415  for (int i = 0; i < NumBaseOctaves; i++)
416  {
417  m_BaseNoise.AddOctave(wavlen, ampl);
418  wavlen = wavlen * 2;
419  ampl = ampl / 2;
420  }
421 }
422 
423 
424 
425 
426 
428 {
429  if (a_ChunkCoords == m_LastChunkCoords)
430  {
431  // The noise for this chunk is already generated in m_NoiseArray
432  return;
433  }
434  m_LastChunkCoords = a_ChunkCoords;
435 
436  // Generate all the noises:
437  NOISE_DATATYPE ChoiceNoise[5 * 5 * 33];
438  NOISE_DATATYPE Workspace[5 * 5 * 33];
439  NOISE_DATATYPE DensityNoiseA[5 * 5 * 33];
440  NOISE_DATATYPE DensityNoiseB[5 * 5 * 33];
441  NOISE_DATATYPE BaseNoise[5 * 5];
442  NOISE_DATATYPE BlockX = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkX * cChunkDef::Width);
443  NOISE_DATATYPE BlockZ = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkZ * cChunkDef::Width);
444  // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x":
445  m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace);
446  m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
447  m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
448  m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
449 
450  // Calculate the final noise based on the partial noises:
451  for (int z = 0; z < 5; z++)
452  {
453  for (int x = 0; x < 5; x++)
454  {
455  NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z];
456  for (int y = 0; y < 33; y++)
457  {
458  NOISE_DATATYPE AddHeight = (static_cast<NOISE_DATATYPE>(y * 8) - m_MidPoint) * m_HeightAmplification;
459 
460  // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope:
461  if (AddHeight < 0)
462  {
463  AddHeight *= 4;
464  }
465 
466  // If too high, cut off any terrain:
467  if (y > 28)
468  {
469  AddHeight = AddHeight + static_cast<NOISE_DATATYPE>(y - 28) / 4;
470  }
471 
472  // Decide between the two density noises:
473  int idx = 33 * x + 33 * 5 * z + y;
474  Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise;
475  }
476  }
477  }
478  LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4);
479 }
480 
481 
482 
483 
484 
486 {
487  GenerateNoiseArrayIfNeeded(a_ChunkCoords);
488 
489  // Translate the noise array into Shape:
490  for (int z = 0; z < cChunkDef::Width; z++)
491  {
492  for (int x = 0; x < cChunkDef::Width; x++)
493  {
494  for (int y = 0; y < cChunkDef::Height; y++)
495  {
496  a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1;
497  }
498  } // for x
499  } // for z
500 }
501 
502 
503 
504 
505 
507 // cBiomalNoise3DComposable:
508 
510  m_ChoiceNoise(a_Seed),
511  m_DensityNoiseA(a_Seed + 1),
512  m_DensityNoiseB(a_Seed + 2),
513  m_BaseNoise(a_Seed + 3),
514  m_BiomeGen(a_BiomeGen),
515  m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Set impossible coords for the chunk so that it's always considered stale
516 {
517  // Generate the weight distribution for summing up neighboring biomes:
518  m_WeightSum = 0;
519  for (int z = 0; z <= AVERAGING_SIZE * 2; z++)
520  {
521  for (int x = 0; x <= AVERAGING_SIZE * 2; x++)
522  {
523  m_Weight[z][x] = static_cast<NOISE_DATATYPE>((AVERAGING_SIZE - std::abs(AVERAGING_SIZE - x)) + (AVERAGING_SIZE - std::abs(AVERAGING_SIZE - z)));
524  m_WeightSum += m_Weight[z][x];
525  }
526  }
527 }
528 
529 
530 
531 
532 
534 {
535  // Params:
536  // The defaults generate extreme hills terrain
537  m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62);
538  m_FrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40));
539  m_FrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40));
540  m_FrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40));
541  m_BaseFrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyX", 40));
542  m_BaseFrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyZ", 40));
543  m_ChoiceFrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyX", 40));
544  m_ChoiceFrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyY", 80));
545  m_ChoiceFrequencyZ = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyZ", 40));
546  m_AirThreshold = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DAirThreshold", 0));
547  int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumChoiceOctaves", 4);
548  int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumDensityOctaves", 6);
549  int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumBaseOctaves", 6);
550  NOISE_DATATYPE BaseNoiseAmplitude = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseAmplitude", 1));
551 
552  // Add octaves for the choice noise:
553  NOISE_DATATYPE wavlen = 1, ampl = 0.5;
554  for (int i = 0; i < NumChoiceOctaves; i++)
555  {
556  m_ChoiceNoise.AddOctave(wavlen, ampl);
557  wavlen = wavlen * 2;
558  ampl = ampl / 2;
559  }
560 
561  // Add octaves for the density noises:
562  wavlen = 1; ampl = 1;
563  for (int i = 0; i < NumDensityOctaves; i++)
564  {
565  m_DensityNoiseA.AddOctave(wavlen, ampl);
566  m_DensityNoiseB.AddOctave(wavlen, ampl);
567  wavlen = wavlen * 2;
568  ampl = ampl / 2;
569  }
570 
571  // Add octaves for the base noise:
572  wavlen = 1; ampl = BaseNoiseAmplitude;
573  for (int i = 0; i < NumBaseOctaves; i++)
574  {
575  m_BaseNoise.AddOctave(wavlen, ampl);
576  wavlen = wavlen * 2;
577  ampl = ampl / 2;
578  }
579 }
580 
581 
582 
583 
584 
586 {
587  if (a_ChunkCoords == m_LastChunkCoords)
588  {
589  // The noise for this chunk is already generated in m_NoiseArray
590  return;
591  }
592  m_LastChunkCoords = a_ChunkCoords;
593 
594  // Calculate the parameters for the biomes:
595  ChunkParam MidPoint;
596  ChunkParam HeightAmp;
597  CalcBiomeParamArrays(a_ChunkCoords, HeightAmp, MidPoint);
598 
599  // Generate all the noises:
600  NOISE_DATATYPE ChoiceNoise[5 * 5 * 33];
601  NOISE_DATATYPE Workspace[5 * 5 * 33];
602  NOISE_DATATYPE DensityNoiseA[5 * 5 * 33];
603  NOISE_DATATYPE DensityNoiseB[5 * 5 * 33];
604  NOISE_DATATYPE BaseNoise[5 * 5];
605  NOISE_DATATYPE BlockX = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkX * cChunkDef::Width);
606  NOISE_DATATYPE BlockZ = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkZ * cChunkDef::Width);
607  // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x":
608  m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace);
609  m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
610  m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
611  m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
612 
613  // Calculate the final noise based on the partial noises:
614  for (int z = 0; z < 5; z++)
615  {
616  for (int x = 0; x < 5; x++)
617  {
618  NOISE_DATATYPE curMidPoint = MidPoint[x + 5 * z];
619  NOISE_DATATYPE curHeightAmp = HeightAmp[x + 5 * z];
620  NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z];
621  for (int y = 0; y < 33; y++)
622  {
623  NOISE_DATATYPE AddHeight = (static_cast<NOISE_DATATYPE>(y * 8) - curMidPoint) * curHeightAmp;
624 
625  // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope:
626  if (AddHeight < 0)
627  {
628  AddHeight *= 4;
629  }
630  // If too high, cut off any terrain:
631  if (y > 28)
632  {
633  AddHeight = AddHeight + static_cast<NOISE_DATATYPE>(y - 28) / 4;
634  }
635 
636  // Decide between the two density noises:
637  int idx = 33 * x + y + 33 * 5 * z;
638  Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise;
639  }
640  }
641  }
642  LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4);
643 }
644 
645 
646 
647 
648 
649 void cBiomalNoise3DComposable::CalcBiomeParamArrays(cChunkCoords a_ChunkCoords, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint)
650 {
651  // Generate the 3 * 3 chunks of biomes around this chunk:
652  cChunkDef::BiomeMap neighborBiomes[3 * 3];
653  for (int z = 0; z < 3; z++)
654  {
655  for (int x = 0; x < 3; x++)
656  {
657  m_BiomeGen.GenBiomes({a_ChunkCoords.m_ChunkX + x - 1, a_ChunkCoords.m_ChunkZ + z - 1}, neighborBiomes[x + 3 * z]);
658  }
659  }
660 
661  // Sum up the biome values:
662  for (int z = 0; z < 5; z++)
663  {
664  for (int x = 0; x < 5; x++)
665  {
666  NOISE_DATATYPE totalHeightAmp = 0;
667  NOISE_DATATYPE totalMidPoint = 0;
668  // Add up the biomes around this point:
669  for (int relz = 0; relz <= AVERAGING_SIZE * 2; ++relz)
670  {
671  int colz = 16 + z * 4 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start
672  int neicellz = colz / 16; // Chunk Z coord relative to the neighborBiomes start
673  int neirelz = colz % 16; // Biome Z coord relative to cz in neighborBiomes
674  for (int relx = 0; relx <= AVERAGING_SIZE * 2; ++relx)
675  {
676  int colx = 16 + x * 4 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start
677  int neicellx = colx / 16; // Chunk X coord relative to the neighborBiomes start
678  int neirelx = colx % 16; // Biome X coord relative to cz in neighborBiomes
679  EMCSBiome biome = cChunkDef::GetBiome(neighborBiomes[neicellx + neicellz * 3], neirelx, neirelz);
680  NOISE_DATATYPE heightAmp, midPoint;
681  GetBiomeParams(biome, heightAmp, midPoint);
682  totalHeightAmp += heightAmp * m_Weight[relz][relx];
683  totalMidPoint += midPoint * m_Weight[relz][relx];
684  } // for relx
685  } // for relz
686  a_HeightAmp[x + 5 * z] = totalHeightAmp / m_WeightSum;
687  a_MidPoint[x + 5 * z] = totalMidPoint / m_WeightSum;
688  } // for x
689  } // for z
690 }
691 
692 
693 
694 
695 
697 {
698  switch (a_Biome)
699  {
700  case biBeach: a_HeightAmp = 0.2f; a_MidPoint = 60; break;
701  case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
702  case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
703  case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
704  case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
705  case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
706  case biColdTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
707  case biColdTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
708  case biColdTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
709  case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
710  case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break;
711  case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break;
712  case biDesertM: a_HeightAmp = 0.29f; a_MidPoint = 62; break;
713  case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break;
714  case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break;
715  case biExtremeHillsEdge: a_HeightAmp = 0.1f; a_MidPoint = 70; break;
716  case biExtremeHillsM: a_HeightAmp = 0.045f; a_MidPoint = 75; break;
717  case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break;
718  case biExtremeHillsPlusM: a_HeightAmp = 0.04f; a_MidPoint = 80; break;
719  case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
720  case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
721  case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
722  case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break;
723  case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break;
724  case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
725  case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
726  case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
727  case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break;
728  case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 62; break;
729  case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 62; break;
730  case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
731  case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break;
732  case biMegaSpruceTaiga: a_HeightAmp = 0.09f; a_MidPoint = 64; break;
733  case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
734  case biMegaTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
735  case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
736  case biMesa: a_HeightAmp = 0.09f; a_MidPoint = 61; break;
737  case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 61; break;
738  case biMesaPlateau: a_HeightAmp = 0.25f; a_MidPoint = 86; break;
739  case biMesaPlateauF: a_HeightAmp = 0.25f; a_MidPoint = 96; break;
740  case biMesaPlateauFM: a_HeightAmp = 0.25f; a_MidPoint = 96; break;
741  case biMesaPlateauM: a_HeightAmp = 0.25f; a_MidPoint = 86; break;
742  case biMushroomShore: a_HeightAmp = 0.075f; a_MidPoint = 60; break;
743  case biMushroomIsland: a_HeightAmp = 0.06f; a_MidPoint = 80; break;
744  case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64; break;
745  case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break;
746  case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
747  case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break;
748  case biRoofedForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
749  case biRoofedForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
750  case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
751  case biSavannaM: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
752  case biSavannaPlateau: a_HeightAmp = 0.3f; a_MidPoint = 85; break;
753  case biSavannaPlateauM: a_HeightAmp = 0.012f; a_MidPoint = 105; break;
754  case biStoneBeach: a_HeightAmp = 0.075f; a_MidPoint = 60; break;
755  case biSunflowerPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break;
756  case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break;
757  case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break;
758  case biTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break;
759  case biTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 70; break;
760  case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break;
761  case biInvalidBiome:
762  case biNumBiomes:
763  case biVariant:
764  case biNumVariantBiomes:
765  {
766  // Make a crazy terrain so that it stands out
767  a_HeightAmp = 0.001f;
768  a_MidPoint = 90;
769  break;
770  }
771  }
772 }
773 
774 
775 
776 
777 
779 {
780  GenerateNoiseArrayIfNeeded(a_ChunkCoords);
781 
782  // Translate the noise array into Shape:
783  for (int z = 0; z < cChunkDef::Width; z++)
784  {
785  for (int x = 0; x < cChunkDef::Width; x++)
786  {
787  for (int y = 0; y < cChunkDef::Height; y++)
788  {
789  a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1;
790  }
791  } // for x
792  } // for z
793 }
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:18
@ biJungleEdge
Definition: BiomeDef.h:50
@ biIceMountains
Definition: BiomeDef.h:38
@ biMesa
Definition: BiomeDef.h:64
@ biMesaPlateau
Definition: BiomeDef.h:66
@ biExtremeHillsM
Definition: BiomeDef.h:79
@ biForestHills
Definition: BiomeDef.h:43
@ biNether
Definition: BiomeDef.h:31
@ biBirchForest
Definition: BiomeDef.h:54
@ biBirchForestM
Definition: BiomeDef.h:86
@ biDesert
Definition: BiomeDef.h:24
@ biMesaPlateauF
Definition: BiomeDef.h:65
@ biSunflowerPlains
Definition: BiomeDef.h:77
@ biExtremeHillsPlusM
Definition: BiomeDef.h:92
@ biColdTaigaHills
Definition: BiomeDef.h:58
@ biFlowerForest
Definition: BiomeDef.h:80
@ biInvalidBiome
Definition: BiomeDef.h:19
@ biMegaSpruceTaiga
Definition: BiomeDef.h:90
@ biStoneBeach
Definition: BiomeDef.h:52
@ biMushroomShore
Definition: BiomeDef.h:40
@ biSavanna
Definition: BiomeDef.h:62
@ biTaigaHills
Definition: BiomeDef.h:44
@ biExtremeHillsPlus
Definition: BiomeDef.h:61
@ biJungle
Definition: BiomeDef.h:46
@ biMegaTaiga
Definition: BiomeDef.h:59
@ biJungleHills
Definition: BiomeDef.h:47
@ biOcean
Definition: BiomeDef.h:22
@ biDesertHills
Definition: BiomeDef.h:42
@ biBeach
Definition: BiomeDef.h:41
@ biForest
Definition: BiomeDef.h:26
@ biJungleEdgeM
Definition: BiomeDef.h:85
@ biTaigaM
Definition: BiomeDef.h:81
@ biBirchForestHillsM
Definition: BiomeDef.h:87
@ biJungleM
Definition: BiomeDef.h:84
@ biExtremeHillsEdge
Definition: BiomeDef.h:45
@ biNumVariantBiomes
Definition: BiomeDef.h:99
@ biFrozenRiver
Definition: BiomeDef.h:35
@ biRiver
Definition: BiomeDef.h:29
@ biMesaPlateauFM
Definition: BiomeDef.h:96
@ biMushroomIsland
Definition: BiomeDef.h:39
@ biDeepOcean
Definition: BiomeDef.h:51
@ biSavannaPlateauM
Definition: BiomeDef.h:94
@ biMesaBryce
Definition: BiomeDef.h:95
@ biPlains
Definition: BiomeDef.h:23
@ biRoofedForestM
Definition: BiomeDef.h:88
@ biBirchForestHills
Definition: BiomeDef.h:55
@ biColdBeach
Definition: BiomeDef.h:53
@ biMegaSpruceTaigaHills
Definition: BiomeDef.h:91
@ biSavannaM
Definition: BiomeDef.h:93
@ biSwamplandM
Definition: BiomeDef.h:82
@ biVariant
Definition: BiomeDef.h:73
@ biEnd
Definition: BiomeDef.h:33
@ biIcePlainsSpikes
Definition: BiomeDef.h:83
@ biFrozenOcean
Definition: BiomeDef.h:34
@ biExtremeHills
Definition: BiomeDef.h:25
@ biColdTaiga
Definition: BiomeDef.h:57
@ biMegaTaigaHills
Definition: BiomeDef.h:60
@ biNumBiomes
Definition: BiomeDef.h:69
@ biRoofedForest
Definition: BiomeDef.h:56
@ biIcePlains
Definition: BiomeDef.h:36
@ biTaiga
Definition: BiomeDef.h:27
@ biDesertM
Definition: BiomeDef.h:78
@ biSavannaPlateau
Definition: BiomeDef.h:63
@ biMesaPlateauM
Definition: BiomeDef.h:97
@ biColdTaigaM
Definition: BiomeDef.h:89
@ biSwampland
Definition: BiomeDef.h:28
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_GRASS
Definition: BlockType.h:12
@ E_BLOCK_BEDROCK
Definition: BlockType.h:17
@ E_BLOCK_STONE
Definition: BlockType.h:11
@ E_BLOCK_DIRT
Definition: BlockType.h:13
@ E_BLOCK_SAND
Definition: BlockType.h:22
@ E_BLOCK_STATIONARY_WATER
Definition: BlockType.h:19
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:231
#define UNUSED
Definition: Globals.h:72
void LinearUpscale3DArray(TYPE *a_Src, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, TYPE *a_Dst, int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
Linearly interpolates between two values, clamping the ratio to [0, 1] first.
Definition: Noise.h:334
float NOISE_DATATYPE
The datatype used by all the noise generators.
Definition: Noise.h:9
BlockType
Definition: BlockTypes.h:4
Wraps the chunk coords into a single structure.
Definition: ChunkDef.h:57
int m_ChunkZ
Definition: ChunkDef.h:60
int m_ChunkX
Definition: ChunkDef.h:59
static const int Width
Definition: ChunkDef.h:124
static const int Height
Definition: ChunkDef.h:125
static EMCSBiome GetBiome(const BiomeMap &a_BiomeMap, int a_X, int a_Z)
Definition: ChunkDef.h:319
EMCSBiome BiomeMap[Width *Width]
The type used for any biomemap operations and storage inside Cuberite, using Cuberite biomes (need no...
Definition: ChunkDef.h:137
HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const
Definition: ChunkDesc.cpp:144
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
Definition: ChunkDesc.cpp:81
Byte Shape[256 *16 *16]
The datatype used to represent the entire chunk worth of shape.
Definition: ChunkDesc.h:36
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
Definition: ChunkDesc.cpp:90
cChunkCoords GetChunkCoords() const
Definition: ChunkDesc.h:54
void UpdateHeightmap(void)
Updates the heightmap to match the current contents.
Definition: ChunkDesc.cpp:612
The interface that all chunk generators must implement to provide the generated chunks.
The interface that a biome generator must implement A biome generator takes chunk coords on input and...
virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap &a_BiomeMap)=0
Generates biomes for the given chunk.
cOctavedNoise< cInterp5DegNoise > m_Perlin
The base 3D noise source for the actual composition.
void ComposeTerrain(cChunkDesc &a_ChunkDesc)
Composes terrain - adds dirt, grass and sand.
NOISE_DATATYPE m_FrequencyZ
void GenerateNoiseArray(cChunkCoords a_ChunkCoords, NOISE_DATATYPE *a_Noise)
Generates the 3D noise array used for terrain generation into a_Noise; a_Noise is of ChunkData-size.
static const int DIM_Z
cOctavedNoise< cInterp5DegNoise > m_Cubic
The noise used for heightmap directing.
NOISE_DATATYPE m_FrequencyY
virtual void Initialize(cIniFile &a_IniFile) override
Called to initialize the generator on server startup.
virtual void Generate(cChunkDesc &a_ChunkDesc) override
Does the actual chunk generation.
NOISE_DATATYPE m_MidPoint
static const int UPSCALE_X
virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap &a_BiomeMap) override
Generates the biomes for the specified chunk.
NOISE_DATATYPE m_FrequencyX
virtual ~cNoise3DGenerator() override
NOISE_DATATYPE m_AirThreshold
static const int DIM_X
NOISE_DATATYPE m_HeightAmplification
static const int DIM_Y
static const int UPSCALE_Z
static const int UPSCALE_Y
NOISE_DATATYPE m_ChoiceFrequencyX
NOISE_DATATYPE m_FrequencyY
NOISE_DATATYPE m_ChoiceFrequencyY
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseA
Density 3D noise, variant A.
NOISE_DATATYPE m_FrequencyZ
NOISE_DATATYPE m_BaseFrequencyX
virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape &a_Shape) override
Generates the shape for the given chunk.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_BaseNoise
Heightmap-like noise used to provide variance for low-amplitude biomes.
NOISE_DATATYPE m_MidPoint
Where the vertical "center" of the noise should be, as block height.
NOISE_DATATYPE m_NoiseArray[17 *17 *257]
cChunkCoords m_LastChunkCoords
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseB
Density 3D noise, variant B.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_ChoiceNoise
The 3D noise that is used to choose between density noise A and B.
NOISE_DATATYPE m_FrequencyX
NOISE_DATATYPE m_HeightAmplification
The main parameter of the generator, specifies the slope of the vertical linear gradient.
NOISE_DATATYPE m_BaseFrequencyZ
NOISE_DATATYPE m_AirThreshold
NOISE_DATATYPE m_ChoiceFrequencyZ
cNoise3DComposable(int a_Seed)
void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords)
Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords ...
void Initialize(cIniFile &a_IniFile)
NOISE_DATATYPE m_ChoiceFrequencyY
NOISE_DATATYPE m_ChoiceFrequencyZ
NOISE_DATATYPE m_Weight[AVERAGING_SIZE *2+1][AVERAGING_SIZE *2+1]
Weights for summing up neighboring biomes.
NOISE_DATATYPE m_NoiseArray[17 *17 *257]
void CalcBiomeParamArrays(cChunkCoords a_ChunkCoords, ChunkParam &a_HeightAmp, ChunkParam &a_MidPoint)
Calculates the biome-related parameters for the chunk.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_BaseNoise
Heightmap-like noise used to provide variance for low-amplitude biomes.
NOISE_DATATYPE m_WeightSum
The sum of m_Weight[].
void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords)
Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords ...
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_ChoiceNoise
The noise that is used to choose between density noise A and B.
cBiomeGen & m_BiomeGen
The underlying biome generator.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseA
Density 3D noise, variant A.
void Initialize(cIniFile &a_IniFile)
cBiomalNoise3DComposable(int a_Seed, cBiomeGen &a_BiomeGen)
int m_SeaLevel
Block height of the sealevel, used for composing the terrain.
NOISE_DATATYPE m_ChoiceFrequencyX
static const int AVERAGING_SIZE
Number of columns around the pixel to query for biomes for averaging.
NOISE_DATATYPE ChunkParam[5 *5]
Type used for a single parameter across the entire (downscaled) chunk.
void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE &a_HeightAmp, NOISE_DATATYPE &a_MidPoint)
Returns the parameters for the specified biome.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseB
Density 3D noise, variant B.
NOISE_DATATYPE m_BaseFrequencyZ
virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape &a_Shape) override
Generates the shape for the given chunk.
NOISE_DATATYPE m_BaseFrequencyX
int GetValueSetI(const AString &keyname, const AString &valuename, const int defValue=0) override
Definition: IniFile.cpp:559
double GetValueSetF(const AString &keyname, const AString &valuename, const double defValue=0.0)
Definition: IniFile.cpp:549
void Generate3D(NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, int a_SizeZ, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ, NOISE_DATATYPE *a_Workspace=nullptr) const
Fills a 3D array with the values of the noise.
Definition: OctavedNoise.h:104
void AddOctave(NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude)
Adds a new octave to the list of octaves that compose this noise.
Definition: OctavedNoise.h:38
void Generate2D(NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, NOISE_DATATYPE *a_Workspace=nullptr) const
Fills a 2D array with the values of the noise.
Definition: OctavedNoise.h:45