add basic heightmaps generator optimization
This commit is contained in:
parent
8c0a3f4260
commit
8fb0f6a1bb
@ -7,34 +7,49 @@ layers = {
|
||||
{block="base:bazalt", height=1},
|
||||
}
|
||||
|
||||
function generate_heightmap(x, y, w, h, seed)
|
||||
local function _generate_heightmap(x, y, w, h, seed, s)
|
||||
local umap = Heightmap(w, h)
|
||||
local vmap = Heightmap(w, h)
|
||||
umap.noiseSeed = seed
|
||||
vmap.noiseSeed = seed
|
||||
umap:noise({x+521, y+73}, 0.05, 1, 20.8)
|
||||
umap:noise({x+51, y+75}, 0.05, 1, 21.8)
|
||||
vmap:noise({x+521, y+70}, 0.1, 3, 35.8)
|
||||
vmap:noise({x+95, y+246}, 0.15, 3, 35.8)
|
||||
vmap:noise({x+521, y+70}, 0.1*s, 3, 25.8)
|
||||
vmap:noise({x+95, y+246}, 0.15*s, 3, 25.8)
|
||||
|
||||
local map = Heightmap(w, h)
|
||||
map.noiseSeed = seed
|
||||
map:noise({x, y}, 0.02, 7, 0.2)
|
||||
map:noise({x, y}, 0.06, 8, 0.4, umap, vmap)
|
||||
map:noise({x, y}, 0.8*s, 4, 0.04)
|
||||
map:cellnoise({x, y}, 0.1*s, 3, 0.7, umap, vmap)
|
||||
map:mul(0.5)
|
||||
map:add(0.1)
|
||||
map:pow(2.0)
|
||||
map:add(0.3)
|
||||
|
||||
local rivermap = Heightmap(w, h)
|
||||
rivermap.noiseSeed = seed
|
||||
rivermap:noise({x+21, y+12}, 0.1, 4)
|
||||
rivermap:noise({x+21, y+12}, 0.1*s, 4)
|
||||
rivermap:abs()
|
||||
rivermap:mul(2.0)
|
||||
rivermap:pow(0.4)
|
||||
rivermap:pow(0.3)
|
||||
rivermap:max(0.6)
|
||||
map:add(0.4)
|
||||
map:mul(rivermap)
|
||||
map:add(-0.2)
|
||||
map:add(-0.15)
|
||||
|
||||
return map
|
||||
end
|
||||
|
||||
function generate_heightmap(x, y, w, h, seed)
|
||||
-- blocks per dot
|
||||
-- 8 - linear interpolation is visible, but not so much (Minecraft)
|
||||
-- 4 - high quality, but slower
|
||||
-- 2 - you really don't need it
|
||||
-- 1 - please have mercy on your CPU
|
||||
local bpd = 8
|
||||
local map = _generate_heightmap(
|
||||
math.floor(x/bpd), math.floor(y/bpd),
|
||||
math.floor(w/bpd)+1, math.floor(h/bpd)+1, seed, bpd)
|
||||
map:resize(w+bpd, h+bpd, 'linear')
|
||||
map:crop(0, 0, w, h)
|
||||
return map
|
||||
end
|
||||
|
||||
local map = generate_heightmap(0, 0, 1024, 1024, 0)
|
||||
map:dump("heightmap.png")
|
||||
|
||||
@ -166,6 +166,19 @@ static int l_resize(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_crop(lua::State* L) {
|
||||
if (auto heightmap = touserdata<LuaHeightmap>(L, 1)) {
|
||||
uint srcX = touinteger(L, 2);
|
||||
uint srcY = touinteger(L, 3);
|
||||
|
||||
uint dstWidth = touinteger(L, 4);
|
||||
uint dstHeight = touinteger(L, 5);
|
||||
|
||||
heightmap->getHeightmap()->crop(srcX, srcY, dstWidth, dstHeight);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"dump", lua::wrap<l_dump>},
|
||||
{"noise", lua::wrap<l_noise<FNL_NOISE_OPENSIMPLEX2>>},
|
||||
@ -177,6 +190,7 @@ static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"max", lua::wrap<l_binop_func<util::max>>},
|
||||
{"abs", lua::wrap<l_unaryop_func<util::abs>>},
|
||||
{"resize", lua::wrap<l_resize>},
|
||||
{"crop", lua::wrap<l_crop>},
|
||||
};
|
||||
|
||||
static int l_meta_meta_call(lua::State* L) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "Heightmap.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
@ -59,6 +60,9 @@ static inline float sample_at(
|
||||
void Heightmap::resize(
|
||||
uint dstwidth, uint dstheight, InterpolationType interp
|
||||
) {
|
||||
if (width == dstwidth && height == dstheight) {
|
||||
return;
|
||||
}
|
||||
std::vector<float> dst;
|
||||
dst.resize(dstwidth*dstheight);
|
||||
|
||||
@ -75,3 +79,29 @@ void Heightmap::resize(
|
||||
height = dstheight;
|
||||
buffer = std::move(dst);
|
||||
}
|
||||
|
||||
void Heightmap::crop(
|
||||
uint srcx, uint srcy, uint dstwidth, uint dstheight
|
||||
) {
|
||||
if (srcx + dstwidth > width || srcy + dstheight > height) {
|
||||
throw std::runtime_error(
|
||||
"crop zone is not fully inside of the source image");
|
||||
}
|
||||
if (dstwidth == width && dstheight == height) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> dst;
|
||||
dst.resize(dstwidth*dstheight);
|
||||
|
||||
for (uint y = 0; y < dstheight; y++) {
|
||||
std::memcpy(
|
||||
dst.data()+y*dstwidth,
|
||||
buffer.data()+(y+srcy)*width+srcx,
|
||||
dstwidth*sizeof(float));
|
||||
}
|
||||
|
||||
width = dstwidth;
|
||||
height = dstheight;
|
||||
buffer = std::move(dst);
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@ public:
|
||||
|
||||
void resize(uint width, uint height, InterpolationType interpolation);
|
||||
|
||||
void crop(uint srcX, uint srcY, uint dstWidth, uint dstHeight);
|
||||
|
||||
uint getWidth() const {
|
||||
return width;
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ void WorldGenerator::generate(
|
||||
for (uint x = 0; x < CHUNK_W; x++) {
|
||||
// generate water
|
||||
int height = values[z * CHUNK_W + x] * CHUNK_H;
|
||||
height = std::max(0, height);
|
||||
for (uint y = height+1; y <= seaLevel; y++) {
|
||||
voxels[vox_index(x, y, z)].id = baseWater;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user