diff --git a/CMakeLists.txt b/CMakeLists.txt index e56da46f..f290a9b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/src/Main.cpp b/src/Main.cpp index c78fde22..77431ec5 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -26,4 +26,4 @@ int main(int argc, char* argv[]) { return StartGame(argc, argv); -} +} \ No newline at end of file diff --git a/src/client/graph/mesh/ChunkMeshGenerator.cpp b/src/client/graph/mesh/ChunkMeshGenerator.cpp index b5ff7696..c15f0ef9 100644 --- a/src/client/graph/mesh/ChunkMeshGenerator.cpp +++ b/src/client/graph/mesh/ChunkMeshGenerator.cpp @@ -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(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(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, diff --git a/src/client/gui/GuiBuilder.cpp b/src/client/gui/GuiBuilder.cpp index 1d12f24d..3e0f19d4 100644 --- a/src/client/gui/GuiBuilder.cpp +++ b/src/client/gui/GuiBuilder.cpp @@ -57,13 +57,17 @@ std::shared_ptr 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; } diff --git a/src/client/stream/MeshGenStream.cpp b/src/client/stream/MeshGenStream.cpp index 5c097020..6fc4c497 100644 --- a/src/client/stream/MeshGenStream.cpp +++ b/src/client/stream/MeshGenStream.cpp @@ -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(); + // 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; } diff --git a/src/client/stream/MeshGenStream.h b/src/client/stream/MeshGenStream.h index 413a6a11..18873678 100644 --- a/src/client/stream/MeshGenStream.h +++ b/src/client/stream/MeshGenStream.h @@ -70,5 +70,7 @@ private: std::unordered_set queuedMap; constexpr const static u8 HIGH_DETAIL_RANGE = 4; + + FastNoise::SmartNode<> generator; }; diff --git a/src/game/ServerSubgame.cpp b/src/game/ServerSubgame.cpp index 1508ea73..b296f9d1 100644 --- a/src/game/ServerSubgame.cpp +++ b/src/game/ServerSubgame.cpp @@ -15,7 +15,7 @@ ServerSubgame::ServerSubgame(const string& subgame, usize seed) : lua(make_unique(*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) { diff --git a/src/game/def/BiomeDef.h b/src/game/def/BiomeDef.h index f0c16daa..97177fbb 100644 --- a/src/game/def/BiomeDef.h +++ b/src/game/def/BiomeDef.h @@ -6,31 +6,27 @@ #pragma once -#include -#include -#include -#include -#include +#include class Structure; struct BiomeDef { - std::string identifier = ""; - unsigned int index = 0; - std::unordered_map tags{}; + u32 index = 0; + string identifier = ""; + std::unordered_map 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 heightmap; - std::vector volume; + FastNoise::SmartNode<> heightmap; + FastNoise::SmartNode<> volume; - std::vector> schematics; + vec> schematics; - glm::vec3 tint {}; + vec3 tint {}; }; diff --git a/src/lua/NoiseFromLua.cpp b/src/lua/NoiseFromLua.cpp index 7bbdcdd0..4bd87a38 100644 --- a/src/lua/NoiseFromLua.cpp +++ b/src/lua/NoiseFromLua.cpp @@ -2,251 +2,349 @@ #include "NoiseFromLua.h" -std::vector NoiseFromLua::build(sol::table noise) { - std::vector modules; - parseNoise(modules, noise); - return std::move(modules); -} - -noise::module::Module* NoiseFromLua::parseNoise(std::vector& 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("low", noise::module::DEFAULT_CLAMP_LOWER_BOUND), - noise.get_or("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("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("scale", noise::module::DEFAULT_SCALE)); - module->SetBias(noise.get_or("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("seed", 0)); - module->SetOctaveCount(noise.get_or("octaves", noise::module::DEFAULT_BILLOW_OCTAVE_COUNT)); - module->SetFrequency(noise.get_or("frequency", noise::module::DEFAULT_BILLOW_FREQUENCY)); - module->SetLacunarity(noise.get_or("lacunarity", noise::module::DEFAULT_BILLOW_LACUNARITY)); - module->SetPersistence(noise.get_or("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("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("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("seed", 0)); - module->SetOctaveCount(noise.get_or("octaves", noise::module::DEFAULT_RIDGED_OCTAVE_COUNT)); - module->SetFrequency(noise.get_or("frequency", noise::module::DEFAULT_RIDGED_FREQUENCY)); - module->SetLacunarity(noise.get_or("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("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("seed", 0)); - module->SetOctaveCount(noise.get_or("octaves", noise::module::DEFAULT_PERLIN_OCTAVE_COUNT)); - module->SetFrequency(noise.get_or("frequency", noise::module::DEFAULT_PERLIN_FREQUENCY)); - module->SetLacunarity(noise.get_or("lacunarity", noise::module::DEFAULT_PERLIN_LACUNARITY)); - module->SetPersistence(noise.get_or("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("seed", 0)); -// module->EnableDistance(noise.get_or("distance", false)); - module->SetDisplacement(noise.get_or("displacement", 0)); - module->SetFrequency(noise.get_or("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("power", noise::module::DEFAULT_TURBULENCE_POWER)); - module->SetFrequency(noise.get_or("frequency", noise::module::DEFAULT_TURBULENCE_FREQUENCY)); - module->SetRoughness(noise.get_or("roughness", noise::module::DEFAULT_TURBULENCE_ROUGHNESS)); - - modules.push_back(module); + let type = table.get("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(); + module->SetValue(table.get_or("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(); - auto mod0 = parseNoise(modules, source); - module->SetSourceModule(0, *mod0); - module->SetXScale(noise.get_or("x_scale", 1)); - module->SetYScale(noise.get_or("y_scale", 1)); - module->SetZScale(noise.get_or("z_scale", 1)); + module->Set(table.get_or("x_factor", 0), table.get_or("x_offset", 0)); + module->Set(table.get_or("y_factor", 0), table.get_or("y_offset", 0)); + module->Set(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(); + + if (table.get>("sources")) { + module->SetLHS(parse(table["sources"][1])); + module->SetRHS(parse(table["sources"][2])); + } + else { + module->SetLHS(parse(table["source"])); + module->SetRHS(table.get_or("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(); + + if (table.get>("sources")) { + module->SetLHS(parse(table["sources"][1])); + module->SetRHS(parse(table["sources"][2])); + } + else { + module->SetLHS(parse(table["source"])); + module->SetRHS(table.get_or("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(); + + if (table.get>("sources")) { + module->SetLHS(parse(table["sources"][1])); + module->SetRHS(parse(table["sources"][2])); + } + else { + module->SetLHS(parse(table["source"])); + module->SetRHS(table.get_or("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(); + + if (table.get>("sources")) { + module->SetLHS(parse(table["sources"][1])); + module->SetRHS(parse(table["sources"][2])); + } + else { + module->SetLHS(parse(table["source"])); + module->SetRHS(table.get_or("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(); + + module->SetA(parse(table["sources"][1])); + module->SetB(parse(table["sources"][2])); + module->SetFade(table.get_or("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(); + 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("scalar", 1)); + } + + return module; + } + else { + let module = New(); + 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("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(); + 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("scalar", 1)); + } + + return module; + } + else { + let module = New(); + 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("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("smoothness", 0); + + if (smoothness > 0) { + let minModule = New(); + minModule->SetLHS(source); + minModule->SetRHS(table.get_or("min", 0)); + minModule->SetSmoothness(smoothness); + + let maxModule = New(); + maxModule->SetLHS(minModule); + maxModule->SetRHS(table.get_or("max", 1)); + maxModule->SetSmoothness(smoothness); + + return maxModule; + } + else { + let minModule = New(); + minModule->SetLHS(source); + minModule->SetRHS(table.get_or("min", 0)); + + let maxModule = New(); + maxModule->SetLHS(minModule); + maxModule->SetRHS(table.get_or("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(); + + let seed = table.get_or("seed", 0); + let frequency = table.get_or("frequency", 1); + let octaves = table.get_or("octaves", 3); + let persistence = table.get_or("persistence", 0.5); + let lacunarity = table.get_or("lacunarity", 0.5); + + if (frequency != 1) { + let scaleModule = New(); + scaleModule->SetSource(module); + scaleModule->SetScale(frequency); + module = scaleModule; + } + + if (octaves > 1) { + let fractalModule = New(); + fractalModule->SetSource(module); + fractalModule->SetOctaveCount(octaves); + fractalModule->SetLacunarity(lacunarity); + fractalModule->SetGain(persistence); + module = fractalModule; + } + + if (seed != 0) { + let seedOffsetModule = New(); + 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(); + + module->SetSource(parse(table["source"])); + module->SetScale(table.get_or("x_scale", 1)); + module->SetScale(table.get_or("y_scale", 1)); + module->SetScale(table.get_or("z_scale", 1)); + + return module; + } + + throw std::runtime_error("Invalid module name: " + type); } \ No newline at end of file diff --git a/src/lua/NoiseFromLua.h b/src/lua/NoiseFromLua.h index 77370f17..be401a19 100644 --- a/src/lua/NoiseFromLua.h +++ b/src/lua/NoiseFromLua.h @@ -1,35 +1,13 @@ #pragma once -#include +#include "util/Types.h" + #include -#include -#include -#include +#include 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 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& modules, sol::table noise); + /** Builds a FastNoise node tree from a Lua table. */ + FastNoise::SmartNode<> parse(sol::table table); }; diff --git a/src/lua/register/RegisterBiome.h b/src/lua/register/RegisterBiome.h index 32d95ea6..c33e8165 100644 --- a/src/lua/register/RegisterBiome.h +++ b/src/lua/register/RegisterBiome.h @@ -66,21 +66,18 @@ namespace RegisterBiome { if (!biomeTint) throw identifier + "biome definitions require a biome_tint"; // Get noise parameters + let constGenerator = FastNoise::New(); + constGenerator->SetValue(0); + FastNoise::SmartNode<> heightmap = constGenerator, volume = constGenerator; + auto noiseList = biomeTable.get>("noise"); - std::vector volumeModules, heightmapModules; if (noiseList) { - if (noiseList->get>("heightmap")) - NoiseFromLua::parseNoise(heightmapModules, noiseList->get("heightmap")); - else heightmapModules.push_back(new noise::module::Const); + let heightTable = noiseList->get>("heightmap"); + if (heightTable) heightmap = NoiseFromLua::parse(*heightTable); - if (noiseList->get>("volume")) - NoiseFromLua::parseNoise(volumeModules, noiseList->get("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>("volume"); + if (volumeTable) volume = NoiseFromLua::parse(*volumeTable); } std::vector> 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; diff --git a/src/server/stream/ServerGenStream.h b/src/server/stream/ServerGenStream.h index 0d6fe653..0f366843 100644 --- a/src/server/stream/ServerGenStream.h +++ b/src/server/stream/ServerGenStream.h @@ -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 created) : diff --git a/src/util/Space.h b/src/util/Space.h index a458948a..682fe9c2 100644 --- a/src/util/Space.h +++ b/src/util/Space.h @@ -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(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(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(vec.y) * CHUNK_SIZE * CHUNK_SIZE); - vec.z = ind / CHUNK_SIZE; - vec.x = ind % CHUNK_SIZE; - - return vec; + return Space::indexToPos(ind, CHUNK_SIZE); } } } diff --git a/src/util/Types.h b/src/util/Types.h index 0ac13b6f..02a8535e 100644 --- a/src/util/Types.h +++ b/src/util/Types.h @@ -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; diff --git a/src/world/gen/MapGen.cpp b/src/world/gen/MapGen.cpp index 98bdb50b..20c823bb 100644 --- a/src/world/gen/MapGen.cpp +++ b/src/world/gen/MapGen.cpp @@ -26,6 +26,18 @@ MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set } generateVoronoi(biomeIndices); + + let biomePerlin = FastNoise::New(); + + let biomeScale = FastNoise::New(); + biomeScale->SetSource(biomePerlin); + biomeScale->SetScale(1/1000.f); + + let biomeFractal = FastNoise::New(); + biomeFractal->SetSource(biomeScale); + biomeFractal->SetOctaveCount(4); + + biomeGenerator = biomeFractal; } [[maybe_unused]] uptr MapGen::generateChunk(u16 dim, ivec3 pos) { @@ -39,50 +51,29 @@ uptr MapGen::generateMapBlock(u16 dim, ivec3 pos) { std::unique_ptr 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(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 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(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(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(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(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(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(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::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::populateChunkDensity(MapGen::Job& job, ivec3 localPos) { auto data = make_unique(); - + for (u16 i = 0; i < 4096; i++) { ivec3 indPos = Space::Block::fromIndex(i); - vec3 queryPos = (vec3(localPos) + vec3(indPos) / 16.f) / static_cast(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 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 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++) { diff --git a/src/world/gen/MapGen.h b/src/world/gen/MapGen.h index c87bbeeb..9a6ef09a 100644 --- a/src/world/gen/MapGen.h +++ b/src/world/gen/MapGen.h @@ -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, 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 chunks = make_unique(); std::queue 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; diff --git a/src/world/gen/NoiseSample.cpp b/src/world/gen/NoiseSample.cpp index 671b5cc6..e47aea95 100644 --- a/src/world/gen/NoiseSample.cpp +++ b/src/world/gen/NoiseSample.cpp @@ -1,21 +1,57 @@ +#include +#include + #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(precision); + u16vec3 a = u16vec3(glm::floor(frac)) * static_cast(precision); + u16vec3 b = u16vec3(glm::ceil(frac)) * static_cast(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); } -} + } + } +} \ No newline at end of file diff --git a/src/world/gen/NoiseSample.h b/src/world/gen/NoiseSample.h index d05399ef..a9fd233f 100644 --- a/src/world/gen/NoiseSample.h +++ b/src/world/gen/NoiseSample.h @@ -1,54 +1,87 @@ #pragma once #include +#include #include "util/Types.h" #include "util/Interp.h" class NoiseSample { public: - typedef std::function fill_function; + typedef std::function 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(std::ceil(scaled.x)), precision.x), - (std::min)(static_cast(std::ceil(scaled.y)), precision.y), - (std::min)(static_cast(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(std::ceil(scaled.x)), precision.x), +// (std::min)(static_cast(std::ceil(scaled.y)), precision.y), +// (std::min)(static_cast(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(x) * size.x * size.y + y * size.x + z; +// }; + + inline u32 index(u16vec3 pos) { + return index(pos.x, pos.y, pos.z); }; - std::vector data {}; - ivec3 precision {}; - vec3 scaleBy; + inline u32 index(u16 x, u16 y, u16 z) { + return static_cast(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 data {}; }; diff --git a/src/world/player/LocalPlayer.cpp b/src/world/player/LocalPlayer.cpp index e4f787ed..57cc4f47 100644 --- a/src/world/player/LocalPlayer.cpp +++ b/src/world/player/LocalPlayer.cpp @@ -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" diff --git a/subgames/zeus/mods/zeus_inventory/script/menu.lua b/subgames/zeus/mods/zeus_inventory/script/menu.lua index 84b3d64d..bb638fdc 100644 --- a/subgames/zeus/mods/zeus_inventory/script/menu.lua +++ b/subgames/zeus/mods/zeus_inventory/script/menu.lua @@ -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", diff --git a/subgames/zeus/mods/zeus_world/script/biomes/desert.lua b/subgames/zeus/mods/zeus_world/script/biomes/desert.lua index fb393745..eb045dde 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/desert.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/desert.lua @@ -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 + } } } } diff --git a/subgames/zeus/mods/zeus_world/script/biomes/forest.lua b/subgames/zeus/mods/zeus_world/script/biomes/forest.lua index 90ecb500..48b523e1 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/forest.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/forest.lua @@ -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 \ No newline at end of file +-- 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 \ No newline at end of file diff --git a/subgames/zeus/mods/zeus_world/script/biomes/plains.lua b/subgames/zeus/mods/zeus_world/script/biomes/plains.lua index e3e1c60b..9442f181 100644 --- a/subgames/zeus/mods/zeus_world/script/biomes/plains.lua +++ b/subgames/zeus/mods/zeus_world/script/biomes/plains.lua @@ -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 + } } } } diff --git a/subgames/zeus/mods/zeus_world/script/register_biomes.lua b/subgames/zeus/mods/zeus_world/script/register_biomes.lua index d407f5b9..9dd49703 100644 --- a/subgames/zeus/mods/zeus_world/script/register_biomes.lua +++ b/subgames/zeus/mods/zeus_world/script/register_biomes.lua @@ -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") }