add Heightmap methods
This commit is contained in:
@@ -1,3 +1,48 @@
|
|||||||
-- use for engine development tests
|
-- use for engine development tests
|
||||||
-- must be empty in release
|
-- must be empty in release
|
||||||
-- must not be modified by content-packs
|
-- 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;
|
return TYPENAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float* getValues() {
|
||||||
|
return buffer.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
const float* getValues() const {
|
||||||
|
return buffer.data();
|
||||||
|
}
|
||||||
|
|
||||||
static int createMetatable(lua::State*);
|
static int createMetatable(lua::State*);
|
||||||
inline static std::string TYPENAME = "heightmap";
|
inline static std::string TYPENAME = "heightmap";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static int l_remove(lua::State* L) {
|
|||||||
return 0;
|
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>},
|
{"append", lua::wrap<l_append>},
|
||||||
{"insert", lua::wrap<l_insert>},
|
{"insert", lua::wrap<l_insert>},
|
||||||
{"remove", lua::wrap<l_remove>},
|
{"remove", lua::wrap<l_remove>},
|
||||||
@@ -85,8 +85,8 @@ static int l_meta_index(lua::State* L) {
|
|||||||
}
|
}
|
||||||
auto& data = buffer->data();
|
auto& data = buffer->data();
|
||||||
if (isstring(L, 2)) {
|
if (isstring(L, 2)) {
|
||||||
auto found = bytearray_methods.find(tostring(L, 2));
|
auto found = methods.find(tostring(L, 2));
|
||||||
if (found != bytearray_methods.end()) {
|
if (found != methods.end()) {
|
||||||
return pushcfunction(L, found->second);
|
return pushcfunction(L, found->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,17 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "maths/FastNoiseLite.h"
|
||||||
|
#include "coders/png.hpp"
|
||||||
|
#include "graphics/core/ImageData.hpp"
|
||||||
#include "lua_util.hpp"
|
#include "lua_util.hpp"
|
||||||
|
|
||||||
using namespace lua;
|
using namespace lua;
|
||||||
|
|
||||||
|
static fnl_state noise = fnlCreateState();
|
||||||
|
|
||||||
Heightmap::Heightmap(uint width, uint height) : width(width), height(height) {
|
Heightmap::Heightmap(uint width, uint height) : width(width), height(height) {
|
||||||
buffer.resize(width*height);
|
buffer.resize(width*height);
|
||||||
}
|
}
|
||||||
@@ -15,6 +21,230 @@ Heightmap::Heightmap(uint width, uint height) : width(width), height(height) {
|
|||||||
Heightmap::~Heightmap() {
|
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) {
|
static int l_meta_meta_call(lua::State* L) {
|
||||||
auto width = tointeger(L, 2);
|
auto width = tointeger(L, 2);
|
||||||
auto height = tointeger(L, 3);
|
auto height = tointeger(L, 3);
|
||||||
@@ -37,6 +267,11 @@ static int l_meta_index(lua::State* L) {
|
|||||||
return pushinteger(L, map->getWidth());
|
return pushinteger(L, map->getWidth());
|
||||||
} else if (!std::strcmp(fieldname, "height")) {
|
} else if (!std::strcmp(fieldname, "height")) {
|
||||||
return pushinteger(L, map->getHeight());
|
return pushinteger(L, map->getHeight());
|
||||||
|
} else {
|
||||||
|
auto found = methods.find(tostring(L, 2));
|
||||||
|
if (found != methods.end()) {
|
||||||
|
return pushcfunction(L, found->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user