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 <string.h> // 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 #define NOISE_MAGIC_SEED 1013
40 typedef float (*Interp2dFxn)(
41 float v00, float v10, float v01, float v11,
44 typedef float (*Interp3dFxn)(
45 float v000, float v100, float v010, float v110,
46 float v001, float v101, float v011, float v111,
47 float x, float y, float z);
49 float cos_lookup[16] = {
50 1.0, 0.9238, 0.7071, 0.3826, 0, -0.3826, -0.7071, -0.9238,
51 1.0, -0.9238, -0.7071, -0.3826, 0, 0.3826, 0.7071, 0.9238
54 FlagDesc flagdesc_noiseparams[] = {
55 {"defaults", NOISE_FLAG_DEFAULTS},
56 {"eased", NOISE_FLAG_EASED},
57 {"absvalue", NOISE_FLAG_ABSVALUE},
58 {"pointbuffer", NOISE_FLAG_POINTBUFFER},
59 {"simplex", NOISE_FLAG_SIMPLEX},
63 ///////////////////////////////////////////////////////////////////////////////
65 PcgRandom::PcgRandom(u64 state, u64 seq)
70 void PcgRandom::seed(u64 state, u64 seq)
73 m_inc = (seq << 1u) | 1u;
82 u64 oldstate = m_state;
83 m_state = oldstate * 6364136223846793005ULL + m_inc;
85 u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
86 u32 rot = oldstate >> 59u;
87 return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
91 u32 PcgRandom::range(u32 bound)
94 If the bound is not a multiple of the RNG's range, it may cause bias,
95 e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
96 Using rand() % 3, the number 0 would be twice as likely to appear.
97 With a very large RNG range, the effect becomes less prevalent but
98 still present. This can be solved by modifying the range of the RNG
99 to become a multiple of bound by dropping values above the a threshhold.
100 In our example, threshhold == 4 - 3 = 1 % 3 == 1, so reject 0, thus
101 making the range 3 with no bias.
103 This loop looks dangerous, but will always terminate due to the
104 RNG's property of uniformity.
106 u32 threshhold = -bound % bound;
109 while ((r = next()) < threshhold)
116 s32 PcgRandom::range(s32 min, s32 max)
119 u32 bound = max - min + 1;
120 return range(bound) + min;
124 void PcgRandom::bytes(void *out, size_t len)
126 u8 *outb = (u8 *)out;
131 if (bytes_left == 0) {
132 bytes_left = sizeof(u32);
144 s32 PcgRandom::randNormalDist(s32 min, s32 max, int num_trials)
147 for (int i = 0; i != num_trials; i++)
148 accum += range(min, max);
149 return ((float)accum / num_trials) + 0.5f;
152 ///////////////////////////////////////////////////////////////////////////////
154 float noise2d(int x, int y, int seed)
156 int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
157 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
159 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
160 return 1.f - (float)n / 0x40000000;
164 float noise3d(int x, int y, int z, int seed)
166 int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
167 + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
169 n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
170 return 1.f - (float)n / 0x40000000;
174 inline float dotProduct(float vx, float vy, float wx, float wy)
176 return vx * wx + vy * wy;
180 inline float linearInterpolation(float v0, float v1, float t)
182 return v0 + (v1 - v0) * t;
186 inline float biLinearInterpolation(
187 float v00, float v10,
188 float v01, float v11,
191 float tx = easeCurve(x);
192 float ty = easeCurve(y);
195 v00 * (1 - tx) * (1 - ty) +
196 v10 * tx * (1 - ty) +
197 v01 * (1 - tx) * ty +
201 float u = linearInterpolation(v00, v10, tx);
202 float v = linearInterpolation(v01, v11, tx);
203 return linearInterpolation(u, v, ty);
207 inline float biLinearInterpolationNoEase(
208 float v00, float v10,
209 float v01, float v11,
212 float u = linearInterpolation(v00, v10, x);
213 float v = linearInterpolation(v01, v11, x);
214 return linearInterpolation(u, v, y);
218 float triLinearInterpolation(
219 float v000, float v100, float v010, float v110,
220 float v001, float v101, float v011, float v111,
221 float x, float y, float z)
223 float tx = easeCurve(x);
224 float ty = easeCurve(y);
225 float tz = easeCurve(z);
228 v000 * (1 - tx) * (1 - ty) * (1 - tz) +
229 v100 * tx * (1 - ty) * (1 - tz) +
230 v010 * (1 - tx) * ty * (1 - tz) +
231 v110 * tx * ty * (1 - tz) +
232 v001 * (1 - tx) * (1 - ty) * tz +
233 v101 * tx * (1 - ty) * tz +
234 v011 * (1 - tx) * ty * tz +
238 float u = biLinearInterpolationNoEase(v000, v100, v010, v110, tx, ty);
239 float v = biLinearInterpolationNoEase(v001, v101, v011, v111, tx, ty);
240 return linearInterpolation(u, v, tz);
243 float triLinearInterpolationNoEase(
244 float v000, float v100, float v010, float v110,
245 float v001, float v101, float v011, float v111,
246 float x, float y, float z)
248 float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
249 float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
250 return linearInterpolation(u, v, z);
255 float noise2d_gradient(float x, float y, int seed)
257 // Calculate the integer coordinates
258 int x0 = (x > 0.0 ? (int)x : (int)x - 1);
259 int y0 = (y > 0.0 ? (int)y : (int)y - 1);
260 // Calculate the remaining part of the coordinates
261 float xl = x - (float)x0;
262 float yl = y - (float)y0;
263 // Calculate random cosine lookup table indices for the integer corners.
264 // They are looked up as unit vector gradients from the lookup table.
265 int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
266 int n10 = (int)((noise2d(x0+1, y0, seed)+1)*8);
267 int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
268 int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
269 // Make a dot product for the gradients and the positions, to get the values
270 float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
271 float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
272 float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
273 float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
274 // Interpolate between the values
275 return biLinearInterpolation(s,u,v,w,xl,yl);
280 float noise2d_gradient(float x, float y, int seed, bool eased)
282 // Calculate the integer coordinates
285 // Calculate the remaining part of the coordinates
286 float xl = x - (float)x0;
287 float yl = y - (float)y0;
288 // Get values for corners of square
289 float v00 = noise2d(x0, y0, seed);
290 float v10 = noise2d(x0+1, y0, seed);
291 float v01 = noise2d(x0, y0+1, seed);
292 float v11 = noise2d(x0+1, y0+1, seed);
295 return biLinearInterpolation(v00, v10, v01, v11, xl, yl);
297 return biLinearInterpolationNoEase(v00, v10, v01, v11, xl, yl);
301 float noise3d_gradient(float x, float y, float z, int seed, bool eased)
303 // Calculate the integer coordinates
307 // Calculate the remaining part of the coordinates
308 float xl = x - (float)x0;
309 float yl = y - (float)y0;
310 float zl = z - (float)z0;
311 // Get values for corners of cube
312 float v000 = noise3d(x0, y0, z0, seed);
313 float v100 = noise3d(x0 + 1, y0, z0, seed);
314 float v010 = noise3d(x0, y0 + 1, z0, seed);
315 float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
316 float v001 = noise3d(x0, y0, z0 + 1, seed);
317 float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
318 float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
319 float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
322 return triLinearInterpolation(
323 v000, v100, v010, v110,
324 v001, v101, v011, v111,
327 return triLinearInterpolationNoEase(
328 v000, v100, v010, v110,
329 v001, v101, v011, v111,
335 float noise2d_perlin(float x, float y, int seed,
336 int octaves, float persistence, bool eased)
341 for (int i = 0; i < octaves; i++)
343 a += g * noise2d_gradient(x * f, y * f, seed + i, eased);
351 float noise2d_perlin_abs(float x, float y, int seed,
352 int octaves, float persistence, bool eased)
357 for (int i = 0; i < octaves; i++) {
358 a += g * fabs(noise2d_gradient(x * f, y * f, seed + i, eased));
366 float noise3d_perlin(float x, float y, float z, int seed,
367 int octaves, float persistence, bool eased)
372 for (int i = 0; i < octaves; i++) {
373 a += g * noise3d_gradient(x * f, y * f, z * f, seed + i, eased);
381 float noise3d_perlin_abs(float x, float y, float z, int seed,
382 int octaves, float persistence, bool eased)
387 for (int i = 0; i < octaves; i++) {
388 a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i, eased));
396 float contour(float v)
405 ///////////////////////// [ New noise ] ////////////////////////////
408 float NoisePerlin2D(NoiseParams *np, float x, float y, int seed)
418 for (size_t i = 0; i < np->octaves; i++) {
419 float noiseval = noise2d_gradient(x * f, y * f, seed + i,
420 np->flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED));
422 if (np->flags & NOISE_FLAG_ABSVALUE)
423 noiseval = fabs(noiseval);
430 return np->offset + a * np->scale;
434 float NoisePerlin3D(NoiseParams *np, float x, float y, float z, int seed)
445 for (size_t i = 0; i < np->octaves; i++) {
446 float noiseval = noise3d_gradient(x * f, y * f, z * f, seed + i,
447 np->flags & NOISE_FLAG_EASED);
449 if (np->flags & NOISE_FLAG_ABSVALUE)
450 noiseval = fabs(noiseval);
457 return np->offset + a * np->scale;
461 Noise::Noise(NoiseParams *np_, int seed, int sx, int sy, int sz)
463 memcpy(&np, np_, sizeof(np));
469 this->persist_buf = NULL;
470 this->gradient_buf = NULL;
479 delete[] gradient_buf;
480 delete[] persist_buf;
486 void Noise::allocBuffers()
488 this->noise_buf = NULL;
489 resizeNoiseBuf(sz > 1);
491 delete[] gradient_buf;
492 delete[] persist_buf;
496 size_t bufsize = sx * sy * sz;
497 this->persist_buf = NULL;
498 this->gradient_buf = new float[bufsize];
499 this->result = new float[bufsize];
500 } catch (std::bad_alloc &e) {
501 throw InvalidNoiseParamsException();
506 void Noise::setSize(int sx, int sy, int sz)
516 void Noise::setSpreadFactor(v3f spread)
518 this->np.spread = spread;
520 resizeNoiseBuf(sz > 1);
524 void Noise::setOctaves(int octaves)
526 this->np.octaves = octaves;
528 resizeNoiseBuf(sz > 1);
532 void Noise::resizeNoiseBuf(bool is3d)
537 //maximum possible spread value factor
538 ofactor = pow(np.lacunarity, np.octaves - 1);
540 //noise lattice point count
541 //(int)(sz * spread * ofactor) is # of lattice points crossed due to length
542 // + 2 for the two initial endpoints
543 // + 1 for potentially crossing a boundary due to offset
544 nlx = (int)ceil(sx * ofactor / np.spread.X) + 3;
545 nly = (int)ceil(sy * ofactor / np.spread.Y) + 3;
546 nlz = is3d ? (int)ceil(sz * ofactor / np.spread.Z) + 3 : 1;
550 noise_buf = new float[nlx * nly * nlz];
551 } catch (std::bad_alloc &e) {
552 throw InvalidNoiseParamsException();
558 * NB: This algorithm is not optimal in terms of space complexity. The entire
559 * integer lattice of noise points could be done as 2 lines instead, and for 3D,
560 * 2 lines + 2 planes.
561 * However, this would require the noise calls to be interposed with the
562 * interpolation loops, which may trash the icache, leading to lower overall
564 * Another optimization that could save half as many noise calls is to carry over
565 * values from the previous noise lattice as midpoints in the new lattice for the
568 #define idx(x, y) ((y) * nlx + (x))
569 void Noise::gradientMap2D(
571 float step_x, float step_y,
574 float v00, v01, v10, v11, u, v, orig_u;
575 int index, i, j, x0, y0, noisex, noisey;
578 bool eased = np.flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED);
579 Interp2dFxn interpolate = eased ?
580 biLinearInterpolation : biLinearInterpolationNoEase;
588 //calculate noise point lattice
589 nlx = (int)(u + sx * step_x) + 2;
590 nly = (int)(v + sy * step_y) + 2;
592 for (j = 0; j != nly; j++)
593 for (i = 0; i != nlx; i++)
594 noise_buf[index++] = noise2d(x0 + i, y0 + j, seed);
596 //calculate interpolations
599 for (j = 0; j != sy; j++) {
600 v00 = noise_buf[idx(0, noisey)];
601 v10 = noise_buf[idx(1, noisey)];
602 v01 = noise_buf[idx(0, noisey + 1)];
603 v11 = noise_buf[idx(1, noisey + 1)];
607 for (i = 0; i != sx; i++) {
608 gradient_buf[index++] = interpolate(v00, v10, v01, v11, u, v);
616 v10 = noise_buf[idx(noisex + 1, noisey)];
617 v11 = noise_buf[idx(noisex + 1, noisey + 1)];
631 #define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
632 void Noise::gradientMap3D(
633 float x, float y, float z,
634 float step_x, float step_y, float step_z,
637 float v000, v010, v100, v110;
638 float v001, v011, v101, v111;
639 float u, v, w, orig_u, orig_v;
640 int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
643 Interp3dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ?
644 triLinearInterpolation : triLinearInterpolationNoEase;
655 //calculate noise point lattice
656 nlx = (int)(u + sx * step_x) + 2;
657 nly = (int)(v + sy * step_y) + 2;
658 nlz = (int)(w + sz * step_z) + 2;
660 for (k = 0; k != nlz; k++)
661 for (j = 0; j != nly; j++)
662 for (i = 0; i != nlx; i++)
663 noise_buf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
665 //calculate interpolations
669 for (k = 0; k != sz; k++) {
672 for (j = 0; j != sy; j++) {
673 v000 = noise_buf[idx(0, noisey, noisez)];
674 v100 = noise_buf[idx(1, noisey, noisez)];
675 v010 = noise_buf[idx(0, noisey + 1, noisez)];
676 v110 = noise_buf[idx(1, noisey + 1, noisez)];
677 v001 = noise_buf[idx(0, noisey, noisez + 1)];
678 v101 = noise_buf[idx(1, noisey, noisez + 1)];
679 v011 = noise_buf[idx(0, noisey + 1, noisez + 1)];
680 v111 = noise_buf[idx(1, noisey + 1, noisez + 1)];
684 for (i = 0; i != sx; i++) {
685 gradient_buf[index++] = interpolate(
686 v000, v100, v010, v110,
687 v001, v101, v011, v111,
696 v100 = noise_buf[idx(noisex + 1, noisey, noisez)];
697 v110 = noise_buf[idx(noisex + 1, noisey + 1, noisez)];
700 v101 = noise_buf[idx(noisex + 1, noisey, noisez + 1)];
701 v111 = noise_buf[idx(noisex + 1, noisey + 1, noisez + 1)];
722 float *Noise::perlinMap2D(float x, float y, float *persistence_map)
724 float f = 1.0, g = 1.0;
725 size_t bufsize = sx * sy;
730 memset(result, 0, sizeof(float) * bufsize);
732 if (persistence_map) {
734 persist_buf = new float[bufsize];
735 for (size_t i = 0; i != bufsize; i++)
736 persist_buf[i] = 1.0;
739 for (size_t oct = 0; oct < np.octaves; oct++) {
740 gradientMap2D(x * f, y * f,
741 f / np.spread.X, f / np.spread.Y,
742 seed + np.seed + oct);
744 updateResults(g, persist_buf, persistence_map, bufsize);
750 if (fabs(np.offset - 0.f) > 0.00001 || fabs(np.scale - 1.f) > 0.00001) {
751 for (size_t i = 0; i != bufsize; i++)
752 result[i] = result[i] * np.scale + np.offset;
759 float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
761 float f = 1.0, g = 1.0;
762 size_t bufsize = sx * sy * sz;
768 memset(result, 0, sizeof(float) * bufsize);
770 if (persistence_map) {
772 persist_buf = new float[bufsize];
773 for (size_t i = 0; i != bufsize; i++)
774 persist_buf[i] = 1.0;
777 for (size_t oct = 0; oct < np.octaves; oct++) {
778 gradientMap3D(x * f, y * f, z * f,
779 f / np.spread.X, f / np.spread.Y, f / np.spread.Z,
780 seed + np.seed + oct);
782 updateResults(g, persist_buf, persistence_map, bufsize);
788 if (fabs(np.offset - 0.f) > 0.00001 || fabs(np.scale - 1.f) > 0.00001) {
789 for (size_t i = 0; i != bufsize; i++)
790 result[i] = result[i] * np.scale + np.offset;
797 void Noise::updateResults(float g, float *gmap,
798 float *persistence_map, size_t bufsize)
800 // This looks very ugly, but it is 50-70% faster than having
801 // conditional statements inside the loop
802 if (np.flags & NOISE_FLAG_ABSVALUE) {
803 if (persistence_map) {
804 for (size_t i = 0; i != bufsize; i++) {
805 result[i] += gmap[i] * fabs(gradient_buf[i]);
806 gmap[i] *= persistence_map[i];
809 for (size_t i = 0; i != bufsize; i++)
810 result[i] += g * fabs(gradient_buf[i]);
813 if (persistence_map) {
814 for (size_t i = 0; i != bufsize; i++) {
815 result[i] += gmap[i] * gradient_buf[i];
816 gmap[i] *= persistence_map[i];
819 for (size_t i = 0; i != bufsize; i++)
820 result[i] += g * gradient_buf[i];