Performance fix + SAO factorization
[oweals/minetest.git] / src / cavegen.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef CAVEGEN_HEADER
21 #define CAVEGEN_HEADER
22
23 #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
24 #define DEFAULT_LAVA_DEPTH (-256)
25
26 class GenerateNotifier;
27
28 /*
29         CavesNoiseIntersection is a cave digging algorithm that carves smooth,
30         web-like, continuous tunnels at points where the density of the intersection
31         between two separate 3d noises is above a certain value.  This value,
32         cave_width, can be modified to set the effective width of these tunnels.
33
34         This algorithm is relatively heavyweight, taking ~80ms to generate an
35         80x80x80 chunk of map on a modern processor.  Use sparingly!
36
37         TODO(hmmmm): Remove dependency on biomes
38         TODO(hmmmm): Find alternative to overgeneration as solution for sunlight issue
39 */
40 class CavesNoiseIntersection {
41 public:
42         CavesNoiseIntersection(INodeDefManager *nodedef, BiomeManager *biomemgr,
43                 v3s16 chunksize, NoiseParams *np_cave1, NoiseParams *np_cave2,
44                 s32 seed, float cave_width);
45         ~CavesNoiseIntersection();
46
47         void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, u8 *biomemap);
48
49 private:
50         INodeDefManager *m_ndef;
51         BiomeManager *m_bmgr;
52
53         // configurable parameters
54         v3s16 m_csize;
55         float m_cave_width;
56
57         // intermediate state variables
58         u16 m_ystride;
59         u16 m_zstride_1d;
60
61         Noise *noise_cave1;
62         Noise *noise_cave2;
63 };
64
65 /*
66         CavesRandomWalk is an implementation of a cave-digging algorithm that
67         operates on the principle of a "random walk" to approximate the stochiastic
68         activity of cavern development.
69
70         In summary, this algorithm works by carving a randomly sized tunnel in a
71         random direction a random amount of times, randomly varying in width.
72         All randomness here is uniformly distributed; alternative distributions have
73         not yet been implemented.
74
75         This algorithm is very fast, executing in less than 1ms on average for an
76         80x80x80 chunk of map on a modern processor.
77 */
78 class CavesRandomWalk {
79 public:
80         MMVManip *vm;
81         INodeDefManager *ndef;
82         GenerateNotifier *gennotify;
83         s16 *heightmap;
84
85         // configurable parameters
86         s32 seed;
87         int water_level;
88         int lava_depth;
89         NoiseParams *np_caveliquids;
90
91         // intermediate state variables
92         u16 ystride;
93
94         s16 min_tunnel_diameter;
95         s16 max_tunnel_diameter;
96         u16 tunnel_routepoints;
97         int part_max_length_rs;
98
99         bool large_cave;
100         bool large_cave_is_flat;
101         bool flooded;
102
103         s16 max_stone_y;
104         v3s16 node_min;
105         v3s16 node_max;
106
107         v3f orp;  // starting point, relative to caved space
108         v3s16 of; // absolute coordinates of caved space
109         v3s16 ar; // allowed route area
110         s16 rs;   // tunnel radius size
111         v3f main_direction;
112
113         s16 route_y_min;
114         s16 route_y_max;
115
116         PseudoRandom *ps;
117
118         content_t c_water_source;
119         content_t c_lava_source;
120
121         // ndef is a mandatory parameter.
122         // If gennotify is NULL, generation events are not logged.
123         CavesRandomWalk(INodeDefManager *ndef,
124                 GenerateNotifier *gennotify = NULL,
125                 s32 seed = 0,
126                 int water_level = 1,
127                 content_t water_source = CONTENT_IGNORE,
128                 content_t lava_source = CONTENT_IGNORE);
129
130         // vm and ps are mandatory parameters.
131         // If heightmap is NULL, the surface level at all points is assumed to
132         // be water_level.
133         void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps,
134                 bool is_large_cave, int max_stone_height, s16 *heightmap);
135
136 private:
137         void makeTunnel(bool dirswitch);
138         void carveRoute(v3f vec, float f, bool randomize_xz);
139
140         inline bool isPosAboveSurface(v3s16 p);
141 };
142
143 /*
144         CavesV6 is the original version of caves used with Mapgen V6.
145
146         Though it uses the same fundamental algorithm as CavesRandomWalk, it is made
147         separate to preserve the exact sequence of PseudoRandom calls - any change
148         to this ordering results in the output being radically different.
149         Because caves in Mapgen V6 are responsible for a large portion of the basic
150         terrain shape, modifying this will break our contract of reverse
151         compatibility for a 'stable' mapgen such as V6.
152
153         tl;dr,
154         *** DO NOT TOUCH THIS CLASS UNLESS YOU KNOW WHAT YOU ARE DOING ***
155 */
156 class CavesV6 {
157 public:
158         MMVManip *vm;
159         INodeDefManager *ndef;
160         GenerateNotifier *gennotify;
161         PseudoRandom *ps;
162         PseudoRandom *ps2;
163
164         // configurable parameters
165         s16 *heightmap;
166         content_t c_water_source;
167         content_t c_lava_source;
168         int water_level;
169
170         // intermediate state variables
171         u16 ystride;
172
173         s16 min_tunnel_diameter;
174         s16 max_tunnel_diameter;
175         u16 tunnel_routepoints;
176         int part_max_length_rs;
177
178         bool large_cave;
179         bool large_cave_is_flat;
180
181         v3s16 node_min;
182         v3s16 node_max;
183
184         v3f orp;  // starting point, relative to caved space
185         v3s16 of; // absolute coordinates of caved space
186         v3s16 ar; // allowed route area
187         s16 rs;   // tunnel radius size
188         v3f main_direction;
189
190         s16 route_y_min;
191         s16 route_y_max;
192
193         // ndef is a mandatory parameter.
194         // If gennotify is NULL, generation events are not logged.
195         CavesV6(INodeDefManager *ndef,
196                 GenerateNotifier *gennotify = NULL,
197                 int water_level = 1,
198                 content_t water_source = CONTENT_IGNORE,
199                 content_t lava_source = CONTENT_IGNORE);
200
201         // vm, ps, and ps2 are mandatory parameters.
202         // If heightmap is NULL, the surface level at all points is assumed to
203         // be water_level.
204         void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
205                 PseudoRandom *ps, PseudoRandom *ps2,
206                 bool is_large_cave, int max_stone_height, s16 *heightmap = NULL);
207
208 private:
209         void makeTunnel(bool dirswitch);
210         void carveRoute(v3f vec, float f, bool randomize_xz, bool tunnel_above_ground);
211
212         inline s16 getSurfaceFromHeightmap(v3s16 p);
213 };
214
215 #endif