Clean up NoiseSample class & MapGen, allow heightmap and volume noise.

master
Nicole Collings 2020-03-05 15:31:32 -08:00
parent af9c38abf3
commit 7886dc8097
12 changed files with 259 additions and 109 deletions

View File

@ -4,8 +4,11 @@
#include "BiomeDef.h"
BiomeDef::BiomeDef(const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock, const std::vector<noise::module::Module*>& modules, glm::vec3 biomeTint) :
BiomeDef::BiomeDef(
const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock,
const std::vector<noise::module::Module*>& heightmap, const std::vector<noise::module::Module*>& volume,
glm::vec3 biomeTint) :
identifier(identifier),
index(index),
@ -18,6 +21,7 @@ BiomeDef::BiomeDef(const std::string& identifier, unsigned int index, float temp
soilBlock(soilBlock),
rockBlock(rockBlock),
modules(modules),
heightmap(heightmap),
volume(volume),
biomeTint(biomeTint) {}

View File

@ -12,7 +12,9 @@
struct BiomeDef {
BiomeDef() = default;
BiomeDef(const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock, const std::vector<noise::module::Module*>& modules, glm::vec3 biomeTint);
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock,
const std::vector<noise::module::Module*>& heightmap, const std::vector<noise::module::Module*>& volume,
glm::vec3 biomeTint);
std::string identifier = "";
unsigned int index = 0;
@ -25,7 +27,8 @@ struct BiomeDef {
unsigned int soilBlock = 0;
unsigned int rockBlock = 0;
std::vector<noise::module::Module*> modules;
std::vector<noise::module::Module*> heightmap;
std::vector<noise::module::Module*> volume;
glm::vec3 biomeTint {};
};

View File

@ -6,7 +6,7 @@
LocalBiomeAtlas::LocalBiomeAtlas() {
//Invalid Biome
BiomeDef* invalid = new BiomeDef("invalid", 0, -1, -1, -1, 0, 0, 0, {}, {});
BiomeDef* invalid = new BiomeDef("invalid", 0, -1, -1, -1, 0, 0, 0, {}, {}, {});
defs.push_back(invalid);
defTable.insert({"invalid", 0});
}

View File

@ -81,34 +81,31 @@ void MapGen::generateChunk(chunk_partials_map& chunks, glm::ivec3 worldPos) {
}
void MapGen::buildDensityMap(MapGenJob* job, glm::ivec3 worldPos) {
job->temperature = NoiseSample(temperature, {worldPos.x, 0, worldPos.z}, {4, 1}, true);
job->humidity = NoiseSample(humidity, {worldPos.x, 0, worldPos.z}, {4, 1}, true);
job->roughness = NoiseSample(roughness, {worldPos.x, 0, worldPos.z}, {4, 1}, true);
job->temperature = {}; job->humidity = {}; job->roughness = {};
// TODO: This is... a travesty. Please stop doing this weird jank insertion into a
// noisesample and create a proper constructor or *something*... could probs use a module owo
job->temperature.fill([&](glm::ivec3 pos) {
return temperature.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
job->humidity.fill([&](glm::ivec3 pos) {
return humidity.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
job->roughness.fill([&](glm::ivec3 pos) {
return roughness.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
auto terrain = NoiseSample({4, 4});
NoiseSample volume = {}, heightmap = {};
float offsetH = 16.f / 4.f;
float offsetV = 16.f / 4.f;
volume.fill([&](glm::ivec3 pos) {
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
return biome.volume[biome.volume.size() - 1]->GetValue(worldPos.x + pos.x / 16.f, worldPos.y + pos.y / 16.f, worldPos.z + pos.z / 16.f);
}, {4, 4});
for (int i = 0; i <= 4; i++) {
for (int j = 0; j <= 4; j++) {
for (int k = 0; k <= 4; k++) {
glm::vec3 localPos = {(offsetH * i) / 1.01f, (offsetV * j) / 1.01f, (offsetH * k) / 1.01f};
glm::vec3 pos = {(worldPos.x * 16 + offsetH * i) / 16.f, (worldPos.y * 16 + offsetV * j) / 16.f, (worldPos.z * 16 + offsetH * k) / 16.f};
auto& biome = biomes.getBiomeAt(job->temperature.get(localPos), job->humidity.get(localPos), job->roughness.get(localPos));
auto& mod = biome.modules[biome.modules.size() - 1];
terrain.set({i, j, k}, static_cast<float>(mod->GetValue(pos.x, pos.y, pos.z)));
}
}
}
heightmap.fill([&](glm::ivec3 pos) {
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
return biome.heightmap[biome.heightmap.size() - 1]->GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f);
}, 4);
glm::ivec3 lp;
for (int m = 0; m < 4096; m++) {
Vec::indAssignVec(m, lp);
job->density[m] = terrain.get(lp) - (lp.y + worldPos.y * 16);
job->density[m] = (volume.get(lp) + heightmap.get(lp)) - (lp.y + worldPos.y * 16);
}
}
@ -186,8 +183,6 @@ void MapGen::generateBlocks(chunk_partial& chunk) {
chunk.second->biomes.emplace_back(biome.index);
}
// if (chunk.second->blocks[ind] != DefinitionAtlas::INVALID) continue;
int d = std::floor(chunk.first->depth[m]);
unsigned int targetBlock
= d <= 1 ? DefinitionAtlas::AIR

View File

@ -3,61 +3,65 @@
//
#include "NoiseSample.h"
NoiseSample::NoiseSample(glm::ivec2 precision) :
prec(precision) {
reserveSpace();
void NoiseSample::fill(const NoiseSample::fill_function &fun, float precision) {
fill(fun, {precision, 1});
}
NoiseSample::NoiseSample(noise::module::Module &module, glm::vec3 chunkPos, glm::ivec2 precision, bool flat) :
prec(precision) {
reserveSpace();
void NoiseSample::fill(const NoiseSample::fill_function &fun, glm::ivec2 precision) {
this->precision = precision;
reserve();
float offsetH = 16.f / prec.x;
float offsetV = 16.f / prec.y;
float offsetH = 16.f / precision.x;
float offsetV = 16.f / precision.y;
for (int i = 0; i <= prec.x; i++) {
for (int j = 0; j <= prec.y; j++) {
for (int k = 0; k <= prec.x; k++) {
glm::vec3 pos = {(chunkPos.x * 16 + offsetH * i) / 16.f,
flat ? 0 : (chunkPos.y * 16 + offsetV * j) / 16.f,
(chunkPos.z * 16 + offsetH * k) / 16.f};
set({i, j, k}, static_cast<float>(module.GetValue(pos.x, pos.y, pos.z)));
// Iterate over the array
for (int i = 0; i <= precision.x; i++) {
for (int j = 0; j <= (precision.y == 1 ? 0 : precision.y); j++) {
for (int k = 0; k <= precision.x; k++) {
set({i, j, k}, fun({ offsetH * i, offsetV * j, offsetH * k }));
}
}
}
}
void NoiseSample::set(glm::ivec3 pos, float value) {
data[pos.x][pos.y][pos.z] = value;
}
float NoiseSample::get(glm::ivec3 localPos) {
assert(precision.x != 0);
assert(precision.y != 0);
float NoiseSample::get(const glm::ivec3& pos) {
glm::vec3 prec3 {prec.x, prec.y, prec.x};
glm::vec3 prec3 {precision.x, precision.y, precision.x};
const glm::ivec3 base = pos / (glm::ivec3(16) / glm::ivec3(prec3));
const glm::vec3 factor = glm::floor(glm::mod(glm::vec3(pos), (glm::vec3(16.f) / prec3))) / 16.f * prec3;
if (localPos.x == 16) localPos.x = 15;
if (localPos.y == 16) localPos.y = 15;
if (localPos.z == 16) localPos.z = 15;
glm::ivec3 base = localPos / (glm::ivec3(16) / glm::ivec3(prec3));
const glm::vec3 factor = glm::floor(glm::mod(glm::vec3(localPos), (glm::vec3(16.f) / prec3))) / 16.f * prec3;
const auto& x0y0 = data[base.x][base.y];
const auto& x1y0 = data[base.x + 1][base.y];
//No Vertical Interpolation
if (prec.y <= 1)
return Interp::bilerp(x0y0[base.z], x1y0[base.z], x0y0[base.z + 1], x1y0[base.z + 1], factor.x, factor.z);
if (precision.y <= 1) return Interp::bilerp(x0y0[base.z], x1y0[base.z], x0y0[base.z + 1], x1y0[base.z + 1], factor.x, factor.z);
const auto& x0y1 = data[base.x][base.y + 1];
const auto& x1y1 = data[base.x + 1][base.y + 1];
return Interp::trilerp(x0y0[base.z], x1y0[base.z], x0y0[base.z + 1], x1y0[base.z + 1],
x0y1[base.z], x1y1[base.z], x0y1[base.z + 1], x1y1[base.z + 1], factor.x, factor.z, factor.y);
return Interp::trilerp(
x0y0[base.z], x1y0[base.z], x0y0[base.z + 1], x1y0[base.z + 1],
x0y1[base.z], x1y1[base.z], x0y1[base.z + 1], x1y1[base.z + 1], factor.x, factor.z, factor.y);
}
void NoiseSample::reserveSpace() {
data.reserve(prec.x + 1);
for (unsigned int i = 0; i <= prec.x; i++) {
void NoiseSample::set(glm::ivec3 localPos, float value) {
data[localPos.x][localPos.y][localPos.z] = value;
}
void NoiseSample::reserve() {
data.reserve(precision.x + 1);
for (unsigned int i = 0; i <= precision.x; i++) {
std::vector<std::vector<float>> subdata;
subdata.reserve(prec.y + 1);
for (int j = 0; j <= prec.y; j++)
subdata.emplace_back(prec.x + 1);
subdata.reserve(precision.y + 1);
for (int j = 0; j <= precision.y; j++)
subdata.emplace_back(precision.x + 1);
data.push_back(subdata);
}
}
}

View File

@ -9,20 +9,24 @@
#include <noise/noise.h>
#include <glm/glm.hpp>
#include <glm/common.hpp>
#include <functional>
#include "../../util/Interp.h"
class NoiseSample {
public:
typedef std::function<float(glm::ivec3 pos)> fill_function;
NoiseSample() = default;
explicit NoiseSample(glm::ivec2 precision);
NoiseSample(noise::module::Module& module, glm::vec3 pos, glm::ivec2 precision, bool flat = false);
void set(glm::ivec3 pos, float value);
float get(const glm::ivec3& pos);
void fill(const fill_function& fun, float precision);
void fill(const fill_function& fun, glm::ivec2 precision);
float get(glm::ivec3 localPos);
void set(glm::ivec3 localPos, float value);
private:
void reserveSpace();
void reserve();
glm::ivec2 prec {};
std::vector<std::vector<std::vector<float>>> data {};
glm::ivec2 precision {};
};

View File

@ -6,7 +6,7 @@
ServerBiomeAtlas::ServerBiomeAtlas() {
//Invalid Biome
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {});
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {}, {});
registerBiome(invalid);
}

View File

@ -21,12 +21,11 @@ MeshGenStream::MeshGenStream(ClientGame &defs, LocalDimension &dimension) :
offsetTurbulence.SetFrequency(4.0);
offsetTurbulence.SetPower(0.125);
noiseSampler = { NoiseSample {}, NoiseSample {}, NoiseSample {} };
//8 is just a random value to offset results
noiseSampler = {
NoiseSample {offsetTurbulence, {0, 0, 8}, {16, 16}},
NoiseSample {offsetTurbulence, {0, 8, 0}, {16, 16}},
NoiseSample {offsetTurbulence, {8, 0, 0}, {16, 16}}
};
noiseSampler[0].fill([&](glm::ivec3 pos) -> float { return offsetTurbulence.GetValue(pos.x + 8, pos.y, pos.z); }, {16, 16});
noiseSampler[1].fill([&](glm::ivec3 pos) -> float { return offsetTurbulence.GetValue(pos.x, pos.y + 8, pos.z); }, {16, 16});
noiseSampler[2].fill([&](glm::ivec3 pos) -> float { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); }, {16, 16});
threads.reserve(THREADS);
for (int i = 0; i < THREADS; i++) {

View File

@ -282,9 +282,23 @@ namespace RegisterBiomes {
auto biomeTint = biomeTable.get < sol::optional < std::string >> ("biome_tint");
if (!biomeTint) throw identifier + "biome definitions require a biome_tint";
// Parse Noise params
std::vector<noise::module::Module*> modules;
parseNoise(modules, biomeTable.get<sol::table>("noise"));
// Get noise parameters
auto noiseList = biomeTable.get<sol::optional<sol::table>>("noise");
std::vector<noise::module::Module*> volumeModules, heightmapModules;
if (noiseList) {
if (noiseList->get<sol::optional<sol::table>>("heightmap"))
parseNoise(heightmapModules, noiseList->get<sol::table>("heightmap"));
else heightmapModules.push_back(new noise::module::Const);
if (noiseList->get<sol::optional<sol::table>>("volume"))
parseNoise(volumeModules, noiseList->get<sol::table>("volume"));
else volumeModules.push_back(new noise::module::Const);
}
else {
volumeModules.push_back(new noise::module::Const);
heightmapModules.push_back(new noise::module::Const);
}
// Create biome definition
BiomeDef* biomeDef = new BiomeDef(
@ -293,7 +307,8 @@ namespace RegisterBiomes {
defs.blockFromStr(*bTop).index,
defs.blockFromStr(*bSoil).index,
defs.blockFromStr(*bRock).index,
modules,
heightmapModules,
volumeModules,
glm::vec3(Util::hexToColorVec((*biomeTint)))
);

View File

@ -0,0 +1,126 @@
local formspec = zepha.create_menu(function()
return Gui.Body {
background = "#0003",
callbacks = {
primary = zepha.player:close_menu
},
Gui.Rect {
key = "inventory",
position = { pc(50), pc(50) },
position_anchor = { pc(50), pc(55) },
size = { 218, 160 },
Gui.Rect {
key = "inventory_background",
position = { 0, 45 },
size = { 218, 100 },
padding = { 20, 10, 8, 10 },
background = "zeus:inventory:inventory",
Gui.InventoryList {
position = { 1, 1 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "main",
}
},
Gui.Rect {
key = "crafting_background",
position = { 0, -5 },
size = { 218, 72 },
padding = { 20, 10, 8, 10 },
background = "zeus:inventory:crafting",
Gui.InventoryList {
position = { 111, 1 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "craft",
},
Gui.InventoryList {
position = { 163, 10 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "craft_result",
},
Gui.Rect {
key = "player_clamp",
position = { 41, -8 },
size = { 32, 52 },
overflow = "hidden",
Gui.Model {
position = { 15, 52 },
scale = { 86, 86 },
type = "model",
source = "zeus:default:player",
texture = "zeus:default:player",
anim_range = { 0, 300 }
}
}
},
Gui.Rect {
position = { 2, 160 },
size = { 214, 67 },
background = "zeus:inventory:inventory_wheel",
children = {
Gui.InventoryList {
position = { 9, 1 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_1",
},
Gui.InventoryList {
position = { 117, 1 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_2",
},
Gui.InventoryList {
position = { 125, 25 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_3",
},
Gui.InventoryList {
position = { 117, 50 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_4",
},
Gui.InventoryList {
position = { 9, 50 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_5",
},
Gui.InventoryList {
position = { 1, 25 },
slot_spacing = { 2, 2 },
source = "current_player",
list = "hot_wheel_6",
}
}
}
}
end)
-- Register the inventory menu and keybind
zepha.register_keybind("zeus:inventory:open_inventory", {
description = "Open Inventory",
default = zepha.keys.e,
on_press = function()
if (zepha.player.menu_state == "") then
zepha.player:open_menu(formspec)
else
zepha.player:close_menu()
end
}
})

View File

@ -1,31 +1,30 @@
local noise = {
module = "add",
sources = {
{
volume = {
module = "add",
sources = {{
module = "add",
sources = {
{ ## Voronoi
module = "scale_bias",
source = {
module = "voronoi",
frequency = 0.2,
displacement = 5
},
scale = 8,
bias = -32
sources = {{
## Voronoi
module = "scale_bias",
source = {
module = "voronoi",
frequency = 0.2,
displacement = 5
},
{ ## Features
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.6,
octaves = 3,
},
scale = 3
}
}
},
{ ## Variation
scale = 8,
bias = -32
}, {
## Features
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.6,
octaves = 3,
},
scale = 3
}}
}, {
## Variation
module = "scale_bias",
source = {
module = "perlin",
@ -33,7 +32,7 @@ local noise = {
octaves = 6
},
scale = 15
}
}}
}
}

View File

@ -1,7 +1,8 @@
local noise = {
module = "add",
sources = {
{ ## Elevation
heightmap = {
module = "add",
sources = {{
## Elevation
module = "scale_bias",
source = {
module = "perlin",
@ -10,8 +11,8 @@ local noise = {
},
scale = 250,
bias = -32
},
{ ## Features
}, {
## Features
module = "scale_bias",
source = {
module = "perlin",
@ -20,7 +21,7 @@ local noise = {
},
scale = 6,
bias = 6
}
}}
}
}