50 lines
2.0 KiB
C++
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;
|
|
};
|
|
} |