add Heightmap methods
This commit is contained in:
parent
da4b8bd7d4
commit
13b97f4398
@ -1,3 +1,48 @@
|
||||
-- use for engine development tests
|
||||
-- must be empty in release
|
||||
-- must not be modified by content-packs
|
||||
|
||||
local W = 16
|
||||
local H = 16
|
||||
|
||||
for t=1,1 do
|
||||
local tm = time.uptime()
|
||||
|
||||
local umap = Heightmap(W, H)
|
||||
local vmap = Heightmap(W, H)
|
||||
umap:noise({521, 73}, 0.2, 1, 11.8)
|
||||
umap:noise({51, 73}, 0.2, 1, 11.8)
|
||||
umap:noise({521, 73}, 0.4, 6, 5.8)
|
||||
vmap:noise({95, 246}, 0.6, 6, 5.8)
|
||||
|
||||
local bmap = Heightmap(W, H)
|
||||
bmap:noise({3, 6}, 0.1, 1, 3)
|
||||
local map = Heightmap(W, H)
|
||||
|
||||
|
||||
map:noise({0, 0}, 0.06, 4, 0.2, umap, vmap)
|
||||
map:noise({0, 0}, 0.25, 6, 0.5, umap, vmap)
|
||||
map:mul(bmap)
|
||||
map:mul(0.7)
|
||||
|
||||
local rivermap = Heightmap(W, H)
|
||||
rivermap:noise({21, 12}, 0.05, 3)
|
||||
rivermap:abs()
|
||||
rivermap:min(0.02)
|
||||
rivermap:mul(50.0)
|
||||
rivermap:pow(0.4)
|
||||
map:add(1.7)
|
||||
map:mul(rivermap)
|
||||
map:add(-1.0)
|
||||
map:mul(0.5)
|
||||
|
||||
local overmap = Heightmap(W, H)
|
||||
overmap:noise({1, 5122}, 0.02, 2, 0.2)
|
||||
overmap:abs()
|
||||
overmap:pow(0.5)
|
||||
overmap:mul(-1.0)
|
||||
map:add(overmap)
|
||||
|
||||
print(math.floor((time.uptime() - tm) * 1000000).." mcs")
|
||||
map:dump("heightmap.png")
|
||||
end
|
||||
|
||||
@ -49,6 +49,14 @@ namespace lua {
|
||||
return TYPENAME;
|
||||
}
|
||||
|
||||
float* getValues() {
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
const float* getValues() const {
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
static int createMetatable(lua::State*);
|
||||
inline static std::string TYPENAME = "heightmap";
|
||||
};
|
||||
|
||||
@ -53,7 +53,7 @@ static int l_remove(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, lua_CFunction> bytearray_methods {
|
||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"append", lua::wrap<l_append>},
|
||||
{"insert", lua::wrap<l_insert>},
|
||||
{"remove", lua::wrap<l_remove>},
|
||||
@ -85,8 +85,8 @@ static int l_meta_index(lua::State* L) {
|
||||
}
|
||||
auto& data = buffer->data();
|
||||
if (isstring(L, 2)) {
|
||||
auto found = bytearray_methods.find(tostring(L, 2));
|
||||
if (found != bytearray_methods.end()) {
|
||||
auto found = methods.find(tostring(L, 2));
|
||||
if (found != methods.end()) {
|
||||
return pushcfunction(L, found->second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,17 @@
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <filesystem>
|
||||
|
||||
#include "maths/FastNoiseLite.h"
|
||||
#include "coders/png.hpp"
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
#include "lua_util.hpp"
|
||||
|
||||
using namespace lua;
|
||||
|
||||
static fnl_state noise = fnlCreateState();
|
||||
|
||||
Heightmap::Heightmap(uint width, uint height) : width(width), height(height) {
|
||||
buffer.resize(width*height);
|
||||
}
|
||||
@ -15,6 +21,230 @@ Heightmap::Heightmap(uint width, uint height) : width(width), height(height) {
|
||||
Heightmap::~Heightmap() {
|
||||
}
|
||||
|
||||
static int l_dump(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
auto filename = tostring(L, 2);
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
ImageData image(ImageFormat::rgb888, w, h);
|
||||
auto heights = heightmap->getValues();
|
||||
auto raster = image.getData();
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
int val = heights[i] * 127 + 128;
|
||||
val = std::max(std::min(val, 255), 0);
|
||||
raster[i*3] = val;
|
||||
raster[i*3 + 1] = val;
|
||||
raster[i*3 + 2] = val;
|
||||
}
|
||||
}
|
||||
png::write_image(filename, &image);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_noise(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
|
||||
auto offset = tovec<2>(L, 2);
|
||||
|
||||
float s = tonumber(L, 3);
|
||||
int octaves = 1;
|
||||
float multiplier = 1.0f;
|
||||
if (gettop(L) > 3) {
|
||||
octaves = tointeger(L, 4);
|
||||
}
|
||||
if (gettop(L) > 4) {
|
||||
multiplier = tonumber(L, 5);
|
||||
}
|
||||
const Heightmap* shiftMapX = nullptr;
|
||||
const Heightmap* shiftMapY = nullptr;
|
||||
if (gettop(L) > 5) {
|
||||
shiftMapX = touserdata<Heightmap>(L, 6);
|
||||
}
|
||||
if (gettop(L) > 6) {
|
||||
shiftMapY = touserdata<Heightmap>(L, 7);
|
||||
}
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
for (uint c = 0; c < octaves; c++) {
|
||||
float m = s * (1 << c);
|
||||
float value = heights[i];
|
||||
float u = (x + offset.x) * m;
|
||||
float v = (y + offset.y) * m;
|
||||
if (shiftMapX) {
|
||||
u += shiftMapX->getValues()[i];
|
||||
}
|
||||
if (shiftMapY) {
|
||||
v += shiftMapY->getValues()[i];
|
||||
}
|
||||
|
||||
value += fnlGetNoise2D(&noise, u, v) /
|
||||
static_cast<float>(1 << c) * multiplier;
|
||||
heights[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_pow(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
float power = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] = glm::pow(heights[i], power);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_add(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
|
||||
if (isnumber(L, 2)) {
|
||||
float scalar = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] += scalar;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto map = touserdata<Heightmap>(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] += map->getValues()[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_mul(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
|
||||
if (isnumber(L, 2)) {
|
||||
float scalar = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] *= scalar;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto map = touserdata<Heightmap>(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] *= map->getValues()[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_max(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
|
||||
if (isnumber(L, 2)) {
|
||||
float scalar = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] *= scalar;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto map = touserdata<Heightmap>(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] = glm::max(map->getValues()[i], heights[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_min(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
|
||||
if (isnumber(L, 2)) {
|
||||
float scalar = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] *= scalar;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto map = touserdata<Heightmap>(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] = glm::min(map->getValues()[i], heights[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_abs(lua::State* L) {
|
||||
if (auto heightmap = touserdata<Heightmap>(L, 1)) {
|
||||
uint w = heightmap->getWidth();
|
||||
uint h = heightmap->getHeight();
|
||||
auto heights = heightmap->getValues();
|
||||
float power = tonumber(L, 2);
|
||||
for (uint y = 0; y < h; y++) {
|
||||
for (uint x = 0; x < w; x++) {
|
||||
uint i = y * w + x;
|
||||
heights[i] = glm::abs(heights[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"dump", lua::wrap<l_dump>},
|
||||
{"noise", lua::wrap<l_noise>},
|
||||
{"pow", lua::wrap<l_pow>},
|
||||
{"add", lua::wrap<l_add>},
|
||||
{"mul", lua::wrap<l_mul>},
|
||||
{"min", lua::wrap<l_min>},
|
||||
{"max", lua::wrap<l_max>},
|
||||
{"abs", lua::wrap<l_abs>},
|
||||
};
|
||||
|
||||
static int l_meta_meta_call(lua::State* L) {
|
||||
auto width = tointeger(L, 2);
|
||||
auto height = tointeger(L, 3);
|
||||
@ -37,6 +267,11 @@ static int l_meta_index(lua::State* L) {
|
||||
return pushinteger(L, map->getWidth());
|
||||
} else if (!std::strcmp(fieldname, "height")) {
|
||||
return pushinteger(L, map->getHeight());
|
||||
} else {
|
||||
auto found = methods.find(tostring(L, 2));
|
||||
if (found != methods.end()) {
|
||||
return pushcfunction(L, found->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user