/* -*-c++-*- */ /* osgEarth - Geospatial SDK for OpenSceneGraph * Copyright 2020 Pelican Mapping * http://osgearth.org * * osgEarth is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTH_SIMPLEX_NOISE_H #define OSGEARTH_SIMPLEX_NOISE_H 1 #include #include namespace osgEarth { namespace Util { /** * Simplex Noise Generator. * Adapted from https://github.com/Taywee/Noise */ class OSGEARTH_EXPORT SimplexNoise { public: SimplexNoise(); SimplexNoise(const SimplexNoise& rhs); virtual ~SimplexNoise() { } static const double DefaultFrequency; static const double DefaultPersistence; static const double DefaultLacunarity; static const double DefaultRangeLow; static const double DefaultRangeHigh; static const unsigned DefaultOctaves; static const bool DefaultNormalize; /** * Frequency is how often the noise pattern resets to zero across * the input domain. For example, if your input range from * -100 < x < 100, a frequency of 1/200 will cause the noise function to * reset every 200 units, i.e., the extent of the input domain. (It will * be zero at -100 and zero again at 100. It may cross zero in between, * but that is not guaranteed.) * * In mapping terms, say your map is 100000m wide. A frequency of 1/100000 * will result in a pattern that resets (and wraps around) every 100000m. * * Default = 1.0. */ void setFrequency(double freq) { _freq = freq; } double getFrequency() const { return _freq; } /** * Persietence is the factor by which the noise function's amplitude * decreases with each successive octave. * i.e.: Amp(Oct2) = Amp(Oct1) * Persistance. * Default = 0.5. * Effect: Higher persistence: noisiness persists as you get more detail; * Lower persistence: data smooths out faster as you get more detail. */ void setPersistence(double pers) { _pers = pers; } double getPersistence() const { return _pers; } /** * Lacunarity is the factor by which the noise function's frequency * increases with each successive octave. * i.e.: Freq(Oct2) = Freq(Oct1) * Lacunarity. * Default = 2.0. * Effect: Higher lacunarity: more "plateaus" in the output; * Lower lacunarity: more "chopiness" in the output. */ void setLacunarity(double lac) { _lacunarity = lac; } double getLacunarity() const { return _lacunarity; } /** * The output range for noise data. * Default = [-1..1]. */ void setRange(double low, double high) { _low = low, _high = high; } double getRangeLow() const { return _low; } double getRangeHigh() const { return _high; } /** * Whether to normalize output values within the limits set by * setRange(). */ void setNormalize(bool value) { _normalize = value; } bool getNormalize() const { return _normalize; } /** * Number of iterations over which to generate noise. The frequency starts * where you set it, and over each successive iteration, it is scaled by * the persistence. This lets you control the rate at which the "noisiness" * decreases with each octave. * Default = 1. */ void setOctaves(unsigned octaves) { _octaves = octaves; } unsigned getOctaves() const { return _octaves; } /** * Generates 2D simplex Noise */ double getValue(double xin, double yin) const; /** * Generates 3D simplex Noise */ double getValue(double xin, double yin, double zin) const; /** * Generates 4D simplex Noise */ double getValue(double x, double y, double z, double w) const; /** * Generates tilable 2D noise for x[0..1), y[0..1). */ double getTiledValue(double x, double y) const; double getTiledValueWithTurbulence(double x, double y, double F) const; /** * Creates a tileable image of the requested dimensions. * The image will be histogram-stretched in the range [0..1]. */ class osg::Image* createSeamlessImage(unsigned dim) const; private: // Inner class to speed up gradient computations // (array access is a lot slower than member access) struct Grad { Grad(double x, double y, double z); Grad(double x, double y, double z, double w); double x, y, z, w; }; const static Grad grad3[12]; const static Grad grad4[32]; const static unsigned char perm[512]; // Skewing and unskewing factors for 2, 3, and 4 dimensions static double const F2; static double const G2; static double const F3; static double const G3; static double const F4; static double const G4; unsigned char permMod12[512]; // This method is a *lot* faster than using (int)Math.floor(x) inline static int FastFloor(double x); static double Dot(Grad const & g, double x, double y); static double Dot(Grad const & g, double x, double y, double z); static double Dot(Grad const & g, double x, double y, double z, double w); double Noise(double x, double y) const; double Noise(double x, double y, double z) const; double Noise(double x, double y, double z, double w) const; double _freq; double _pers; double _lacunarity; double _low, _high; unsigned _octaves; bool _normalize; }; } } // namespace osgEarth #endif //OSGEARTH_SIMPLEX_NOISE_H