1
0
Fork 0
Univerxel/src/core/world/generator/Cave.hpp

50 lines
2.0 KiB
C++

#pragma once
#include "./Abstract.hpp"
#include "../Registry.hpp"
namespace world::generator {
/// Endless cave network
class Cave: public Abstract {
private:
template<uint32_t level>
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<int>(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;
};
}