aboutsummaryrefslogtreecommitdiff
path: root/src/mapgen_v7.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mapgen_v7.cpp')
-rw-r--r--src/mapgen_v7.cpp147
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) {