--- deliantra/server/include/noise.h 2011/04/23 04:46:26 1.5 +++ deliantra/server/include/noise.h 2011/04/30 11:02:25 1.11 @@ -1,7 +1,7 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2010,2011 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 @@ -31,55 +31,84 @@ typedef blitz::TinyVector vec2d; typedef blitz::TinyVector vec3d; -///////////////////////////////////////////////////////////////////////////// - -template -struct permutation +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 -{ - permutation<256, uint8_t> rvmap[2]; - vec2d rvec[256]; // random unit vectors +// linear +template +inline T +sigmoid0 (T x) +{ + return x; +} + +// 3x²-2x³ +template +inline T +sigmoid1 (T x) +{ + return (3 - 2 * x) * x * x; +} + +// 6x⁵ - 15x⁴ + 10x³ +template +inline T +sigmoid2 (T x) +{ +#ifdef MORE_PARALLELITY + float x2 = x * x; + float x4 = x2 * x2; - noise_gen (uint32_t seed); - vec2d::T_numtype operator() (vec2d P); -}; + return (6 * x4 + 10 * x2) * x - 15 * x4; +#endif -template<> -struct noise_gen + // 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) { - permutation<256, uint8_t> rvmap[3]; - - noise_gen (uint32_t seed); - vec2d::T_numtype operator() (vec3d P); - - // noise projected on a surface with normal n - vec2d::T_numtype operator() (vec3d P, vec3d N); -}; + return blend (a, b, c, -c_w, c_w, weight); +} template struct rotate_nn @@ -116,34 +145,97 @@ { }; +///////////////////////////////////////////////////////////////////////////// + +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 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; + #endif