diff options
Diffstat (limited to 'src/cavegen.cpp')
-rw-r--r-- | src/cavegen.cpp | 95 |
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 //// |