]> git.lizzy.rs Git - minetest.git/blob - src/noise.h
Fix uninitialized variable Player::local_animation_speed
[minetest.git] / src / noise.h
1 /*
2  * Minetest
3  * Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
4  * Copyright (C) 2010-2014 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are
8  * permitted provided that the following conditions are met:
9  *  1. Redistributions of source code must retain the above copyright notice, this list of
10  *     conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *     of conditions and the following disclaimer in the documentation and/or other materials
13  *     provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
16  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef NOISE_HEADER
27 #define NOISE_HEADER
28
29 #include "debug.h"
30 #include "irr_v3d.h"
31 #include "util/string.h"
32
33 extern FlagDesc flagdesc_noiseparams[];
34
35 // Note: this class is not polymorphic so that its high level of
36 // optimizability may be preserved in the common use case
37 class PseudoRandom {
38 public:
39         const static u32 RANDOM_RANGE = 32767;
40
41         inline PseudoRandom(int seed=0):
42                 m_next(seed)
43         {
44         }
45
46         inline void seed(int seed)
47         {
48                 m_next = seed;
49         }
50
51         inline int next()
52         {
53                 m_next = m_next * 1103515245 + 12345;
54                 return (unsigned)(m_next / 65536) % (RANDOM_RANGE + 1);
55         }
56
57         inline int range(int min, int max)
58         {
59                 assert(max >= min);
60                 /*
61                 Here, we ensure the range is not too large relative to RANDOM_MAX,
62                 as otherwise the effects of bias would become noticable.  Unlike
63                 PcgRandom, we cannot modify this RNG's range as it would change the
64                 output of this RNG for reverse compatibility.
65                 */
66                 assert((u32)(max - min) <= (RANDOM_RANGE + 1) / 10);
67
68                 return (next() % (max - min + 1)) + min;
69         }
70
71 private:
72         int m_next;
73 };
74
75 class PcgRandom {
76 public:
77         const static s32 RANDOM_MIN   = -0x7fffffff - 1;
78         const static s32 RANDOM_MAX   = 0x7fffffff;
79         const static u32 RANDOM_RANGE = 0xffffffff;
80
81         PcgRandom(u64 state=0x853c49e6748fea9bULL, u64 seq=0xda3e39cb94b95bdbULL);
82         void seed(u64 state, u64 seq=0xda3e39cb94b95bdbULL);
83         u32 next();
84         u32 range(u32 bound);
85         s32 range(s32 min, s32 max);
86         void bytes(void *out, size_t len);
87         s32 randNormalDist(s32 min, s32 max, int num_trials=6);
88
89 private:
90         u64 m_state;
91         u64 m_inc;
92 };
93
94 #define NOISE_FLAG_DEFAULTS    0x01
95 #define NOISE_FLAG_EASED       0x02
96 #define NOISE_FLAG_ABSVALUE    0x04
97
98 //// TODO(hmmmm): implement these!
99 #define NOISE_FLAG_POINTBUFFER 0x08
100 #define NOISE_FLAG_SIMPLEX     0x10
101
102 struct NoiseParams {
103         float offset;
104         float scale;
105         v3f spread;
106         s32 seed;
107         u16 octaves;
108         float persist;
109         float lacunarity;
110         u32 flags;
111
112         NoiseParams()
113         {
114                 offset     = 0.0f;
115                 scale      = 1.0f;
116                 spread     = v3f(250, 250, 250);
117                 seed       = 12345;
118                 octaves    = 3;
119                 persist    = 0.6f;
120                 lacunarity = 2.0f;
121                 flags      = NOISE_FLAG_DEFAULTS;
122         }
123
124         NoiseParams(float offset_, float scale_, v3f spread_, s32 seed_,
125                 u16 octaves_, float persist_, float lacunarity_,
126                 u32 flags_=NOISE_FLAG_DEFAULTS)
127         {
128                 offset     = offset_;
129                 scale      = scale_;
130                 spread     = spread_;
131                 seed       = seed_;
132                 octaves    = octaves_;
133                 persist    = persist_;
134                 lacunarity = lacunarity_;
135                 flags      = flags_;
136         }
137 };
138
139
140 // Convenience macros for getting/setting NoiseParams in Settings as a string
141 // WARNING:  Deprecated, use Settings::getNoiseParamsFromValue() instead
142 #define NOISEPARAMS_FMT_STR "f,f,v3,s32,u16,f"
143 //#define getNoiseParams(x, y) getStruct((x), NOISEPARAMS_FMT_STR, &(y), sizeof(y))
144 //#define setNoiseParams(x, y) setStruct((x), NOISEPARAMS_FMT_STR, &(y))
145
146 class Noise {
147 public:
148         NoiseParams np;
149         int seed;
150         int sx;
151         int sy;
152         int sz;
153         float *noise_buf;
154         float *gradient_buf;
155         float *persist_buf;
156         float *result;
157
158         Noise(NoiseParams *np, int seed, int sx, int sy, int sz=1);
159         ~Noise();
160
161         void setSize(int sx, int sy, int sz=1);
162         void setSpreadFactor(v3f spread);
163         void setOctaves(int octaves);
164
165         void gradientMap2D(
166                 float x, float y,
167                 float step_x, float step_y,
168                 int seed);
169         void gradientMap3D(
170                 float x, float y, float z,
171                 float step_x, float step_y, float step_z,
172                 int seed);
173
174         float *perlinMap2D(float x, float y, float *persistence_map=NULL);
175         float *perlinMap3D(float x, float y, float z, float *persistence_map=NULL);
176
177         inline float *perlinMap2D_PO(float x, float xoff, float y, float yoff,
178                 float *persistence_map=NULL)
179         {
180                 return perlinMap2D(
181                         x + xoff * np.spread.X,
182                         y + yoff * np.spread.Y,
183                         persistence_map);
184         }
185
186         inline float *perlinMap3D_PO(float x, float xoff, float y, float yoff,
187                 float z, float zoff, float *persistence_map=NULL)
188         {
189                 return perlinMap3D(
190                         x + xoff * np.spread.X,
191                         y + yoff * np.spread.Y,
192                         z + zoff * np.spread.Z,
193                         persistence_map);
194         }
195
196 private:
197         void allocBuffers();
198         void resizeNoiseBuf(bool is3d);
199         void updateResults(float g, float *gmap, float *persistence_map, size_t bufsize);
200
201 };
202
203 float NoisePerlin2D(NoiseParams *np, float x, float y, int seed);
204 float NoisePerlin3D(NoiseParams *np, float x, float y, float z, int seed);
205
206 inline float NoisePerlin2D_PO(NoiseParams *np, float x, float xoff,
207         float y, float yoff, int seed)
208 {
209         return NoisePerlin2D(np,
210                 x + xoff * np->spread.X,
211                 y + yoff * np->spread.Y,
212                 seed);
213 }
214
215 inline float NoisePerlin3D_PO(NoiseParams *np, float x, float xoff,
216         float y, float yoff, float z, float zoff, int seed)
217 {
218         return NoisePerlin3D(np,
219                 x + xoff * np->spread.X,
220                 y + yoff * np->spread.Y,
221                 z + zoff * np->spread.Z,
222                 seed);
223 }
224
225 // Return value: -1 ... 1
226 float noise2d(int x, int y, int seed);
227 float noise3d(int x, int y, int z, int seed);
228
229 float noise2d_gradient(float x, float y, int seed, bool eased=true);
230 float noise3d_gradient(float x, float y, float z, int seed, bool eased=false);
231
232 float noise2d_perlin(float x, float y, int seed,
233                 int octaves, float persistence, bool eased=true);
234
235 float noise2d_perlin_abs(float x, float y, int seed,
236                 int octaves, float persistence, bool eased=true);
237
238 float noise3d_perlin(float x, float y, float z, int seed,
239                 int octaves, float persistence, bool eased=false);
240
241 float noise3d_perlin_abs(float x, float y, float z, int seed,
242                 int octaves, float persistence, bool eased=false);
243
244 inline float easeCurve(float t)
245 {
246         return t * t * t * (t * (6.f * t - 15.f) + 10.f);
247 }
248
249 float contour(float v);
250
251 #endif
252