/* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * * 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 * 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_ #include #include #include "global.h" typedef blitz::TinyVector vec2d; typedef blitz::TinyVector vec3d; vec2d inline floor (vec2d v) { return vec2d (fastfloor (v[0]), fastfloor (v[1])); } vec3d inline floor (vec3d v) { return vec3d (fastfloor (v[0]), fastfloor (v[1]), fastfloor (v[2])); } vec2d inline pow (vec2d v, vec2d p) { return vec2d (pow (v[0], p[0]), pow (v[1], p[1])); } ///////////////////////////////////////////////////////////////////////////// // various s-shaped curves, smooth to, first, or second derivative // used for smooth interpolation from 0..1 // 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; return (6 * x4 + 10 * x2) * x - 15 * x4; #endif // 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 { typename vec_t::T_numtype s, c; void set (typename vec_t::T_numtype angle) { s = sin (angle); c = cos (angle); } void operator ()(vec_t &P) const { vec_t o = P; P[a] = o[a] * c - o[b] * s; P[b] = o[a] * s + o[b] * c; } }; template struct rotate_xy : rotate_nn { }; template struct rotate_xz : rotate_nn { }; template struct rotate_yz : rotate_nn { }; ///////////////////////////////////////////////////////////////////////////// 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 = 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]; 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, seed); } 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 T inline 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