--- deliantra/server/include/noise.h 2011/04/23 04:46:26 1.5
+++ deliantra/server/include/noise.h 2016/11/16 22:14:05 1.19
@@ -1,85 +1,135 @@
/*
* This file is part of Deliantra, the Roguelike Realtime MMORPG.
- *
- * Copyright (©) 2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
- *
+ *
+ * Copyright (©) 2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ *
* Deliantra is free software: you can redistribute it and/or modify it under
* the terms of the Affero GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the Affero GNU General Public License
* and the GNU General Public License along with this program. If not, see
* .
- *
+ *
* The authors can be reached via e-mail to
*/
#ifndef NOISE_H_
#define NOISE_H_
+#if 0 // blitz++0.09
+#include // workaround for tinyvec using memcpy without including string.h
+#include // workaround for tinyvec using labs without including cstdlib
#include
#include
-
-#include "global.h"
-
typedef blitz::TinyVector vec2d;
typedef blitz::TinyVector vec3d;
+#else
-/////////////////////////////////////////////////////////////////////////////
+// blitz++ 0.10 - not working
+#include
+#include
+#include
+
+template
+struct vecnd
+: blitz::TinyVector
+{
+ static const int numElements = length;
+ using blitz::TinyVector::TinyVector;
+};
-template
-struct permutation
+typedef vecnd vec2d;
+typedef vecnd vec3d;
+
+#endif
+
+#include "global.h"
+
+vec2d
+inline floor (vec2d v)
{
- T pmap[N];
+ return vec2d (fastfloor (v[0]), fastfloor (v[1]));
+}
- template
- void seed (generator &rng)
- {
- for (int i = 0; i < N; ++i)
- pmap[i] = i;
+vec3d
+inline floor (vec3d v)
+{
+ return vec3d (fastfloor (v[0]), fastfloor (v[1]), fastfloor (v[2]));
+}
- // fisher-yates to randomly perturb
- for (int i = N; --i; )
- ::swap (pmap[i], pmap[rng (i + 1)]);
- }
+vec2d
+inline pow (vec2d v, vec2d p)
+{
+ return vec2d (pow (v[0], p[0]), pow (v[1], p[1]));
+}
- T operator ()(T v)
- {
- return pmap[v & (N - 1)];
- }
-};
+/////////////////////////////////////////////////////////////////////////////
-template
-struct noise_gen;
+// various s-shaped curves, smooth to, first, or second derivative
+// used for smooth interpolation from 0..1
-// modelled after 2d/3d kensler noise without projection
-template<>
-struct noise_gen
+// linear
+template
+inline T
+sigmoid0 (T x)
{
- permutation<256, uint8_t> rvmap[2];
- vec2d rvec[256]; // random unit vectors
+ return x;
+}
- noise_gen (uint32_t seed);
- vec2d::T_numtype operator() (vec2d P);
-};
+// 3x²-2x³
+template
+inline T
+sigmoid1 (T x)
+{
+ return (3 - 2 * x) * x * x;
+}
-template<>
-struct noise_gen
+// 6x⁵ - 15x⁴ + 10x³
+template
+inline T
+sigmoid2 (T x)
{
- permutation<256, uint8_t> rvmap[3];
+#ifdef MORE_PARALLELITY
+ float x2 = x * x;
+ float x4 = x2 * x2;
- noise_gen (uint32_t seed);
- vec2d::T_numtype operator() (vec3d P);
+ return (6 * x4 + 10 * x2) * x - 15 * x4;
+#endif
- // noise projected on a surface with normal n
- vec2d::T_numtype operator() (vec3d P, vec3d N);
-};
+ // simple horner
+ return ((6 * x - 15) * x + 10) * x * x * x;
+}
+
+// blend between a and b
+// c is the control function - if lower than ca
+// then return a, if higher than cb, return b
+template
+inline T
+blend (T a, T b, U c, U ca, U cb, U weight (U) = sigmoid1)
+{
+ if (c <= ca) return a;
+ if (c >= cb) return b;
+
+ U w = weight ((c - ca) / (cb - ca));
+ return (U(1) - w) * a + w * b;
+}
+
+// blend between a and b
+// c is the control function - if lower than -c_w
+// then return a, if higher than +c_w then b.
+template
+inline T
+blend0 (T a, T b, U c, U c_w, U weight (U) = sigmoid1)
+{
+ return blend (a, b, c, -c_w, c_w, weight);
+}
template
struct rotate_nn
@@ -116,34 +166,113 @@
{
};
+/////////////////////////////////////////////////////////////////////////////
+
+template< int N, typename T>
+struct permutation
+{
+ T pmap[N];
+
+ void seed (seedable_rand_gen &rng);
+
+ T operator ()(T v) func_pure
+ {
+ return pmap[v & T(N - 1)];
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+template
+struct noise_gen_base
+{
+ permutation<256, uint8_t> rvmap[vec_t::numElements + 1];
+
+ typedef typename vec_t::T_numtype value_t;
+
+ void seed (seedable_rand_gen &rng);
+ void seed (seed_t seed);
+
+ value_t operator ()(vec_t P, uint32_t seed = 0) func_pure;
+};
+
+template
+struct noise_gen;
+
+// modelled after 2d/3d kensler noise without projection
+template<>
+struct noise_gen
+: noise_gen_base
+{
+ static value_t abs_avg() { return 0.2231; } // avg(abs(noise))
+};
+
+template<>
+struct noise_gen
+: noise_gen_base
+{
+ static vec3d::T_numtype abs_avg() { return 0.415; } // avg(abs(noise))
+
+ using noise_gen_base::operator ();
+
+ // noise projected on a surface with normal n
+ vec2d::T_numtype operator() (vec3d P, vec3d N, uint32_t seed = 0) func_pure;
+};
+
+typedef noise_gen noise2d;
+typedef noise_gen noise3d;
+
+/////////////////////////////////////////////////////////////////////////////
+
template
struct frac_gen
: noise_gen
{
- enum { MAX_OCTAVES = 64 };
+ enum { MAX_OCTAVES = 32 };
typedef typename vec_t::T_numtype value_t;
+ int octaves;
value_t h, lac, ex[MAX_OCTAVES];
value_t fbm_mul[MAX_OCTAVES];
rotate_xy rot[MAX_OCTAVES];
- value_t noise (vec_t P)
+ frac_gen (int octaves = 3, value_t lacunarity = 2, value_t hurst_expo = .5, uint32_t seed = 0);
+
+ value_t noise (vec_t P, uint32_t seed = 0) func_pure
{
- return operator() (P);
+ return this->operator() (P, seed);
}
- frac_gen (value_t hurst_expo = .5f, value_t lacunarity = 2.f);
-
- value_t fBm (vec_t P, int octaves);
- value_t turbulence (vec_t P, int octaves);
- value_t multifractal (vec_t P, int octaves, value_t offset = 1);
- value_t heterofractal (vec_t P, int octaves, value_t offset = 1);
- value_t hybridfractal (vec_t P, int octaves, value_t offset = 1, value_t gain = 1);
- value_t terrain (vec_t P, int octaves);
- value_t terrain2 (vec_t P, int octaves);
- value_t ridgedmultifractal (vec_t P, int octaves, value_t offset = 1, value_t gain = 8);
+ value_t fBm (vec_t P) func_pure;
+ value_t turbulence (vec_t P) func_pure;
+ value_t multifractal (vec_t P, value_t offset = 1) func_pure;
+ value_t heterofractal (vec_t P, value_t offset = 1) func_pure;
+ value_t hybridfractal (vec_t P, value_t offset = 1, value_t gain = 1) func_pure;
+ value_t ridgedmultifractal (vec_t P, value_t offset = 1, value_t gain = 8) func_pure;
+ value_t billowfractal (vec_t P, value_t offset = 1, value_t gain = 2) func_pure;
+ value_t terrain (vec_t P) func_pure;
+ value_t terrain2 (vec_t P) func_pure;
};
+typedef frac_gen frac2d;
+typedef frac_gen frac3d;
+
+/////////////////////////////////////////////////////////////////////////////
+
+template
+inline T
+border_blend (T a, T b, vec2d P, U N, U W)
+{
+ U border = W; // within n places of the border
+
+ min_it (border, P [0]);
+ min_it (border, N - P [0]);
+ min_it (border, P [1]);
+ min_it (border, N - P [1]);
+
+ return blend (a, b, border, U(0), W);
+}
+
#endif