X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmapgen%2Fmapgen_carpathian.cpp;h=12ce07da40ceb2d4db6bab5961330ad8c0dc016a;hb=37923920a07f06d201662d8f1f4e5821efcc7b09;hp=24f570b6497d06c3d2c94346d0146948c6f335c1;hpb=7e3f88f539109955b21a129e4203a1cadb913483;p=oweals%2Fminetest.git diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index 24f570b64..12ce07da4 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -1,8 +1,7 @@ /* Minetest -Copyright (C) 2017-2018 vlapsley, Vaughan Lapsley -Copyright (C) 2010-2018 paramat -Copyright (C) 2010-2018 kwolekr, Ryan Kwolek +Copyright (C) 2017-2019 vlapsley, Vaughan Lapsley +Copyright (C) 2017-2019 paramat This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -43,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_carpathian[] = { {"caverns", MGCARPATHIAN_CAVERNS}, + {"rivers", MGCARPATHIAN_RIVERS}, {NULL, 0} }; @@ -50,11 +50,13 @@ FlagDesc flagdesc_mapgen_carpathian[] = { /////////////////////////////////////////////////////////////////////////////// -MapgenCarpathian::MapgenCarpathian( - int mapgenid, MapgenCarpathianParams *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenCarpathian::MapgenCarpathian(MapgenCarpathianParams *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_CARPATHIAN, params, emerge) { base_level = params->base_level; + river_width = params->river_width; + river_depth = params->river_depth; + valley_width = params->valley_width; spflags = params->spflags; cave_width = params->cave_width; @@ -80,6 +82,8 @@ MapgenCarpathian::MapgenCarpathian( noise_hills = new Noise(¶ms->np_hills, seed, csize.X, csize.Z); noise_ridge_mnt = new Noise(¶ms->np_ridge_mnt, seed, csize.X, csize.Z); noise_step_mnt = new Noise(¶ms->np_step_mnt, seed, csize.X, csize.Z); + if (spflags & MGCARPATHIAN_RIVERS) + noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z); //// 3D terrain noise // 1 up 1 down overgeneration @@ -89,6 +93,7 @@ MapgenCarpathian::MapgenCarpathian( MapgenBasic::np_cave1 = params->np_cave1; MapgenBasic::np_cave2 = params->np_cave2; MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -105,26 +110,31 @@ MapgenCarpathian::~MapgenCarpathian() delete noise_hills; delete noise_ridge_mnt; delete noise_step_mnt; + if (spflags & MGCARPATHIAN_RIVERS) + delete noise_rivers; + delete noise_mnt_var; } MapgenCarpathianParams::MapgenCarpathianParams(): - np_filler_depth (0, 1, v3f(128, 128, 128), 261, 3, 0.7, 2.0), - np_height1 (0, 5, v3f(251, 251, 251), 9613, 5, 0.5, 2.0), - np_height2 (0, 5, v3f(383, 383, 383), 1949, 5, 0.5, 2.0), - np_height3 (0, 5, v3f(509, 509, 509), 3211, 5, 0.5, 2.0), - np_height4 (0, 5, v3f(631, 631, 631), 1583, 5, 0.5, 2.0), - np_hills_terrain (1, 1, v3f(1301, 1301, 1301), 1692, 5, 0.5, 2.0), - np_ridge_terrain (1, 1, v3f(1889, 1889, 1889), 3568, 5, 0.5, 2.0), - np_step_terrain (1, 1, v3f(1889, 1889, 1889), 4157, 5, 0.5, 2.0), - np_hills (0, 3, v3f(257, 257, 257), 6604, 6, 0.5, 2.0), - np_ridge_mnt (0, 12, v3f(743, 743, 743), 5520, 6, 0.7, 2.0), - np_step_mnt (0, 8, v3f(509, 509, 509), 2590, 6, 0.6, 2.0), - np_mnt_var (0, 1, v3f(499, 499, 499), 2490, 5, 0.55, 2.0), - np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), - np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0) + np_filler_depth (0, 1, v3f(128, 128, 128), 261, 3, 0.7, 2.0), + np_height1 (0, 5, v3f(251, 251, 251), 9613, 5, 0.5, 2.0), + np_height2 (0, 5, v3f(383, 383, 383), 1949, 5, 0.5, 2.0), + np_height3 (0, 5, v3f(509, 509, 509), 3211, 5, 0.5, 2.0), + np_height4 (0, 5, v3f(631, 631, 631), 1583, 5, 0.5, 2.0), + np_hills_terrain (1, 1, v3f(1301, 1301, 1301), 1692, 5, 0.5, 2.0), + np_ridge_terrain (1, 1, v3f(1889, 1889, 1889), 3568, 5, 0.5, 2.0), + np_step_terrain (1, 1, v3f(1889, 1889, 1889), 4157, 5, 0.5, 2.0), + np_hills (0, 3, v3f(257, 257, 257), 6604, 6, 0.5, 2.0), + np_ridge_mnt (0, 12, v3f(743, 743, 743), 5520, 6, 0.7, 2.0), + np_step_mnt (0, 8, v3f(509, 509, 509), 2590, 6, 0.6, 2.0), + np_rivers (0, 1, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0), + np_mnt_var (0, 1, v3f(499, 499, 499), 2490, 5, 0.55, 2.0), + np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -132,7 +142,12 @@ MapgenCarpathianParams::MapgenCarpathianParams(): void MapgenCarpathianParams::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian); - settings->getFloatNoEx("mgcarpathian_base_level", base_level); + + settings->getFloatNoEx("mgcarpathian_base_level", base_level); + settings->getFloatNoEx("mgcarpathian_river_width", river_width); + settings->getFloatNoEx("mgcarpathian_river_depth", river_depth); + settings->getFloatNoEx("mgcarpathian_valley_width", valley_width); + settings->getFloatNoEx("mgcarpathian_cave_width", cave_width); settings->getS16NoEx("mgcarpathian_large_cave_depth", large_cave_depth); settings->getS16NoEx("mgcarpathian_lava_depth", lava_depth); @@ -153,17 +168,24 @@ void MapgenCarpathianParams::readParams(const Settings *settings) settings->getNoiseParams("mgcarpathian_np_hills", np_hills); settings->getNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt); settings->getNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt); + settings->getNoiseParams("mgcarpathian_np_rivers", np_rivers); settings->getNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var); settings->getNoiseParams("mgcarpathian_np_cave1", np_cave1); settings->getNoiseParams("mgcarpathian_np_cave2", np_cave2); settings->getNoiseParams("mgcarpathian_np_cavern", np_cavern); + settings->getNoiseParams("mgcarpathian_np_dungeons", np_dungeons); } void MapgenCarpathianParams::writeParams(Settings *settings) const { settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX); - settings->setFloat("mgcarpathian_base_level", base_level); + + settings->setFloat("mgcarpathian_base_level", base_level); + settings->setFloat("mgcarpathian_river_width", river_width); + settings->setFloat("mgcarpathian_river_depth", river_depth); + settings->setFloat("mgcarpathian_valley_width", valley_width); + settings->setFloat("mgcarpathian_cave_width", cave_width); settings->setS16("mgcarpathian_large_cave_depth", large_cave_depth); settings->setS16("mgcarpathian_lava_depth", lava_depth); @@ -184,10 +206,12 @@ void MapgenCarpathianParams::writeParams(Settings *settings) const settings->setNoiseParams("mgcarpathian_np_hills", np_hills); settings->setNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt); settings->setNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt); + settings->setNoiseParams("mgcarpathian_np_rivers", np_rivers); settings->setNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var); settings->setNoiseParams("mgcarpathian_np_cave1", np_cave1); settings->setNoiseParams("mgcarpathian_np_cave2", np_cave2); settings->setNoiseParams("mgcarpathian_np_cavern", np_cavern); + settings->setNoiseParams("mgcarpathian_np_dungeons", np_dungeons); } @@ -247,42 +271,47 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) updateHeightmap(node_min, node_max); // Init biome generator, place biome-specific nodes, and build biomemap - biomegen->calcBiomeNoise(node_min); - - MgStoneType mgstone_type; - content_t biome_stone; - generateBiomes(&mgstone_type, &biome_stone); + if (flags & MG_BIOMES) { + biomegen->calcBiomeNoise(node_min); + generateBiomes(); + } - // Generate caverns, tunnels and classic caves + // Generate tunnels, caverns and large randomwalk caves if (flags & MG_CAVES) { - bool has_cavern = false; + // Generate tunnels first as caverns confuse them + generateCavesNoiseIntersection(stone_surface_max_y); + // Generate caverns + bool near_cavern = false; if (spflags & MGCARPATHIAN_CAVERNS) - has_cavern = generateCaverns(stone_surface_max_y); - // Generate tunnels and classic caves - if (has_cavern) - // Disable classic caves in this mapchunk by setting + near_cavern = generateCavernsNoise(stone_surface_max_y); + + // Generate large randomwalk caves + if (near_cavern) + // Disable large randomwalk caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. - generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); else - generateCaves(stone_surface_max_y, large_cave_depth); + generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } + // Generate the registered ores + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + // Generate dungeons if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && full_node_max.Y <= dungeon_ymax) - generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); + generateDungeons(stone_surface_max_y); // Generate the registered decorations if (flags & MG_DECORATIONS) m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); - // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); - // Sprinkle some dust on top after everything else was generated - dustTopNodes(); + if (flags & MG_BIOMES) + dustTopNodes(); // Update liquids updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); @@ -302,64 +331,95 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) { - s16 level_at_point = terrainLevelAtPoint(p.X, p.Y); - if (level_at_point <= water_level || level_at_point > water_level + 32) - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - - return level_at_point; -} - - -float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z) -{ - float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed); - float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed); - float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed); - float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed); - float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed); - float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed); - float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed); - float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed); - float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed); - float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed); - - int height = -MAX_MAP_GENERATION_LIMIT; + // If rivers are enabled, first check if in a river channel + if (spflags & MGCARPATHIAN_RIVERS) { + float river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) - + river_width; + if (river < 0.0f) + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + } - for (s16 y = 1; y <= 30; y++) { - float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed); + float height1 = NoisePerlin2D(&noise_height1->np, p.X, p.Y, seed); + float height2 = NoisePerlin2D(&noise_height2->np, p.X, p.Y, seed); + float height3 = NoisePerlin2D(&noise_height3->np, p.X, p.Y, seed); + float height4 = NoisePerlin2D(&noise_height4->np, p.X, p.Y, seed); + + float hterabs = std::fabs(NoisePerlin2D(&noise_hills_terrain->np, p.X, p.Y, seed)); + float n_hills = NoisePerlin2D(&noise_hills->np, p.X, p.Y, seed); + float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills; + + float rterabs = std::fabs(NoisePerlin2D(&noise_ridge_terrain->np, p.X, p.Y, seed)); + float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, p.X, p.Y, seed); + float ridge_mnt = rterabs * rterabs * rterabs * (1.0f - std::fabs(n_ridge_mnt)); + + float sterabs = std::fabs(NoisePerlin2D(&noise_step_terrain->np, p.X, p.Y, seed)); + float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, p.X, p.Y, seed); + float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt); + + float valley = 1.0f; + float river = 0.0f; + + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) { + river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) - river_width; + if (river <= valley_width) { + // Within river valley + if (river < 0.0f) { + // River channel + valley = river; + } else { + // Valley slopes. + // 0 at river edge, 1 at valley edge. + float riversc = river / valley_width; + // Smoothstep + valley = riversc * riversc * (3.0f - 2.0f * riversc); + } + } + } - // Gradient & shallow seabed - s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y; + bool solid_below = false; + u8 cons_non_solid = 0; // consecutive non-solid nodes - // Hill/Mountain height (hilliness) + for (s16 y = water_level; y <= water_level + 32; y++) { + float mnt_var = NoisePerlin3D(&noise_mnt_var->np, p.X, y, p.Y, seed); float hill1 = getLerp(height1, height2, mnt_var); float hill2 = getLerp(height3, height4, mnt_var); float hill3 = getLerp(height3, height2, mnt_var); float hill4 = getLerp(height1, height4, mnt_var); - float hilliness = - std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4)); - // Rolling hills - float hill_mnt = hilliness * std::pow(n_hills, 2.f); - float hills = std::pow(std::fabs(hter), 3.f) * hill_mnt; + float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4)); + float hills = hill_mnt * hilliness; + float ridged_mountains = ridge_mnt * hilliness; + float step_mountains = step_mnt * hilliness; - // Ridged mountains - float ridge_mnt = hilliness * (1.f - std::fabs(n_ridge_mnt)); - float ridged_mountains = std::pow(std::fabs(rter), 3.f) * ridge_mnt; - - // Step (terraced) mountains - float step_mnt = hilliness * getSteps(n_step_mnt); - float step_mountains = std::pow(std::fabs(ster), 3.f) * step_mnt; + s32 grad = 1 - y; - // Final terrain level float mountains = hills + ridged_mountains + step_mountains; float surface_level = base_level + mountains + grad; - if (y > surface_level && height < 0) - height = y; + if ((spflags & MGCARPATHIAN_RIVERS) && river <= valley_width) { + if (valley < 0.0f) { + // River channel + surface_level = std::fmin(surface_level, + water_level - std::sqrt(-valley) * river_depth); + } else if (surface_level > water_level) { + // Valley slopes + surface_level = water_level + (surface_level - water_level) * valley; + } + } + + if (y < surface_level) { //TODO '<=' fix from generateTerrain() + // solid node + solid_below = true; + cons_non_solid = 0; + } else { + // non-solid node + cons_non_solid++; + if (cons_non_solid == 3 && solid_below) + return y - 1; + } } - return height; + return MAX_MAP_GENERATION_LIMIT; // No suitable spawn point found } @@ -385,6 +445,9 @@ int MapgenCarpathian::generateTerrain() noise_step_mnt->perlinMap2D(node_min.X, node_min.Z); noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); + if (spflags & MGCARPATHIAN_RIVERS) + noise_rivers->perlinMap2D(node_min.X, node_min.Z); + //// Place nodes const v3s16 &em = vm->m_area.getExtent(); s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; @@ -407,13 +470,34 @@ int MapgenCarpathian::generateTerrain() float rterabs = std::fabs(noise_ridge_terrain->result[index2d]); float n_ridge_mnt = noise_ridge_mnt->result[index2d]; float ridge_mnt = rterabs * rterabs * rterabs * - (1.f - std::fabs(n_ridge_mnt)); + (1.0f - std::fabs(n_ridge_mnt)); // Step (terraced) mountains float sterabs = std::fabs(noise_step_terrain->result[index2d]); float n_step_mnt = noise_step_mnt->result[index2d]; float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt); + // Rivers + float valley = 1.0f; + float river = 0.0f; + + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) { + river = std::fabs(noise_rivers->result[index2d]) - river_width; + if (river <= valley_width) { + // Within river valley + if (river < 0.0f) { + // River channel + valley = river; + } else { + // Valley slopes. + // 0 at river edge, 1 at valley edge. + float riversc = river / valley_width; + // Smoothstep + valley = riversc * riversc * (3.0f - 2.0f * riversc); + } + } + } + // Initialise 3D noise index and voxelmanip index to column base u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X); u32 vi = vm->m_area.index(x, node_min.Y - 1, z); @@ -448,7 +532,20 @@ int MapgenCarpathian::generateTerrain() float mountains = hills + ridged_mountains + step_mountains; float surface_level = base_level + mountains + grad; - if (y < surface_level) { + // Rivers + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16 && + river <= valley_width) { + if (valley < 0.0f) { + // River channel + surface_level = std::fmin(surface_level, + water_level - std::sqrt(-valley) * river_depth); + } else if (surface_level > water_level) { + // Valley slopes + surface_level = water_level + (surface_level - water_level) * valley; + } + } + + if (y < surface_level) { //TODO '<=' vm->m_data[vi] = mn_stone; // Stone if (y > stone_surface_max_y) stone_surface_max_y = y;