Exemplo n.º 1
0
void MapgenV7::carveRidges() {
	if (node_max.Y <= water_level)
		return;
		
	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++) {
			// Removing this check will create huge underwater caverns,
			// which are interesting but not desirable for gameplay
			if (y <= water_level)
				continue;
				
			if (noise_ridge->result[index] * (float)(y * y) < 15.0)
				continue;

			int j = (z - node_min.Z) * csize.Z + (x - node_min.X); //////obviously just temporary
			if (y < ridge_heightmap[j])
				ridge_heightmap[j] = y - 1; 

			vm->m_data[vi] = n_air;
		}
	}
}
Exemplo n.º 2
0
void MapgenV7::generateRidgeTerrain()
{
	if ((node_max.Y < water_level - 16) || (node_max.Y > shadow_limit))
		return;

	noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
	noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z);

	MapNode n_water(c_water_source);
	MapNode n_air(CONTENT_AIR);
	u32 index = 0;
	float width = 0.2;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; 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);

			float uwatern = noise_ridge_uwater->result[j] * 2;
			if (fabs(uwatern) > width)
				continue;

			float altitude = y - water_level;
			float height_mod = (altitude + 17) / 2.5;
			float width_mod  = width - fabs(uwatern);
			float nridge = noise_ridge->result[index] * MYMAX(altitude, 0) / 7.0;

			if (nridge + width_mod * height_mod < 0.6)
				continue;

			vm->m_data[vi] = (y > water_level) ? n_air : n_water;
		}
	}
}
Exemplo n.º 3
0
s16 MapgenFractal::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++) {
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			u32 vi = vm->m_area.index(node_min.X, y, z);
			for (s16 x = node_min.X; x <= node_max.X; x++, vi++, index2d++) {
				if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
					s16 seabed_height = noise_seabed->result[index2d];

					if (y <= seabed_height || getFractalAtPoint(x, y, z)) {
						vm->m_data[vi] = n_stone;
						if (y > stone_surface_max_y)
							stone_surface_max_y = y;
					} else if (y <= water_level) {
						vm->m_data[vi] = n_water;
					} else {
						vm->m_data[vi] = n_air;
					}
				}
			}
			index2d -= ystride;
		}
		index2d += ystride;
	}

	return stone_surface_max_y;
}
Exemplo n.º 4
0
void MapgenV7::generateTerrain() {
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone);

	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++) {
		s16 surface_y = heightmap[index];
		Biome *biome = bmgr->biomes[biomemap[index]];
		
		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) {
					vm->m_data[i] = (y > water_level + biome->filler_height) ?
						MapNode(biome->c_filler) : n_stone;
				} else if (y <= water_level) {
					vm->m_data[i] = n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}
}
Exemplo n.º 5
0
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++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
		float terrain_mod  = noise_terrain_mod->result[index];
		NoiseParams *np = noise_terrain_river->np;
		np.persist = noise_terrain_persist->result[index];
		float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed);
		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;
		}
	}
}
Exemplo n.º 6
0
int MapgenIndev::generateGround() {
    //TimeTaker timer1("Generating ground level");
    MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
    MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
    MapNode n_ice(c_ice), n_dirt(c_dirt),n_sand(c_sand), n_gravel(c_gravel), n_lava_source(c_lava_source);
    int stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
    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++) {
            // Surface height
            s16 surface_y = (s16)baseTerrainLevelFromMap(index);

            // Log it
            if (surface_y > stone_surface_max_y)
                stone_surface_max_y = surface_y;

            auto bt = getBiome(index, v3POS(x, surface_y, z));

            s16 heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x,node_max.Y,z), nullptr, &heat_cache) : 0;

            // Fill ground with stone
            v3POS em = vm->m_area.getExtent();
            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]) {

                    if (y <= surface_y) {
                        int index3 = (z - node_min.Z) * zstride + (y - node_min.Y) * ystride + (x - node_min.X) * xstride;
                        if (cave_noise_threshold && noise_cave_indev->result[index3] > cave_noise_threshold) {
                            vm->m_data[i] = n_air;
                        } else {
                            auto n = (y > water_level - surface_y && bt == BT_DESERT) ? n_desert_stone : layers_get(index3);
                            bool protect = n.getContent() != CONTENT_AIR;
                            if (cave_noise_threshold && noise_cave_indev->result[index3] > cave_noise_threshold - 50) {
                                vm->m_data[i] = protect ? n_stone : n; //cave shell without layers
                                protect = true;
                            } else {
                                vm->m_data[i] = n;
                            }
                            if (protect)
                                vm->m_flags[i] |= VOXELFLAG_CHECKED2; // no cave liquid
                        }
                    } else if (y <= water_level) {
                        vm->m_data[i] = (heat < 0 && y > heat/3) ? n_ice : n_water_source;
                        if (liquid_pressure && y <= 0)
                            vm->m_data[i].addLevel(m_emerge->ndef, water_level - y, 1);
                    } else {
                        vm->m_data[i] = n_air;
                    }
                }
                vm->m_area.add_y(em, i, 1);
            }
        }

    return stone_surface_max_y;
}
Exemplo n.º 7
0
void MapgenV7::generateBaseTerrain(s16 *stone_surface_min_y, s16 *stone_surface_max_y)
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);
	MapNode n_ice(c_ice);

	v3s16 em = vm->m_area.getExtent();
	s16 surface_min_y = MAX_MAP_GENERATION_LIMIT;
	s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	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;
		ridge_heightmap[index] = surface_y;

		if (surface_y < surface_min_y)
			surface_min_y = surface_y;

		if (surface_y > surface_max_y)
			surface_max_y = surface_y;

		s16 heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x,node_max.Y,z), nullptr, &heat_cache) : 0;

		u32 i = vm->m_area.index(x, node_min.Y - 1, z);
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {

					int index3 = (z - node_min.Z) * zstride +
						(y - node_min.Y + 1) * ystride +
						(x - node_min.X);

					vm->m_data[i] = layers_get(index3);
				}
				else if (y <= water_level)
				{
					vm->m_data[i] = (heat < 0 && y > heat/3) ? n_ice : n_water;
					if (liquid_pressure && y <= 0)
						vm->m_data[i].addLevel(m_emerge->ndef, water_level - y, 1);
				}
				else
					vm->m_data[i] = n_air;
			}
			vm->m_area.add_y(em, i, 1);
		}
	}

	*stone_surface_min_y = surface_min_y;
	*stone_surface_max_y = surface_max_y;
}
Exemplo n.º 8
0
int MapgenV7P::generateTerrain()
{
	MapNode n_stone(c_stone);
	MapNode n_bedrock(c_bedrock);
	MapNode n_water(c_water_source);
	MapNode n_air(CONTENT_AIR);

	//// Calculate noise for terrain generation
	noise_terrain_persist->perlinMap2D(node_min.X, node_min.Z);
	float *persistmap = noise_terrain_persist->result;

	noise_terrain_base ->perlinMap2D(node_min.X, node_min.Z, persistmap);
	noise_terrain_alt  ->perlinMap2D(node_min.X, node_min.Z, persistmap);
	noise_height_select->perlinMap2D(node_min.X, node_min.Z);

	if (spflags & MGV7P_MOUNTAINS) {
		noise_mount_height->perlinMap2D(node_min.X, node_min.Z);
		noise_mountain    ->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;
	u32 index2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
		s16 surface_y = baseTerrainLevelFromMap(index2d);
		if (spflags & MGV7P_MOUNTAINS)
			surface_y = MYMAX(mountainLevelFromMap(index2d), surface_y);

		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		u32 vi = vm->m_area.index(x, node_min.Y - 1, z);

		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {
					if (y <= bedrock_level)
						vm->m_data[vi] = n_bedrock; // Bedrock
					else
						vm->m_data[vi] = n_stone; // Base and mountain terrain
				} else if (y <= water_level) {
					vm->m_data[vi] = n_water; // Water
				} else {
					vm->m_data[vi] = n_air; // Air
				}
			}
			vm->m_area.add_y(em, vi, 1);
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 9
0
s16 MapgenFlat::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 ni2d = 0;

	bool use_noise = (spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS);
	if (use_noise)
		noise_terrain->perlinMap2D(node_min.X, node_min.Z);

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, ni2d++) {
		s16 stone_level = ground_level;
		float n_terrain = use_noise ? noise_terrain->result[ni2d] : 0.0f;

		if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) {
			s16 depress = (lake_threshold - n_terrain) * lake_steepness;
			stone_level = ground_level - depress;
		} else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) {
			s16 rise = (n_terrain - hill_threshold) * hill_steepness;
		 	stone_level = ground_level + rise;
		}

		u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
				if (y <= stone_level) {
					vm->m_data[vi] = n_stone;
					if (y > stone_surface_max_y)
						stone_surface_max_y = y;
				} else if (y <= water_level) {
					vm->m_data[vi] = n_water;
				} else {
					vm->m_data[vi] = n_air;
				}
			}
			vm->m_area.add_y(em, vi, 1);
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 10
0
int MapgenV6::generateGround()
{
	//TimeTaker timer1("Generating ground level");
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
	MapNode n_ice(c_ice);
	int stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;

	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++) {
		// Surface height
		s16 surface_y = (s16)baseTerrainLevelFromMap(index);

		// Log it
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		BiomeV6Type bt = getBiome(v3POS(x, node_min.Y, z));
		s16 heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x,node_max.Y,z), nullptr, &heat_cache) : 0;

		// Fill ground with stone
		v3s16 em = vm->m_area.getExtent();
		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) {
					vm->m_data[i] = (y >= MGV6_DESERT_STONE_BASE - surface_y
							&& bt == BT_DESERT) ?
						n_desert_stone : n_stone;
				} else if (y <= water_level) {
					vm->m_data[i] = ((heat < 0 && y > heat/3) || (y >= MGV6_ICE_BASE
							&& bt == BT_TUNDRA)) ?
						n_ice : n_water_source;
					if (liquid_pressure && y <= 0)
						vm->m_data[i].addLevel(m_emerge->ndef, water_level - y, 1);
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 11
0
int MapgenV7::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index2d = 0;
	bool mountain_flag = spflags & MGV7_MOUNTAINS;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
		s16 surface_y = baseTerrainLevelFromMap(index2d);
		heightmap[index2d]       = surface_y;  // Create base terrain heightmap
		ridge_heightmap[index2d] = surface_y;

		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
		u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);

		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {
					vm->m_data[vi] = n_stone;  // Base terrain
				} else if (mountain_flag &&
						getMountainTerrainFromMap(index3d, index2d, y)) {
					vm->m_data[vi] = n_stone;  // Mountain terrain
					if (y > stone_surface_max_y)
						stone_surface_max_y = y;
				} else if (y <= water_level) {
					vm->m_data[vi] = n_water;
				} else {
					vm->m_data[vi] = n_air;
				}
			}
			vm->m_area.add_y(em, vi, 1);
			index3d += ystride;
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 12
0
int MapgenV6::generateGround()
{
	//TimeTaker timer1("Generating ground level");
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
	MapNode n_ice(c_ice);
	int stone_surface_max_y = -MAP_GENERATION_LIMIT;

	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++) {
		// Surface height
		s16 surface_y = (s16)baseTerrainLevelFromMap(index);

		// Log it
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		BiomeV6Type bt = getBiome(v2s16(x, z));

		// Fill ground with stone
		v3s16 em = vm->m_area.getExtent();
		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) {
					vm->m_data[i] = (y >= DESERT_STONE_BASE
							&& bt == BT_DESERT) ?
						n_desert_stone : n_stone;
				} else if (y <= water_level) {
					vm->m_data[i] = (y >= ICE_BASE
							&& bt == BT_TUNDRA) ?
						n_ice : n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 13
0
void MapgenV7::generateRidgeTerrain()
{
	if (node_max.Y < water_level)
		return;

	MapNode n_water(c_water_source);
	MapNode n_ice(c_ice);
	MapNode n_air(CONTENT_AIR);
	u32 index = 0;
	float width = 0.2; // TODO: figure out acceptable perlin noise values

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; 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 - 16)
				continue;

			float uwatern = noise_ridge_uwater->result[j] * 2;
			if (fabs(uwatern) > width)
				continue;

			float altitude = y - water_level;
			float height_mod = (altitude + 17) / 2.5;
			float width_mod  = width - fabs(uwatern);
			float nridge = noise_ridge->result[index] * MYMAX(altitude, 0) / 7.0;

			if (nridge + width_mod * height_mod < 0.6)
				continue;

			if (y < ridge_heightmap[j])
				ridge_heightmap[j] = y - 1;

			s16 heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x,node_max.Y,z), NULL, &heat_cache) : 0;
			MapNode n_water_or_ice = (heat < 0 && y > water_level + heat/4) ? n_ice : n_water;

			vm->m_data[vi] = (y > water_level) ? n_air : n_water_or_ice;
		}
	}
}
Exemplo n.º 14
0
void MapgenV7::generateBaseTerrain(s16 *stone_surface_min_y, s16 *stone_surface_max_y)
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 surface_min_y = MAX_MAP_GENERATION_LIMIT;
	s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	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;
		ridge_heightmap[index] = surface_y;

		if (surface_y < surface_min_y)
			surface_min_y = surface_y;

		if (surface_y > surface_max_y)
			surface_max_y = surface_y;

		u32 i = vm->m_area.index(x, node_min.Y - 1, z);
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y)
					vm->m_data[i] = n_stone;
				else if (y <= water_level)
					vm->m_data[i] = n_water;
				else
					vm->m_data[i] = n_air;
			}
			vm->m_area.add_y(em, i, 1);
		}
	}

	*stone_surface_min_y = surface_min_y;
	*stone_surface_max_y = surface_max_y;
}
Exemplo n.º 15
0
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;

			vm->m_data[vi] = (y > water_level) ? n_air : n_water;
		}
	}
}
Exemplo n.º 16
0
int MapgenV6::generateGround() {
	//TimeTaker timer1("Generating ground level");
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
	MapNode n_ice(c_ice);
	int stone_surface_max_y = -MAP_GENERATION_LIMIT;
	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++) {
		// Surface height
		s16 surface_y = (s16)baseTerrainLevelFromMap(index);
		
		// Log it
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		BiomeType bt = getBiome(index, v2s16(x, z));
		
		// Fill ground with stone
		v3s16 em = vm->m_area.getExtent();
		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) {
					vm->m_data[i] = (y > water_level - surface_y && bt == BT_DESERT) ? 
						n_desert_stone : n_stone;
				} else if (y <= water_level) {
					s16 heat = emerge->env->m_use_weather ? emerge->env->getServerMap().updateBlockHeat(emerge->env, v3s16(x,y,z)) : 0;
					vm->m_data[i] = (heat < 0 && y > heat/3) ? n_ice : n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}
	
	return stone_surface_max_y;
}
Exemplo n.º 17
0
void MapgenV7::generateRidgeTerrain()
{
	if (node_max.Y < water_level)
		return;

	MapNode n_water(c_water_source);
	MapNode n_air(CONTENT_AIR);
	u32 index = 0;
	float width = 0.2; // TODO: figure out acceptable perlin noise values

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; 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 - 16)
				continue;

			float uwatern = noise_ridge_uwater->result[j] * 2;
			if (fabs(uwatern) > width)
				continue;

			float altitude = y - water_level;
			float height_mod = (altitude + 17) / 2.5;
			float width_mod  = width - fabs(uwatern);
			float nridge = noise_ridge->result[index] * MYMAX(altitude, 0) / 7.0;

			if (nridge + width_mod * height_mod < 0.6)
				continue;

			if (y < ridge_heightmap[j])
				ridge_heightmap[j] = y - 1;

			vm->m_data[vi] = (y > water_level) ? n_air : n_water;
		}
	}
}
Exemplo n.º 18
0
void MapgenV6::moveMud(u32 remove_index, u32 place_index,
	u32 above_remove_index, v2s16 pos, v3s16 em)
{
	MapNode n_air(CONTENT_AIR);
	// Copy mud from old place to new place
	vm->m_data[place_index] = vm->m_data[remove_index];
	// Set old place to be air
	vm->m_data[remove_index] = n_air;
	// Outside the mapchunk decorations may need to be removed if above removed
	// mud or if half-buried in placed mud. Placed mud is to the side of pos so
	// use 'pos.X >= node_max.X' etc.
	if (pos.X >= node_max.X || pos.X <= node_min.X ||
			pos.Y >= node_max.Z || pos.Y <= node_min.Z) {
		// 'above remove' node is above removed mud. If it is not air, water or
		// 'ignore' it is a decoration that needs removing. Also search upwards
		// to remove a possible stacked decoration.
		// Check for 'ignore' because stacked decorations can penetrate into
		// 'ignore' nodes above the mapchunk.
		while (vm->m_area.contains(above_remove_index) &&
				vm->m_data[above_remove_index].getContent() != CONTENT_AIR &&
				vm->m_data[above_remove_index].getContent() != c_water_source &&
				vm->m_data[above_remove_index].getContent() != CONTENT_IGNORE) {
			vm->m_data[above_remove_index] = n_air;
			vm->m_area.add_y(em, above_remove_index, 1);
		}
		// Mud placed may have partially-buried a stacked decoration, search
		// above and remove.
		vm->m_area.add_y(em, place_index, 1);
		while (vm->m_area.contains(place_index) &&
				vm->m_data[place_index].getContent() != CONTENT_AIR &&
				vm->m_data[place_index].getContent() != c_water_source &&
				vm->m_data[place_index].getContent() != CONTENT_IGNORE) {
			vm->m_data[place_index] = n_air;
			vm->m_area.add_y(em, place_index, 1);
		}
	}
}
Exemplo n.º 19
0
int MapgenV7::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	//// Calculate noise for terrain generation
	noise_terrain_persist->perlinMap2D(node_min.X, node_min.Z);
	float *persistmap = noise_terrain_persist->result;

	noise_terrain_base->perlinMap2D(node_min.X, node_min.Z, persistmap);
	noise_terrain_alt->perlinMap2D(node_min.X, node_min.Z, persistmap);
	noise_height_select->perlinMap2D(node_min.X, node_min.Z);

	if ((spflags & MGV7_MOUNTAINS) || (spflags & MGV7_FLOATLANDS)) {
		noise_mountain->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
	}

	if (spflags & MGV7_MOUNTAINS) {
		noise_mount_height->perlinMap2D(node_min.X, node_min.Z);
	}

	if (spflags & MGV7_FLOATLANDS) {
		noise_floatland_base->perlinMap2D(node_min.X, node_min.Z);
		noise_float_base_height->perlinMap2D(node_min.X, node_min.Z);
	}

	//// Place nodes
	v3s16 em = vm->m_area.getExtent();
	s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
		s16 surface_y = baseTerrainLevelFromMap(index2d);
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		// Get extent of floatland base terrain
		// '+1' to avoid a layer of stone at y = MAX_MAP_GENERATION_LIMIT
		s16 float_base_min = MAX_MAP_GENERATION_LIMIT + 1;
		s16 float_base_max = MAX_MAP_GENERATION_LIMIT;
		if (spflags & MGV7_FLOATLANDS)
			floatBaseExtentFromMap(&float_base_min, &float_base_max, index2d);

		u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
		u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);

		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {
					vm->m_data[vi] = n_stone;  // Base terrain
				} else if ((spflags & MGV7_MOUNTAINS) &&
						getMountainTerrainFromMap(index3d, index2d, y)) {
					vm->m_data[vi] = n_stone;  // Mountain terrain
					if (y > stone_surface_max_y)
						stone_surface_max_y = y;
				} else if ((spflags & MGV7_FLOATLANDS) &&
						((y >= float_base_min && y <= float_base_max) ||
						getFloatlandMountainFromMap(index3d, index2d, y))) {
					vm->m_data[vi] = n_stone;  // Floatland terrain
					stone_surface_max_y = node_max.Y;
				} else if (y <= water_level) {
					vm->m_data[vi] = n_water;  // Ground level water
				} else if ((spflags & MGV7_FLOATLANDS) &&
						(y >= float_base_max && y <= floatland_level)) {
					vm->m_data[vi] = n_water;  // Floatland water
				} else {
					vm->m_data[vi] = n_air;
				}
			}
			vm->m_area.add_y(em, vi, 1);
			index3d += ystride;
		}
	}

	return stone_surface_max_y;
}
Exemplo n.º 20
0
int MapgenValleys::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_river_water(c_river_water_source);
	MapNode n_sand(c_sand);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index_2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
		s16 river_y = floor(noise_rivers->result[index_2d]);
		s16 surface_y = floor(noise_terrain_height->result[index_2d]);
		float slope = noise_inter_valley_slope->result[index_2d];

		heightmap[index_2d] = surface_y;

		if (surface_y > surface_max_y)
			surface_max_y = surface_y;

		u32 index_3d = 0;
		if (!fast_terrain)
			index_3d = (z - node_min.Z) * zstride + (x - node_min.X);

		u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);

		// Mapgens concern themselves with stone and water.
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			float fill = 0.f;
			if (!fast_terrain)
				fill = noise_inter_valley_fill->result[index_3d];

			if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
				bool river = (river_y > surface_y);

				if (river && y == surface_y) {
					// river bottom
					vm->m_data[index_data] = n_sand;
				} else if ((fast_terrain || river) && y <= surface_y) {
					// ground
					vm->m_data[index_data] = n_stone;
				} else if (river && y < river_y) {
					// river
					vm->m_data[index_data] = n_river_water;
				} else if ((!fast_terrain) && (!river) && round(fill * slope) >= y - surface_y) {
					// ground (slow method)
					vm->m_data[index_data] = n_stone;
					heightmap[index_2d] = surface_max_y = y;
				} else if (y <= water_level) {
					// sea
					vm->m_data[index_data] = n_water;
				} else {
					vm->m_data[index_data] = n_air;
				}
			}

			vm->m_area.add_y(em, index_data, 1);
			if (!fast_terrain)
				index_3d += ystride;
		}

		if (!fast_terrain) {
			// Assign the humidity adjusted by water proximity.
			noise_humidity->result[index_2d] = humidityByTerrain(
					noise_humidity->result[index_2d],
					surface_max_y,
					noise_rivers->result[index_2d],
					noise_valley_depth->result[index_2d]);

			// Assign the heat adjusted by altitude. See humidity, above.
			if (use_altitude_chill && surface_max_y > 0)
				noise_heat->result[index_2d]
					*= pow(0.5f, (surface_max_y - altitude_chill / 3.f) / altitude_chill);
		}
	}

	return surface_max_y;
}
Exemplo n.º 21
0
void MapgenValleys::generateSimpleCaves(s16 max_stone_y)
{
	PseudoRandom ps(blockseed + 72202);

	MapNode n_air(CONTENT_AIR);
	MapNode n_dirt(c_dirt);
	MapNode n_lava(c_lava_source);
	MapNode n_water(c_river_water_source);

	v3s16 em = vm->m_area.getExtent();

	s16 base_water_chance = 0;
	if (water_features < 11)
		base_water_chance = ceil(MAX_MAP_GENERATION_LIMIT / (water_features * 1000));

	if (max_stone_y >= node_min.Y) {
		u32 index_2d = 0;
		u32 index_3d = 0;
		for (s16 z = node_min.Z; z <= node_max.Z; z++)
		for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
			bool air_above = false;
			//bool underground = false;
			u32 index_data = vm->m_area.index(x, node_max.Y + 1, z);

			index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);

			// Dig caves on down loop to check for air above.
			for (s16 y = node_max.Y + 1;
					y >= node_min.Y - 1;
					y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) {
				float terrain = noise_terrain_height->result[index_2d];

				// Saves some time and prevents removing above ground nodes.
				if (y > terrain + 1) {
					air_above = true;
					continue;
				}

				content_t c = vm->m_data[index_data].getContent();
				bool n1 = (fabs(noise_simple_caves_1->result[index_3d]) < 0.07f);
				bool n2 = (fabs(noise_simple_caves_2->result[index_3d]) < 0.07f);

				// River water is (foolishly) not set as ground content
				// in the default game. This can produce strange results
				// when a cave undercuts a river. However, that's not for
				// the mapgen to correct. Fix it in lua.

				if (c == CONTENT_AIR) {
					air_above = true;
				} else if (n1 && n2 && ndef->get(c).is_ground_content) {
					// When both n's are true, we're in a cave.
					vm->m_data[index_data] = n_air;
					air_above = true;
				} else if (air_above
						&& (c == c_stone || c == c_sandstone || c == c_desert_stone)) {
					// At the cave floor
					s16 sr = ps.next() & 1023;
					u32 j = index_data;
					vm->m_area.add_y(em, j, 1);

					if (sr > (terrain - y) * 25) {
						// Put dirt in caves near the surface.
						Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
						vm->m_data[index_data] = MapNode(biome->c_filler);
					} else {
						s16 lava_chance = 0;

						if (y <= lava_max_height && c == c_stone) {
							// Lava spawns increase with depth.
							lava_chance = ceil((lava_max_height - y + 1) / 10000);

							if (sr < lava_chance)
								vm->m_data[j] = n_lava;
						}

						if (base_water_chance > 0 && y <= cave_water_max_height) {
							s16 water_chance = base_water_chance
								- (abs(y - water_level) / (water_features * 1000));

							// Waterfalls may get out of control above ground.
							sr -= lava_chance;
							// If sr < 0 then we should have already placed lava --
							// don't immediately dump water on it.
							if (sr >= 0 && sr < water_chance)
								vm->m_data[j] = n_water;
						}
					}

					air_above = false;
				}

				// If we're not in a cave, there's no open space.
				if (!(n1 && n2))
					air_above = false;
			}
		}
	}
}
Exemplo n.º 22
0
void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
{
	if (max_stone_y < node_min.Y)
		return;

	noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
	noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);

	PseudoRandom ps(blockseed + 72202);

	MapNode n_air(CONTENT_AIR);
	MapNode n_lava(c_lava_source);
	MapNode n_water(c_river_water_source);

	v3s16 em = vm->m_area.getExtent();

	// Cave blend distance near YMIN, YMAX
	const float massive_cave_blend = 128.f;
	// noise threshold for massive caves
	const float massive_cave_threshold = 0.6f;
	// mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.

	float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
	float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
	bool made_a_big_one = false;

	// Cache the tcave values as they only vary by altitude.
	if (node_max.Y <= massive_cave_depth) {
		noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);

		for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
			float tcave = massive_cave_threshold;

			if (y < yblmin) {
				float t = (yblmin - y) / massive_cave_blend;
				tcave += MYSQUARE(t);
			} else if (y > yblmax) {
				float t = (y - yblmax) / massive_cave_blend;
				tcave += MYSQUARE(t);
			}

			tcave_cache[y - node_min.Y + 1] = tcave;
		}
	}

	// lava_depth varies between one and ten as you approach
	//  the bottom of the world.
	s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
	// This allows random lava spawns to be less common at the surface.
	s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
	// water_depth varies between ten and one on the way down.
	s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
	// This allows random water spawns to be more common at the surface.
	s16 water_chance = MYCUBE(water_features_lim) * water_depth;

	// Reduce the odds of overflows even further.
	if (node_max.Y > water_level) {
		lava_chance /= 3;
		water_chance /= 3;
	}

	u32 index_2d = 0;
	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
		Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index_2d]);
		bool tunnel_air_above = false;
		bool is_under_river = false;
		bool underground = false;
		u32 index_data = vm->m_area.index(x, node_max.Y, z);
		u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);

		// Dig caves on down loop to check for air above.
		// Don't excavate the overgenerated stone at node_max.Y + 1,
		// this creates a 'roof' over the tunnel, preventing light in
		// tunnels at mapchunk borders when generating mapchunks upwards.
		// This 'roof' is removed when the mapchunk above is generated.
		for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
				index_3d -= ystride,
				vm->m_area.add_y(em, index_data, -1)) {

			float terrain = noise_terrain_height->result[index_2d];

			// Saves some time.
			if (y > terrain + 10)
				continue;
			else if (y < terrain - 40)
				underground = true;

			// Dig massive caves.
			if (node_max.Y <= massive_cave_depth
					&& noise_massive_caves->result[index_3d]
					> tcave_cache[y - node_min.Y + 1]) {
				vm->m_data[index_data] = n_air;
				made_a_big_one = true;
				continue;
			}

			content_t c = vm->m_data[index_data].getContent();
			// Detect river water to place riverbed nodes in tunnels
			if (c == biome->c_river_water)
				is_under_river = true;

			float d1 = contour(noise_cave1->result[index_3d]);
			float d2 = contour(noise_cave2->result[index_3d]);

			if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
				// in a tunnel
				vm->m_data[index_data] = n_air;
				tunnel_air_above = true;
			} else if (c == biome->c_filler || c == biome->c_stone) {
				if (tunnel_air_above) {
					// at the tunnel floor
					s16 sr = ps.range(0, 39);
					u32 j = index_data;
					vm->m_area.add_y(em, j, 1);

					if (sr > terrain - y) {
						// Put biome nodes in tunnels near the surface
						if (is_under_river)
							vm->m_data[index_data] = MapNode(biome->c_riverbed);
						else if (underground)
							vm->m_data[index_data] = MapNode(biome->c_filler);
						else
							vm->m_data[index_data] = MapNode(biome->c_top);
					} else if (sr < 3 && underground) {
						sr = abs(ps.next());
						if (lava_features_lim > 0 && y <= lava_max_height
								&& c == biome->c_stone && sr < lava_chance)
							vm->m_data[j] = n_lava;

						sr -= lava_chance;

						// If sr < 0 then we should have already placed lava --
						// don't immediately dump water on it.
						if (water_features_lim > 0 && y <= cave_water_max_height
								&& sr >= 0 && sr < water_chance)
							vm->m_data[j] = n_water;
					}
				}

				tunnel_air_above = false;
				underground = true;
			} else {
				tunnel_air_above = false;
			}
		}
	}

	if (node_max.Y <= large_cave_depth && !made_a_big_one) {
		u32 bruises_count = ps.range(0, 2);
		for (u32 i = 0; i < bruises_count; i++) {
			CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
				c_water_source, c_lava_source);

			cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
		}
	}
}
Exemplo n.º 23
0
void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
{
	MapNode n_cobble(cid_cobble);
	MapNode n_air(CONTENT_AIR);
	
	// Make +-X walls
	for (s16 z = 0; z < roomsize.Z; z++)
	for (s16 y = 0; y < roomsize.Y; y++)
	{
		{
			v3s16 p = roomplace + v3s16(0, y, z);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
		{
			v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
	}

	// Make +-Z walls
	for (s16 x = 0; x < roomsize.X; x++)
	for (s16 y = 0; y < roomsize.Y; y++)
	{
		{
			v3s16 p = roomplace + v3s16(x, y, 0);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
		{
			v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
	}

	// Make +-Y walls (floor and ceiling)
	for (s16 z = 0; z < roomsize.Z; z++)
	for (s16 x = 0; x < roomsize.X; x++)
	{
		{
			v3s16 p = roomplace + v3s16(x, 0, z);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
		{
			v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z);
			if (vmanip->m_area.contains(p) == false)
				continue;
			u32 vi = vmanip->m_area.index(p);
			if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
				continue;
			vmanip->m_data[vi] = n_cobble;
		}
	}

	// Fill with air
	for (s16 z = 1; z < roomsize.Z - 1; z++)
	for (s16 y = 1; y < roomsize.Y - 1; y++)
	for (s16 x = 1; x < roomsize.X - 1; x++)
	{
		v3s16 p = roomplace + v3s16(x, y, z);
		if (vmanip->m_area.contains(p) == false)
			continue;
		u32 vi = vmanip->m_area.index(p);
		vmanip->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
		vmanip->m_data[vi]   = n_air;
	}
}
Exemplo n.º 24
0
int MapgenValleys::generateTerrain()
{
	// Raising this reduces the rate of evaporation.
	static const float evaporation = 300.f;
	// from the lua
	static const float humidity_dropoff = 4.f;
	// constant to convert altitude chill (compatible with lua) to heat
	static const float alt_to_heat = 20.f;
	// humidity reduction by altitude
	static const float alt_to_humid = 10.f;

	MapNode n_air(CONTENT_AIR);
	MapNode n_river_water(c_river_water_source);
	MapNode n_sand(c_sand);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index_2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
		float river_y = noise_rivers->result[index_2d];
		float surface_y = noise_terrain_height->result[index_2d];
		float slope = noise_inter_valley_slope->result[index_2d];
		float t_heat = m_bgen->heatmap[index_2d];

		heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;

		if (surface_y > surface_max_y)
			surface_max_y = ceil(surface_y);

		if (humid_rivers) {
			// Derive heat from (base) altitude. This will be most correct
			// at rivers, since other surface heights may vary below.
			if (use_altitude_chill && (surface_y > 0.f || river_y > 0.f))
				t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;

			// If humidity is low or heat is high, lower the water table.
			float delta = m_bgen->humidmap[index_2d] - 50.f;
			if (delta < 0.f) {
				float t_evap = (t_heat - 32.f) / evaporation;
				river_y += delta * MYMAX(t_evap, 0.08f);
			}
		}

		u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
		u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);

		// Mapgens concern themselves with stone and water.
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
				float fill = noise_inter_valley_fill->result[index_3d];
				float surface_delta = (float)y - surface_y;
				bool river = y + 1 < river_y;

				if (fabs(surface_delta) <= 0.5f && y > water_level && river) {
					// river bottom
					vm->m_data[index_data] = n_sand;
				} else if (slope * fill > surface_delta) {
					// ground
					vm->m_data[index_data] = n_stone;
					if (y > heightmap[index_2d])
						heightmap[index_2d] = y;
					if (y > surface_max_y)
						surface_max_y = y;
				} else if (y <= water_level) {
					// sea
					vm->m_data[index_data] = n_water;
				} else if (river) {
					// river
					vm->m_data[index_data] = n_river_water;
				} else {
					vm->m_data[index_data] = n_air;
				}
			}

			vm->m_area.add_y(em, index_data, 1);
			index_3d += ystride;
		}

		// This happens if we're generating a chunk that doesn't
		// contain the terrain surface, in which case, we need
		// to set heightmap to a value outside of the chunk,
		// to avoid confusing lua mods that use heightmap.
		if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
			s16 surface_y_int = myround(surface_y);
			if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
				// If surface_y is outside the chunk, it's good enough.
				heightmap[index_2d] = surface_y_int;
			} else {
				// If the ground is outside of this chunk, but surface_y
				// is within the chunk, give a value outside.
				heightmap[index_2d] = node_min.Y - 2;
			}
		}

		if (humid_rivers) {
			// Use base ground (water table) in a riverbed, to
			// avoid an unnatural rise in humidity.
			float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
			float humid = m_bgen->humidmap[index_2d];
			float water_depth = (t_alt - river_y) / humidity_dropoff;
			humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));

			// Reduce humidity with altitude (ignoring riverbeds).
			// This is similar to the lua version's seawater adjustment,
			// but doesn't increase the base humidity, which causes
			// problems with the default biomes.
			if (t_alt > 0.f)
				humid -= alt_to_humid * t_alt / altitude_chill;

			m_bgen->humidmap[index_2d] = humid;
		}

		// Assign the heat adjusted by any changed altitudes.
		// The altitude will change about half the time.
		if (use_altitude_chill) {
			// ground height ignoring riverbeds
			float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
			if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
				// The altitude hasn't changed. Use the first result.
				m_bgen->heatmap[index_2d] = t_heat;
			else if (t_alt > 0.f)
				m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill;
		}
	}

	return surface_max_y;
}
Exemplo n.º 25
0
int MapgenValleys::generateTerrain()
{
	MapNode n_air(CONTENT_AIR);
	MapNode n_river_water(c_river_water_source);
	MapNode n_sand(c_sand);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	v3s16 em = vm->m_area.getExtent();
	s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
	u32 index_2d = 0;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
		s16 river_y = floor(noise_rivers->result[index_2d]);
		s16 surface_y = floor(noise_terrain_height->result[index_2d]);
		float slope = noise_inter_valley_slope->result[index_2d];

		heightmap[index_2d] = surface_y;

		if (surface_y > surface_max_y)
			surface_max_y = surface_y;

		u32 index_3d = (z - node_min.Z) * zstride + (x - node_min.X);
		u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);

		// Mapgens concern themselves with stone and water.
		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			float fill = 0.f;
			fill = noise_inter_valley_fill->result[index_3d];

			if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
				bool river = (river_y > surface_y);

				if (river && y == surface_y) {
					// river bottom
					vm->m_data[index_data] = n_sand;
				} else if (river && y <= surface_y) {
					// ground
					vm->m_data[index_data] = n_stone;
				} else if (river && y < river_y) {
					// river
					vm->m_data[index_data] = n_river_water;
				} else if ((!river) && myround(fill * slope) >= y - surface_y) {
					// ground
					vm->m_data[index_data] = n_stone;
					heightmap[index_2d] = surface_max_y = y;
				} else if (y <= water_level) {
					// sea
					vm->m_data[index_data] = n_water;
				} else {
					vm->m_data[index_data] = n_air;
				}
			}

			vm->m_area.add_y(em, index_data, 1);
			index_3d += ystride;
		}

		// Although the original valleys adjusts humidity by distance
		// from seawater, this causes problems with the default biomes.
		// Adjust only by freshwater proximity.
		const float humidity_offset = 0.8f;  // derived by testing
		if (humid_rivers)
			noise_humidity->result[index_2d] *= (1 + pow(0.5f, MYMAX((surface_max_y
					- noise_rivers->result[index_2d]) / 3.f, 0.f))) * humidity_offset;

		// Assign the heat adjusted by altitude.
		if (use_altitude_chill && surface_max_y > 0)
			noise_heat->result[index_2d] *=
				pow(0.5f, (surface_max_y - altitude_chill / 3.f) / altitude_chill);
	}

	return surface_max_y;
}
Exemplo n.º 26
0
void MapgenValleys::generateCaves(s16 max_stone_y)
{
	if (max_stone_y < node_min.Y)
		return;

	noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
	noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);

	PseudoRandom ps(blockseed + 72202);

	MapNode n_air(CONTENT_AIR);
	MapNode n_lava(c_lava_source);
	MapNode n_water(c_river_water_source);

	v3s16 em = vm->m_area.getExtent();

	// Cave blend distance near YMIN, YMAX
	const float massive_cave_blend = 128.f;
	// noise threshold for massive caves
	const float massive_cave_threshold = 0.6f;
	// mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.

	float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
	float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
	bool made_a_big_one = false;

	// Cache the tcave values as they only vary by altitude.
	if (node_max.Y <= massive_cave_depth) {
		noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);

		for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
			float tcave = massive_cave_threshold;

			if (y < yblmin) {
				float t = (yblmin - y) / massive_cave_blend;
				tcave += MYSQUARE(t);
			} else if (y > yblmax) {
				float t = (y - yblmax) / massive_cave_blend;
				tcave += MYSQUARE(t);
			}

			tcave_cache[y - node_min.Y + 1] = tcave;
		}
	}

	// lava_depth varies between one and ten as you approach
	//  the bottom of the world.
	s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
	// This allows random lava spawns to be less common at the surface.
	s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
	// water_depth varies between ten and one on the way down.
	s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
	// This allows random water spawns to be more common at the surface.
	s16 water_chance = MYCUBE(water_features_lim) * water_depth;

	// Reduce the odds of overflows even further.
	if (node_max.Y > water_level) {
		lava_chance /= 5;
		water_chance /= 5;
	}

	u32 index_2d = 0;
	u32 index_3d = 0;
	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
		Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
		bool air_above = false;
		bool underground = false;
		u32 index_data = vm->m_area.index(x, node_max.Y + 1, z);

		index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);

		// Dig caves on down loop to check for air above.
		for (s16 y = node_max.Y + 1;
				y >= node_min.Y - 1;
				y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) {
			float terrain = noise_terrain_height->result[index_2d];

			// Saves some time.
			if (y > terrain + 10) {
				air_above = true;
				continue;
			} else if (y < terrain - 40) {
				underground = true;
			}

			// Dig massive caves.
			if (node_max.Y <= massive_cave_depth
					&& noise_massive_caves->result[index_3d]
					> tcave_cache[y - node_min.Y + 1]) {
				vm->m_data[index_data] = n_air;
				made_a_big_one = true;
			}

			content_t c = vm->m_data[index_data].getContent();
			float d1 = contour(noise_cave1->result[index_3d]);
			float d2 = contour(noise_cave2->result[index_3d]);

			// River water is not set as ground content
			// in the default game. This can produce strange results
			// when a cave undercuts a river. However, that's not for
			// the mapgen to correct. Fix it in lua.

			if (c == CONTENT_AIR) {
				air_above = true;
			} else if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
				// in a cave
				vm->m_data[index_data] = n_air;
				air_above = true;
			} else if (air_above && (c == biome->c_filler || c == biome->c_stone)) {
				// at the cave floor
				s16 sr = ps.range(0,39);
				u32 j = index_data;
				vm->m_area.add_y(em, j, 1);

				if (sr > terrain - y) {
					// Put dirt in caves near the surface.
					if (underground)
						vm->m_data[index_data] = MapNode(biome->c_filler);
					else
						vm->m_data[index_data] = MapNode(biome->c_top);
				} else if (sr < 3 && underground) {
					sr = abs(ps.next());
					if (lava_features_lim > 0 && y <= lava_max_height
							&& c == biome->c_stone && sr < lava_chance)
						vm->m_data[j] = n_lava;

					sr -= lava_chance;

					// If sr < 0 then we should have already placed lava --
					// don't immediately dump water on it.
					if (water_features_lim > 0 && y <= cave_water_max_height
							&& sr >= 0 && sr < water_chance)
						vm->m_data[j] = n_water;
				}

				air_above = false;
				underground = true;
			} else if (c == biome->c_filler || c == biome->c_stone) {
				air_above = false;
				underground = true;
			} else {
				air_above = false;
			}
		}
	}

	if (node_max.Y <= large_cave_depth && (!made_a_big_one)) {
		u32 bruises_count = ps.range(0, 2);
		for (u32 i = 0; i < bruises_count; i++) {
			CaveV5 cave(this, &ps);
			cave.makeCave(node_min, node_max, max_stone_y);
		}
	}
}
Exemplo n.º 27
0
void MapgenV7::generateBiomes()
{
	if (node_max.Y < water_level)
		return;

	MapNode n_air(CONTENT_AIR);
	MapNode n_stone(c_stone);
	MapNode n_water(c_water_source);

	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]);
		s16 dfiller         = biome->depth_filler + noise_filler_depth->result[index];
		s16 y0_top          = biome->depth_top;
		s16 y0_filler       = biome->depth_top + dfiller;
		s16 shore_max       = water_level + biome->height_shore;
		s16 depth_water_top = biome->depth_water_top;

		s16 nplaced = 0;
		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 &&
				y == heightmap[index] && c == c_stone) {
				int j = (z - node_min.Z) * zstride +
						(y - node_min.Y) * ystride +
						(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)
							vm->m_data[i] = MapNode(biome->c_underwater);
						else if(y <= shore_max)
							vm->m_data[i] = MapNode(biome->c_shore_top);
						else
							vm->m_data[i] = MapNode(biome->c_top);
						nplaced++;
					} else if (nplaced < y0_filler && nplaced >= y0_top) {
						if(y < water_level)
							vm->m_data[i] = MapNode(biome->c_underwater);
						else if(y <= shore_max)
							vm->m_data[i] = MapNode(biome->c_shore_filler);
						else
							vm->m_data[i] = MapNode(biome->c_filler);
						nplaced++;
					} else if (c == c_stone) {
						have_air = false;
						nplaced  = 0;
						vm->m_data[i] = MapNode(biome->c_stone);
					} else {
						have_air = false;
						nplaced  = 0;
					}
				} else if (c == c_stone) {
					have_air = false;
					nplaced = 0;
					vm->m_data[i] = MapNode(biome->c_stone);
				}
			} else if (c == c_stone) {
				have_air = false;
				nplaced = 0;
				vm->m_data[i] = MapNode(biome->c_stone);
			} else if (c == c_water_source) {
				have_air = true;
				nplaced = 0;
				if(y > water_level - depth_water_top)
					vm->m_data[i] = MapNode(biome->c_water_top);
				else
					vm->m_data[i] = MapNode(biome->c_water);
			} else if (c == CONTENT_AIR) {
				have_air = true;
				nplaced = 0;
			}

			vm->m_area.add_y(em, i, -1);
		}
	}
}
Exemplo n.º 28
0
int MapgenMath::generateTerrain() {

	MapNode n_air(CONTENT_AIR, LIGHT_SUN), n_water_source(c_water_source, LIGHT_SUN);
	MapNode n_stone(c_stone, LIGHT_SUN);
	u32 index = 0;
	v3s16 em = vm->m_area.getExtent();

#if 1

	/* debug
	v3f vec0 = (v3f(node_min.X, node_min.Y, node_min.Z) - center) * scale ;
	errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z
	            //<< " N="<< mengersponge(vec0.X, vec0.Y, vec0.Z, distance, iterations)
	            << " N=" << (*func)(vec0.X, vec0.Y, vec0.Z, distance, iterations)
	            << " Sc=" << scale << " gen=" << params["generator"].asString() << " J=" << Json::FastWriter().write(params) << std::endl;
	*/
	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]];
			u32 i = vm->m_area.index(x, node_min.Y, z);
			for (s16 y = node_min.Y; y <= node_max.Y; y++) {
				v3f vec = (v3f(x, y, z) - center) * scale ;
				double d = (*func)(vec.X, vec.Y, vec.Z, distance, iterations);
				if ((!invert && d > 0) || (invert && d == 0)  ) {
					if (vm->m_data[i].getContent() == CONTENT_IGNORE)
	//					vm->m_data[i] = (y > water_level + biome->filler) ?
		//				                MapNode(biome->c_filler) : n_stone;
						vm->m_data[i] = n_stone;
				} else if (y <= water_level) {
					vm->m_data[i] = n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
				vm->m_area.add_y(em, i, 1);
			}
		}
	}
