X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnoise.h;h=7b5e83251883a90d1fb5f83a66b5225a3df096d9;hb=f77f19a9412c9ae9f6b54a8794af219861a5e2e2;hp=6e4fedbc4d154f4be032ba61941f28adbc3dee34;hpb=7538b4c6201675c566c98b21c8ecddb798a14943;p=dragonfireclient.git diff --git a/src/noise.h b/src/noise.h index 6e4fedbc4..7b5e83251 100644 --- a/src/noise.h +++ b/src/noise.h @@ -1,109 +1,234 @@ /* -Minetest-c55 -Copyright (C) 2010-2011 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 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 GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef NOISE_HEADER -#define NOISE_HEADER + * Minetest + * Copyright (C) 2010-2014 celeron55, Perttu Ahola + * Copyright (C) 2010-2014 kwolekr, Ryan Kwolek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "irr_v3d.h" +#include "exceptions.h" +#include "util/string.h" + +extern FlagDesc flagdesc_noiseparams[]; + +// Note: this class is not polymorphic so that its high level of +// optimizability may be preserved in the common use case +class PseudoRandom { +public: + const static u32 RANDOM_RANGE = 32767; -double easeCurve(double t); - -// Return value: -1 ... 1 -double noise2d(int x, int y, int seed); -double noise3d(int x, int y, int z, int seed); + inline PseudoRandom(int seed=0): + m_next(seed) + { + } -double noise2d_gradient(double x, double y, int seed); -double noise3d_gradient(double x, double y, double z, int seed); + inline void seed(int seed) + { + m_next = seed; + } -double noise2d_perlin(double x, double y, int seed, - int octaves, double persistence); + inline int next() + { + m_next = m_next * 1103515245 + 12345; + return (unsigned)(m_next / 65536) % (RANDOM_RANGE + 1); + } -double noise2d_perlin_abs(double x, double y, int seed, - int octaves, double persistence); + inline int range(int min, int max) + { + if (max < min) + throw PrngException("Invalid range (max < min)"); + /* + Here, we ensure the range is not too large relative to RANDOM_MAX, + as otherwise the effects of bias would become noticable. Unlike + PcgRandom, we cannot modify this RNG's range as it would change the + output of this RNG for reverse compatibility. + */ + if ((u32)(max - min) > (RANDOM_RANGE + 1) / 10) + throw PrngException("Range too large"); + + return (next() % (max - min + 1)) + min; + } -double noise3d_perlin(double x, double y, double z, int seed, - int octaves, double persistence); +private: + int m_next; +}; -double noise3d_perlin_abs(double x, double y, double z, int seed, - int octaves, double persistence); +class PcgRandom { +public: + const static s32 RANDOM_MIN = -0x7fffffff - 1; + const static s32 RANDOM_MAX = 0x7fffffff; + const static u32 RANDOM_RANGE = 0xffffffff; + + PcgRandom(u64 state=0x853c49e6748fea9bULL, u64 seq=0xda3e39cb94b95bdbULL); + void seed(u64 state, u64 seq=0xda3e39cb94b95bdbULL); + u32 next(); + u32 range(u32 bound); + s32 range(s32 min, s32 max); + void bytes(void *out, size_t len); + s32 randNormalDist(s32 min, s32 max, int num_trials=6); -enum NoiseType -{ - NOISE_PERLIN, - NOISE_PERLIN_ABS, - NOISE_PERLIN_CONTOUR, - NOISE_PERLIN_CONTOUR_FLIP_YZ +private: + u64 m_state; + u64 m_inc; }; -struct NoiseParams -{ - NoiseType type; - int seed; - int octaves; - double persistence; - double pos_scale; - double noise_scale; // Useful for contour noises - - NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0, - int octaves_=3, double persistence_=0.5, - double pos_scale_=100.0, double noise_scale_=1.0): - type(type_), - seed(seed_), - octaves(octaves_), - persistence(persistence_), - pos_scale(pos_scale_), - noise_scale(noise_scale_) +#define NOISE_FLAG_DEFAULTS 0x01 +#define NOISE_FLAG_EASED 0x02 +#define NOISE_FLAG_ABSVALUE 0x04 + +//// TODO(hmmmm): implement these! +#define NOISE_FLAG_POINTBUFFER 0x08 +#define NOISE_FLAG_SIMPLEX 0x10 + +struct NoiseParams { + float offset = 0.0f; + float scale = 1.0f; + v3f spread = v3f(250, 250, 250); + s32 seed = 12345; + u16 octaves = 3; + float persist = 0.6f; + float lacunarity = 2.0f; + u32 flags = NOISE_FLAG_DEFAULTS; + + NoiseParams() = default; + + NoiseParams(float offset_, float scale_, const v3f &spread_, s32 seed_, + u16 octaves_, float persist_, float lacunarity_, + u32 flags_=NOISE_FLAG_DEFAULTS) { + offset = offset_; + scale = scale_; + spread = spread_; + seed = seed_; + octaves = octaves_; + persist = persist_; + lacunarity = lacunarity_; + flags = flags_; } }; -double noise3d_param(const NoiseParams ¶m, double x, double y, double z); - -class NoiseBuffer -{ +class Noise { public: - NoiseBuffer(); - ~NoiseBuffer(); - - void clear(); - void create(const NoiseParams ¶m, - double first_x, double first_y, double first_z, - double last_x, double last_y, double last_z, - double samplelength_x, double samplelength_y, double samplelength_z); - void multiply(const NoiseParams ¶m); - // Deprecated - void create(int seed, int octaves, double persistence, - bool abs, - double first_x, double first_y, double first_z, - double last_x, double last_y, double last_z, - double samplelength_x, double samplelength_y, double samplelength_z); - - void intSet(int x, int y, int z, double d); - void intMultiply(int x, int y, int z, double d); - double intGet(int x, int y, int z); - double get(double x, double y, double z); - //bool contains(double x, double y, double z); + NoiseParams np; + s32 seed; + u32 sx; + u32 sy; + u32 sz; + float *noise_buf = nullptr; + float *gradient_buf = nullptr; + float *persist_buf = nullptr; + float *result = nullptr; + + Noise(NoiseParams *np, s32 seed, u32 sx, u32 sy, u32 sz=1); + ~Noise(); + + void setSize(u32 sx, u32 sy, u32 sz=1); + void setSpreadFactor(v3f spread); + void setOctaves(int octaves); + + void gradientMap2D( + float x, float y, + float step_x, float step_y, + s32 seed); + void gradientMap3D( + float x, float y, float z, + float step_x, float step_y, float step_z, + s32 seed); + + float *perlinMap2D(float x, float y, float *persistence_map=NULL); + float *perlinMap3D(float x, float y, float z, float *persistence_map=NULL); + + inline float *perlinMap2D_PO(float x, float xoff, float y, float yoff, + float *persistence_map=NULL) + { + return perlinMap2D( + x + xoff * np.spread.X, + y + yoff * np.spread.Y, + persistence_map); + } + + inline float *perlinMap3D_PO(float x, float xoff, float y, float yoff, + float z, float zoff, float *persistence_map=NULL) + { + return perlinMap3D( + x + xoff * np.spread.X, + y + yoff * np.spread.Y, + z + zoff * np.spread.Z, + persistence_map); + } private: - double *m_data; - double m_start_x, m_start_y, m_start_z; - double m_samplelength_x, m_samplelength_y, m_samplelength_z; - int m_size_x, m_size_y, m_size_z; + void allocBuffers(); + void resizeNoiseBuf(bool is3d); + void updateResults(float g, float *gmap, const float *persistence_map, + size_t bufsize); + }; -#endif +float NoisePerlin2D(NoiseParams *np, float x, float y, s32 seed); +float NoisePerlin3D(NoiseParams *np, float x, float y, float z, s32 seed); + +inline float NoisePerlin2D_PO(NoiseParams *np, float x, float xoff, + float y, float yoff, s32 seed) +{ + return NoisePerlin2D(np, + x + xoff * np->spread.X, + y + yoff * np->spread.Y, + seed); +} + +inline float NoisePerlin3D_PO(NoiseParams *np, float x, float xoff, + float y, float yoff, float z, float zoff, s32 seed) +{ + return NoisePerlin3D(np, + x + xoff * np->spread.X, + y + yoff * np->spread.Y, + z + zoff * np->spread.Z, + seed); +} + +// Return value: -1 ... 1 +float noise2d(int x, int y, s32 seed); +float noise3d(int x, int y, int z, s32 seed); + +float noise2d_gradient(float x, float y, s32 seed, bool eased=true); +float noise3d_gradient(float x, float y, float z, s32 seed, bool eased=false); + +float noise2d_perlin(float x, float y, s32 seed, + int octaves, float persistence, bool eased=true); + +float noise2d_perlin_abs(float x, float y, s32 seed, + int octaves, float persistence, bool eased=true); + +float noise3d_perlin(float x, float y, float z, s32 seed, + int octaves, float persistence, bool eased=false); + +float noise3d_perlin_abs(float x, float y, float z, s32 seed, + int octaves, float persistence, bool eased=false); + +inline float easeCurve(float t) +{ + return t * t * t * (t * (6.f * t - 15.f) + 10.f); +} +float contour(float v);