Cuberite
A lightweight, fast and extensible game server for Minecraft
Noise.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "Noise.h"
5 
6 #define FAST_FLOOR(x) (((x) < 0) ? ((static_cast<int>(x)) - 1) : (static_cast<int>(x)))
7 
8 
9 
10 
11 
12 #if 0
16 static class cImprovedPerlinNoiseTest
17 {
18 public:
19  cImprovedPerlinNoiseTest(void)
20  {
21  printf("Performing Improved Perlin Noise tests...\n");
22  TestImage();
23  TestSpeed();
24  TestSpeedArr();
25  printf("Improved Perlin Noise tests complete.\n");
26  }
27 
28 
30  void TestImage(void)
31  {
32  static const int SIZE_X = 256;
33  static const int SIZE_Y = 256;
34  static const int SIZE_Z = 16;
35 
36  cImprovedNoise noise(1);
37  std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
38  noise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
39  Debug3DNoise(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, "ImprovedPerlinNoiseTest3D", 128);
40  noise.Generate2D(arr.get(), SIZE_X, SIZE_Y, 0, 14, 15, 28);
41  Debug2DNoise(arr.get(), SIZE_X, SIZE_Y, "ImprovedPerlinNoiseTest2D", 128);
42  }
43 
44 
46  void TestSpeed(void)
47  {
48  cImprovedNoise improvedNoise(1);
49  cNoise noise(1);
50  cTimer timer;
51 
52  // Measure the improvedNoise:
53  NOISE_DATATYPE sum = 0;
54  long long start = timer.GetNowTime();
55  for (int i = 0; i < 100000000; i++)
56  {
57  sum += improvedNoise.GetValueAt(i, 0, -i);
58  }
59  long long finish = timer.GetNowTime();
60  printf("cImprovedNoise took %.2f seconds; total is %f.\n", static_cast<float>(finish - start) / 1000.0f, sum);
61 
62  // Measure the cubicNoise:
63  sum = 0;
64  start = timer.GetNowTime();
65  for (int i = 0; i < 100000000; i++)
66  {
67  sum += noise.IntNoise3D(i, 0, -i);
68  }
69  finish = timer.GetNowTime();
70  printf("cCubicNoise took %.2f seconds; total is %f.\n", static_cast<float>(finish - start) / 1000.0f, sum);
71  }
72 
73 
75  void TestSpeedArr(void)
76  {
77  static const int SIZE_X = 256;
78  static const int SIZE_Y = 256;
79  static const int SIZE_Z = 16;
80 
81  std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
82  cTimer timer;
83  cImprovedNoise improvedNoise(1);
84  cCubicNoise cubicNoise(1);
85 
86  // Measure the improvedNoise:
87  long long start = timer.GetNowTime();
88  for (int i = 0; i < 40; i++)
89  {
90  improvedNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
91  }
92  long long finish = timer.GetNowTime();
93  printf("cImprovedNoise(arr) took %.2f seconds.\n", static_cast<float>(finish - start) / 1000.0f);
94 
95  // Measure the cubicNoise:
96  start = timer.GetNowTime();
97  for (int i = 0; i < 40; i++)
98  {
99  cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
100  }
101  finish = timer.GetNowTime();
102  printf("cCubicNoise(arr) took %.2f seconds.\n", static_cast<float>(finish - start) / 1000.0f);
103  }
104 } g_Test;
105 
106 #endif
107 
108 
109 
110 
111 
113 // Globals:
114 
115 void Debug3DNoise(const NOISE_DATATYPE * a_Noise, size_t a_SizeX, size_t a_SizeY, size_t a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff)
116 {
117  const int BUF_SIZE = 512;
118  ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed
119 
120  // Save in XY cuts:
121  cFile f1;
122  if (f1.Open(fmt::format(FMT_STRING("{}_XY ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite))
123  {
124  for (size_t z = 0; z < a_SizeZ; z++)
125  {
126  for (size_t y = 0; y < a_SizeY; y++)
127  {
128  size_t idx = y * a_SizeX + z * a_SizeX * a_SizeY;
129  unsigned char buf[BUF_SIZE];
130  for (size_t x = 0; x < a_SizeX; x++)
131  {
132  buf[x] = static_cast<unsigned char>(Clamp(static_cast<int>(128 + a_Coeff * a_Noise[idx++]), 0, 255));
133  }
134  f1.Write(buf, a_SizeX);
135  } // for y
136  unsigned char buf[BUF_SIZE];
137  memset(buf, 0, a_SizeX);
138  f1.Write(buf, a_SizeX);
139  } // for z
140  } // if (XY file open)
141 
142  cFile f2;
143  if (f2.Open(fmt::format(FMT_STRING("{}_XZ ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite))
144  {
145  for (size_t y = 0; y < a_SizeY; y++)
146  {
147  for (size_t z = 0; z < a_SizeZ; z++)
148  {
149  size_t idx = y * a_SizeX + z * a_SizeX * a_SizeY;
150  unsigned char buf[BUF_SIZE];
151  for (size_t x = 0; x < a_SizeX; x++)
152  {
153  buf[x] = static_cast<unsigned char>(Clamp(static_cast<int>(128 + a_Coeff * a_Noise[idx++]), 0, 255));
154  }
155  f2.Write(buf, a_SizeX);
156  } // for z
157  unsigned char buf[BUF_SIZE];
158  memset(buf, 0, a_SizeX);
159  f2.Write(buf, a_SizeX);
160  } // for y
161  } // if (XZ file open)
162 }
163 
164 
165 
166 
167 
168 void Debug2DNoise(const NOISE_DATATYPE * a_Noise, size_t a_SizeX, size_t a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff)
169 {
170  const int BUF_SIZE = 512;
171  ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed
172 
173  cFile f1;
174  if (f1.Open(fmt::format(FMT_STRING("{} ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite))
175  {
176  for (size_t y = 0; y < a_SizeY; y++)
177  {
178  size_t idx = y * a_SizeX;
179  unsigned char buf[BUF_SIZE];
180  for (size_t x = 0; x < a_SizeX; x++)
181  {
182  buf[x] = static_cast<unsigned char>(Clamp(static_cast<int>(128 + a_Coeff * a_Noise[idx++]), 0, 255));
183  }
184  f1.Write(buf, a_SizeX);
185  } // for y
186  } // if (file open)
187 }
188 
189 
190 
191 
192 
194 // cCubicCell2D:
195 
197 {
198 public:
199  cCubicCell2D(
200  const cNoise & a_Noise,
201  NOISE_DATATYPE * a_Array,
202  int a_SizeX, int a_SizeY,
203  const NOISE_DATATYPE * a_FracX,
204  const NOISE_DATATYPE * a_FracY
205  );
206 
208  void Generate(
209  int a_FromX, int a_ToX,
210  int a_FromY, int a_ToY
211  );
212 
214  void InitWorkRnds(int a_FloorX, int a_FloorY);
215 
217  void Move(int a_NewFloorX, int a_NewFloorY);
218 
219 protected:
220  typedef NOISE_DATATYPE Workspace[4][4];
221 
222  const cNoise & m_Noise;
223 
229 
234 } ;
235 
236 
237 
238 
239 
241  const cNoise & a_Noise,
242  NOISE_DATATYPE * a_Array,
243  int a_SizeX, int a_SizeY,
244  const NOISE_DATATYPE * a_FracX,
245  const NOISE_DATATYPE * a_FracY
246 ) :
247  m_Noise(a_Noise),
248  m_WorkRnds(&m_Workspace1),
249  m_CurFloorX(0),
250  m_CurFloorY(0),
251  m_Array(a_Array),
252  m_SizeX(a_SizeX),
253  m_SizeY(a_SizeY),
254  m_FracX(a_FracX),
255  m_FracY(a_FracY)
256 {
257 }
258 
259 
260 
261 
262 
264  int a_FromX, int a_ToX,
265  int a_FromY, int a_ToY
266 )
267 {
268  for (int y = a_FromY; y < a_ToY; y++)
269  {
270  NOISE_DATATYPE Interp[4];
271  NOISE_DATATYPE FracY = m_FracY[y];
272  Interp[0] = cNoise::CubicInterpolate((*m_WorkRnds)[0][0], (*m_WorkRnds)[0][1], (*m_WorkRnds)[0][2], (*m_WorkRnds)[0][3], FracY);
273  Interp[1] = cNoise::CubicInterpolate((*m_WorkRnds)[1][0], (*m_WorkRnds)[1][1], (*m_WorkRnds)[1][2], (*m_WorkRnds)[1][3], FracY);
274  Interp[2] = cNoise::CubicInterpolate((*m_WorkRnds)[2][0], (*m_WorkRnds)[2][1], (*m_WorkRnds)[2][2], (*m_WorkRnds)[2][3], FracY);
275  Interp[3] = cNoise::CubicInterpolate((*m_WorkRnds)[3][0], (*m_WorkRnds)[3][1], (*m_WorkRnds)[3][2], (*m_WorkRnds)[3][3], FracY);
276  int idx = y * m_SizeX + a_FromX;
277  for (int x = a_FromX; x < a_ToX; x++)
278  {
279  m_Array[idx++] = cNoise::CubicInterpolate(Interp[0], Interp[1], Interp[2], Interp[3], m_FracX[x]);
280  } // for x
281  } // for y
282 }
283 
284 
285 
286 
287 
288 void cCubicCell2D::InitWorkRnds(int a_FloorX, int a_FloorY)
289 {
290  m_CurFloorX = a_FloorX;
291  m_CurFloorY = a_FloorY;
292  for (int x = 0; x < 4; x++)
293  {
294  int cx = a_FloorX + x - 1;
295  for (int y = 0; y < 4; y++)
296  {
297  int cy = a_FloorY + y - 1;
298  (*m_WorkRnds)[x][y] = static_cast<NOISE_DATATYPE>(m_Noise.IntNoise2D(cx, cy));
299  }
300  }
301 }
302 
303 
304 
305 
306 
307 void cCubicCell2D::Move(int a_NewFloorX, int a_NewFloorY)
308 {
309  // Swap the doublebuffer:
310  int OldFloorX = m_CurFloorX;
311  int OldFloorY = m_CurFloorY;
312  Workspace * OldWorkRnds = m_WorkRnds;
314 
315  // Reuse as much of the old workspace as possible:
316  int DiffX = OldFloorX - a_NewFloorX;
317  int DiffY = OldFloorY - a_NewFloorY;
318  for (int x = 0; x < 4; x++)
319  {
320  int cx = a_NewFloorX + x - 1;
321  int OldX = x - DiffX; // Where would this X be in the old grid?
322  for (int y = 0; y < 4; y++)
323  {
324  int cy = a_NewFloorY + y - 1;
325  int OldY = y - DiffY; // Where would this Y be in the old grid?
326  if ((OldX >= 0) && (OldX < 4) && (OldY >= 0) && (OldY < 4))
327  {
328  (*m_WorkRnds)[x][y] = (*OldWorkRnds)[OldX][OldY];
329  }
330  else
331  {
332  (*m_WorkRnds)[x][y] = static_cast<NOISE_DATATYPE>(m_Noise.IntNoise2D(cx, cy));
333  }
334  }
335  }
336  m_CurFloorX = a_NewFloorX;
337  m_CurFloorY = a_NewFloorY;
338 }
339 
340 
341 
342 
343 
345 // cCubicCell3D:
346 
348 {
349 public:
350  cCubicCell3D(
351  const cNoise & a_Noise,
352  NOISE_DATATYPE * a_Array,
353  int a_SizeX, int a_SizeY, int a_SizeZ,
354  const NOISE_DATATYPE * a_FracX,
355  const NOISE_DATATYPE * a_FracY,
356  const NOISE_DATATYPE * a_FracZ
357  );
358 
360  void Generate(
361  int a_FromX, int a_ToX,
362  int a_FromY, int a_ToY,
363  int a_FromZ, int a_ToZ
364  );
365 
367  void InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ);
368 
370  void Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ);
371 
372 protected:
373  typedef NOISE_DATATYPE Workspace[4][4][4];
374 
375  const cNoise & m_Noise;
376 
383 
389 } ;
390 
391 
392 
393 
394 
396  const cNoise & a_Noise,
397  NOISE_DATATYPE * a_Array,
398  int a_SizeX, int a_SizeY, int a_SizeZ,
399  const NOISE_DATATYPE * a_FracX,
400  const NOISE_DATATYPE * a_FracY,
401  const NOISE_DATATYPE * a_FracZ
402 ) :
403  m_Noise(a_Noise),
404  m_WorkRnds(&m_Workspace1),
405  m_CurFloorX(0),
406  m_CurFloorY(0),
407  m_CurFloorZ(0),
408  m_Array(a_Array),
409  m_SizeX(a_SizeX),
410  m_SizeY(a_SizeY),
411  m_SizeZ(a_SizeZ),
412  m_FracX(a_FracX),
413  m_FracY(a_FracY),
414  m_FracZ(a_FracZ)
415 {
416 }
417 
418 
419 
420 
421 
423  int a_FromX, int a_ToX,
424  int a_FromY, int a_ToY,
425  int a_FromZ, int a_ToZ
426 )
427 {
428  for (int z = a_FromZ; z < a_ToZ; z++)
429  {
430  int idxZ = z * m_SizeX * m_SizeY;
431  NOISE_DATATYPE Interp2[4][4];
432  NOISE_DATATYPE FracZ = m_FracZ[z];
433  for (int x = 0; x < 4; x++)
434  {
435  for (int y = 0; y < 4; y++)
436  {
437  Interp2[x][y] = cNoise::CubicInterpolate((*m_WorkRnds)[x][y][0], (*m_WorkRnds)[x][y][1], (*m_WorkRnds)[x][y][2], (*m_WorkRnds)[x][y][3], FracZ);
438  }
439  }
440  for (int y = a_FromY; y < a_ToY; y++)
441  {
442  NOISE_DATATYPE Interp[4];
443  NOISE_DATATYPE FracY = m_FracY[y];
444  Interp[0] = cNoise::CubicInterpolate(Interp2[0][0], Interp2[0][1], Interp2[0][2], Interp2[0][3], FracY);
445  Interp[1] = cNoise::CubicInterpolate(Interp2[1][0], Interp2[1][1], Interp2[1][2], Interp2[1][3], FracY);
446  Interp[2] = cNoise::CubicInterpolate(Interp2[2][0], Interp2[2][1], Interp2[2][2], Interp2[2][3], FracY);
447  Interp[3] = cNoise::CubicInterpolate(Interp2[3][0], Interp2[3][1], Interp2[3][2], Interp2[3][3], FracY);
448  int idx = idxZ + y * m_SizeX + a_FromX;
449  for (int x = a_FromX; x < a_ToX; x++)
450  {
451  m_Array[idx++] = cNoise::CubicInterpolate(Interp[0], Interp[1], Interp[2], Interp[3], m_FracX[x]);
452  } // for x
453  } // for y
454  } // for z
455 }
456 
457 
458 
459 
460 
461 void cCubicCell3D::InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ)
462 {
463  m_CurFloorX = a_FloorX;
464  m_CurFloorY = a_FloorY;
465  m_CurFloorZ = a_FloorZ;
466  for (int x = 0; x < 4; x++)
467  {
468  int cx = a_FloorX + x - 1;
469  for (int y = 0; y < 4; y++)
470  {
471  int cy = a_FloorY + y - 1;
472  for (int z = 0; z < 4; z++)
473  {
474  int cz = a_FloorZ + z - 1;
475  (*m_WorkRnds)[x][y][z] = static_cast<NOISE_DATATYPE>(m_Noise.IntNoise3D(cx, cy, cz));
476  }
477  }
478  }
479 }
480 
481 
482 
483 
484 
485 void cCubicCell3D::Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ)
486 {
487  // Swap the doublebuffer:
488  int OldFloorX = m_CurFloorX;
489  int OldFloorY = m_CurFloorY;
490  int OldFloorZ = m_CurFloorZ;
491  Workspace * OldWorkRnds = m_WorkRnds;
493 
494  // Reuse as much of the old workspace as possible:
495  int DiffX = OldFloorX - a_NewFloorX;
496  int DiffY = OldFloorY - a_NewFloorY;
497  int DiffZ = OldFloorZ - a_NewFloorZ;
498  for (int x = 0; x < 4; x++)
499  {
500  int cx = a_NewFloorX + x - 1;
501  int OldX = x - DiffX; // Where would this X be in the old grid?
502  for (int y = 0; y < 4; y++)
503  {
504  int cy = a_NewFloorY + y - 1;
505  int OldY = y - DiffY; // Where would this Y be in the old grid?
506  for (int z = 0; z < 4; z++)
507  {
508  int cz = a_NewFloorZ + z - 1;
509  int OldZ = z - DiffZ;
510  if ((OldX >= 0) && (OldX < 4) && (OldY >= 0) && (OldY < 4) && (OldZ >= 0) && (OldZ < 4))
511  {
512  (*m_WorkRnds)[x][y][z] = (*OldWorkRnds)[OldX][OldY][OldZ];
513  }
514  else
515  {
516  (*m_WorkRnds)[x][y][z] = static_cast<NOISE_DATATYPE>(m_Noise.IntNoise3D(cx, cy, cz));
517  }
518  } // for z
519  } // for y
520  } // for x
521  m_CurFloorX = a_NewFloorX;
522  m_CurFloorY = a_NewFloorY;
523  m_CurFloorZ = a_NewFloorZ;
524 }
525 
526 
527 
528 
529 
531 // cNoise:
532 
533 cNoise::cNoise(int a_Seed) :
534  m_Seed(a_Seed)
535 {
536 }
537 
538 
539 
540 
541 
542 cNoise::cNoise(const cNoise & a_Noise) :
543  m_Seed(a_Noise.m_Seed)
544 {
545 }
546 
547 
548 
549 
550 
552 {
553  int BaseX = FAST_FLOOR(a_X);
554  NOISE_DATATYPE FracX = a_X - BaseX;
555  return LinearInterpolate(IntNoise1D(BaseX), IntNoise1D(BaseX + 1), FracX);
556 }
557 
558 
559 
560 
561 
563 {
564  int BaseX = FAST_FLOOR(a_X);
565  NOISE_DATATYPE FracX = a_X - BaseX;
566  return CosineInterpolate(IntNoise1D(BaseX), IntNoise1D(BaseX + 1), FracX);
567 }
568 
569 
570 
571 
572 
574 {
575  int BaseX = FAST_FLOOR(a_X);
576  NOISE_DATATYPE FracX = a_X - BaseX;
577  return CubicInterpolate(IntNoise1D(BaseX - 1), IntNoise1D(BaseX), IntNoise1D(BaseX + 1), IntNoise1D(BaseX + 2), FracX);
578 }
579 
580 
581 
582 
583 
585 {
586  return IntNoise1D(a_X) / 2 + IntNoise1D(a_X - 1) / 4 + IntNoise1D(a_X + 1) / 4;
587 }
588 
589 
590 
591 
592 
594 {
595  const int BaseX = FAST_FLOOR(a_X);
596  const int BaseY = FAST_FLOOR(a_Y);
597 
598  const NOISE_DATATYPE points[4][4] =
599  {
600  { IntNoise2D(BaseX - 1, BaseY - 1), IntNoise2D(BaseX, BaseY - 1), IntNoise2D(BaseX + 1, BaseY - 1), IntNoise2D(BaseX + 2, BaseY - 1), },
601  { IntNoise2D(BaseX - 1, BaseY), IntNoise2D(BaseX, BaseY), IntNoise2D(BaseX + 1, BaseY), IntNoise2D(BaseX + 2, BaseY), },
602  { IntNoise2D(BaseX - 1, BaseY + 1), IntNoise2D(BaseX, BaseY + 1), IntNoise2D(BaseX + 1, BaseY + 1), IntNoise2D(BaseX + 2, BaseY + 1), },
603  { IntNoise2D(BaseX - 1, BaseY + 2), IntNoise2D(BaseX, BaseY + 2), IntNoise2D(BaseX + 1, BaseY + 2), IntNoise2D(BaseX + 2, BaseY + 2), },
604  };
605 
606  const NOISE_DATATYPE FracX = a_X - BaseX;
607  const NOISE_DATATYPE interp1 = CubicInterpolate(points[0][0], points[0][1], points[0][2], points[0][3], FracX);
608  const NOISE_DATATYPE interp2 = CubicInterpolate(points[1][0], points[1][1], points[1][2], points[1][3], FracX);
609  const NOISE_DATATYPE interp3 = CubicInterpolate(points[2][0], points[2][1], points[2][2], points[2][3], FracX);
610  const NOISE_DATATYPE interp4 = CubicInterpolate(points[3][0], points[3][1], points[3][2], points[3][3], FracX);
611 
612 
613  const NOISE_DATATYPE FracY = a_Y - BaseY;
614  return CubicInterpolate(interp1, interp2, interp3, interp4, FracY);
615 }
616 
617 
618 
619 
620 
622 {
623  const int BaseX = FAST_FLOOR(a_X);
624  const int BaseY = FAST_FLOOR(a_Y);
625  const int BaseZ = FAST_FLOOR(a_Z);
626 
627  const NOISE_DATATYPE points1[4][4] =
628  {
629  { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ - 1), },
630  { IntNoise3D(BaseX - 1, BaseY, BaseZ - 1), IntNoise3D(BaseX, BaseY, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY, BaseZ - 1), },
631  { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ - 1), },
632  { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ - 1), },
633  };
634 
635  const NOISE_DATATYPE FracX = (a_X) - BaseX;
636  const NOISE_DATATYPE x1interp1 = CubicInterpolate(points1[0][0], points1[0][1], points1[0][2], points1[0][3], FracX);
637  const NOISE_DATATYPE x1interp2 = CubicInterpolate(points1[1][0], points1[1][1], points1[1][2], points1[1][3], FracX);
638  const NOISE_DATATYPE x1interp3 = CubicInterpolate(points1[2][0], points1[2][1], points1[2][2], points1[2][3], FracX);
639  const NOISE_DATATYPE x1interp4 = CubicInterpolate(points1[3][0], points1[3][1], points1[3][2], points1[3][3], FracX);
640 
641  const NOISE_DATATYPE points2[4][4] =
642  {
643  { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ), IntNoise3D(BaseX, BaseY - 1, BaseZ), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ), },
644  { IntNoise3D(BaseX - 1, BaseY, BaseZ), IntNoise3D(BaseX, BaseY, BaseZ), IntNoise3D(BaseX + 1, BaseY, BaseZ), IntNoise3D(BaseX + 2, BaseY, BaseZ), },
645  { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ), IntNoise3D(BaseX, BaseY + 1, BaseZ), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ), },
646  { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ), IntNoise3D(BaseX, BaseY + 2, BaseZ), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ), },
647  };
648 
649  const NOISE_DATATYPE x2interp1 = CubicInterpolate(points2[0][0], points2[0][1], points2[0][2], points2[0][3], FracX);
650  const NOISE_DATATYPE x2interp2 = CubicInterpolate(points2[1][0], points2[1][1], points2[1][2], points2[1][3], FracX);
651  const NOISE_DATATYPE x2interp3 = CubicInterpolate(points2[2][0], points2[2][1], points2[2][2], points2[2][3], FracX);
652  const NOISE_DATATYPE x2interp4 = CubicInterpolate(points2[3][0], points2[3][1], points2[3][2], points2[3][3], FracX);
653 
654  const NOISE_DATATYPE points3[4][4] =
655  {
656  { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ + 1), },
657  { IntNoise3D(BaseX - 1, BaseY, BaseZ + 1), IntNoise3D(BaseX, BaseY, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY, BaseZ + 1), },
658  { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ + 1), },
659  { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ + 1), },
660  };
661 
662  const NOISE_DATATYPE x3interp1 = CubicInterpolate(points3[0][0], points3[0][1], points3[0][2], points3[0][3], FracX);
663  const NOISE_DATATYPE x3interp2 = CubicInterpolate(points3[1][0], points3[1][1], points3[1][2], points3[1][3], FracX);
664  const NOISE_DATATYPE x3interp3 = CubicInterpolate(points3[2][0], points3[2][1], points3[2][2], points3[2][3], FracX);
665  const NOISE_DATATYPE x3interp4 = CubicInterpolate(points3[3][0], points3[3][1], points3[3][2], points3[3][3], FracX);
666 
667  const NOISE_DATATYPE points4[4][4] =
668  {
669  { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ + 2), },
670  { IntNoise3D(BaseX - 1, BaseY, BaseZ + 2), IntNoise3D(BaseX, BaseY, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY, BaseZ + 2), },
671  { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ + 2), },
672  { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ + 2), },
673  };
674 
675  const NOISE_DATATYPE x4interp1 = CubicInterpolate(points4[0][0], points4[0][1], points4[0][2], points4[0][3], FracX);
676  const NOISE_DATATYPE x4interp2 = CubicInterpolate(points4[1][0], points4[1][1], points4[1][2], points4[1][3], FracX);
677  const NOISE_DATATYPE x4interp3 = CubicInterpolate(points4[2][0], points4[2][1], points4[2][2], points4[2][3], FracX);
678  const NOISE_DATATYPE x4interp4 = CubicInterpolate(points4[3][0], points4[3][1], points4[3][2], points4[3][3], FracX);
679 
680  const NOISE_DATATYPE FracY = (a_Y) - BaseY;
681  const NOISE_DATATYPE yinterp1 = CubicInterpolate(x1interp1, x1interp2, x1interp3, x1interp4, FracY);
682  const NOISE_DATATYPE yinterp2 = CubicInterpolate(x2interp1, x2interp2, x2interp3, x2interp4, FracY);
683  const NOISE_DATATYPE yinterp3 = CubicInterpolate(x3interp1, x3interp2, x3interp3, x3interp4, FracY);
684  const NOISE_DATATYPE yinterp4 = CubicInterpolate(x4interp1, x4interp2, x4interp3, x4interp4, FracY);
685 
686  const NOISE_DATATYPE FracZ = (a_Z) - BaseZ;
687  return CubicInterpolate(yinterp1, yinterp2, yinterp3, yinterp4, FracZ);
688 }
689 
690 
691 
692 
693 
695 // cCubicNoise:
696 
698  m_Noise(a_Seed)
699 {
700 }
701 
702 
703 
704 
705 
707  NOISE_DATATYPE * a_Array,
708  int a_SizeX, int a_SizeY,
709  NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
710  NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY
711 ) const
712 {
713  ASSERT(a_SizeX > 0);
714  ASSERT(a_SizeY > 0);
715  ASSERT(a_SizeX < MAX_SIZE);
716  ASSERT(a_SizeY < MAX_SIZE);
717  ASSERT(a_StartX < a_EndX);
718  ASSERT(a_StartY < a_EndY);
719 
720  // Calculate the integral and fractional parts of each coord:
721  int FloorX[MAX_SIZE];
722  int FloorY[MAX_SIZE];
723  NOISE_DATATYPE FracX[MAX_SIZE];
724  NOISE_DATATYPE FracY[MAX_SIZE];
725  int SameX[MAX_SIZE];
726  int SameY[MAX_SIZE];
727  int NumSameX, NumSameY;
728  CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX);
729  CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY);
730 
731  cCubicCell2D Cell(m_Noise, a_Array, a_SizeX, a_SizeY, FracX, FracY);
732 
733  Cell.InitWorkRnds(FloorX[0], FloorY[0]);
734 
735  // Calculate query values using Cell:
736  int FromY = 0;
737  for (int y = 0; y < NumSameY; y++)
738  {
739  int ToY = FromY + SameY[y];
740  int FromX = 0;
741  int CurFloorY = FloorY[FromY];
742  for (int x = 0; x < NumSameX; x++)
743  {
744  int ToX = FromX + SameX[x];
745  Cell.Generate(FromX, ToX, FromY, ToY);
746  Cell.Move(FloorX[ToX], CurFloorY);
747  FromX = ToX;
748  }
749  Cell.Move(FloorX[0], FloorY[ToY]);
750  FromY = ToY;
751  }
752 }
753 
754 
755 
756 
757 
759  NOISE_DATATYPE * a_Array,
760  int a_SizeX, int a_SizeY, int a_SizeZ,
761  NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
762  NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY,
763  NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ
764 ) const
765 {
766  ASSERT(a_SizeX < MAX_SIZE);
767  ASSERT(a_SizeY < MAX_SIZE);
768  ASSERT(a_SizeZ < MAX_SIZE);
769  ASSERT(a_StartX < a_EndX);
770  ASSERT(a_StartY < a_EndY);
771  ASSERT(a_StartZ < a_EndZ);
772 
773  // Calculate the integral and fractional parts of each coord:
774  int FloorX[MAX_SIZE];
775  int FloorY[MAX_SIZE];
776  int FloorZ[MAX_SIZE];
777  NOISE_DATATYPE FracX[MAX_SIZE];
778  NOISE_DATATYPE FracY[MAX_SIZE];
779  NOISE_DATATYPE FracZ[MAX_SIZE];
780  int SameX[MAX_SIZE];
781  int SameY[MAX_SIZE];
782  int SameZ[MAX_SIZE];
783  int NumSameX, NumSameY, NumSameZ;
784  CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX);
785  CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY);
786  CalcFloorFrac(a_SizeZ, a_StartZ, a_EndZ, FloorZ, FracZ, SameZ, NumSameZ);
787 
788  cCubicCell3D Cell(
789  m_Noise, a_Array,
790  a_SizeX, a_SizeY, a_SizeZ,
791  FracX, FracY, FracZ
792  );
793 
794  Cell.InitWorkRnds(FloorX[0], FloorY[0], FloorZ[0]);
795 
796  // Calculate query values using Cell:
797  int FromZ = 0;
798  for (int z = 0; z < NumSameZ; z++)
799  {
800  int ToZ = FromZ + SameZ[z];
801  int CurFloorZ = FloorZ[FromZ];
802  int FromY = 0;
803  for (int y = 0; y < NumSameY; y++)
804  {
805  int ToY = FromY + SameY[y];
806  int CurFloorY = FloorY[FromY];
807  int FromX = 0;
808  for (int x = 0; x < NumSameX; x++)
809  {
810  int ToX = FromX + SameX[x];
811  Cell.Generate(FromX, ToX, FromY, ToY, FromZ, ToZ);
812  Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ);
813  FromX = ToX;
814  }
815  Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ);
816  FromY = ToY;
817  } // for y
818  Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]);
819  FromZ = ToZ;
820  } // for z
821 }
822 
823 
824 
825 
826 
828  int a_Size,
829  NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End,
830  int * a_Floor, NOISE_DATATYPE * a_Frac,
831  int * a_Same, int & a_NumSame
832 ) const
833 {
834  ASSERT(a_Size > 0);
835 
836  NOISE_DATATYPE val = a_Start;
837  NOISE_DATATYPE dif = (a_End - a_Start) / (a_Size - 1);
838  for (int i = 0; i < a_Size; i++)
839  {
840  a_Floor[i] = FAST_FLOOR(val);
841  a_Frac[i] = val - a_Floor[i];
842  val += dif;
843  }
844 
845  // Mark up the same floor values into a_Same / a_NumSame:
846  int CurFloor = a_Floor[0];
847  int LastSame = 0;
848  a_NumSame = 0;
849  for (int i = 1; i < a_Size; i++)
850  {
851  if (a_Floor[i] != CurFloor)
852  {
853  a_Same[a_NumSame] = i - LastSame;
854  LastSame = i;
855  a_NumSame += 1;
856  CurFloor = a_Floor[i];
857  }
858  } // for i - a_Floor[]
859  if (LastSame < a_Size)
860  {
861  a_Same[a_NumSame] = a_Size - LastSame;
862  a_NumSame += 1;
863  }
864 }
865 
866 
867 
868 
869 
871 // cImprovedNoise:
872 
874 {
875  // Initialize the permutations with identity:
876  for (int i = 0; i < 256; i++)
877  {
878  m_Perm[i] = i;
879  }
880 
881  // Randomize the permutation table - swap each element with a random other element:
882  cNoise noise(a_Seed);
883  for (int i = 0; i < 256; i++)
884  {
885  int rnd = (noise.IntNoise1DInt(i) / 7) % 256;
886  std::swap(m_Perm[i], m_Perm[rnd]);
887  }
888 
889  // Copy the lower 256 entries into upper 256 entries:
890  for (int i = 0; i < 256; i++)
891  {
892  m_Perm[i + 256] = m_Perm[i];
893  }
894 }
895 
896 
897 
898 
899 
901  NOISE_DATATYPE * a_Array,
902  int a_SizeX, int a_SizeY,
903  NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
904  NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY
905 ) const
906 {
907  size_t idx = 0;
908  for (int y = 0; y < a_SizeY; y++)
909  {
910  NOISE_DATATYPE ratioY = static_cast<NOISE_DATATYPE>(y) / (a_SizeY - 1);
911  NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY);
912  int noiseYInt = FAST_FLOOR(noiseY);
913  int yCoord = noiseYInt & 255;
914  NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt;
915  NOISE_DATATYPE fadeY = Fade(noiseYFrac);
916  for (int x = 0; x < a_SizeX; x++)
917  {
918  NOISE_DATATYPE ratioX = static_cast<NOISE_DATATYPE>(x) / (a_SizeX - 1);
919  NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX);
920  int noiseXInt = FAST_FLOOR(noiseX);
921  int xCoord = noiseXInt & 255;
922  NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt;
923  NOISE_DATATYPE fadeX = Fade(noiseXFrac);
924 
925  // Hash the coordinates:
926  int A = m_Perm[xCoord] + yCoord;
927  int AA = m_Perm[A];
928  int AB = m_Perm[A + 1];
929  int B = m_Perm[xCoord + 1] + yCoord;
930  int BA = m_Perm[B];
931  int BB = m_Perm[B + 1];
932 
933  // Lerp the gradients:
934  a_Array[idx++] = Lerp(
935  Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, 0), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, 0), fadeX),
936  Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, 0), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, 0), fadeX),
937  fadeY
938  );
939  } // for x
940  } // for y
941 }
942 
943 
944 
945 
946 
948  NOISE_DATATYPE * a_Array,
949  int a_SizeX, int a_SizeY, int a_SizeZ,
950  NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
951  NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY,
952  NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ
953 ) const
954 {
955  size_t idx = 0;
956  for (int z = 0; z < a_SizeZ; z++)
957  {
958  NOISE_DATATYPE ratioZ = static_cast<NOISE_DATATYPE>(z) / (a_SizeZ - 1);
959  NOISE_DATATYPE noiseZ = Lerp(a_StartZ, a_EndZ, ratioZ);
960  int noiseZInt = FAST_FLOOR(noiseZ);
961  int zCoord = noiseZInt & 255;
962  NOISE_DATATYPE noiseZFrac = noiseZ - noiseZInt;
963  NOISE_DATATYPE fadeZ = Fade(noiseZFrac);
964  for (int y = 0; y < a_SizeY; y++)
965  {
966  NOISE_DATATYPE ratioY = static_cast<NOISE_DATATYPE>(y) / (a_SizeY - 1);
967  NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY);
968  int noiseYInt = FAST_FLOOR(noiseY);
969  int yCoord = noiseYInt & 255;
970  NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt;
971  NOISE_DATATYPE fadeY = Fade(noiseYFrac);
972  for (int x = 0; x < a_SizeX; x++)
973  {
974  NOISE_DATATYPE ratioX = static_cast<NOISE_DATATYPE>(x) / (a_SizeX - 1);
975  NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX);
976  int noiseXInt = FAST_FLOOR(noiseX);
977  int xCoord = noiseXInt & 255;
978  NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt;
979  NOISE_DATATYPE fadeX = Fade(noiseXFrac);
980 
981  // Hash the coordinates:
982  int A = m_Perm[xCoord] + yCoord;
983  int AA = m_Perm[A] + zCoord;
984  int AB = m_Perm[A + 1] + zCoord;
985  int B = m_Perm[xCoord + 1] + yCoord;
986  int BA = m_Perm[B] + zCoord;
987  int BB = m_Perm[B + 1] + zCoord;
988 
989  // Lerp the gradients:
990  // TODO: This may be optimized by swapping the coords and recalculating most lerps only "once every x"
991  a_Array[idx++] = Lerp(
992  Lerp(
993  Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, noiseZFrac), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, noiseZFrac), fadeX),
994  Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, noiseZFrac), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac), fadeX),
995  fadeY
996  ),
997  Lerp(
998  Lerp(Grad(m_Perm[AA + 1], noiseXFrac, noiseYFrac, noiseZFrac - 1), Grad(m_Perm[BA + 1], noiseXFrac - 1, noiseYFrac, noiseZFrac - 1), fadeX),
999  Lerp(Grad(m_Perm[AB + 1], noiseXFrac, noiseYFrac - 1, noiseZFrac - 1), Grad(m_Perm[BB + 1], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac - 1), fadeX),
1000  fadeY
1001  ),
1002  fadeZ
1003  );
1004  } // for x
1005  } // for y
1006  } // for z
1007 }
1008 
1009 
1010 
1011 
1012 
1013 NOISE_DATATYPE cImprovedNoise::GetValueAt(int a_X, int a_Y, int a_Z)
1014 {
1015  // Hash the coordinates:
1016  a_X = a_X & 255;
1017  a_Y = a_Y & 255;
1018  a_Z = a_Z & 255;
1019  int A = m_Perm[a_X] + a_Y;
1020  int AA = m_Perm[A] + a_Z;
1021 
1022  return Grad(m_Perm[AA], 1, 1, 1);
1023 }
1024 
1025 
1026 
1027 
1028 
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:336
#define ASSERT(x)
Definition: Globals.h:276
void Debug2DNoise(const NOISE_DATATYPE *a_Noise, size_t a_SizeX, size_t a_SizeY, const AString &a_FileNameBase, NOISE_DATATYPE a_Coeff)
Exports the noise array into a file.
Definition: Noise.cpp:168
void Debug3DNoise(const NOISE_DATATYPE *a_Noise, size_t a_SizeX, size_t a_SizeY, size_t a_SizeZ, const AString &a_FileNameBase, NOISE_DATATYPE a_Coeff)
Exports the noise array into a set of files, ordered by XY and XZ.
Definition: Noise.cpp:115
#define FAST_FLOOR(x)
Definition: Noise.cpp:6
NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
Linearly interpolates between two values.
Definition: Noise.h:324
float NOISE_DATATYPE
The datatype used by all the noise generators.
Definition: Noise.h:9
std::string AString
Definition: StringUtils.h:11
void InitWorkRnds(int a_FloorX, int a_FloorY)
Initializes m_WorkRnds[] with the specified Floor values.
Definition: Noise.cpp:288
NOISE_DATATYPE Workspace[4][4]
Definition: Noise.cpp:220
int m_CurFloorY
Definition: Noise.cpp:228
int m_SizeY
Definition: Noise.cpp:231
const NOISE_DATATYPE * m_FracY
Definition: Noise.cpp:233
int m_CurFloorX
Definition: Noise.cpp:227
NOISE_DATATYPE * m_Array
Definition: Noise.cpp:230
Workspace m_Workspace2
Buffer 2 for workspace doublebuffering, used in Move()
Definition: Noise.cpp:226
int m_SizeX
Definition: Noise.cpp:231
void Generate(int a_FromX, int a_ToX, int a_FromY, int a_ToY)
Uses current m_WorkRnds[] to generate part of the array.
Definition: Noise.cpp:263
const cNoise & m_Noise
Definition: Noise.cpp:222
cCubicCell2D(const cNoise &a_Noise, NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, const NOISE_DATATYPE *a_FracX, const NOISE_DATATYPE *a_FracY)
Definition: Noise.cpp:240
Workspace m_Workspace1
Buffer 1 for workspace doublebuffering, used in Move()
Definition: Noise.cpp:225
void Move(int a_NewFloorX, int a_NewFloorY)
Updates m_WorkRnds[] for the new Floor values.
Definition: Noise.cpp:307
const NOISE_DATATYPE * m_FracX
Definition: Noise.cpp:232
Workspace * m_WorkRnds
The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering)
Definition: Noise.cpp:224
Workspace * m_WorkRnds
The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering)
Definition: Noise.cpp:377
void Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ)
Updates m_WorkRnds[] for the new Floor values.
Definition: Noise.cpp:485
const NOISE_DATATYPE * m_FracX
Definition: Noise.cpp:386
const cNoise & m_Noise
Definition: Noise.cpp:375
Workspace m_Workspace2
Buffer 2 for workspace doublebuffering, used in Move()
Definition: Noise.cpp:379
int m_SizeZ
Definition: Noise.cpp:385
cCubicCell3D(const cNoise &a_Noise, NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, int a_SizeZ, const NOISE_DATATYPE *a_FracX, const NOISE_DATATYPE *a_FracY, const NOISE_DATATYPE *a_FracZ)
Definition: Noise.cpp:395
Workspace m_Workspace1
Buffer 1 for workspace doublebuffering, used in Move()
Definition: Noise.cpp:378
void InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ)
Initializes m_WorkRnds[] with the specified Floor values.
Definition: Noise.cpp:461
int m_CurFloorY
Definition: Noise.cpp:381
int m_CurFloorX
Definition: Noise.cpp:380
NOISE_DATATYPE * m_Array
Definition: Noise.cpp:384
const NOISE_DATATYPE * m_FracY
Definition: Noise.cpp:387
NOISE_DATATYPE Workspace[4][4][4]
Definition: Noise.cpp:373
const NOISE_DATATYPE * m_FracZ
Definition: Noise.cpp:388
int m_SizeX
Definition: Noise.cpp:385
int m_CurFloorZ
Definition: Noise.cpp:382
void Generate(int a_FromX, int a_ToX, int a_FromY, int a_ToY, int a_FromZ, int a_ToZ)
Uses current m_WorkRnds[] to generate part of the array.
Definition: Noise.cpp:422
int m_SizeY
Definition: Noise.cpp:385
Definition: Noise.h:20
static NOISE_DATATYPE CubicInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct)
Definition: Noise.h:274
int IntNoise1DInt(int a_X) const
Definition: Noise.h:233
static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct)
Definition: Noise.h:288
NOISE_DATATYPE CosineNoise1D(NOISE_DATATYPE a_X) const
Definition: Noise.cpp:562
cNoise(int a_Seed)
Definition: Noise.cpp:533
NOISE_DATATYPE CubicNoise2D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const
Definition: Noise.cpp:593
NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) const
Definition: Noise.h:198
NOISE_DATATYPE CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const
Definition: Noise.cpp:621
NOISE_DATATYPE SmoothNoise1D(int a_X) const
Definition: Noise.cpp:584
static NOISE_DATATYPE LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct)
Definition: Noise.h:299
NOISE_DATATYPE LinearNoise1D(NOISE_DATATYPE a_X) const
Definition: Noise.cpp:551
NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const
Definition: Noise.h:210
NOISE_DATATYPE IntNoise1D(int a_X) const
Definition: Noise.h:187
NOISE_DATATYPE CubicNoise1D(NOISE_DATATYPE a_X) const
Definition: Noise.cpp:573
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) const
Fills a 3D array with the values of the noise.
Definition: Noise.cpp:758
cNoise m_Noise
Noise used for integral random values.
Definition: Noise.h:99
cCubicNoise(int a_Seed)
Creates a new instance with the specified seed.
Definition: Noise.cpp:697
void CalcFloorFrac(int a_Size, NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End, int *a_Floor, NOISE_DATATYPE *a_Frac, int *a_Same, int &a_NumSame) const
Calculates the integral and fractional parts along one axis.
Definition: Noise.cpp:827
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) const
Fills a 2D array with the values of the noise.
Definition: Noise.cpp:706
static const int MAX_SIZE
Maximum size of each dimension of the query arrays.
Definition: Noise.h:71
Improved noise, as described by Ken Perlin: https://mrl.nyu.edu/~perlin/paper445.pdf Implementation a...
Definition: Noise.h:122
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) const
Fills a 3D array with the values of the noise.
Definition: Noise.cpp:947
cImprovedNoise(int a_Seed)
Constructs a new instance of the noise obbject.
Definition: Noise.cpp:873
NOISE_DATATYPE GetValueAt(int a_X, int a_Y, int a_Z)
Returns the value at the specified integral coords.
Definition: Noise.cpp:1013
static NOISE_DATATYPE Fade(NOISE_DATATYPE a_T)
Calculates the fade curve, 6 * t^5 - 15 * t^4 + 10 * t^3.
Definition: Noise.h:157
int m_Perm[512]
The permutation table used by the noise function.
Definition: Noise.h:153
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) const
Fills a 2D array with the values of the noise.
Definition: Noise.cpp:900
static NOISE_DATATYPE Grad(int a_Hash, NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z)
Returns the gradient value based on the hash.
Definition: Noise.h:163
Definition: File.h:38
@ fmWrite
Definition: File.h:55
bool Open(const AString &iFileName, eMode iMode)
Definition: File.cpp:52
int Write(const void *a_Buffer, size_t a_NumBytes)
Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written,...
Definition: File.cpp:180