#endif


#if 0
// mandelbulber, unfinished but works
	sFractal par;
	par.doubles.N = 10;

	par.doubles.power = 9.0;
	par.doubles.foldingSphericalFixed =  1.0;
	par.doubles.foldingSphericalMin = 0.5;
	//no par.formula = smoothMandelbox; par.doubles.N = 40; invert = 0;//no
	par.mandelbox.doubles.sharpness = 3.0;
	par.mandelbox.doubles.scale = 1;
	par.mandelbox.doubles.sharpness = 2;
	par.mandelbox.doubles.foldingLimit = 1.0;
	par.mandelbox.doubles.foldingValue = 2;

//ok	par.formula = mandelboxVaryScale4D; par.doubles.N = 50; scale = 5; invert = 1; //ok
	par.mandelbox.doubles.vary4D.scaleVary =  0.1;
	par.mandelbox.doubles.vary4D.fold = 1;
	par.mandelbox.doubles.vary4D.rPower = 1;
	par.mandelbox.doubles.vary4D.minR = 0.5;
	par.mandelbox.doubles.vary4D.wadd = 0;
	par.doubles.constantFactor = 1.0;

	par.formula = menger_sponge; par.doubles.N = 15; invert = 0; size = 30000; center = v3f(-size / 2, -size + (-2 * -invert), 2);  scale = (double)1 / size; //ok

	//double tresh = 1.5;
	//par.formula = mandelbulb2; par.doubles.N = 10; scale = (double)1/size; invert=1; center = v3f(5,-size-5,0); //ok
	//par.formula = hypercomplex; par.doubles.N = 20; scale = 0.0001; invert=1; center = v3f(0,-10001,0); //(double)50 / max_r;

	//no par.formula = trig_DE; par.doubles.N = 5;  scale = (double)10; invert=1;

	//no par.formula = trig_optim; scale = (double)10;  par.doubles.N = 4;

	//par.formula = mandelbulb2; scale = (double)1/10000; par.doubles.N = 10; invert = 1; center = v3f(1,-4201,1); //ok
	// no par.formula = tglad;

	//par.formula = xenodreambuie;  par.juliaMode = 1; par.doubles.julia.x = -1; par.doubles.power = 2.0; center=v3f(-size/2,-size/2-5,5); //ok

	par.mandelbox.doubles.vary4D.scaleVary = 0.1;
	par.mandelbox.doubles.vary4D.fold = 1;
	par.mandelbox.doubles.vary4D.minR = 0.5;
	par.mandelbox.doubles.vary4D.rPower = 1;
	par.mandelbox.doubles.vary4D.wadd = 0;
	//no par.formula = mandelboxVaryScale4D;
	par.doubles.cadd = -1.3;
	//par.formula = aexion; // ok but center
	//par.formula = benesi; par.doubles.N = 10; center = v3f(0,0,0); invert = 0; //ok

	// par.formula = bristorbrot; //ok

	v3f vec0(node_min.X, node_min.Y, node_min.Z);
	vec0 = (vec0 - center) * scale ;
	errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z
	            << " N=" << Compute<normal>(CVector3(vec0.X, vec0.Y, vec0.Z), par)
	            //<<" F="<< Compute<fake_AO>(CVector3(node_min.X,node_min.Y,node_min.Z), par)
	            //<<" L="<<node_min.getLength()<< " -="<<node_min.getLength() - Compute<normal>(CVector3(node_min.X,node_min.Y,node_min.Z), par)
	            << " Sc=" << scale
	            << std::endl;

	for (s16 z = node_min.Z; z <= node_max.Z; z++)
		for (s16 y = node_min.Y; y <= node_max.Y; y++) {
			u32 i = vm->m_area.index(node_min.X, y, z);
			for (s16 x = node_min.X; x <= node_max.X; x++) {
				v3f vec(x, y, z);
				vec = (vec - center) * scale ;
				//double d = Compute<fake_AO>(CVector3(x,y,z), par);
				double d = Compute<normal>(CVector3(vec.X, vec.Y, vec.Z), par);
				//if (d>0)
				// errorstream << " d=" << d  <<" v="<< vec.getLength()<< " -="<< vec.getLength() - d <<" yad="
				//<< Compute<normal>(CVector3(x,y,z), par)
				//<< std::endl;
				if ((!invert && d > 0) || (invert && d == 0)/*&& vec.getLength() - d > tresh*/ ) {
					if (vm->m_data[i].getContent() == CONTENT_IGNORE)
						vm->m_data[i] = n_stone;
				} else {
					vm->m_data[i] = n_air;
				}
				i++;
			}
		}


#endif
	return 0;
}