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 typedef float (*Interp2dFxn)(
42 float v00, float v10, float v01, float v11,
45 typedef float (*Interp3dFxn)(
46 float v000, float v100, float v010, float v110,
47 float v001, float v101, float v011, float v111,
48 float x, float y, float z);
50 FlagDesc flagdesc_noiseparams[] = {
51 {"defaults", NOISE_FLAG_DEFAULTS},
52 {"eased", NOISE_FLAG_EASED},
53 {"absvalue", NOISE_FLAG_ABSVALUE},
54 {"pointbuffer", NOISE_FLAG_POINTBUFFER},
55 {"simplex", NOISE_FLAG_SIMPLEX},
59 ///////////////////////////////////////////////////////////////////////////////
61 PcgRandom::PcgRandom(u64 state, u64 seq)
66 void PcgRandom::seed(u64 state, u64 seq)
69 m_inc = (seq << 1u) | 1u;
78 u64 oldstate = m_state;
79 m_state = oldstate * 6364136223846793005ULL + m_inc;
81 u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
82 u32 rot = oldstate >> 59u;
83 return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
87 u32 PcgRandom::range(u32 bound)
89 // If the bound is 0, we cover the whole RNG's range
94 This is an optimization of the expression:
95 0x100000000ull % bound
96 since 64-bit modulo operations typically much slower than 32.
98 u32 threshold = -bound % bound;
102 If the bound is not a multiple of the RNG's range, it may cause bias,
103 e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
104 Using rand() % 3, the number 0 would be twice as likely to appear.
105 With a very large RNG range, the effect becomes less prevalent but
108 This can be solved by modifying the range of the RNG to become a
109 multiple of bound by dropping values above the a threshold.
111 In our example, threshold == 4 % 3 == 1, so reject values < 1
112 (that is, 0), thus making the range == 3 with no bias.
114 This loop may look dangerous, but will always terminate due to the
115 RNG's property of uniformity.
117 while ((r = next()) < threshold)
124 s32 PcgRandom::range(s32 min, s32 max)
127 throw PrngException("Invalid range (max < min)");
129 // We have to cast to s64 because otherwise this could overflow,
130 // and signed overflow is undefined behavior.
131 u32 bound = (s64)max - (s64)min + 1;
132 return range(bound) + min;
136 void PcgRandom::bytes(void *out, size_t len)
138 u8 *outb = (u8 *)out;
143 if (bytes_left == 0) {
144 bytes_left = sizeof(u32);
156 s32 PcgRandom::randNormalDist(s32 min, s32 max, int num_trials)
159 for (int i = 0; i != num_trials; i++)
160 accum += range(min, max);
161 return myround((float)accum / num_trials);
164 ///////////////////////////////////////////////////////////////////////////////
166 float noise2d(int x, int y, s32 seed)
168 unsigned int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
169 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
171 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
172 return 1.f - (float)(int)n / 0x40000000;
176 float noise3d(int x, int y, int z, s32 seed)
178 unsigned int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
179 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
181 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
182 return 1.f - (float)(int)n / 0x40000000;
186 inline float dotProduct(float vx, float vy, float wx, float wy)
188 return vx * wx + vy * wy;
192 inline float linearInterpolation(float v0, float v1, float t)
194 return v0 + (v1 - v0) * t;
198 inline float biLinearInterpolation(
199 float v00, float v10,
200 float v01, float v11,
203 float tx = easeCurve(x);
204 float ty = easeCurve(y);
205 float u = linearInterpolation(v00, v10, tx);
206 float v = linearInterpolation(v01, v11, tx);
207 return linearInterpolation(u, v, ty);
211 inline float biLinearInterpolationNoEase(
212 float v00, float v10,
213 float v01, float v11,
216 float u = linearInterpolation(v00, v10, x);
217 float v = linearInterpolation(v01, v11, x);
218 return linearInterpolation(u, v, y);
222 float triLinearInterpolation(
223 float v000, float v100, float v010, float v110,
224 float v001, float v101, float v011, float v111,
225 float x, float y, float z)
227 float tx = easeCurve(x);
228 float ty = easeCurve(y);
229 float tz = easeCurve(z);
230 float u = biLinearInterpolationNoEase(v000, v100, v010, v110, tx, ty);
231 float v = biLinearInterpolationNoEase(v001, v101, v011, v111, tx, ty);
232 return linearInterpolation(u, v, tz);
235 float triLinearInterpolationNoEase(
236 float v000, float v100, float v010, float v110,
237 float v001, float v101, float v011, float v111,
238 float x, float y, float z)
240 float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
241 float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
242 return linearInterpolation(u, v, z);
245 float noise2d_gradient(float x, float y, s32 seed, bool eased)
247 // Calculate the integer coordinates
250 // Calculate the remaining part of the coordinates
251 float xl = x - (float)x0;
252 float yl = y - (float)y0;
253 // Get values for corners of square
254 float v00 = noise2d(x0, y0, seed);
255 float v10 = noise2d(x0+1, y0, seed);
256 float v01 = noise2d(x0, y0+1, seed);
257 float v11 = noise2d(x0+1, y0+1, seed);
260 return biLinearInterpolation(v00, v10, v01, v11, xl, yl);
262 return biLinearInterpolationNoEase(v00, v10, v01, v11, xl, yl);
266 float noise3d_gradient(float x, float y, float z, s32 seed, bool eased)
268 // Calculate the integer coordinates
272 // Calculate the remaining part of the coordinates
273 float xl = x - (float)x0;
274 float yl = y - (float)y0;
275 float zl = z - (float)z0;
276 // Get values for corners of cube
277 float v000 = noise3d(x0, y0, z0, seed);
278 float v100 = noise3d(x0 + 1, y0, z0, seed);
279 float v010 = noise3d(x0, y0 + 1, z0, seed);
280 float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
281 float v001 = noise3d(x0, y0, z0 + 1, seed);
282 float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
283 float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
284 float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
287 return triLinearInterpolation(
288 v000, v100, v010, v110,
289 v001, v101, v011, v111,
293 return triLinearInterpolationNoEase(
294 v000, v100, v010, v110,
295 v001, v101, v011, v111,
300 float noise2d_perlin(float x, float y, s32 seed,
301 int octaves, float persistence, bool eased)
306 for (int i = 0; i < octaves; i++)
308 a += g * noise2d_gradient(x * f, y * f, seed + i, eased);
316 float contour(float v)
325 ///////////////////////// [ New noise ] ////////////////////////////
328 float NoisePerlin2D(const NoiseParams *np, float x, float y, s32 seed)
338 for (size_t i = 0; i < np->octaves; i++) {
339 float noiseval = noise2d_gradient(x * f, y * f, seed + i,
340 np->flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED));
342 if (np->flags & NOISE_FLAG_ABSVALUE)
343 noiseval = std::fabs(noiseval);
350 return np->offset + a * np->scale;
354 float NoisePerlin3D(const NoiseParams *np, float x, float y, float z, s32 seed)
365 for (size_t i = 0; i < np->octaves; i++) {
366 float noiseval = noise3d_gradient(x * f, y * f, z * f, seed + i,
367 np->flags & NOISE_FLAG_EASED);
369 if (np->flags & NOISE_FLAG_ABSVALUE)
370 noiseval = std::fabs(noiseval);
377 return np->offset + a * np->scale;
381 Noise::Noise(const NoiseParams *np_, s32 seed, u32 sx, u32 sy, u32 sz)
395 delete[] gradient_buf;
396 delete[] persist_buf;
402 void Noise::allocBuffers()
411 this->noise_buf = NULL;
412 resizeNoiseBuf(sz > 1);
414 delete[] gradient_buf;
415 delete[] persist_buf;
419 size_t bufsize = sx * sy * sz;
420 this->persist_buf = NULL;
421 this->gradient_buf = new float[bufsize];
422 this->result = new float[bufsize];
423 } catch (std::bad_alloc &e) {
424 throw InvalidNoiseParamsException();
429 void Noise::setSize(u32 sx, u32 sy, u32 sz)
439 void Noise::setSpreadFactor(v3f spread)
441 this->np.spread = spread;
443 resizeNoiseBuf(sz > 1);
447 void Noise::setOctaves(int octaves)
449 this->np.octaves = octaves;
451 resizeNoiseBuf(sz > 1);
455 void Noise::resizeNoiseBuf(bool is3d)
457 // Maximum possible spread value factor
458 float ofactor = (np.lacunarity > 1.0) ?
459 pow(np.lacunarity, np.octaves - 1) :
462 // Noise lattice point count
463 // (int)(sz * spread * ofactor) is # of lattice points crossed due to length
464 float num_noise_points_x = sx * ofactor / np.spread.X;
465 float num_noise_points_y = sy * ofactor / np.spread.Y;
466 float num_noise_points_z = sz * ofactor / np.spread.Z;
468 // Protect against obviously invalid parameters
469 if (num_noise_points_x > 1000000000.f ||
470 num_noise_points_y > 1000000000.f ||
471 num_noise_points_z > 1000000000.f)
472 throw InvalidNoiseParamsException();
474 // Protect against an octave having a spread < 1, causing broken noise values
475 if (np.spread.X / ofactor < 1.0f ||
476 np.spread.Y / ofactor < 1.0f ||
477 np.spread.Z / ofactor < 1.0f) {
478 errorstream << "A noise parameter has too many octaves: "
479 << np.octaves << " octaves" << std::endl;
480 throw InvalidNoiseParamsException("A noise parameter has too many octaves");
483 // + 2 for the two initial endpoints
484 // + 1 for potentially crossing a boundary due to offset
485 size_t nlx = (size_t)std::ceil(num_noise_points_x) + 3;
486 size_t nly = (size_t)std::ceil(num_noise_points_y) + 3;
487 size_t nlz = is3d ? (size_t)std::ceil(num_noise_points_z) + 3 : 1;
491 noise_buf = new float[nlx * nly * nlz];
492 } catch (std::bad_alloc &e) {
493 throw InvalidNoiseParamsException();
499 * NB: This algorithm is not optimal in terms of space complexity. The entire
500 * integer lattice of noise points could be done as 2 lines instead, and for 3D,
501 * 2 lines + 2 planes.
502 * However, this would require the noise calls to be interposed with the
503 * interpolation loops, which may trash the icache, leading to lower overall
505 * Another optimization that could save half as many noise calls is to carry over
506 * values from the previous noise lattice as midpoints in the new lattice for the
509 #define idx(x, y) ((y) * nlx + (x))
510 void Noise::gradientMap2D(
512 float step_x, float step_y,
515 float v00, v01, v10, v11, u, v, orig_u;
516 u32 index, i, j, noisex, noisey;
520 bool eased = np.flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED);
521 Interp2dFxn interpolate = eased ?
522 biLinearInterpolation : biLinearInterpolationNoEase;
530 //calculate noise point lattice
531 nlx = (u32)(u + sx * step_x) + 2;
532 nly = (u32)(v + sy * step_y) + 2;
534 for (j = 0; j != nly; j++)
535 for (i = 0; i != nlx; i++)
536 noise_buf[index++] = noise2d(x0 + i, y0 + j, seed);
538 //calculate interpolations
541 for (j = 0; j != sy; j++) {
542 v00 = noise_buf[idx(0, noisey)];
543 v10 = noise_buf[idx(1, noisey)];
544 v01 = noise_buf[idx(0, noisey + 1)];
545 v11 = noise_buf[idx(1, noisey + 1)];
549 for (i = 0; i != sx; i++) {
550 gradient_buf[index++] = interpolate(v00, v10, v01, v11, u, v);
558 v10 = noise_buf[idx(noisex + 1, noisey)];
559 v11 = noise_buf[idx(noisex + 1, noisey + 1)];
573 #define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
574 void Noise::gradientMap3D(
575 float x, float y, float z,
576 float step_x, float step_y, float step_z,
579 float v000, v010, v100, v110;
580 float v001, v011, v101, v111;
581 float u, v, w, orig_u, orig_v;
582 u32 index, i, j, k, noisex, noisey, noisez;
586 Interp3dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ?
587 triLinearInterpolation : triLinearInterpolationNoEase;
598 //calculate noise point lattice
599 nlx = (u32)(u + sx * step_x) + 2;
600 nly = (u32)(v + sy * step_y) + 2;
601 nlz = (u32)(w + sz * step_z) + 2;
603 for (k = 0; k != nlz; k++)
604 for (j = 0; j != nly; j++)
605 for (i = 0; i != nlx; i++)
606 noise_buf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
608 //calculate interpolations
612 for (k = 0; k != sz; k++) {
615 for (j = 0; j != sy; j++) {
616 v000 = noise_buf[idx(0, noisey, noisez)];
617 v100 = noise_buf[idx(1, noisey, noisez)];
618 v010 = noise_buf[idx(0, noisey + 1, noisez)];
619 v110 = noise_buf[idx(1, noisey + 1, noisez)];
620 v001 = noise_buf[idx(0, noisey, noisez + 1)];
621 v101 = noise_buf[idx(1, noisey, noisez + 1)];
622 v011 = noise_buf[idx(0, noisey + 1, noisez + 1)];
623 v111 = noise_buf[idx(1, noisey + 1, noisez + 1)];
627 for (i = 0; i != sx; i++) {
628 gradient_buf[index++] = interpolate(
629 v000, v100, v010, v110,
630 v001, v101, v011, v111,
639 v100 = noise_buf[idx(noisex + 1, noisey, noisez)];
640 v110 = noise_buf[idx(noisex + 1, noisey + 1, noisez)];
643 v101 = noise_buf[idx(noisex + 1, noisey, noisez + 1)];
644 v111 = noise_buf[idx(noisex + 1, noisey + 1, noisez + 1)];
665 float *Noise::perlinMap2D(float x, float y, float *persistence_map)
667 float f = 1.0, g = 1.0;
668 size_t bufsize = sx * sy;
673 memset(result, 0, sizeof(float) * bufsize);
675 if (persistence_map) {
677 persist_buf = new float[bufsize];
678 for (size_t i = 0; i != bufsize; i++)
679 persist_buf[i] = 1.0;
682 for (size_t oct = 0; oct < np.octaves; oct++) {
683 gradientMap2D(x * f, y * f,
684 f / np.spread.X, f / np.spread.Y,
685 seed + np.seed + oct);
687 updateResults(g, persist_buf, persistence_map, bufsize);
693 if (std::fabs(np.offset - 0.f) > 0.00001 || std::fabs(np.scale - 1.f) > 0.00001) {
694 for (size_t i = 0; i != bufsize; i++)
695 result[i] = result[i] * np.scale + np.offset;
702 float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
704 float f = 1.0, g = 1.0;
705 size_t bufsize = sx * sy * sz;
711 memset(result, 0, sizeof(float) * bufsize);
713 if (persistence_map) {
715 persist_buf = new float[bufsize];
716 for (size_t i = 0; i != bufsize; i++)
717 persist_buf[i] = 1.0;
720 for (size_t oct = 0; oct < np.octaves; oct++) {
721 gradientMap3D(x * f, y * f, z * f,
722 f / np.spread.X, f / np.spread.Y, f / np.spread.Z,
723 seed + np.seed + oct);
725 updateResults(g, persist_buf, persistence_map, bufsize);
731 if (std::fabs(np.offset - 0.f) > 0.00001 || std::fabs(np.scale - 1.f) > 0.00001) {
732 for (size_t i = 0; i != bufsize; i++)
733 result[i] = result[i] * np.scale + np.offset;
740 void Noise::updateResults(float g, float *gmap,
741 const float *persistence_map, size_t bufsize)
743 // This looks very ugly, but it is 50-70% faster than having
744 // conditional statements inside the loop
745 if (np.flags & NOISE_FLAG_ABSVALUE) {
746 if (persistence_map) {
747 for (size_t i = 0; i != bufsize; i++) {
748 result[i] += gmap[i] * std::fabs(gradient_buf[i]);
749 gmap[i] *= persistence_map[i];
752 for (size_t i = 0; i != bufsize; i++)
753 result[i] += g * std::fabs(gradient_buf[i]);
756 if (persistence_map) {
757 for (size_t i = 0; i != bufsize; i++) {
758 result[i] += gmap[i] * gradient_buf[i];
759 gmap[i] *= persistence_map[i];
762 for (size_t i = 0; i != bufsize; i++)
763 result[i] += g * gradient_buf[i];