diff options
Diffstat (limited to 'src/mapgen_v7.cpp')
-rw-r--r-- | src/mapgen_v7.cpp | 147 |
1 files changed, 70 insertions, 77 deletions
diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index bad01bc2a..82bc4aae8 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -49,19 +49,12 @@ FlagDesc flagdesc_mapgen_v7[] = { /////////////////////////////////////////////////////////////////////////////// -MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) { - this->generating = false; - this->id = mapgenid; +MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) + : Mapgen(mapgenid, params, emerge) +{ this->emerge = emerge; this->bmgr = emerge->biomemgr; - this->seed = (int)params->seed; - this->water_level = params->water_level; - this->flags = params->flags; - this->gennotify = emerge->gennotify; - - this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; - //// amount of elements to skip for the next index //// for noise/height/biome maps (not vmanip) this->ystride = csize.X; @@ -119,7 +112,7 @@ MapgenV7::~MapgenV7() { delete noise_heat; delete noise_humidity; - + delete[] ridge_heightmap; delete[] heightmap; delete[] biomemap; @@ -177,7 +170,7 @@ void MapgenV7Params::writeParams(Settings *settings) { int MapgenV7::getGroundLevelAtPoint(v2s16 p) { // Base terrain calculation s16 y = baseTerrainLevelAtPoint(p.X, p.Y); - + // Ridge/river terrain calculation float width = 0.3; float uwatern = NoisePerlin2DNoTxfm(noise_ridge_uwater->np, p.X, p.Y, seed) * 2; @@ -185,14 +178,14 @@ int MapgenV7::getGroundLevelAtPoint(v2s16 p) { // if inside a river, simply guess if (uwatern >= -width && uwatern <= width) return water_level - 10; - + // Mountain terrain calculation int iters = 128; // don't even bother iterating more than 128 times.. while (iters--) { //current point would have been air if (!getMountainTerrainAtPoint(p.X, y, p.Y)) return y; - + y++; } @@ -209,12 +202,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) { assert(data->blockpos_requested.X <= data->blockpos_max.X && data->blockpos_requested.Y <= data->blockpos_max.Y && data->blockpos_requested.Z <= data->blockpos_max.Z); - + this->generating = true; - this->vm = data->vmanip; + this->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); - + v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; @@ -223,19 +216,19 @@ void MapgenV7::makeChunk(BlockMakeData *data) { full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()! - + // Make some noise calculateNoise(); - + // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); - + updateHeightmap(node_min, node_max); - + // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); - + // Actually place the biome-specific nodes and what not generateBiomes(); @@ -255,17 +248,17 @@ void MapgenV7::makeChunk(BlockMakeData *data) { // Sprinkle some dust on top after everything else was generated dustTopNodes(); - + //printf("makeChunk: %dms\n", t.stop()); - + updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); - + if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); - + this->generating = false; } @@ -275,24 +268,24 @@ void MapgenV7::calculateNoise() { int x = node_min.X; int y = node_min.Y; int z = node_min.Z; - + noise_height_select->perlinMap2D(x, z); noise_height_select->transformNoiseMap(); - + noise_terrain_persist->perlinMap2D(x, z); noise_terrain_persist->transformNoiseMap(); float *persistmap = noise_terrain_persist->result; for (int i = 0; i != csize.X * csize.Z; i++) persistmap[i] = rangelim(persistmap[i], 0.4, 0.9); - + noise_terrain_base->perlinMap2DModulated(x, z, persistmap); noise_terrain_base->transformNoiseMap(); - + noise_terrain_alt->perlinMap2DModulated(x, z, persistmap); noise_terrain_alt->transformNoiseMap(); - + noise_filler_depth->perlinMap2D(x, z); - + if (spflags & MGV7_MOUNTAINS) { noise_mountain->perlinMap3D(x, y, z); noise_mount_height->perlinMap2D(x, z); @@ -303,10 +296,10 @@ void MapgenV7::calculateNoise() { noise_ridge->perlinMap3D(x, y, z); noise_ridge_uwater->perlinMap2D(x, z); } - + noise_heat->perlinMap2D(x, z); noise_humidity->perlinMap2D(x, z); - + //printf("calculateNoise: %dus\n", t.stop()); } @@ -315,7 +308,7 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { float heat = NoisePerlin2D(bmgr->np_heat, p.X, p.Z, seed); float humidity = NoisePerlin2D(bmgr->np_humidity, p.X, p.Z, seed); s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z); - + return bmgr->getBiome(heat, humidity, groundlevel); } @@ -323,7 +316,7 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { float MapgenV7::baseTerrainLevelAtPoint(int x, int z) { float hselect = NoisePerlin2D(noise_height_select->np, x, z, seed); hselect = rangelim(hselect, 0.0, 1.0); - + float persist = NoisePerlin2D(noise_terrain_persist->np, x, z, seed); persist = rangelim(persist, 0.4, 0.9); @@ -335,7 +328,7 @@ float MapgenV7::baseTerrainLevelAtPoint(int x, int z) { if (height_alt > height_base) return height_alt; - + return (height_base * hselect) + (height_alt * (1.0 - hselect)); } @@ -344,7 +337,7 @@ float MapgenV7::baseTerrainLevelFromMap(int index) { float hselect = rangelim(noise_height_select->result[index], 0.0, 1.0); float height_base = noise_terrain_base->result[index]; float height_alt = noise_terrain_alt->result[index]; - + if (height_alt > height_base) return height_alt; @@ -373,7 +366,7 @@ void MapgenV7::carveRivers() { MapNode n_air(CONTENT_AIR), n_water_source(c_water_source); MapNode n_stone(c_stone); u32 index = 0; - + int river_depth = 4; for (s16 z = node_min.Z; z <= node_max.Z; z++) @@ -385,16 +378,16 @@ void MapgenV7::carveRivers() { float height = terrain_river * (1 - abs(terrain_mod)) * noise_terrain_river->np->scale; height = log(height * height); //log(h^3) is pretty interesting for terrain - + s16 y = heightmap[index]; if (height < 1.0 && y > river_depth && y - river_depth >= node_min.Y && y <= node_max.Y) { - + for (s16 ry = y; ry != y - river_depth; ry--) { u32 vi = vm->m_area.index(x, ry, z); vm->m_data[vi] = n_air; } - + u32 vi = vm->m_area.index(x, y - river_depth, z); vm->m_data[vi] = n_water_source; } @@ -411,7 +404,7 @@ int MapgenV7::generateTerrain() { if (spflags & MGV7_RIDGES) generateRidgeTerrain(); - + return ymax; } @@ -420,23 +413,23 @@ int MapgenV7::generateBaseTerrain() { MapNode n_air(CONTENT_AIR); MapNode n_stone(c_stone); MapNode n_water(c_water_source); - + int stone_surface_max_y = -MAP_GENERATION_LIMIT; v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { float surface_height = baseTerrainLevelFromMap(index); s16 surface_y = (s16)surface_height; - - heightmap[index] = surface_y; + + heightmap[index] = surface_y; ridge_heightmap[index] = surface_y; - + if (surface_y > stone_surface_max_y) stone_surface_max_y = surface_y; - u32 i = vm->m_area.index(x, node_min.Y, z); + u32 i = vm->m_area.index(x, node_min.Y, z); for (s16 y = node_min.Y; y <= node_max.Y; y++) { if (vm->m_data[i].getContent() == CONTENT_IGNORE) { if (y <= surface_y) @@ -449,7 +442,7 @@ int MapgenV7::generateBaseTerrain() { vm->m_area.add_y(em, i, 1); } } - + return stone_surface_max_y; } @@ -457,10 +450,10 @@ int MapgenV7::generateBaseTerrain() { void MapgenV7::generateMountainTerrain() { if (node_max.Y <= water_level) return; - + MapNode n_stone(c_stone); u32 j = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 y = node_min.Y; y <= node_max.Y; y++) { u32 vi = vm->m_area.index(node_min.X, y, z); @@ -469,7 +462,7 @@ void MapgenV7::generateMountainTerrain() { if (getMountainTerrainFromMap(j, index, y)) vm->m_data[vi] = n_stone; - + vi++; j++; } @@ -481,36 +474,36 @@ void MapgenV7::generateRidgeTerrain() { MapNode n_water(c_water_source); MapNode n_air(CONTENT_AIR); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 y = node_min.Y; y <= node_max.Y; y++) { u32 vi = vm->m_area.index(node_min.X, y, z); for (s16 x = node_min.X; x <= node_max.X; x++, index++, vi++) { int j = (z - node_min.Z) * csize.X + (x - node_min.X); - + if (heightmap[j] < water_level - 4) continue; - + float widthn = (noise_terrain_persist->result[j] - 0.6) / 0.1; //widthn = rangelim(widthn, -0.05, 0.5); - + float width = 0.3; // TODO: figure out acceptable perlin noise values float uwatern = noise_ridge_uwater->result[j] * 2; if (uwatern < -width || uwatern > width) continue; - + float height_mod = (float)(y + 17) / 2.5; float width_mod = (width - fabs(uwatern)); float nridge = noise_ridge->result[index] * (float)y / 7.0; if (y < water_level) nridge = -fabs(nridge) * 3.0 * widthn * 0.3; - + if (nridge + width_mod * height_mod < 0.6) continue; - + if (y < ridge_heightmap[j]) - ridge_heightmap[j] = y - 1; + ridge_heightmap[j] = y - 1; vm->m_data[vi] = (y > water_level) ? n_air : n_water; } @@ -528,7 +521,7 @@ void MapgenV7::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); @@ -537,14 +530,14 @@ void MapgenV7::generateBiomes() { s16 y0_filler = biome->depth_top + dfiller; s16 nplaced = 0; - u32 i = vm->m_area.index(x, node_max.Y, z); + u32 i = vm->m_area.index(x, node_max.Y, z); content_t c_above = vm->m_data[i + em.X].getContent(); bool have_air = c_above == CONTENT_AIR; - + for (s16 y = node_max.Y; y >= node_min.Y; y--) { content_t c = vm->m_data[i].getContent(); - + // It could be the case that the elevation is equal to the chunk // boundary, but the chunk above has not been generated yet if (y == node_max.Y && c_above == CONTENT_IGNORE && @@ -554,10 +547,10 @@ void MapgenV7::generateBiomes() { (x - node_min.X); have_air = !getMountainTerrainFromMap(j, index, y); } - + if (c == c_stone && have_air) { content_t c_below = vm->m_data[i - em.X].getContent(); - + if (c_below != CONTENT_AIR) { if (nplaced < y0_top) { if(y < water_level) @@ -593,7 +586,7 @@ void MapgenV7::generateBiomes() { have_air = true; nplaced = 0; } - + vm->m_area.add_y(em, i, -1); } } @@ -603,14 +596,14 @@ void MapgenV7::generateBiomes() { void MapgenV7::dustTopNodes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + if (water_level > node_max.Y) return; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); - + if (biome->c_dust == CONTENT_IGNORE) continue; @@ -622,17 +615,17 @@ void MapgenV7::dustTopNodes() { vm->m_area.add_y(em, vi, -1); } - + content_t c = vm->m_data[vi].getContent(); if (c == biome->c_water && biome->c_dust_water != CONTENT_IGNORE) { if (y < node_min.Y) continue; - + vm->m_data[vi] = MapNode(biome->c_dust_water); } else if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE) { if (y == node_max.Y) continue; - + vm->m_area.add_y(em, vi, 1); vm->m_data[vi] = MapNode(biome->c_dust); } @@ -649,10 +642,10 @@ void MapgenV7::addTopNodes() { for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = bmgr->biomes[biomemap[index]]; - + //////////////////// First, add top nodes below the ridge s16 y = ridge_heightmap[index]; - + // This cutoff is good enough, but not perfect. // It will cut off potentially placed top nodes at chunk boundaries if (y < node_min.Y) @@ -664,7 +657,7 @@ void MapgenV7::addTopNodes() { if (ndef->get(c).walkable) continue; } - + // N.B. It is necessary to search downward since ridge_heightmap[i] // might not be the actual height, just the lowest part in the chunk // where a ridge had been carved @@ -692,7 +685,7 @@ void MapgenV7::addTopNodes() { vm->m_data[i] = MapNode(c_dirt_with_grass); } } - + //////////////////// Now, add top nodes on top of the ridge y = heightmap[index]; if (y > node_max.Y) { |