3 * Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
4 * Copyright (C) 2010-2014 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
7 * Redistribution and use in source and binary forms, with or without modification, are
8 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <cstring> // memset
31 #include "util/numeric.h"
32 #include "util/string.h"
33 #include "exceptions.h"
35 #define NOISE_MAGIC_X 1619
36 #define NOISE_MAGIC_Y 31337
37 #define NOISE_MAGIC_Z 52591
38 // Unsigned magic seed prevents undefined behavior.
39 #define NOISE_MAGIC_SEED 1013U
41 FlagDesc flagdesc_noiseparams[] = {
42 {"defaults", NOISE_FLAG_DEFAULTS},
43 {"eased", NOISE_FLAG_EASED},
44 {"absvalue", NOISE_FLAG_ABSVALUE},
45 {"pointbuffer", NOISE_FLAG_POINTBUFFER},
46 {"simplex", NOISE_FLAG_SIMPLEX},
50 ///////////////////////////////////////////////////////////////////////////////
52 PcgRandom::PcgRandom(u64 state, u64 seq)
57 void PcgRandom::seed(u64 state, u64 seq)
60 m_inc = (seq << 1u) | 1u;
69 u64 oldstate = m_state;
70 m_state = oldstate * 6364136223846793005ULL + m_inc;
72 u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
73 u32 rot = oldstate >> 59u;
74 return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
78 u32 PcgRandom::range(u32 bound)
80 // If the bound is 0, we cover the whole RNG's range
85 This is an optimization of the expression:
86 0x100000000ull % bound
87 since 64-bit modulo operations typically much slower than 32.
89 u32 threshold = -bound % bound;
93 If the bound is not a multiple of the RNG's range, it may cause bias,
94 e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
95 Using rand() % 3, the number 0 would be twice as likely to appear.
96 With a very large RNG range, the effect becomes less prevalent but
99 This can be solved by modifying the range of the RNG to become a
100 multiple of bound by dropping values above the a threshold.
102 In our example, threshold == 4 % 3 == 1, so reject values < 1
103 (that is, 0), thus making the range == 3 with no bias.
105 This loop may look dangerous, but will always terminate due to the
106 RNG's property of uniformity.
108 while ((r = next()) < threshold)
115 s32 PcgRandom::range(s32 min, s32 max)
118 throw PrngException("Invalid range (max < min)");
120 // We have to cast to s64 because otherwise this could overflow,
121 // and signed overflow is undefined behavior.
122 u32 bound = (s64)max - (s64)min + 1;
123 return range(bound) + min;
127 void PcgRandom::bytes(void *out, size_t len)
129 u8 *outb = (u8 *)out;
134 if (bytes_left == 0) {
135 bytes_left = sizeof(u32);
147 s32 PcgRandom::randNormalDist(s32 min, s32 max, int num_trials)
150 for (int i = 0; i != num_trials; i++)
151 accum += range(min, max);
152 return myround((float)accum / num_trials);
155 ///////////////////////////////////////////////////////////////////////////////
157 float noise2d(int x, int y, s32 seed)
159 unsigned int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
160 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
162 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
163 return 1.f - (float)(int)n / 0x40000000;
167 float noise3d(int x, int y, int z, s32 seed)
169 unsigned int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
170 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
172 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
173 return 1.f - (float)(int)n / 0x40000000;
177 inline float dotProduct(float vx, float vy, float wx, float wy)
179 return vx * wx + vy * wy;
183 inline float linearInterpolation(float v0, float v1, float t)
185 return v0 + (v1 - v0) * t;
189 inline float biLinearInterpolation(
190 float v00, float v10,
191 float v01, float v11,
195 // Inlining will optimize this branch out when possible
200 float u = linearInterpolation(v00, v10, x);
201 float v = linearInterpolation(v01, v11, x);
202 return linearInterpolation(u, v, y);
206 inline float triLinearInterpolation(
207 float v000, float v100, float v010, float v110,
208 float v001, float v101, float v011, float v111,
209 float x, float y, float z,
212 // Inlining will optimize this branch out when possible
218 float u = biLinearInterpolation(v000, v100, v010, v110, x, y, false);
219 float v = biLinearInterpolation(v001, v101, v011, v111, x, y, false);
220 return linearInterpolation(u, v, z);
223 float noise2d_gradient(float x, float y, s32 seed, bool eased)
225 // Calculate the integer coordinates
228 // Calculate the remaining part of the coordinates
229 float xl = x - (float)x0;
230 float yl = y - (float)y0;
231 // Get values for corners of square
232 float v00 = noise2d(x0, y0, seed);
233 float v10 = noise2d(x0+1, y0, seed);
234 float v01 = noise2d(x0, y0+1, seed);
235 float v11 = noise2d(x0+1, y0+1, seed);
237 return biLinearInterpolation(v00, v10, v01, v11, xl, yl, eased);
241 float noise3d_gradient(float x, float y, float z, s32 seed, bool eased)
243 // Calculate the integer coordinates
247 // Calculate the remaining part of the coordinates
248 float xl = x - (float)x0;
249 float yl = y - (float)y0;
250 float zl = z - (float)z0;
251 // Get values for corners of cube
252 float v000 = noise3d(x0, y0, z0, seed);
253 float v100 = noise3d(x0 + 1, y0, z0, seed);
254 float v010 = noise3d(x0, y0 + 1, z0, seed);
255 float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
256 float v001 = noise3d(x0, y0, z0 + 1, seed);
257 float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
258 float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
259 float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
261 return triLinearInterpolation(
262 v000, v100, v010, v110,
263 v001, v101, v011, v111,
269 float noise2d_perlin(float x, float y, s32 seed,
270 int octaves, float persistence, bool eased)
275 for (int i = 0; i < octaves; i++)
277 a += g * noise2d_gradient(x * f, y * f, seed + i, eased);
285 float contour(float v)
294 ///////////////////////// [ New noise ] ////////////////////////////
297 float NoisePerlin2D(const NoiseParams *np, float x, float y, s32 seed)
307 for (size_t i = 0; i < np->octaves; i++) {
308 float noiseval = noise2d_gradient(x * f, y * f, seed + i,
309 np->flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED));
311 if (np->flags & NOISE_FLAG_ABSVALUE)
312 noiseval = std::fabs(noiseval);
319 return np->offset + a * np->scale;
323 float NoisePerlin3D(const NoiseParams *np, float x, float y, float z, s32 seed)
334 for (size_t i = 0; i < np->octaves; i++) {
335 float noiseval = noise3d_gradient(x * f, y * f, z * f, seed + i,
336 np->flags & NOISE_FLAG_EASED);
338 if (np->flags & NOISE_FLAG_ABSVALUE)
339 noiseval = std::fabs(noiseval);
346 return np->offset + a * np->scale;
350 Noise::Noise(const NoiseParams *np_, s32 seed, u32 sx, u32 sy, u32 sz)
364 delete[] gradient_buf;
365 delete[] persist_buf;
371 void Noise::allocBuffers()
380 this->noise_buf = NULL;
381 resizeNoiseBuf(sz > 1);
383 delete[] gradient_buf;
384 delete[] persist_buf;
388 size_t bufsize = sx * sy * sz;
389 this->persist_buf = NULL;
390 this->gradient_buf = new float[bufsize];
391 this->result = new float[bufsize];
392 } catch (std::bad_alloc &e) {
393 throw InvalidNoiseParamsException();
398 void Noise::setSize(u32 sx, u32 sy, u32 sz)
408 void Noise::setSpreadFactor(v3f spread)
410 this->np.spread = spread;
412 resizeNoiseBuf(sz > 1);
416 void Noise::setOctaves(int octaves)
418 this->np.octaves = octaves;
420 resizeNoiseBuf(sz > 1);
424 void Noise::resizeNoiseBuf(bool is3d)
426 // Maximum possible spread value factor
427 float ofactor = (np.lacunarity > 1.0) ?
428 pow(np.lacunarity, np.octaves - 1) :
431 // Noise lattice point count
432 // (int)(sz * spread * ofactor) is # of lattice points crossed due to length
433 float num_noise_points_x = sx * ofactor / np.spread.X;
434 float num_noise_points_y = sy * ofactor / np.spread.Y;
435 float num_noise_points_z = sz * ofactor / np.spread.Z;
437 // Protect against obviously invalid parameters
438 if (num_noise_points_x > 1000000000.f ||
439 num_noise_points_y > 1000000000.f ||
440 num_noise_points_z > 1000000000.f)
441 throw InvalidNoiseParamsException();
443 // Protect against an octave having a spread < 1, causing broken noise values
444 if (np.spread.X / ofactor < 1.0f ||
445 np.spread.Y / ofactor < 1.0f ||
446 np.spread.Z / ofactor < 1.0f) {
447 errorstream << "A noise parameter has too many octaves: "
448 << np.octaves << " octaves" << std::endl;
449 throw InvalidNoiseParamsException("A noise parameter has too many octaves");
452 // + 2 for the two initial endpoints
453 // + 1 for potentially crossing a boundary due to offset
454 size_t nlx = (size_t)std::ceil(num_noise_points_x) + 3;
455 size_t nly = (size_t)std::ceil(num_noise_points_y) + 3;
456 size_t nlz = is3d ? (size_t)std::ceil(num_noise_points_z) + 3 : 1;
460 noise_buf = new float[nlx * nly * nlz];
461 } catch (std::bad_alloc &e) {
462 throw InvalidNoiseParamsException();
468 * NB: This algorithm is not optimal in terms of space complexity. The entire
469 * integer lattice of noise points could be done as 2 lines instead, and for 3D,
470 * 2 lines + 2 planes.
471 * However, this would require the noise calls to be interposed with the
472 * interpolation loops, which may trash the icache, leading to lower overall
474 * Another optimization that could save half as many noise calls is to carry over
475 * values from the previous noise lattice as midpoints in the new lattice for the
478 #define idx(x, y) ((y) * nlx + (x))
479 void Noise::gradientMap2D(
481 float step_x, float step_y,
484 float v00, v01, v10, v11, u, v, orig_u;
485 u32 index, i, j, noisex, noisey;
489 bool eased = np.flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED);
496 //calculate noise point lattice
497 nlx = (u32)(u + sx * step_x) + 2;
498 nly = (u32)(v + sy * step_y) + 2;
500 for (j = 0; j != nly; j++)
501 for (i = 0; i != nlx; i++)
502 noise_buf[index++] = noise2d(x0 + i, y0 + j, seed);
504 //calculate interpolations
507 for (j = 0; j != sy; j++) {
508 v00 = noise_buf[idx(0, noisey)];
509 v10 = noise_buf[idx(1, noisey)];
510 v01 = noise_buf[idx(0, noisey + 1)];
511 v11 = noise_buf[idx(1, noisey + 1)];
515 for (i = 0; i != sx; i++) {
516 gradient_buf[index++] =
517 biLinearInterpolation(v00, v10, v01, v11, u, v, eased);
525 v10 = noise_buf[idx(noisex + 1, noisey)];
526 v11 = noise_buf[idx(noisex + 1, noisey + 1)];
540 #define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
541 void Noise::gradientMap3D(
542 float x, float y, float z,
543 float step_x, float step_y, float step_z,
546 float v000, v010, v100, v110;
547 float v001, v011, v101, v111;
548 float u, v, w, orig_u, orig_v;
549 u32 index, i, j, k, noisex, noisey, noisez;
553 bool eased = np.flags & NOISE_FLAG_EASED;
564 //calculate noise point lattice
565 nlx = (u32)(u + sx * step_x) + 2;
566 nly = (u32)(v + sy * step_y) + 2;
567 nlz = (u32)(w + sz * step_z) + 2;
569 for (k = 0; k != nlz; k++)
570 for (j = 0; j != nly; j++)
571 for (i = 0; i != nlx; i++)
572 noise_buf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
574 //calculate interpolations
578 for (k = 0; k != sz; k++) {
581 for (j = 0; j != sy; j++) {
582 v000 = noise_buf[idx(0, noisey, noisez)];
583 v100 = noise_buf[idx(1, noisey, noisez)];
584 v010 = noise_buf[idx(0, noisey + 1, noisez)];
585 v110 = noise_buf[idx(1, noisey + 1, noisez)];
586 v001 = noise_buf[idx(0, noisey, noisez + 1)];
587 v101 = noise_buf[idx(1, noisey, noisez + 1)];
588 v011 = noise_buf[idx(0, noisey + 1, noisez + 1)];
589 v111 = noise_buf[idx(1, noisey + 1, noisez + 1)];
593 for (i = 0; i != sx; i++) {
594 gradient_buf[index++] = triLinearInterpolation(
595 v000, v100, v010, v110,
596 v001, v101, v011, v111,
606 v100 = noise_buf[idx(noisex + 1, noisey, noisez)];
607 v110 = noise_buf[idx(noisex + 1, noisey + 1, noisez)];
610 v101 = noise_buf[idx(noisex + 1, noisey, noisez + 1)];
611 v111 = noise_buf[idx(noisex + 1, noisey + 1, noisez + 1)];
632 float *Noise::perlinMap2D(float x, float y, float *persistence_map)
634 float f = 1.0, g = 1.0;
635 size_t bufsize = sx * sy;
640 memset(result, 0, sizeof(float) * bufsize);
642 if (persistence_map) {
644 persist_buf = new float[bufsize];
645 for (size_t i = 0; i != bufsize; i++)
646 persist_buf[i] = 1.0;
649 for (size_t oct = 0; oct < np.octaves; oct++) {
650 gradientMap2D(x * f, y * f,
651 f / np.spread.X, f / np.spread.Y,
652 seed + np.seed + oct);
654 updateResults(g, persist_buf, persistence_map, bufsize);
660 if (std::fabs(np.offset - 0.f) > 0.00001 || std::fabs(np.scale - 1.f) > 0.00001) {
661 for (size_t i = 0; i != bufsize; i++)
662 result[i] = result[i] * np.scale + np.offset;
669 float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
671 float f = 1.0, g = 1.0;
672 size_t bufsize = sx * sy * sz;
678 memset(result, 0, sizeof(float) * bufsize);
680 if (persistence_map) {
682 persist_buf = new float[bufsize];
683 for (size_t i = 0; i != bufsize; i++)
684 persist_buf[i] = 1.0;
687 for (size_t oct = 0; oct < np.octaves; oct++) {
688 gradientMap3D(x * f, y * f, z * f,
689 f / np.spread.X, f / np.spread.Y, f / np.spread.Z,
690 seed + np.seed + oct);
692 updateResults(g, persist_buf, persistence_map, bufsize);
698 if (std::fabs(np.offset - 0.f) > 0.00001 || std::fabs(np.scale - 1.f) > 0.00001) {
699 for (size_t i = 0; i != bufsize; i++)
700 result[i] = result[i] * np.scale + np.offset;
707 void Noise::updateResults(float g, float *gmap,
708 const float *persistence_map, size_t bufsize)
710 // This looks very ugly, but it is 50-70% faster than having
711 // conditional statements inside the loop
712 if (np.flags & NOISE_FLAG_ABSVALUE) {
713 if (persistence_map) {
714 for (size_t i = 0; i != bufsize; i++) {
715 result[i] += gmap[i] * std::fabs(gradient_buf[i]);
716 gmap[i] *= persistence_map[i];
719 for (size_t i = 0; i != bufsize; i++)
720 result[i] += g * std::fabs(gradient_buf[i]);
723 if (persistence_map) {
724 for (size_t i = 0; i != bufsize; i++) {
725 result[i] += gmap[i] * gradient_buf[i];
726 gmap[i] *= persistence_map[i];
729 for (size_t i = 0; i != bufsize; i++)
730 result[i] += g * gradient_buf[i];