Cavegen: Remove CavesRandomWalk dependency on Mapgen

This commit is contained in:
kwolekr 2016-05-10 22:56:03 -04:00
parent 68b1cd8d1b
commit db1b4dc890
4 changed files with 98 additions and 38 deletions

@ -31,23 +31,52 @@ NoiseParams nparams_caveliquids(0, 1, v3f(150.0, 150.0, 150.0), 776, 3, 0.6, 2.0
//// CavesRandomWalk //// CavesRandomWalk
//// ////
CavesRandomWalk::CavesRandomWalk(Mapgen *mg, PseudoRandom *ps) CavesRandomWalk::CavesRandomWalk(
INodeDefManager *ndef,
GenerateNotifier *gennotify,
int seed,
int water_level,
content_t water_source,
content_t lava_source)
{ {
this->mg = mg; assert(ndef);
this->vm = mg->vm;
this->ndef = mg->ndef; this->ndef = ndef;
this->water_level = mg->water_level; this->gennotify = gennotify;
this->ps = ps; this->seed = seed;
c_water_source = ndef->getId("mapgen_water_source"); this->water_level = water_level;
c_lava_source = ndef->getId("mapgen_lava_source");
c_ice = ndef->getId("mapgen_ice");
this->np_caveliquids = &nparams_caveliquids; this->np_caveliquids = &nparams_caveliquids;
this->ystride = mg->csize.X;
this->lava_depth = DEFAULT_LAVA_DEPTH; this->lava_depth = DEFAULT_LAVA_DEPTH;
if (c_ice == CONTENT_IGNORE) c_water_source = water_source;
c_ice = CONTENT_AIR; if (c_water_source == CONTENT_IGNORE)
c_water_source = ndef->getId("mapgen_water_source");
if (c_water_source == CONTENT_IGNORE)
c_water_source = CONTENT_AIR;
c_lava_source = lava_source;
if (c_lava_source == CONTENT_IGNORE)
c_lava_source = ndef->getId("mapgen_lava_source");
if (c_lava_source == CONTENT_IGNORE)
c_lava_source = CONTENT_AIR;
}
void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
PseudoRandom *ps, int max_stone_height, s16 *heightmap)
{
assert(vm);
assert(ps);
this->vm = vm;
this->ps = ps;
this->node_min = nmin;
this->node_max = nmax;
this->heightmap = heightmap;
this->ystride = nmax.X - nmin.X + 1;
// Set initial parameters from randomness
dswitchint = ps->range(1, 14); dswitchint = ps->range(1, 14);
flooded = ps->range(1, 2) == 2; flooded = ps->range(1, 2) == 2;
@ -57,13 +86,7 @@ CavesRandomWalk::CavesRandomWalk(Mapgen *mg, PseudoRandom *ps)
max_tunnel_diameter = ps->range(7, ps->range(8, 24)); max_tunnel_diameter = ps->range(7, ps->range(8, 24));
large_cave_is_flat = (ps->range(0, 1) == 0); large_cave_is_flat = (ps->range(0, 1) == 0);
}
void CavesRandomWalk::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height)
{
node_min = nmin;
node_max = nmax;
main_direction = v3f(0, 0, 0); main_direction = v3f(0, 0, 0);
// Allowed route area size in nodes // Allowed route area size in nodes
@ -107,18 +130,22 @@ void CavesRandomWalk::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height)
); );
// Add generation notify begin event // Add generation notify begin event
v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); if (gennotify) {
GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN; v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
mg->gennotify.addEvent(notifytype, abs_pos); GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN;
gennotify->addEvent(notifytype, abs_pos);
}
// Generate some tunnel starting from orp // Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++) for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0); makeTunnel(j % dswitchint == 0);
// Add generation notify end event // Add generation notify end event
abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); if (gennotify) {
notifytype = GENNOTIFY_LARGECAVE_END; v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
mg->gennotify.addEvent(notifytype, abs_pos); GenNotifyType notifytype = GENNOTIFY_LARGECAVE_END;
gennotify->addEvent(notifytype, abs_pos);
}
} }
@ -197,7 +224,7 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz)
startp += of; startp += of;
float nval = NoisePerlin3D(np_caveliquids, startp.X, float nval = NoisePerlin3D(np_caveliquids, startp.X,
startp.Y, startp.Z, mg->seed); startp.Y, startp.Z, seed);
MapNode liquidnode = (nval < 0.40 && node_max.Y < lava_depth) ? MapNode liquidnode = (nval < 0.40 && node_max.Y < lava_depth) ?
lavanode : waternode; lavanode : waternode;
@ -388,7 +415,7 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
// Add generation notify end event // Add generation notify end event
if (gennotify != NULL) { if (gennotify != NULL) {
v3s16 abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
GenNotifyType notifytype = large_cave ? GenNotifyType notifytype = large_cave ?
GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END;
gennotify->addEvent(notifytype, abs_pos); gennotify->addEvent(notifytype, abs_pos);

@ -25,17 +25,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class GenerateNotifier; class GenerateNotifier;
/*
CavesRandomWalk is an implementation of a cave-digging algorithm that
operates on the principle of a "random walk" to approximate the stochiastic
activity of cavern development.
In summary, this algorithm works by carving a randomly sized tunnel in a
random direction a random amount of times, randomly varying in width.
All randomness here is uniformly distributed; alternative distributions have
not yet been implemented.
This algorithm is very fast, executing in less than 1ms on average for an
80x80x80 chunk of map on a modern processor.
*/
class CavesRandomWalk { class CavesRandomWalk {
public: public:
Mapgen *mg;
MMVManip *vm; MMVManip *vm;
INodeDefManager *ndef; INodeDefManager *ndef;
GenerateNotifier *gennotify;
s16 *heightmap; s16 *heightmap;
// variables // configurable parameters
int seed;
int water_level;
int lava_depth; int lava_depth;
NoiseParams *np_caveliquids; NoiseParams *np_caveliquids;
// intermediate state variables
u16 ystride;
s16 min_tunnel_diameter; s16 min_tunnel_diameter;
s16 max_tunnel_diameter; s16 max_tunnel_diameter;
u16 tunnel_routepoints; u16 tunnel_routepoints;
@ -62,17 +80,26 @@ public:
content_t c_water_source; content_t c_water_source;
content_t c_lava_source; content_t c_lava_source;
content_t c_ice;
int water_level; // ndef is a mandatory parameter.
u16 ystride; // If gennotify is NULL, generation events are not logged.
CavesRandomWalk(INodeDefManager *ndef,
GenerateNotifier *gennotify = NULL,
int seed = 0,
int water_level = 1,
content_t water_source = CONTENT_IGNORE,
content_t lava_source = CONTENT_IGNORE);
CavesRandomWalk(Mapgen *mg, PseudoRandom *ps); // vm and ps are mandatory parameters.
void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height); // If heightmap is NULL, the surface level at all points is assumed to
// be water_level.
void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
PseudoRandom *ps, int max_stone_height, s16 *heightmap);
private:
void makeTunnel(bool dirswitch); void makeTunnel(bool dirswitch);
void carveRoute(v3f vec, float f, bool randomize_xz); void carveRoute(v3f vec, float f, bool randomize_xz);
private:
inline bool isPosAboveSurface(v3s16 p); inline bool isPosAboveSurface(v3s16 p);
}; };
@ -97,11 +124,13 @@ public:
PseudoRandom *ps; PseudoRandom *ps;
PseudoRandom *ps2; PseudoRandom *ps2;
// configurable parameters
s16 *heightmap; s16 *heightmap;
content_t c_water_source; content_t c_water_source;
content_t c_lava_source; content_t c_lava_source;
int water_level; int water_level;
// intermediate state variables
u16 ystride; u16 ystride;
s16 min_tunnel_diameter; s16 min_tunnel_diameter;

@ -599,8 +599,10 @@ void MapgenBasic::generateCaves(s16 max_stone_y, s16 large_cave_depth)
PseudoRandom ps(blockseed + 21343); PseudoRandom ps(blockseed + 21343);
u32 bruises_count = ps.range(0, 2); u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) { for (u32 i = 0; i < bruises_count; i++) {
CavesRandomWalk cave(this, &ps); CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
cave.makeCave(node_min, node_max, max_stone_y); c_water_source, CONTENT_IGNORE);
cave.makeCave(vm, node_min, node_max, &ps, max_stone_y, heightmap);
} }
} }

@ -841,8 +841,10 @@ void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
if (node_max.Y <= large_cave_depth && !made_a_big_one) { if (node_max.Y <= large_cave_depth && !made_a_big_one) {
u32 bruises_count = ps.range(0, 2); u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) { for (u32 i = 0; i < bruises_count; i++) {
CavesRandomWalk cave(this, &ps); CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
cave.makeCave(node_min, node_max, max_stone_y); c_water_source, c_lava_source);
cave.makeCave(vm, node_min, node_max, &ps, max_stone_y, heightmap);
} }
} }
} }