feat: heightmap-inputs
This commit is contained in:
parent
5e79bc07e9
commit
59c4e26eda
@ -1,6 +1,6 @@
|
|||||||
[forest]
|
[forest]
|
||||||
parameters = [
|
parameters = [
|
||||||
{weight=1, value=1},
|
{weight=1, value=0},
|
||||||
{weight=0.5, value=0.2}
|
{weight=0.5, value=0.2}
|
||||||
]
|
]
|
||||||
layers = [
|
layers = [
|
||||||
@ -28,8 +28,8 @@ structures = [
|
|||||||
|
|
||||||
[desert]
|
[desert]
|
||||||
parameters = [
|
parameters = [
|
||||||
{weight=0.3, value=0},
|
{weight=1.0, value=1},
|
||||||
{weight=0.1, value=0}
|
{weight=0.5, value=0}
|
||||||
]
|
]
|
||||||
layers = [
|
layers = [
|
||||||
{height=6, block="base:sand"},
|
{height=6, block="base:sand"},
|
||||||
@ -43,8 +43,8 @@ sea-layers = [
|
|||||||
|
|
||||||
[plains]
|
[plains]
|
||||||
parameters = [
|
parameters = [
|
||||||
{weight=0.6, value=0.5},
|
{weight=0.8, value=0.5},
|
||||||
{weight=0.6, value=0.5}
|
{weight=0.8, value=0.0}
|
||||||
]
|
]
|
||||||
layers = [
|
layers = [
|
||||||
{below-sea-level=false, height=1, block="base:grass_block"},
|
{below-sea-level=false, height=1, block="base:grass_block"},
|
||||||
|
|||||||
@ -43,7 +43,7 @@ function place_structures_wide(x, z, w, d, seed, chunk_height)
|
|||||||
return placements
|
return placements
|
||||||
end
|
end
|
||||||
|
|
||||||
function generate_heightmap(x, y, w, h, seed, s)
|
function generate_heightmap(x, y, w, h, seed, s, inputs)
|
||||||
local umap = Heightmap(w, h)
|
local umap = Heightmap(w, h)
|
||||||
local vmap = Heightmap(w, h)
|
local vmap = Heightmap(w, h)
|
||||||
umap.noiseSeed = seed
|
umap.noiseSeed = seed
|
||||||
@ -65,6 +65,12 @@ function generate_heightmap(x, y, w, h, seed, s)
|
|||||||
rivermap:pow(0.15)
|
rivermap:pow(0.15)
|
||||||
rivermap:max(0.5)
|
rivermap:max(0.5)
|
||||||
map:mul(rivermap)
|
map:mul(rivermap)
|
||||||
|
|
||||||
|
local desertmap = Heightmap(w, h)
|
||||||
|
desertmap.noiseSeed = seed
|
||||||
|
desertmap:cellnoise({x+52, y+326}, 0.3*s, 2, 0.2)
|
||||||
|
desertmap:add(0.4)
|
||||||
|
map:mixin(desertmap, inputs[1])
|
||||||
return map
|
return map
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -72,6 +78,8 @@ function generate_biome_parameters(x, y, w, h, seed, s)
|
|||||||
local tempmap = Heightmap(w, h)
|
local tempmap = Heightmap(w, h)
|
||||||
tempmap.noiseSeed = seed + 5324
|
tempmap.noiseSeed = seed + 5324
|
||||||
tempmap:noise({x, y}, 0.04*s, 6)
|
tempmap:noise({x, y}, 0.04*s, 6)
|
||||||
|
tempmap:mul(0.5)
|
||||||
|
tempmap:add(0.5)
|
||||||
local hummap = Heightmap(w, h)
|
local hummap = Heightmap(w, h)
|
||||||
hummap.noiseSeed = seed + 953
|
hummap.noiseSeed = seed + 953
|
||||||
hummap:noise({x, y}, 0.04*s, 6)
|
hummap:noise({x, y}, 0.04*s, 6)
|
||||||
|
|||||||
@ -2,3 +2,4 @@
|
|||||||
# 2 - humidity
|
# 2 - humidity
|
||||||
biome-parameters = 2
|
biome-parameters = 2
|
||||||
sea-level = 64
|
sea-level = 64
|
||||||
|
heightmap-inputs = [1]
|
||||||
|
|||||||
@ -202,7 +202,20 @@ void ContentLoader::loadGenerator(
|
|||||||
map.at("heights-bpd").get(def.heightsBPD);
|
map.at("heights-bpd").get(def.heightsBPD);
|
||||||
map.at("sea-level").get(def.seaLevel);
|
map.at("sea-level").get(def.seaLevel);
|
||||||
map.at("wide-structs-chunks-radius").get(def.wideStructsChunksRadius);
|
map.at("wide-structs-chunks-radius").get(def.wideStructsChunksRadius);
|
||||||
|
if (map.has("heightmap-inputs")) {
|
||||||
|
for (const auto& element : map["heightmap-inputs"]) {
|
||||||
|
int index = element.asInteger();
|
||||||
|
if (index <= 0 || index > def.biomeParameters) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"invalid biome parameter index " + std::to_string(index));
|
||||||
|
}
|
||||||
|
def.heightmapInputs.push_back(index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!def.heightmapInputs.empty() && def.biomesBPD != def.heightsBPD) {
|
||||||
|
logger.warning() << "generator has heightmap-inputs but biomes-bpd "
|
||||||
|
"is not equal to heights-bpd, generator will work slower!";
|
||||||
|
}
|
||||||
auto folder = generatorsDir / fs::u8path(name + ".files");
|
auto folder = generatorsDir / fs::u8path(name + ".files");
|
||||||
auto scriptFile = folder / fs::u8path("script.lua");
|
auto scriptFile = folder / fs::u8path("script.lua");
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Heightmap> generateHeightmap(
|
std::shared_ptr<Heightmap> generateHeightmap(
|
||||||
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed, uint bpd
|
const glm::ivec2& offset,
|
||||||
|
const glm::ivec2& size,
|
||||||
|
uint64_t seed,
|
||||||
|
uint bpd,
|
||||||
|
const std::vector<std::shared_ptr<Heightmap>>& inputs
|
||||||
) override {
|
) override {
|
||||||
pushenv(L, *env);
|
pushenv(L, *env);
|
||||||
if (getfield(L, "generate_heightmap")) {
|
if (getfield(L, "generate_heightmap")) {
|
||||||
@ -46,7 +50,15 @@ public:
|
|||||||
pushivec_stack(L, size);
|
pushivec_stack(L, size);
|
||||||
pushinteger(L, seed);
|
pushinteger(L, seed);
|
||||||
pushinteger(L, bpd);
|
pushinteger(L, bpd);
|
||||||
if (call_nothrow(L, 6)) {
|
if (!inputs.empty()) {
|
||||||
|
size_t inputsNum = def.heightmapInputs.size();
|
||||||
|
createtable(L, inputsNum, 0);
|
||||||
|
for (size_t i = 0; i < inputsNum; i++) {
|
||||||
|
newuserdata<LuaHeightmap>(L, inputs[i]);
|
||||||
|
rawseti(L, i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (call_nothrow(L, 6 + (!inputs.empty()))) {
|
||||||
auto map = touserdata<LuaHeightmap>(L, -1)->getHeightmap();
|
auto map = touserdata<LuaHeightmap>(L, -1)->getHeightmap();
|
||||||
pop(L, 2);
|
pop(L, 2);
|
||||||
return map;
|
return map;
|
||||||
|
|||||||
@ -105,3 +105,9 @@ void Heightmap::crop(
|
|||||||
height = dstheight;
|
height = dstheight;
|
||||||
buffer = std::move(dst);
|
buffer = std::move(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Heightmap::clamp() {
|
||||||
|
for (uint i = 0; i < width * height; i++) {
|
||||||
|
buffer[i] = std::min(1.0f, std::max(0.0f, buffer[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -30,6 +30,8 @@ public:
|
|||||||
|
|
||||||
void crop(uint srcX, uint srcY, uint dstWidth, uint dstHeight);
|
void crop(uint srcX, uint srcY, uint dstWidth, uint dstHeight);
|
||||||
|
|
||||||
|
void clamp();
|
||||||
|
|
||||||
uint getWidth() const {
|
uint getWidth() const {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,12 +128,14 @@ public:
|
|||||||
/// @param size size of the heightmap
|
/// @param size size of the heightmap
|
||||||
/// @param seed world seed
|
/// @param seed world seed
|
||||||
/// @param bpd blocks per dot
|
/// @param bpd blocks per dot
|
||||||
|
/// @param inputs biome parameter maps passed to generate_heightmap
|
||||||
/// @return generated heightmap (can't be nullptr)
|
/// @return generated heightmap (can't be nullptr)
|
||||||
virtual std::shared_ptr<Heightmap> generateHeightmap(
|
virtual std::shared_ptr<Heightmap> generateHeightmap(
|
||||||
const glm::ivec2& offset,
|
const glm::ivec2& offset,
|
||||||
const glm::ivec2& size,
|
const glm::ivec2& size,
|
||||||
uint64_t seed,
|
uint64_t seed,
|
||||||
uint bpd
|
uint bpd,
|
||||||
|
const std::vector<std::shared_ptr<Heightmap>>& inputs
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/// @brief Generate a biomes parameters maps
|
/// @brief Generate a biomes parameters maps
|
||||||
@ -207,12 +209,15 @@ struct GeneratorDef {
|
|||||||
uint biomesBPD = 8;
|
uint biomesBPD = 8;
|
||||||
|
|
||||||
/// @brief Heightmap blocks per dot
|
/// @brief Heightmap blocks per dot
|
||||||
uint heightsBPD = 4;
|
uint heightsBPD = 8;
|
||||||
|
|
||||||
/// @brief Number of chunks must be generated before and after wide
|
/// @brief Number of chunks must be generated before and after wide
|
||||||
/// structures placement triggered
|
/// structures placement triggered
|
||||||
uint wideStructsChunksRadius = 3;
|
uint wideStructsChunksRadius = 3;
|
||||||
|
|
||||||
|
/// @brief Indices of biome parameter maps passed to generate_heightmap
|
||||||
|
std::vector<uint8_t> heightmapInputs;
|
||||||
|
|
||||||
std::unordered_map<std::string, size_t> structuresIndices;
|
std::unordered_map<std::string, size_t> structuresIndices;
|
||||||
std::vector<std::unique_ptr<VoxelStructure>> structures;
|
std::vector<std::unique_ptr<VoxelStructure>> structures;
|
||||||
std::vector<Biome> biomes;
|
std::vector<Biome> biomes;
|
||||||
|
|||||||
@ -300,6 +300,16 @@ void WorldGenerator::generateBiomes(
|
|||||||
seed,
|
seed,
|
||||||
bpd
|
bpd
|
||||||
);
|
);
|
||||||
|
for (auto index : def.heightmapInputs) {
|
||||||
|
// copy non-scaled maps
|
||||||
|
auto copy = std::make_shared<Heightmap>(*biomeParams[index]);
|
||||||
|
copy->resize(
|
||||||
|
floordiv(CHUNK_W, def.heightsBPD) + 1,
|
||||||
|
floordiv(CHUNK_D, def.heightsBPD) + 1,
|
||||||
|
InterpolationType::LINEAR
|
||||||
|
);
|
||||||
|
prototype.heightmapInputs.push_back(std::move(copy));
|
||||||
|
}
|
||||||
for (const auto& map : biomeParams) {
|
for (const auto& map : biomeParams) {
|
||||||
map->resize(
|
map->resize(
|
||||||
CHUNK_W + bpd, CHUNK_D + bpd, InterpolationType::LINEAR
|
CHUNK_W + bpd, CHUNK_D + bpd, InterpolationType::LINEAR
|
||||||
@ -330,8 +340,10 @@ void WorldGenerator::generateHeightmap(
|
|||||||
{floordiv(chunkX * CHUNK_W, bpd), floordiv(chunkZ * CHUNK_D, bpd)},
|
{floordiv(chunkX * CHUNK_W, bpd), floordiv(chunkZ * CHUNK_D, bpd)},
|
||||||
{floordiv(CHUNK_W, bpd)+1, floordiv(CHUNK_D, bpd)+1},
|
{floordiv(CHUNK_W, bpd)+1, floordiv(CHUNK_D, bpd)+1},
|
||||||
seed,
|
seed,
|
||||||
bpd
|
bpd,
|
||||||
|
prototype.heightmapInputs
|
||||||
);
|
);
|
||||||
|
prototype.heightmap->clamp();
|
||||||
prototype.heightmap->resize(
|
prototype.heightmap->resize(
|
||||||
CHUNK_W + bpd, CHUNK_D + bpd, InterpolationType::LINEAR
|
CHUNK_W + bpd, CHUNK_D + bpd, InterpolationType::LINEAR
|
||||||
);
|
);
|
||||||
@ -363,9 +375,9 @@ void WorldGenerator::generatePlants(
|
|||||||
const Biome* biome = biomes[z * CHUNK_W + x];
|
const Biome* biome = biomes[z * CHUNK_W + x];
|
||||||
|
|
||||||
int height = heights[z * CHUNK_W + x] * CHUNK_H;
|
int height = heights[z * CHUNK_W + x] * CHUNK_H;
|
||||||
height = std::max(0, height);
|
height = std::min(std::max(0, height), CHUNK_H-1);
|
||||||
|
|
||||||
if (height+1 > def.seaLevel) {
|
if (height+1 > def.seaLevel && height+1 < CHUNK_H) {
|
||||||
float rand = plantsRand.randFloat();
|
float rand = plantsRand.randFloat();
|
||||||
blockid_t plant = biome->plants.choose(rand);
|
blockid_t plant = biome->plants.choose(rand);
|
||||||
if (plant) {
|
if (plant) {
|
||||||
|
|||||||
@ -32,6 +32,9 @@ struct ChunkPrototype {
|
|||||||
std::shared_ptr<Heightmap> heightmap;
|
std::shared_ptr<Heightmap> heightmap;
|
||||||
|
|
||||||
std::vector<Placement> placements;
|
std::vector<Placement> placements;
|
||||||
|
|
||||||
|
/// @brief biome parameters maps saved until heightmaps generation
|
||||||
|
std::vector<std::shared_ptr<Heightmap>> heightmapInputs {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorldGenDebugInfo {
|
struct WorldGenDebugInfo {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user