--- 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