Replaced LibNoise in MapGen with FastNoise2 for S U P E R S P E E D

master
Auri 2021-08-09 22:39:20 -07:00
parent c2831a84bc
commit 10edb1eb60
24 changed files with 820 additions and 659 deletions

View File

@ -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})

View File

@ -26,4 +26,4 @@
int main(int argc, char* argv[]) {
return StartGame(argc, argv);
}
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -70,5 +70,7 @@ private:
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
constexpr const static u8 HIGH_DETAIL_RANGE = 4;
FastNoise::SmartNode<> generator;
};

View File

@ -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) {

View File

@ -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 {};
};

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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;

View File

@ -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) :

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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++) {

View File

@ -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;

View File

@ -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);
}
}
}
}
}

View File

@ -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 {};
};

View File

@ -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"

View File

@ -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",

View File

@ -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
}
}
}
}

View File

@ -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

View File

@ -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
}
}
}
}

View File

@ -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")
}