summaryrefslogtreecommitdiff
path: root/src/cavegen.cpp
diff options
context:
space:
mode:
authorparamat <mat.gregory@virginmedia.com>2017-03-12 13:26:09 +0000
committerparamat <mat.gregory@virginmedia.com>2017-04-03 04:49:32 +0100
commit859141a0ce38fbd606d95ae7a2f0999acf2fbe84 (patch)
tree10a77bdb7f52eadbc0dea7dd9e3066e622a681a8 /src/cavegen.cpp
parent86b1542181a92841d174e1caec94d084a34e5158 (diff)
downloadminetest-859141a0ce38fbd606d95ae7a2f0999acf2fbe84.tar.gz
minetest-859141a0ce38fbd606d95ae7a2f0999acf2fbe84.tar.bz2
minetest-859141a0ce38fbd606d95ae7a2f0999acf2fbe84.zip
Cavegen/Mgv5/Mgv7: Add optional giant caverns
Add to MapgenBasic for use by multiple mapgens. Add to mgv5 and mgv7, enabled by default. Similar to mgvalleys caverns but half the scale. Parameters for upper y limit, distance caverns taper to full size, and noise threshold (full cavern size). As with mgvalleys caverns are generated first and classic caves are disabled in any mapchunk containing a cavern, to avoid excessive spreading volumes of liquids. This also avoids floating blobs of liquid where a large classic cave has overgenerated out into a neighbouring previously-generated mapchunk.
Diffstat (limited to 'src/cavegen.cpp')
-rw-r--r--src/cavegen.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/cavegen.cpp b/src/cavegen.cpp
index 1005640c1..6275c516e 100644
--- a/src/cavegen.cpp
+++ b/src/cavegen.cpp
@@ -151,6 +151,101 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
////
+//// CavernsNoise
+////
+
+CavernsNoise::CavernsNoise(
+ INodeDefManager *nodedef, v3s16 chunksize, NoiseParams *np_cavern,
+ s32 seed, float cavern_limit, float cavern_taper, float cavern_threshold)
+{
+ assert(nodedef);
+
+ m_ndef = nodedef;
+
+ m_csize = chunksize;
+ m_cavern_limit = cavern_limit;
+ m_cavern_taper = cavern_taper;
+ m_cavern_threshold = cavern_threshold;
+
+ m_ystride = m_csize.X;
+ m_zstride_1d = m_csize.X * (m_csize.Y + 1);
+
+ // Noise is created using 1-down overgeneration
+ // A Nx-by-1-by-Nz-sized plane is at the bottom of the desired for
+ // re-carving the solid overtop placed for blocking sunlight
+ noise_cavern = new Noise(np_cavern, seed, m_csize.X, m_csize.Y + 1, m_csize.Z);
+
+ c_water_source = m_ndef->getId("mapgen_water_source");
+ if (c_water_source == CONTENT_IGNORE)
+ c_water_source = CONTENT_AIR;
+
+ c_lava_source = m_ndef->getId("mapgen_lava_source");
+ if (c_lava_source == CONTENT_IGNORE)
+ c_lava_source = CONTENT_AIR;
+}
+
+
+CavernsNoise::~CavernsNoise()
+{
+ delete noise_cavern;
+}
+
+
+bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax)
+{
+ assert(vm);
+
+ // Calculate noise
+ noise_cavern->perlinMap3D(nmin.X, nmin.Y - 1, nmin.Z);
+
+ // Cache cavern_amp values
+ float cavern_amp[m_csize.Y + 1];
+ u8 cavern_amp_index = 0; // Index zero at column top
+ for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, cavern_amp_index++) {
+ cavern_amp[cavern_amp_index] =
+ MYMIN((m_cavern_limit - y) / (float)m_cavern_taper, 1.0f);
+ }
+
+ //// Place nodes
+ bool has_cavern = false;
+ v3s16 em = vm->m_area.getExtent();
+ u32 index2d = 0;
+
+ for (s16 z = nmin.Z; z <= nmax.Z; z++)
+ for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) {
+ // Reset cave_amp index to column top
+ cavern_amp_index = 0;
+ // Initial voxelmanip index at column top
+ u32 vi = vm->m_area.index(x, nmax.Y, z);
+ // Initial 3D noise index at column top
+ u32 index3d = (z - nmin.Z) * m_zstride_1d + m_csize.Y * m_ystride +
+ (x - nmin.X);
+ // Don't excavate the overgenerated stone at node_max.Y + 1,
+ // this creates a 'roof' over the cavern, preventing light in
+ // caverns at mapchunk borders when generating mapchunks upwards.
+ // This 'roof' is excavated when the mapchunk above is generated.
+ for (s16 y = nmax.Y; y >= nmin.Y - 1; y--,
+ index3d -= m_ystride,
+ vm->m_area.add_y(em, vi, -1),
+ cavern_amp_index++) {
+ content_t c = vm->m_data[vi].getContent();
+ float nabs_cavern = fabs(noise_cavern->result[index3d]);
+ // Caverns generate first but still remove lava and water in case
+ // of overgenerated classic caves.
+ if (nabs_cavern * cavern_amp[cavern_amp_index] > m_cavern_threshold &&
+ (m_ndef->get(c).is_ground_content ||
+ c == c_lava_source || c == c_water_source)) {
+ vm->m_data[vi] = MapNode(CONTENT_AIR);
+ has_cavern = true;
+ }
+ }
+ }
+
+ return has_cavern;
+}
+
+
+////
//// CavesRandomWalk
////