Replaced LibNoise in MapGen with FastNoise2 for S U P E R S P E E D
parent
c2831a84bc
commit
10edb1eb60
|
@ -48,6 +48,7 @@ include_directories(
|
|||
${ENET_HEADERS}
|
||||
${NOISE_HEADERS}
|
||||
${PTHREAD_HEADERS}
|
||||
lib/fastnoise2/include
|
||||
lib/catch2/include
|
||||
lib/gzip/include
|
||||
lib/cute_files/include
|
||||
|
@ -106,6 +107,11 @@ else()
|
|||
target_link_libraries(${MAIN_EXEC_NAME} assimp)
|
||||
endif()
|
||||
|
||||
# Build and Link FastNoise2
|
||||
|
||||
add_subdirectory(lib/fastnoise2)
|
||||
target_link_libraries(${MAIN_EXEC_NAME} FastNoise)
|
||||
|
||||
# Link Lua 5.3.5
|
||||
find_library(LUA_LIB NAMES lua lua5.3)
|
||||
target_link_libraries(${MAIN_EXEC_NAME} ${LUA_LIB})
|
||||
|
|
|
@ -26,4 +26,4 @@
|
|||
|
||||
int main(int argc, char* argv[]) {
|
||||
return StartGame(argc, argv);
|
||||
}
|
||||
}
|
|
@ -57,15 +57,15 @@ ChunkMeshGenerator::ChunkMeshGenerator(MeshChunkDetails* meshDetails, LocalDefin
|
|||
default: break;
|
||||
|
||||
case MeshMod::OFFSET_X:
|
||||
vis.x += blockOffsets[0].get(vec3(off) / 16.f) * mod.second;
|
||||
// vis.x += blockOffsets[0][vec3(off) / 16.f] * mod.second;
|
||||
break;
|
||||
|
||||
case MeshMod::OFFSET_Y:
|
||||
vis.y += blockOffsets[1].get(vec3(off) / 16.f) * mod.second;
|
||||
// vis.y += blockOffsets[1][vec3(off) / 16.f] * mod.second;
|
||||
break;
|
||||
|
||||
case MeshMod::OFFSET_Z:
|
||||
vis.z += blockOffsets[2].get(vec3(off) / 16.f) * mod.second;
|
||||
// vis.z += blockOffsets[2][vec3(off) / 16.f] * mod.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -97,12 +97,13 @@ u16 ChunkMeshGenerator::getBlockAt(const ivec3& pos) {
|
|||
}
|
||||
|
||||
u8vec4 ChunkMeshGenerator::getLightAt(const ivec3& pos) {
|
||||
auto dir = glm::floor(vec3(pos) / 16.f);
|
||||
if (dir.x != 0 || dir.y != 0 || dir.z != 0) {
|
||||
u8 ind = static_cast<u8>(Vec::TO_ENUM.at(dir));
|
||||
return adjacent[ind]->getLight(Space::Block::index(pos));
|
||||
}
|
||||
return chunk->getLight(Space::Block::index(pos));
|
||||
// auto dir = glm::floor(vec3(pos) / 16.f);
|
||||
// if (dir.x != 0 || dir.y != 0 || dir.z != 0) {
|
||||
// u8 ind = static_cast<u8>(Vec::TO_ENUM.at(dir));
|
||||
// return adjacent[ind]->getLight(Space::Block::index(pos));
|
||||
// }
|
||||
// return chunk->getLight(Space::Block::index(pos));
|
||||
return { 0, 0, 0, 15 };
|
||||
}
|
||||
|
||||
void ChunkMeshGenerator::addFaces(const vec3& offset,
|
||||
|
|
|
@ -57,13 +57,17 @@ std::shared_ptr<GuiComponent> GuiBuilder::createComponent(LuaGuiElement& elem, g
|
|||
c = body;
|
||||
break;
|
||||
}
|
||||
case Util::hash("Rect"):c = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
case Util::hash("Rect"):
|
||||
c = GuiRect::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Button"):c = GuiImageButton::fromSerialized(elem, textures, bounds);
|
||||
case Util::hash("Button"):
|
||||
c = GuiImageButton::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Text"):c = GuiText::fromSerialized(elem, textures, bounds);
|
||||
case Util::hash("Text"):
|
||||
c = GuiText::fromSerialized(elem, textures, bounds);
|
||||
break;
|
||||
case Util::hash("Model"):c = GuiModel::fromSerialized(elem, textures, models, bounds);
|
||||
case Util::hash("Model"):
|
||||
c = GuiModel::fromSerialized(elem, textures, models, bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
#include "world/dim/chunk/Chunk.h"
|
||||
#include "world/dim/LocalDimension.h"
|
||||
|
||||
MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension& dimension) :
|
||||
dimension(dimension),
|
||||
noiseSampler({ NoiseSample{ 16 }, NoiseSample{ 16 }, NoiseSample{ 16 }}) {
|
||||
|
||||
MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension& dimension): dimension(dimension),
|
||||
noiseSampler({ NoiseSample(u16vec3(16), 4), NoiseSample(u16vec3(16), 4), NoiseSample(u16vec3(16), 4) }) {
|
||||
noise::module::Perlin offsetBaseNoise;
|
||||
offsetBaseNoise.SetFrequency(8);
|
||||
offsetBaseNoise.SetOctaveCount(3);
|
||||
|
@ -24,10 +22,12 @@ MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension& dimension) :
|
|||
offsetTurbulence.SetFrequency(4.0);
|
||||
offsetTurbulence.SetPower(0.125);
|
||||
|
||||
generator = FastNoise::New<FastNoise::Constant>();
|
||||
|
||||
// 8 is just a random value to offset results
|
||||
noiseSampler[0].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x + 8, pos.y, pos.z); });
|
||||
noiseSampler[1].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y + 8, pos.z); });
|
||||
noiseSampler[2].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); });
|
||||
// noiseSampler[0].generate(u16vec3(8, 0, 0), generator);
|
||||
// noiseSampler[1].generate(u16vec3(0, 8, 0), generator);
|
||||
// noiseSampler[2].generate(u16vec3(0, 0, 8), generator);
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) threads.emplace_back(*game.l(), noiseSampler);
|
||||
|
@ -93,7 +93,7 @@ void MeshGenStream::Thread::exec() {
|
|||
assert(u.thisChunk);
|
||||
for (int i = 0; i < u.adjacentChunks.size(); i++) assert(u.adjacentChunks[i]);
|
||||
ChunkMeshGenerator m(u.meshDetails, game.getDefs(), game.getBiomes(),
|
||||
std::move(u.thisChunk), std::move(u.adjacentChunks), offsetSamplers, u.detail);
|
||||
std::move(u.thisChunk), std::move(u.adjacentChunks), offsetSamplers, ChunkMeshGenerator::Detail::HIGH);
|
||||
empty = false;
|
||||
u.busy = false;
|
||||
}
|
||||
|
|
|
@ -70,5 +70,7 @@ private:
|
|||
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
|
||||
|
||||
constexpr const static u8 HIGH_DETAIL_RANGE = 4;
|
||||
|
||||
FastNoise::SmartNode<> generator;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ ServerSubgame::ServerSubgame(const string& subgame, usize seed) :
|
|||
lua(make_unique<ServerLuaParser>(*this)) {
|
||||
|
||||
if (subgame.empty()) throw std::runtime_error("No subgame specified.");
|
||||
else if (!cf_file_exists(subgamePath.data())) throw std::runtime_error("Subgame does not exist.");
|
||||
if (!cf_file_exists(subgamePath.data())) throw std::runtime_error("Subgame does not exist.");
|
||||
}
|
||||
|
||||
void ServerSubgame::init(WorldPtr world) {
|
||||
|
|
|
@ -6,31 +6,27 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
#include <libnoise/module/modulebase.h>
|
||||
#include <FastNoise/FastNoise.h>
|
||||
|
||||
class Structure;
|
||||
|
||||
struct BiomeDef {
|
||||
std::string identifier = "";
|
||||
unsigned int index = 0;
|
||||
std::unordered_map<std::string, unsigned short> tags{};
|
||||
u32 index = 0;
|
||||
string identifier = "";
|
||||
std::unordered_map<string, u16> tags {};
|
||||
|
||||
float temperature = 0;
|
||||
float humidity = 0;
|
||||
float roughness = 0;
|
||||
f32 temperature = 0;
|
||||
f32 humidity = 0;
|
||||
f32 roughness = 0;
|
||||
|
||||
unsigned int topBlock = 0;
|
||||
unsigned int soilBlock = 0;
|
||||
unsigned int rockBlock = 0;
|
||||
u16 topBlock = 0;
|
||||
u16 soilBlock = 0;
|
||||
u16 rockBlock = 0;
|
||||
|
||||
std::vector<noise::module::Module*> heightmap;
|
||||
std::vector<noise::module::Module*> volume;
|
||||
FastNoise::SmartNode<> heightmap;
|
||||
FastNoise::SmartNode<> volume;
|
||||
|
||||
std::vector<std::shared_ptr<Structure>> schematics;
|
||||
vec<sptr<Structure>> schematics;
|
||||
|
||||
glm::vec3 tint {};
|
||||
vec3 tint {};
|
||||
};
|
||||
|
|
|
@ -2,251 +2,349 @@
|
|||
|
||||
#include "NoiseFromLua.h"
|
||||
|
||||
std::vector<noise::module::Module*> NoiseFromLua::build(sol::table noise) {
|
||||
std::vector<noise::module::Module*> modules;
|
||||
parseNoise(modules, noise);
|
||||
return std::move(modules);
|
||||
}
|
||||
|
||||
noise::module::Module* NoiseFromLua::parseNoise(std::vector<noise::module::Module*>& modules, sol::table noise) {
|
||||
std::string type = noise["module"];
|
||||
FastNoise::SmartNode<> NoiseFromLua::parse(sol::table table) {
|
||||
using namespace FastNoise;
|
||||
|
||||
// Modifer Modules
|
||||
if (type == "abs") {
|
||||
auto module = new noise::module::Abs();
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "clamp") {
|
||||
auto module = new noise::module::Clamp();
|
||||
module->SetBounds(noise.get_or<float>("low", noise::module::DEFAULT_CLAMP_LOWER_BOUND),
|
||||
noise.get_or<float>("high", noise::module::DEFAULT_CLAMP_UPPER_BOUND));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "curve") {
|
||||
auto module = new noise::module::Exponent();
|
||||
|
||||
module->SetExponent(noise.get_or<float>("exponent", noise::module::DEFAULT_EXPONENT));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "invert") {
|
||||
auto module = new noise::module::Invert();
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "scale_bias") {
|
||||
auto module = new noise::module::ScaleBias();
|
||||
sol::table source = noise["source"];
|
||||
|
||||
auto mod = parseNoise(modules, source);
|
||||
module->SetSourceModule(0, *mod);
|
||||
|
||||
module->SetScale(noise.get_or<float>("scale", noise::module::DEFAULT_SCALE));
|
||||
module->SetBias(noise.get_or<float>("bias", noise::module::DEFAULT_BIAS));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
// Combiner Modules
|
||||
else if (type == "add") {
|
||||
auto module = new noise::module::Add();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "max") {
|
||||
auto module = new noise::module::Max();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "min") {
|
||||
auto module = new noise::module::Min();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "multiply") {
|
||||
auto module = new noise::module::Multiply();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "power") {
|
||||
auto module = new noise::module::Power();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
// Generator modules
|
||||
else if (type == "billow") {
|
||||
auto module = new noise::module::Billow();
|
||||
|
||||
module->SetSeed(noise.get_or<float>("seed", 0));
|
||||
module->SetOctaveCount(noise.get_or<float>("octaves", noise::module::DEFAULT_BILLOW_OCTAVE_COUNT));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_BILLOW_FREQUENCY));
|
||||
module->SetLacunarity(noise.get_or<float>("lacunarity", noise::module::DEFAULT_BILLOW_LACUNARITY));
|
||||
module->SetPersistence(noise.get_or<float>("persistence", noise::module::DEFAULT_BILLOW_PERSISTENCE));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "checkerboard") {
|
||||
auto module = new noise::module::Checkerboard();
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "const") {
|
||||
auto module = new noise::module::Const();
|
||||
|
||||
module->SetConstValue(noise.get_or<float>("value", noise::module::DEFAULT_CONST_VALUE));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "cylinders") {
|
||||
auto module = new noise::module::Cylinders();
|
||||
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_CYLINDERS_FREQUENCY));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "ridged_multi") {
|
||||
auto module = new noise::module::RidgedMulti();
|
||||
|
||||
module->SetSeed(noise.get_or<float>("seed", 0));
|
||||
module->SetOctaveCount(noise.get_or<float>("octaves", noise::module::DEFAULT_RIDGED_OCTAVE_COUNT));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_RIDGED_FREQUENCY));
|
||||
module->SetLacunarity(noise.get_or<float>("lacunarity", noise::module::DEFAULT_RIDGED_LACUNARITY));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "spheres") {
|
||||
auto module = new noise::module::Spheres();
|
||||
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_SPHERES_FREQUENCY));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "perlin") {
|
||||
auto module = new noise::module::Perlin();
|
||||
|
||||
module->SetSeed(noise.get_or<float>("seed", 0));
|
||||
module->SetOctaveCount(noise.get_or<float>("octaves", noise::module::DEFAULT_PERLIN_OCTAVE_COUNT));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_PERLIN_FREQUENCY));
|
||||
module->SetLacunarity(noise.get_or<float>("lacunarity", noise::module::DEFAULT_PERLIN_LACUNARITY));
|
||||
module->SetPersistence(noise.get_or<float>("persistence", noise::module::DEFAULT_PERLIN_PERSISTENCE));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "voronoi") {
|
||||
auto module = new noise::module::Voronoi();
|
||||
|
||||
module->SetSeed(noise.get_or<float>("seed", 0));
|
||||
// module->EnableDistance(noise.get_or<u32>("distance", false));
|
||||
module->SetDisplacement(noise.get_or<float>("displacement", 0));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", 0));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
// Selector Modules
|
||||
else if (type == "blend") {
|
||||
auto module = new noise::module::Blend();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
auto control = parseNoise(modules, noise["control"]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
module->SetSourceModule(1, *control);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
else if (type == "select") {
|
||||
auto module = new noise::module::Select();
|
||||
sol::table sources = noise["sources"];
|
||||
|
||||
auto mod0 = parseNoise(modules, sources[1]);
|
||||
auto mod1 = parseNoise(modules, sources[2]);
|
||||
auto control = parseNoise(modules, noise["control"]);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetSourceModule(1, *mod1);
|
||||
module->SetSourceModule(1, *control);
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
// Transformer Modules
|
||||
else if (type == "turbulence") {
|
||||
auto module = new noise::module::Turbulence();
|
||||
sol::table source = noise["source"];
|
||||
|
||||
auto mod0 = parseNoise(modules, source);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetPower(noise.get_or<float>("power", noise::module::DEFAULT_TURBULENCE_POWER));
|
||||
module->SetFrequency(noise.get_or<float>("frequency", noise::module::DEFAULT_TURBULENCE_FREQUENCY));
|
||||
module->SetRoughness(noise.get_or<float>("roughness", noise::module::DEFAULT_TURBULENCE_ROUGHNESS));
|
||||
|
||||
modules.push_back(module);
|
||||
let type = table.get<string>("module");
|
||||
// std::cout << type << std::endl;
|
||||
|
||||
/**
|
||||
* Produces a constant value, regardless of the position.
|
||||
*
|
||||
* @param value - The value to produce, default 0.
|
||||
*/
|
||||
|
||||
if (type == "const") {
|
||||
let module = New<Constant>();
|
||||
module->SetValue(table.get_or<f32>("value", 0));
|
||||
return module;
|
||||
}
|
||||
|
||||
else if (type == "scale_point") {
|
||||
auto module = new noise::module::ScalePoint();
|
||||
sol::table source = noise["source"];
|
||||
/**
|
||||
* Applies the input position to the output using the factors and offsets provided.
|
||||
* All values default to zero.
|
||||
*
|
||||
* @param x_factor - The factor that the x value should influence the output.
|
||||
* @param y_factor - The factor that the y value should influence the output.
|
||||
* @param z_factor - The factor that the z value should influence the output.
|
||||
* @param x_offset - The offset applied to the x value.
|
||||
* @param y_offset - The offset applied to the y value.
|
||||
* @param z_offset - The offset applied to the z value.
|
||||
*/
|
||||
|
||||
if (type == "position_output") {
|
||||
let module = New<PositionOutput>();
|
||||
|
||||
auto mod0 = parseNoise(modules, source);
|
||||
module->SetSourceModule(0, *mod0);
|
||||
module->SetXScale(noise.get_or<float>("x_scale", 1));
|
||||
module->SetYScale(noise.get_or<float>("y_scale", 1));
|
||||
module->SetZScale(noise.get_or<float>("z_scale", 1));
|
||||
module->Set<Dim::X>(table.get_or("x_factor", 0), table.get_or("x_offset", 0));
|
||||
module->Set<Dim::Y>(table.get_or("y_factor", 0), table.get_or("y_offset", 0));
|
||||
module->Set<Dim::Z>(table.get_or("z_factor", 0), table.get_or("z_offset", 0));
|
||||
|
||||
modules.push_back(module);
|
||||
return module;
|
||||
}
|
||||
throw std::runtime_error("Invalid noise module specified.");
|
||||
|
||||
/**
|
||||
* Adds two sources, or a source and a scalar.
|
||||
*
|
||||
* @param sources - Two sources to add. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value to add to `source`.
|
||||
*/
|
||||
|
||||
if (type == "add") {
|
||||
let module = New<Add>();
|
||||
|
||||
if (table.get<sol::optional<sol::table>>("sources")) {
|
||||
module->SetLHS(parse(table["sources"][1]));
|
||||
module->SetRHS(parse(table["sources"][2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts two sources, or a source and a scalar.
|
||||
*
|
||||
* @param sources - Two sources to subtract. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value to add to `source`.
|
||||
*/
|
||||
|
||||
if (type == "subtract") {
|
||||
let module = New<Subtract>();
|
||||
|
||||
if (table.get<sol::optional<sol::table>>("sources")) {
|
||||
module->SetLHS(parse(table["sources"][1]));
|
||||
module->SetRHS(parse(table["sources"][2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two sources, or a source and a scalar.
|
||||
*
|
||||
* @param sources - Two sources to multiply. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value to multiply `source` by.
|
||||
*/
|
||||
|
||||
if (type == "multiply") {
|
||||
let module = New<Multiply>();
|
||||
|
||||
if (table.get<sol::optional<sol::table>>("sources")) {
|
||||
module->SetLHS(parse(table["sources"][1]));
|
||||
module->SetRHS(parse(table["sources"][2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two sources, or a source and a scalar.
|
||||
*
|
||||
* @param sources - Two sources to divide. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value to divide `source` by.
|
||||
*/
|
||||
|
||||
if (type == "divide") {
|
||||
let module = New<Divide>();
|
||||
|
||||
if (table.get<sol::optional<sol::table>>("sources")) {
|
||||
module->SetLHS(parse(table["sources"][1]));
|
||||
module->SetRHS(parse(table["sources"][2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blends between two sources, weighted by the factor provided.
|
||||
*
|
||||
* @param sources - The two sources to blend.
|
||||
* @param factor - The factor to blend by, default 0.5.
|
||||
*/
|
||||
|
||||
if (type == "fade") {
|
||||
let module = New<Fade>();
|
||||
|
||||
module->SetA(parse(table["sources"][1]));
|
||||
module->SetB(parse(table["sources"][2]));
|
||||
module->SetFade(table.get_or<f32>("factor", 0.5));
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the minimum between two sources, or a source and a scalar.
|
||||
* The two can also be smoothed between.
|
||||
*
|
||||
* @param sources - Two sources to choose the minimum of. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value as the minimum.
|
||||
* @param smoothness - The smoothness of the transition, defaults to 0.
|
||||
*/
|
||||
|
||||
if (type == "min") {
|
||||
let smoothness = table.get_or("smoothness", 0);
|
||||
|
||||
if (smoothness > 0) {
|
||||
let module = New<MinSmooth>();
|
||||
let sources = table["sources"];
|
||||
|
||||
module->SetSmoothness(smoothness);
|
||||
if (sources.valid()) {
|
||||
module->SetLHS(parse(sources[1]));
|
||||
module->SetRHS(parse(sources[2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
else {
|
||||
let module = New<Min>();
|
||||
let sources = table["sources"];
|
||||
|
||||
if (sources.valid()) {
|
||||
module->SetLHS(parse(sources[1]));
|
||||
module->SetRHS(parse(sources[2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the maximum between two sources, or a source and a scalar.
|
||||
* The two can also be smoothed between.
|
||||
*
|
||||
* @param sources - Two sources to choose the maximum of. Supply this or `source` and `scalar`.
|
||||
* @param source - A single source, if supplied, also specify `scalar`.
|
||||
* @param scalar - A scalar value as the maximum.
|
||||
* @param smoothness - The smoothness of the transition, defaults to 0.
|
||||
*/
|
||||
|
||||
if (type == "max") {
|
||||
let smoothness = table.get_or("smoothness", 0);
|
||||
|
||||
if (smoothness > 0) {
|
||||
let module = New<MaxSmooth>();
|
||||
let sources = table["sources"];
|
||||
|
||||
module->SetSmoothness(smoothness);
|
||||
if (sources.valid()) {
|
||||
module->SetLHS(parse(sources[1]));
|
||||
module->SetRHS(parse(sources[2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
else {
|
||||
let module = New<Max>();
|
||||
let sources = table["sources"];
|
||||
|
||||
if (sources.valid()) {
|
||||
module->SetLHS(parse(sources[1]));
|
||||
module->SetRHS(parse(sources[2]));
|
||||
}
|
||||
else {
|
||||
module->SetLHS(parse(table["source"]));
|
||||
module->SetRHS(table.get_or<f32>("scalar", 1));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the source between two scalar values. Can also be smoothed.
|
||||
*
|
||||
* @param source - The source to clamp.
|
||||
* @param min - The minimum value, defaults to 0.
|
||||
* @param max - The maximum value, defaults to 1.
|
||||
* @param smoothness - The smoothness of the transition, defaults to 0.
|
||||
*/
|
||||
|
||||
if (type == "max") {
|
||||
let source = parse(table["source"]);
|
||||
let smoothness = table.get_or<f32>("smoothness", 0);
|
||||
|
||||
if (smoothness > 0) {
|
||||
let minModule = New<MinSmooth>();
|
||||
minModule->SetLHS(source);
|
||||
minModule->SetRHS(table.get_or<f32>("min", 0));
|
||||
minModule->SetSmoothness(smoothness);
|
||||
|
||||
let maxModule = New<MaxSmooth>();
|
||||
maxModule->SetLHS(minModule);
|
||||
maxModule->SetRHS(table.get_or<f32>("max", 1));
|
||||
maxModule->SetSmoothness(smoothness);
|
||||
|
||||
return maxModule;
|
||||
}
|
||||
else {
|
||||
let minModule = New<Min>();
|
||||
minModule->SetLHS(source);
|
||||
minModule->SetRHS(table.get_or<f32>("min", 0));
|
||||
|
||||
let maxModule = New<Max>();
|
||||
maxModule->SetLHS(minModule);
|
||||
maxModule->SetRHS(table.get_or<f32>("max", 1));
|
||||
|
||||
return maxModule;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates Simplex Noise.
|
||||
*
|
||||
* @param frequency - The frequency of the noise, default 1.
|
||||
* @param octaves - The amount of octaves the noise will have, default 3.
|
||||
* @param lacunarity - The lacunarity of the octaves, default 0.5.
|
||||
* @param seed - The seed **offset** to use, relative to the world seed.
|
||||
*/
|
||||
|
||||
if (type == "simplex") {
|
||||
SmartNode<> module = New<Simplex>();
|
||||
|
||||
let seed = table.get_or<u32>("seed", 0);
|
||||
let frequency = table.get_or<f32>("frequency", 1);
|
||||
let octaves = table.get_or<f32>("octaves", 3);
|
||||
let persistence = table.get_or<f32>("persistence", 0.5);
|
||||
let lacunarity = table.get_or<f32>("lacunarity", 0.5);
|
||||
|
||||
if (frequency != 1) {
|
||||
let scaleModule = New<DomainScale>();
|
||||
scaleModule->SetSource(module);
|
||||
scaleModule->SetScale(frequency);
|
||||
module = scaleModule;
|
||||
}
|
||||
|
||||
if (octaves > 1) {
|
||||
let fractalModule = New<FractalFBm>();
|
||||
fractalModule->SetSource(module);
|
||||
fractalModule->SetOctaveCount(octaves);
|
||||
fractalModule->SetLacunarity(lacunarity);
|
||||
fractalModule->SetGain(persistence);
|
||||
module = fractalModule;
|
||||
}
|
||||
|
||||
if (seed != 0) {
|
||||
let seedOffsetModule = New<SeedOffset>();
|
||||
seedOffsetModule->SetSource(module);
|
||||
seedOffsetModule->SetOffset(seed);
|
||||
module = seedOffsetModule;
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the domain by axis.
|
||||
*
|
||||
* @param source - The source to scale.
|
||||
* @param x_scale - The scaling to apply to the x axis.
|
||||
* @param y_scale - The scaling to apply to the y axis.
|
||||
* @param z_scale - The scaling to apply to the z axis.
|
||||
*/
|
||||
|
||||
if (type == "scale") {
|
||||
let module = New<DomainAxisScale>();
|
||||
|
||||
module->SetSource(parse(table["source"]));
|
||||
module->SetScale<Dim::X>(table.get_or<f32>("x_scale", 1));
|
||||
module->SetScale<Dim::Y>(table.get_or<f32>("y_scale", 1));
|
||||
module->SetScale<Dim::Z>(table.get_or<f32>("z_scale", 1));
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Invalid module name: " + type);
|
||||
}
|
|
@ -1,35 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "util/Types.h"
|
||||
|
||||
#include <sol/forward.hpp>
|
||||
#include <libnoise/module/add.h>
|
||||
#include <libnoise/module/module.h>
|
||||
#include <libnoise/module/modulebase.h>
|
||||
#include <FastNoise/FastNoise.h>
|
||||
|
||||
namespace NoiseFromLua {
|
||||
|
||||
/**
|
||||
* Builds a noise module vector from a Lua noise table.
|
||||
* The top level module will always be the last element in the vector.
|
||||
*
|
||||
* @param noise - The lua noise definition to parse.
|
||||
* @returns a vector containing all of the noise modules built.
|
||||
*/
|
||||
|
||||
std::vector<noise::module::Module*> build(sol::table noise);
|
||||
|
||||
|
||||
/**
|
||||
* Will initialize Noise::Module instances from a lua noise module definition, and recursively initialize it's
|
||||
* child modules as well. All modules will be added in reverse-discovered-order to the modules vector reference
|
||||
* passed in. The top level module will always be the last element in the vector.
|
||||
*
|
||||
* @param modules - The vector reference to insert generated noise modules into.
|
||||
* @param noise - The lua noise definition to parse.
|
||||
* @returns the noise module that was parsed.
|
||||
*/
|
||||
|
||||
noise::module::Module* parseNoise(std::vector<noise::module::Module*>& modules, sol::table noise);
|
||||
/** Builds a FastNoise node tree from a Lua table. */
|
||||
FastNoise::SmartNode<> parse(sol::table table);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -66,21 +66,18 @@ namespace RegisterBiome {
|
|||
if (!biomeTint) throw identifier + "biome definitions require a biome_tint";
|
||||
|
||||
// Get noise parameters
|
||||
let constGenerator = FastNoise::New<FastNoise::Constant>();
|
||||
constGenerator->SetValue(0);
|
||||
FastNoise::SmartNode<> heightmap = constGenerator, volume = constGenerator;
|
||||
|
||||
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"))
|
||||
NoiseFromLua::parseNoise(heightmapModules, noiseList->get<sol::table>("heightmap"));
|
||||
else heightmapModules.push_back(new noise::module::Const);
|
||||
let heightTable = noiseList->get<sol::optional<sol::table>>("heightmap");
|
||||
if (heightTable) heightmap = NoiseFromLua::parse(*heightTable);
|
||||
|
||||
if (noiseList->get<sol::optional<sol::table>>("volume"))
|
||||
NoiseFromLua::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);
|
||||
let volumeTable = noiseList->get<sol::optional<sol::table>>("volume");
|
||||
if (volumeTable) volume = NoiseFromLua::parse(*volumeTable);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Structure>> schematics {};
|
||||
|
@ -103,8 +100,8 @@ namespace RegisterBiome {
|
|||
biomeDef->soilBlock = defs.blockFromStr(*bSoil).index;
|
||||
biomeDef->rockBlock = defs.blockFromStr(*bRock).index;
|
||||
|
||||
biomeDef->heightmap = heightmapModules;
|
||||
biomeDef->volume = volumeModules;
|
||||
biomeDef->heightmap = heightmap;
|
||||
biomeDef->volume = volume;
|
||||
|
||||
biomeDef->schematics = schematics;
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ class ServerSubgame;
|
|||
|
||||
class ServerGenStream {
|
||||
public:
|
||||
static const usize THREADS = 6;
|
||||
static const usize THREAD_QUEUE_SIZE = 6;
|
||||
static const usize THREADS = 4;
|
||||
static const usize THREAD_QUEUE_SIZE = 16;
|
||||
|
||||
struct FinishedJob {
|
||||
FinishedJob(u16 dim, ivec3 pos, uptr<MapGen::ChunkMap> created) :
|
||||
|
|
|
@ -21,6 +21,21 @@ namespace Space {
|
|||
const static i16f MAPBLOCK_CHUNK_LENGTH = MAPBLOCK_SIZE;
|
||||
const static i16f REGION_CHUNK_LENGTH = MAPBLOCK_CHUNK_LENGTH * REGION_SIZE;
|
||||
|
||||
// Get the index of a position vector in a cube.
|
||||
static inline u32 posToIndex(const ivec3& pos, const u32 size) {
|
||||
return pos.x + size * (pos.z + size * pos.y);
|
||||
}
|
||||
|
||||
// Return a position vector from an index of a cube.
|
||||
static inline ivec3 indexToPos(u32 ind, const u32 size) {
|
||||
ivec3 vec {};
|
||||
vec.y = ind / pow(size, 2);
|
||||
ind -= static_cast<u32>(vec.y) * pow(size, 2);
|
||||
vec.z = ind / size;
|
||||
vec.x = ind % size;
|
||||
return vec;
|
||||
}
|
||||
|
||||
// Private helper methods
|
||||
namespace {
|
||||
inline u16vec3 localFromGlobal(const ivec3& pos, i16 size) {
|
||||
|
@ -86,8 +101,7 @@ namespace Space {
|
|||
|
||||
// Get the index of a MapBlock within its Region from its local or world position.
|
||||
static inline u16 index(const ivec3& vec) {
|
||||
u8vec3 local = MapBlock::relative::toRegion(vec);
|
||||
return local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z);
|
||||
return Space::posToIndex(MapBlock::relative::toRegion(vec), REGION_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,20 +137,12 @@ namespace Space {
|
|||
|
||||
// Get the index of a Chunk within its MapBlock from its local or world position.
|
||||
static inline u16 index(const glm::ivec3& vec) {
|
||||
u8vec3 local = Chunk::relative::toMapBlock(vec);
|
||||
return local.x + MAPBLOCK_SIZE * (local.z + MAPBLOCK_SIZE * local.y);
|
||||
return Space::posToIndex(Chunk::relative::toMapBlock(vec), MAPBLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Return a local vector of an chunk within its mapblock.
|
||||
static inline ivec3 fromIndex(u16 ind) {
|
||||
u8vec3 vec {};
|
||||
|
||||
vec.y = ind / (MAPBLOCK_SIZE * MAPBLOCK_SIZE);
|
||||
ind -= (static_cast<int>(vec.y) * MAPBLOCK_SIZE * MAPBLOCK_SIZE);
|
||||
vec.z = ind / MAPBLOCK_SIZE;
|
||||
vec.x = ind % MAPBLOCK_SIZE;
|
||||
|
||||
return vec;
|
||||
return Space::indexToPos(ind, MAPBLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,20 +183,12 @@ namespace Space {
|
|||
|
||||
// Get the index of a Block within its Chunk from its local or world position.
|
||||
static inline u16 index(const ivec3& vec) {
|
||||
u8vec3 local = Block::relative::toChunk(vec);
|
||||
return local.x + CHUNK_SIZE * (local.z + CHUNK_SIZE * local.y);
|
||||
return Space::posToIndex(Block::relative::toChunk(vec), CHUNK_SIZE);
|
||||
}
|
||||
|
||||
// Return a local vector of an block within its chunk.
|
||||
static inline u8vec3 fromIndex(u16 ind) {
|
||||
u8vec3 vec {};
|
||||
|
||||
vec.y = ind / (CHUNK_SIZE * CHUNK_SIZE);
|
||||
ind -= (static_cast<int>(vec.y) * CHUNK_SIZE * CHUNK_SIZE);
|
||||
vec.z = ind / CHUNK_SIZE;
|
||||
vec.x = ind % CHUNK_SIZE;
|
||||
|
||||
return vec;
|
||||
return Space::indexToPos(ind, CHUNK_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ using i8 = int8_t;
|
|||
using i16 = int16_t;
|
||||
using i32 = int32_t;
|
||||
using i64 = int64_t;
|
||||
using isize = intmax_t;
|
||||
|
||||
using i8f = int_fast8_t;
|
||||
using i16f = int_fast16_t;
|
||||
|
|
|
@ -26,6 +26,18 @@ MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string>
|
|||
}
|
||||
|
||||
generateVoronoi(biomeIndices);
|
||||
|
||||
let biomePerlin = FastNoise::New<FastNoise::Simplex>();
|
||||
|
||||
let biomeScale = FastNoise::New<FastNoise::DomainScale>();
|
||||
biomeScale->SetSource(biomePerlin);
|
||||
biomeScale->SetScale(1/1000.f);
|
||||
|
||||
let biomeFractal = FastNoise::New<FastNoise::FractalFBm>();
|
||||
biomeFractal->SetSource(biomeScale);
|
||||
biomeFractal->SetOctaveCount(4);
|
||||
|
||||
biomeGenerator = biomeFractal;
|
||||
}
|
||||
|
||||
[[maybe_unused]] uptr<MapGen::ChunkMap> MapGen::generateChunk(u16 dim, ivec3 pos) {
|
||||
|
@ -39,50 +51,29 @@ uptr<MapGen::ChunkMap> MapGen::generateMapBlock(u16 dim, ivec3 pos) {
|
|||
std::unique_ptr<MapGen::ChunkMap> MapGen::generateArea(u16 dim, ivec3 origin, u16 size) {
|
||||
Job job(origin, size);
|
||||
|
||||
// Build Biome Prop Maps
|
||||
|
||||
const auto fill = [&](const noise::module::Module& s) {
|
||||
return [&](vec3 pos) {
|
||||
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
|
||||
return s.GetValue(worldPos.x, 0, worldPos.z);
|
||||
};
|
||||
};
|
||||
|
||||
job.temperature.populate(fill(props.temperature));
|
||||
job.roughness.populate(fill(props.roughness));
|
||||
job.humidity.populate(fill(props.humidity));
|
||||
|
||||
// Generate Biome Topmap
|
||||
|
||||
vec<u16> biomeMap {};
|
||||
biomeMap.resize((job.size * 16 + 1) * (job.size * 16 + 1));
|
||||
|
||||
for (usize i = 0; i < biomeMap.size(); i++) {
|
||||
vec3 indPos = { i / (job.size * 16 + 1), 0, i % (job.size * 16 + 1) };
|
||||
vec3 queryPos = indPos / 16.f / static_cast<f32>(job.size);
|
||||
|
||||
biomeMap[i] = getBiomeAt(job.temperature.get(queryPos),
|
||||
job.humidity.get(queryPos), job.roughness.get(queryPos));
|
||||
job.temperature.generate({ job.pos.x * 16, 0, job.pos.z * 16 }, biomeGenerator);
|
||||
job.roughness.generate({ job.pos.x * 16, 0, job.pos.z * 16 }, biomeGenerator);
|
||||
job.humidity.generate({ job.pos.x * 16, 0, job.pos.z * 16 }, biomeGenerator);
|
||||
|
||||
let biomeMap = vec<u16>(pow(job.size * 16 + 1, 2));
|
||||
u16vec3 bPos {};
|
||||
for (bPos.x = 0; bPos.x < job.size * 16 + 1; bPos.x++) {
|
||||
for (bPos.z = 0; bPos.z < job.size * 16 + 1; bPos.z++) {
|
||||
biomeMap[bPos.z * (job.size * 16 + 1 ) + bPos.x] =
|
||||
getBiomeAt(job.temperature[bPos], job.humidity[bPos], job.roughness[bPos]);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate Heightmap and Volume
|
||||
|
||||
job.heightmap.populate([&](vec3 pos) {
|
||||
ivec3 blockPos = ivec3(pos * 16.f * static_cast<f32>(job.size));
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z));
|
||||
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
|
||||
return biome.heightmap[biome.heightmap.size() - 1]->GetValue(worldPos.x, 0, worldPos.z);
|
||||
|
||||
job.heightmap.fill([&](ivec3 pos) {
|
||||
return game.getBiomes().biomeFromId(biomeMap[pos.z * (job.size * 16 + 1) + pos.x])
|
||||
.heightmap->GenSingle2D(job.pos.x * 16 + pos.x, job.pos.z * 16 + pos.z, 1337);
|
||||
});
|
||||
|
||||
job.volume.populate([&](vec3 pos) {
|
||||
ivec3 blockPos = ivec3(pos * 16.f * static_cast<f32>(job.size));
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z));
|
||||
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
|
||||
return biome.volume[biome.volume.size() - 1]->GetValue(worldPos.x, worldPos.y, worldPos.z);
|
||||
|
||||
job.volume.fill([&](ivec3 pos) {
|
||||
return game.getBiomes().biomeFromId(biomeMap[pos.z * (job.size * 16 + 1) + pos.x])
|
||||
.volume->GenSingle3D(job.pos.x * 16 + pos.x, job.pos.y * 16 + pos.y, job.pos.z * 16 + pos.z, 1337);
|
||||
});
|
||||
|
||||
// Generate Chunks
|
||||
|
||||
|
||||
i16vec3 pos {};
|
||||
for (pos.x = 0; pos.x < job.size; pos.x++) {
|
||||
for (pos.z = 0; pos.z < job.size; pos.z++) {
|
||||
|
@ -104,7 +95,7 @@ std::unique_ptr<MapGen::ChunkMap> MapGen::generateArea(u16 dim, ivec3 origin, u1
|
|||
}
|
||||
}
|
||||
|
||||
propogateSunlightNodes(job);
|
||||
// propogateSunlightNodes(job);
|
||||
|
||||
for (let& chunk : *job.chunks) {
|
||||
chunk.second->compress();
|
||||
|
@ -138,12 +129,12 @@ u16 MapGen::getBiomeAt(f32 temperature, f32 humidity, f32 roughness) {
|
|||
|
||||
uptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job, ivec3 localPos) {
|
||||
auto data = make_unique<ChunkData>();
|
||||
|
||||
|
||||
for (u16 i = 0; i < 4096; i++) {
|
||||
ivec3 indPos = Space::Block::fromIndex(i);
|
||||
vec3 queryPos = (vec3(localPos) + vec3(indPos) / 16.f) / static_cast<f32>(job.size);
|
||||
(*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z }))
|
||||
- ((job.pos.y + localPos.y) * 16 + indPos.y);
|
||||
let ind3d = localPos * 16 + indPos;
|
||||
let ind2d = (localPos.z * 16 + indPos.z) * (job.size * 16) + (localPos.x * 16 + indPos.x);
|
||||
(*data)[i] = (job.heightmap[ind2d]) + (job.volume[ind3d]) - ((job.pos.y + localPos.y) * 16 + indPos.y);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -191,7 +182,7 @@ void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, Ch
|
|||
for (u16 i = 0; i < 4096; i++) {
|
||||
ivec3 indPos = Space::Block::fromIndex(i);
|
||||
|
||||
u16 biomeId = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
|
||||
u16 biomeId = biomeMap[(localPos.z * 16 + indPos.z) * (job.size * 16 + 1) + (localPos.x * 16 + indPos.x)];
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeId);
|
||||
chunk.d->biomes[i] = biomeId;
|
||||
|
||||
|
@ -225,11 +216,10 @@ void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biome
|
|||
job.chunks->count(abovePos) ? job.chunks->at(abovePos) : nullptr : nullptr;
|
||||
|
||||
for (u16 i = 0; i < 256; i++) {
|
||||
ivec3 indPos = { i / 16, 15, i % 16 };
|
||||
|
||||
u16 biomeID = biomeMap[(localPos.x * 16 + indPos.x)
|
||||
* (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeID);
|
||||
ivec3 indPos { i / 16, 15, i % 16 };
|
||||
|
||||
u16 biomeId = biomeMap[(localPos.z * 16 + indPos.z) * (job.size * 16 + 1) + (localPos.x * 16 + indPos.x)];
|
||||
auto& biome = game.getBiomes().biomeFromId(biomeId);
|
||||
|
||||
i16 schemID = -1;
|
||||
for (u16 j = 0; j < biome.schematics.size(); j++) {
|
||||
|
|
|
@ -21,10 +21,10 @@ class DefinitionAtlas;
|
|||
class MapGen {
|
||||
public:
|
||||
/** The precision of the Biome map, as a divisor of the chunk size. */
|
||||
constexpr static u8 BIOP = 4;
|
||||
// constexpr static u8 BIOP = 4;
|
||||
|
||||
/** The precision of the Terrain maps, as a divisor of the chunk size. */
|
||||
constexpr static u8 TERP = 4;
|
||||
// constexpr static u8 TERP = 4;
|
||||
|
||||
/** A type alias for the type the map of Chunks stored in the Job. */
|
||||
typedef std::unordered_map<ivec3, sptr<Chunk>, Vec::ivec3> ChunkMap;
|
||||
|
@ -55,16 +55,20 @@ public:
|
|||
|
||||
Job(ivec3 pos, u16 size) :
|
||||
pos(pos), size(size),
|
||||
volume {{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap {{ size * TERP, 0 }},
|
||||
temperature {{ size * BIOP, 0 }}, roughness {{ size * BIOP, 0 }}, humidity {{ size * BIOP, 0 }} {}
|
||||
volume(u16vec3(size * 16), 4),
|
||||
heightmap(u16vec2(size * 16), 4),
|
||||
|
||||
temperature(u16vec2(size * 16), 4),
|
||||
humidity(u16vec2(size * 16), 4),
|
||||
roughness(u16vec2(size * 16), 4) {}
|
||||
|
||||
ivec3 pos {};
|
||||
u16 size {};
|
||||
|
||||
uptr<ChunkMap> chunks = make_unique<ChunkMap>();
|
||||
std::queue<SunlightNode> sunlightQueue {};
|
||||
|
||||
NoiseSample volume, heightmap;
|
||||
|
||||
NoiseSample heightmap, volume;
|
||||
NoiseSample temperature, humidity, roughness;
|
||||
};
|
||||
|
||||
|
@ -218,6 +222,8 @@ private:
|
|||
|
||||
constexpr const static u16 voronoiSize = 64;
|
||||
Voronoi3D voronoi { voronoiSize };
|
||||
|
||||
FastNoise::SmartNode<> biomeGenerator;
|
||||
|
||||
Subgame& game;
|
||||
World& world;
|
||||
|
|
|
@ -1,21 +1,57 @@
|
|||
#include <iostream>
|
||||
#include <util/Util.h>
|
||||
|
||||
#include "NoiseSample.h"
|
||||
|
||||
NoiseSample::NoiseSample(u16 precision, f32 scaleBy) :
|
||||
NoiseSample({ precision, precision }, { scaleBy, scaleBy }) {}
|
||||
|
||||
NoiseSample::NoiseSample(u16vec2 precision, glm::vec2 scaleBy) :
|
||||
precision(precision.x, precision.y, precision.x),
|
||||
scaleBy(scaleBy.x, scaleBy.y, scaleBy.x) {
|
||||
data.resize((this->precision.x + 1) * (this->precision.y + 1) * (this->precision.z + 1));
|
||||
NoiseSample::NoiseSample(u16vec2 size, u16 precision) : NoiseSample({ size.x, 0, size.y }, precision) {}
|
||||
|
||||
NoiseSample::NoiseSample(u16vec3 size, u16 precision):
|
||||
size(size), precision(precision), data((size.x + 1) * (size.y + 1) * (size.z + 1), 0) {
|
||||
if (size.x % precision != 0 || (size.y != 0 && size.y % precision) != 0 || size.z % precision != 0)
|
||||
throw std::runtime_error("NoiseSample precision must be a divisor of size." +
|
||||
Util::toString(size) + " : " + Util::toString(precision));
|
||||
}
|
||||
|
||||
void NoiseSample::populate(const NoiseSample::fill_function& fn) {
|
||||
vec3 pos {}, precisionFloat = vec3(precision);
|
||||
for (pos.x = 0; pos.x <= precisionFloat.x; pos.x++)
|
||||
for (pos.y = 0; pos.y <= precisionFloat.y; pos.y++)
|
||||
for (pos.z = 0; pos.z <= precisionFloat.z; pos.z++) {
|
||||
vec3 queryPos = pos / precisionFloat * scaleBy;
|
||||
if (queryPos.y == NAN) queryPos.y = 0;
|
||||
data[index(pos.x, pos.y, pos.z)] = fn(queryPos);
|
||||
void NoiseSample::generate(ivec3 pos, const FastNoise::SmartNode<>& generator) {
|
||||
for (u16 x = 0; x < size.x + 1; x += precision)
|
||||
for (u16 y = 0; y < size.y + 1; y += precision)
|
||||
for (u16 z = 0; z < size.z + 1; z += precision)
|
||||
data[index(x, y, z)] = generator->GenSingle3D(
|
||||
pos.x + x, pos.y + y, pos.z + z, 1337);
|
||||
|
||||
interpolateData();
|
||||
}
|
||||
|
||||
void NoiseSample::fill(const NoiseSample::fill_function& fill) {
|
||||
u16vec3 pos {};
|
||||
for (pos.x = 0; pos.x < size.x + 1; pos.x += precision)
|
||||
for (pos.y = 0; pos.y < size.y + 1; pos.y += precision)
|
||||
for (pos.z = 0; pos.z < size.z + 1; pos.z += precision)
|
||||
data[index(pos)] = fill(pos);
|
||||
|
||||
interpolateData();
|
||||
}
|
||||
|
||||
void NoiseSample::interpolateData() {
|
||||
u16vec3 pos = {};
|
||||
for (pos.x = 0; pos.x < size.x + 1; pos.x += 1) {
|
||||
for (pos.y = 0; pos.y < size.y + 1; pos.y += 1) {
|
||||
for (pos.z = 0; pos.z < size.z + 1; pos.z += 1) {
|
||||
if (pos.x % precision == 0 && pos.y % precision == 0 && pos.z % precision == 0) continue;
|
||||
|
||||
vec3 frac = vec3(pos) / static_cast<f32>(precision);
|
||||
u16vec3 a = u16vec3(glm::floor(frac)) * static_cast<u16>(precision);
|
||||
u16vec3 b = u16vec3(glm::ceil(frac)) * static_cast<u16>(precision);
|
||||
vec3 factor = frac - glm::floor(frac);
|
||||
|
||||
data[index(pos)] = Interp::trilerp(
|
||||
data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)],
|
||||
data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)],
|
||||
data[index(a.x, b.y, a.z)], data[index(b.x, b.y, a.z)],
|
||||
data[index(a.x, b.y, b.z)], data[index(b.x, b.y, b.z)],
|
||||
factor.x, factor.z, factor.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <FastNoise/FastNoise.h>
|
||||
|
||||
#include "util/Types.h"
|
||||
#include "util/Interp.h"
|
||||
|
||||
class NoiseSample {
|
||||
public:
|
||||
typedef std::function<f32(vec3 pos)> fill_function;
|
||||
typedef std::function<f32(ivec3 pos)> fill_function;
|
||||
|
||||
NoiseSample(u16 precision, f32 scaleBy = 1);
|
||||
NoiseSample(u16vec2 size, u16 precision);
|
||||
NoiseSample(u16vec3 size, u16 precision);
|
||||
|
||||
NoiseSample(u16vec2 precision, vec2 scaleBy = vec2(1));
|
||||
void generate(ivec3 pos, const FastNoise::SmartNode<>& generator);
|
||||
|
||||
void populate(const fill_function& fn);
|
||||
void fill(const fill_function& fill);
|
||||
|
||||
inline f32 get(vec3 pos) {
|
||||
vec3 scaled = pos * vec3(precision) / scaleBy;
|
||||
|
||||
ivec3 a = { scaled.x, scaled.y, scaled.z };
|
||||
vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z };
|
||||
ivec3 b = {
|
||||
(std::min)(static_cast<i32>(std::ceil(scaled.x)), precision.x),
|
||||
(std::min)(static_cast<i32>(std::ceil(scaled.y)), precision.y),
|
||||
(std::min)(static_cast<i32>(std::ceil(scaled.z)), precision.z) };
|
||||
|
||||
assert(index(b.x, b.y, b.z) < data.size());
|
||||
|
||||
// No vertical interpolation
|
||||
if (precision.y == 0)
|
||||
return Interp::bilerp(
|
||||
data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)],
|
||||
data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)],
|
||||
factor.x, factor.z);
|
||||
|
||||
return Interp::trilerp(
|
||||
data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)],
|
||||
data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)],
|
||||
data[index(a.x, b.y, a.z)], data[index(b.x, b.y, a.z)],
|
||||
data[index(a.x, b.y, b.z)], data[index(b.x, b.y, b.z)],
|
||||
factor.x, factor.z, factor.y);
|
||||
inline f32 operator[](u16vec3 pos) {
|
||||
return data[index(pos)];
|
||||
}
|
||||
|
||||
inline f32 operator[](u32 ind) {
|
||||
return data[shiftIndexByOne(ind)];
|
||||
}
|
||||
|
||||
// inline f32 get(vec3 pos) {
|
||||
// vec3 scaled = pos * vec3(precision) / scaleBy;
|
||||
//
|
||||
// ivec3 a = { scaled.x, scaled.y, scaled.z };
|
||||
// vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z };
|
||||
// ivec3 b = {
|
||||
// (std::min)(static_cast<i32>(std::ceil(scaled.x)), precision.x),
|
||||
// (std::min)(static_cast<i32>(std::ceil(scaled.y)), precision.y),
|
||||
// (std::min)(static_cast<i32>(std::ceil(scaled.z)), precision.z) };
|
||||
//
|
||||
// assert(index(b.x, b.y, b.z) < data.size());
|
||||
//
|
||||
// // No vertical interpolation
|
||||
// if (precision.y == 0)
|
||||
// return Interp::bilerp(
|
||||
// data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)],
|
||||
// data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)],
|
||||
// factor.x, factor.z);
|
||||
//
|
||||
// return Interp::trilerp(
|
||||
// data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)],
|
||||
// data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)],
|
||||
// data[index(a.x, b.y, a.z)], data[index(b.x, b.y, a.z)],
|
||||
// data[index(a.x, b.y, b.z)], data[index(b.x, b.y, b.z)],
|
||||
// factor.x, factor.z, factor.y);
|
||||
// }
|
||||
|
||||
private:
|
||||
inline u16 index(u16 x, u16 y, u16 z) {
|
||||
return x * (precision.x + 1) * (precision.y + 1) + y * (precision.x + 1) + z;
|
||||
void interpolateData();
|
||||
|
||||
// inline u32 innerIndex(u16 x, u16 y, u16 z) {
|
||||
// return static_cast<u32>(x) * size.x * size.y + y * size.x + z;
|
||||
// };
|
||||
|
||||
inline u32 index(u16vec3 pos) {
|
||||
return index(pos.x, pos.y, pos.z);
|
||||
};
|
||||
|
||||
std::vector<f32> data {};
|
||||
ivec3 precision {};
|
||||
vec3 scaleBy;
|
||||
inline u32 index(u16 x, u16 y, u16 z) {
|
||||
return static_cast<u32>(x) * (size.x + 1) * (size.y + 1) + y * (size.x + 1) + z;
|
||||
};
|
||||
|
||||
inline u32 shiftIndexByOne(u32 ind) {
|
||||
u16vec3 vec = {};
|
||||
|
||||
let divY = size.y == 0 ? 1 : size.y;
|
||||
|
||||
vec.z = ind / (size.x * divY);
|
||||
ind -= (vec.z * size.x * divY);
|
||||
vec.y = ind / size.x;
|
||||
vec.x = ind % size.x;
|
||||
|
||||
return index(vec);
|
||||
};
|
||||
|
||||
u16vec3 size;
|
||||
u16 precision;
|
||||
vec<f32> data {};
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "world/LocalWorld.h"
|
||||
#include "game/def/BlockDef.h"
|
||||
#include "util/net/NetField.h"
|
||||
#include "lua/usertype/Player.h"
|
||||
#include "lua/usertype/Target.h"
|
||||
#include "client/graph/Renderer.h"
|
||||
#include "world/dim/chunk/Chunk.h"
|
||||
|
|
|
@ -9,8 +9,8 @@ local menu = zepha.build_gui(function()
|
|||
Gui.Rect {
|
||||
key = "inventory",
|
||||
position = { pc(50), pc(50) },
|
||||
position_anchor = { pc(50), pc(55) },
|
||||
size = { 237, 187 },
|
||||
position_anchor = { pc(50), pc(50) },
|
||||
size = { 342, 187 },
|
||||
|
||||
Gui.Rect {
|
||||
key = "backpack",
|
||||
|
@ -63,10 +63,26 @@ local menu = zepha.build_gui(function()
|
|||
list = "hot_wheel_6",
|
||||
}
|
||||
},
|
||||
Gui.Rect {
|
||||
key = "player_frame",
|
||||
position = { 105, 0 },
|
||||
size = { 106, 187 },
|
||||
background = "zeus:inventory:player_frame",
|
||||
|
||||
Gui.Model {
|
||||
position = { 52, 150 },
|
||||
scale = { 64, 64 },
|
||||
|
||||
type = "model",
|
||||
source = "zeus:default:player",
|
||||
texture = "zeus:default:player",
|
||||
anim_range = { 0, 100 }
|
||||
}
|
||||
},
|
||||
Gui.Rect {
|
||||
key = "equipment",
|
||||
|
||||
position = { 106, 1 },
|
||||
position = { 209, 1 },
|
||||
size = { 132, 80 },
|
||||
padding = { 18, 8, 8, 8 },
|
||||
background = "zeus:inventory:equipment",
|
||||
|
@ -76,23 +92,13 @@ local menu = zepha.build_gui(function()
|
|||
|
||||
position = { 41, 1 },
|
||||
size = { 34, 52 },
|
||||
overflow = "hidden",
|
||||
|
||||
Gui.Model {
|
||||
position = { 15, 52 },
|
||||
scale = { 28, 28 },
|
||||
|
||||
type = "model",
|
||||
source = "zeus:default:player",
|
||||
texture = "zeus:default:player",
|
||||
anim_range = { 0, 100 }
|
||||
}
|
||||
overflow = "hidden"
|
||||
}
|
||||
},
|
||||
Gui.Rect {
|
||||
key = "dynamic",
|
||||
|
||||
position = { 106, 80 },
|
||||
position = { 209, 80 },
|
||||
size = { 132, 107 },
|
||||
padding = { 8, 8, 8, 8 },
|
||||
background = "zeus:inventory:dynamic",
|
||||
|
|
|
@ -65,15 +65,20 @@ local noise = {
|
|||
-- }}
|
||||
-- }
|
||||
volume = {
|
||||
module = "scale_bias",
|
||||
scale = 3000,
|
||||
bias = -3500,
|
||||
module = "scale",
|
||||
y_scale = 2,
|
||||
source = {
|
||||
module = "scale_point",
|
||||
y_scale = 2,
|
||||
module = "add",
|
||||
scalar = -2200,
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.1
|
||||
module = "multiply",
|
||||
scalar = 3000,
|
||||
source = {
|
||||
module = "simplex",
|
||||
frequency = 0.0025,
|
||||
octaves = 6,
|
||||
lacunarity = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
local identifier = "zeus:world:forest"
|
||||
|
||||
local wood = "zeus:default:wood"
|
||||
local leaf = "zeus:default:leaves"
|
||||
local none = "invalid"
|
||||
|
||||
local structures = {}
|
||||
-- local identifier = "zeus:world:forest"
|
||||
--
|
||||
-- local wood = "zeus:default:wood"
|
||||
-- local leaf = "zeus:default:leaves"
|
||||
-- local none = "invalid"
|
||||
--
|
||||
-- local structures = {}
|
||||
-- --
|
||||
-- -- table.insert(structures, zepha.create_structure({
|
||||
-- -- -- noise = {
|
||||
-- -- -- module = "perlin",
|
||||
-- -- -- frequency = 0.002,
|
||||
-- -- -- octaves = 8
|
||||
-- -- -- },
|
||||
-- -- -- region_size = 4,
|
||||
-- -- probability = 0.1,
|
||||
-- -- -- origin = V{1, 1, 1},
|
||||
-- -- origin = V(),
|
||||
-- -- layout = {{{ "zeus:flowers:flower_geranium" }}}
|
||||
-- -- }))
|
||||
--
|
||||
-- for i = 1, 5 do
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.025,
|
||||
-- layout = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
-- }))
|
||||
-- end
|
||||
-- --
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(),
|
||||
-- probability = 0.05,
|
||||
-- layout = {{{ "zeus:flowers:flower_red_mushroom" }}}
|
||||
-- }))
|
||||
--
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- -- noise = {
|
||||
-- -- module = "perlin",
|
||||
-- -- frequency = 0.002,
|
||||
-- -- octaves = 8
|
||||
-- -- },
|
||||
-- -- region_size = 4,
|
||||
-- probability = 0.1,
|
||||
-- -- origin = V{1, 1, 1},
|
||||
-- origin = V(),
|
||||
-- layout = {{{ "zeus:flowers:flower_geranium" }}}
|
||||
-- origin = V(),
|
||||
-- probability = 0.05,
|
||||
-- layout = {{{ "zeus:flowers:flower_brown_mushroom" }}}
|
||||
-- }))
|
||||
|
||||
for i = 1, 5 do
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.025,
|
||||
layout = {{{ "zeus:default:tall_grass_" .. tostring(i) }}}
|
||||
}))
|
||||
end
|
||||
--
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.05,
|
||||
layout = {{{ "zeus:flowers:flower_red_mushroom" }}}
|
||||
}))
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(),
|
||||
probability = 0.05,
|
||||
layout = {{{ "zeus:flowers:flower_brown_mushroom" }}}
|
||||
}))
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(1),
|
||||
probability = 0.1,
|
||||
layout = {{
|
||||
{ none, none, none },
|
||||
{ none, wood, none },
|
||||
{ none, none, none }
|
||||
}, {
|
||||
{ none, leaf, none },
|
||||
{ leaf, wood, leaf },
|
||||
{ none, leaf, none }
|
||||
}, {
|
||||
{ none, none, none },
|
||||
{ none, leaf, none },
|
||||
{ none, none, none }
|
||||
}}
|
||||
}))
|
||||
|
||||
local woo = "zeus:default:wood"
|
||||
local lea = "zeus:default:leaves"
|
||||
local inv = "invalid"
|
||||
|
||||
local trunk_layer_0 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local trunk_layer_1 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, woo, woo, woo, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local trunk_layer_2 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, woo, inv, inv },
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_1 = {
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ lea, lea, lea, lea, lea },
|
||||
{ lea, lea, woo, lea, lea },
|
||||
{ lea, lea, lea, lea, lea },
|
||||
{ inv, lea, lea, lea, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_2 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, lea, woo, lea, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
local leaf_layer_3 = {
|
||||
{ inv, inv, inv, inv, inv },
|
||||
{ inv, lea, lea, inv, inv },
|
||||
{ inv, lea, lea, lea, inv },
|
||||
{ inv, inv, lea, lea, inv },
|
||||
{ inv, inv, inv, inv, inv }
|
||||
}
|
||||
|
||||
table.insert(structures, zepha.create_structure({
|
||||
origin = V(2, 2, 2),
|
||||
probability = 0.05,
|
||||
layout = {
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_0,
|
||||
trunk_layer_1,
|
||||
trunk_layer_1,
|
||||
trunk_layer_1,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
trunk_layer_2,
|
||||
leaf_layer_2,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_1,
|
||||
leaf_layer_2,
|
||||
leaf_layer_3
|
||||
}
|
||||
}))
|
||||
|
||||
local noise = {
|
||||
-- heightmap = runfile(_PATH .. 'world_noise'),
|
||||
volume = {
|
||||
module = "scale_bias",
|
||||
scale = 3000,
|
||||
bias = -3500,
|
||||
source = {
|
||||
module = "scale_point",
|
||||
y_scale = 2,
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zepha.register_biome(identifier, {
|
||||
environment = {
|
||||
temperature = 25/100,
|
||||
humidity = 70/100,
|
||||
roughness = 20/100,
|
||||
},
|
||||
blocks = {
|
||||
top = "zeus:default:grass",
|
||||
soil = "zeus:default:dirt",
|
||||
rock = "zeus:default:stone"
|
||||
},
|
||||
tags = { natural = 1, default = 1 },
|
||||
structures = structures,
|
||||
biome_tint = "#aaed45",
|
||||
noise = noise
|
||||
})
|
||||
|
||||
return identifier
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(1),
|
||||
-- probability = 0.1,
|
||||
-- layout = {{
|
||||
-- { none, none, none },
|
||||
-- { none, wood, none },
|
||||
-- { none, none, none }
|
||||
-- }, {
|
||||
-- { none, leaf, none },
|
||||
-- { leaf, wood, leaf },
|
||||
-- { none, leaf, none }
|
||||
-- }, {
|
||||
-- { none, none, none },
|
||||
-- { none, leaf, none },
|
||||
-- { none, none, none }
|
||||
-- }}
|
||||
-- }))
|
||||
--
|
||||
-- local woo = "zeus:default:wood"
|
||||
-- local lea = "zeus:default:leaves"
|
||||
-- local inv = "invalid"
|
||||
--
|
||||
-- local trunk_layer_0 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
-- }
|
||||
--
|
||||
-- local trunk_layer_1 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, woo, woo, woo, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
-- }
|
||||
--
|
||||
-- local trunk_layer_2 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, woo, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
-- }
|
||||
--
|
||||
-- local leaf_layer_1 = {
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { lea, lea, lea, lea, lea },
|
||||
-- { lea, lea, woo, lea, lea },
|
||||
-- { lea, lea, lea, lea, lea },
|
||||
-- { inv, lea, lea, lea, inv }
|
||||
-- }
|
||||
--
|
||||
-- local leaf_layer_2 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, lea, woo, lea, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
-- }
|
||||
--
|
||||
-- local leaf_layer_3 = {
|
||||
-- { inv, inv, inv, inv, inv },
|
||||
-- { inv, lea, lea, inv, inv },
|
||||
-- { inv, lea, lea, lea, inv },
|
||||
-- { inv, inv, lea, lea, inv },
|
||||
-- { inv, inv, inv, inv, inv }
|
||||
-- }
|
||||
--
|
||||
-- table.insert(structures, zepha.create_structure({
|
||||
-- origin = V(2, 2, 2),
|
||||
-- probability = 0.05,
|
||||
-- layout = {
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_0,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_1,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- trunk_layer_2,
|
||||
-- leaf_layer_2,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_1,
|
||||
-- leaf_layer_2,
|
||||
-- leaf_layer_3
|
||||
-- }
|
||||
-- }))
|
||||
--
|
||||
-- local noise = {
|
||||
-- -- heightmap = runfile(_PATH .. 'world_noise'),
|
||||
-- volume = {
|
||||
-- module = "scale_bias",
|
||||
-- scale = 3000,
|
||||
-- bias = -3500,
|
||||
-- source = {
|
||||
-- module = "scale_point",
|
||||
-- y_scale = 2,
|
||||
-- source = {
|
||||
-- module = "perlin",
|
||||
-- frequency = 0.1
|
||||
-- }
|
||||
-- }
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- zepha.register_biome(identifier, {
|
||||
-- environment = {
|
||||
-- temperature = 25/100,
|
||||
-- humidity = 70/100,
|
||||
-- roughness = 20/100,
|
||||
-- },
|
||||
-- blocks = {
|
||||
-- top = "zeus:default:grass",
|
||||
-- soil = "zeus:default:dirt",
|
||||
-- rock = "zeus:default:stone"
|
||||
-- },
|
||||
-- tags = { natural = 1, default = 1 },
|
||||
-- structures = structures,
|
||||
-- biome_tint = "#aaed45",
|
||||
-- noise = noise
|
||||
-- })
|
||||
--
|
||||
-- return identifier
|
|
@ -144,15 +144,20 @@ table.insert(structures, zepha.create_structure({
|
|||
local noise = {
|
||||
-- heightmap = runfile(_PATH .. 'world_noise'),
|
||||
volume = {
|
||||
module = "scale_bias",
|
||||
scale = 3000,
|
||||
bias = -3500,
|
||||
module = "scale",
|
||||
y_scale = 2,
|
||||
source = {
|
||||
module = "scale_point",
|
||||
y_scale = 2,
|
||||
module = "add",
|
||||
scalar = -2200,
|
||||
source = {
|
||||
module = "perlin",
|
||||
frequency = 0.1
|
||||
module = "multiply",
|
||||
scalar = 3000,
|
||||
source = {
|
||||
module = "simplex",
|
||||
frequency = 0.0025,
|
||||
octaves = 6,
|
||||
lacunarity = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
return {
|
||||
runfile(_PATH.."biomes/plains"),
|
||||
runfile(_PATH.."biomes/highlands"),
|
||||
runfile(_PATH.."biomes/desert"),
|
||||
runfile(_PATH.."biomes/forest")
|
||||
runfile(_PATH .. "biomes/plains"),
|
||||
runfile(_PATH .. "biomes/highlands"),
|
||||
runfile(_PATH .. "biomes/desert"),
|
||||
runfile(_PATH .. "biomes/forest")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue