#pragma once #include "./Abstract.hpp" #include "../Registry.hpp" namespace world::generator { /// Endless cave network class Cave: public Abstract { private: template inline void generate(const voxel_pos& min, voxels& out) const { constexpr uint32_t LENGTH = 1u << level; constexpr size_t SIZE = glm::pow3(LENGTH); constexpr auto VEC = glm::ivec3(LENGTH); const auto densitySet = density.getRaw(min, VEC); const auto materialSet = material.getRaw(min, VEC); constexpr auto MATERIAL_SKIP = 2; const int materialMax = module::Registry::Get()->getMaterials().names.size() - (MATERIAL_SKIP + 1); out.resize(SIZE); for (size_t i = 0; i < SIZE; i++) { const auto density = std::clamp((densitySet.get()[i] + params.density) * params.granularity, 0.f, 1.f) * Voxel::DENSITY_MAX; const auto material = density > 0 ? MATERIAL_SKIP + std::clamp(static_cast(std::lrint((materialSet.get()[i] + 1) / 2 * materialMax)), 0, materialMax) : 1; //NOTE: map (approx -1, 1) to (1, mat_max) out[i] = Voxel(material, density); } } public: struct Params { Params(int seed = 42, float density = 0, float gran = 30): seed(seed), density(density), granularity(gran) { } /// Random generator start int seed; /// Offset density overrage float density; /// Speed of density change float granularity; }; Cave(const Params p): params(p), density(Noise::SimplexFractal(p.seed)), material(Noise::Cellular(p.seed * 5, .1)) { } void generate5(const voxel_pos& min, voxels& out) override { generate<5>(min, out); } glm::vec3 getGravity(const voxel_pos&) const override { return glm::vec3(-1, 0, 0); } private: Params params; Noise density; Noise material; }; }