1 #include "Generator.hpp"
3 #include "BlockType.hpp"
4 #include "BlockTypeRegistry.hpp"
6 #include "../rand/OctaveNoise.hpp"
16 const BlockType *type;
18 Candidate(const BlockType *type, float threshold)
19 : type(type), threshold(threshold) { }
22 std::vector<Candidate> candidates;
26 Generator::Generator(const Config &config) noexcept
30 , solidity_noise(config.seed ^ config.solidity.seed_mask)
31 , humidity_noise(config.seed ^ config.humidity.seed_mask)
32 , temperature_noise(config.seed ^ config.temperature.seed_mask)
33 , richness_noise(config.seed ^ config.richness.seed_mask)
34 , random_noise(config.seed ^ config.randomness.seed_mask) {
38 void Generator::LoadTypes(const BlockTypeRegistry ®) {
41 for (const BlockType &type : reg) {
43 types.push_back(&type);
44 if (type.min_solidity < min_solidity) {
45 min_solidity = type.min_solidity;
49 candidates.reserve(types.size());
52 void Generator::operator ()(Chunk &chunk) const noexcept {
53 Chunk::Pos pos(chunk.Position());
54 glm::vec3 coords(pos * Chunk::Extent());
55 for (int z = 0; z < Chunk::depth; ++z) {
56 for (int y = 0; y < Chunk::height; ++y) {
57 for (int x = 0; x < Chunk::width; ++x) {
58 Block::Pos block_pos(x, y, z);
59 chunk.SetBlock(block_pos, Generate(coords + block_pos));
66 Block Generator::Generate(const glm::vec3 &pos) const noexcept {
67 float solidity = GetValue(solidity_noise, pos, config.solidity);
68 if (solidity < min_solidity) {
71 float humidity = GetValue(humidity_noise, pos, config.humidity);
72 float temperature = GetValue(temperature_noise, pos, config.temperature);
73 float richness = GetValue(richness_noise, pos, config.richness);
77 for (const BlockType *type : types) {
78 if (solidity < type->min_solidity || solidity > type->max_solidity) continue;
79 if (humidity < type->min_humidity || humidity > type->max_humidity) continue;
80 if (temperature < type->min_temperature || temperature > type->max_temperature) continue;
81 if (richness < type->min_richness || richness > type->max_richness) continue;
82 float solidity_match = 4.0f - ((solidity - type->mid_solidity) * (solidity - type->mid_solidity));
83 float humidity_match = 4.0f - ((humidity - type->mid_humidity) * (humidity - type->mid_humidity));
84 float temperature_match = 4.0f - ((temperature - type->mid_temperature) * (temperature - type->mid_temperature));
85 float richness_match = 4.0f - ((richness - type->mid_richness) * (richness - type->mid_richness));
86 float chance = (solidity_match + humidity_match + temperature_match + richness_match) * type->commonness;
88 candidates.emplace_back(type, total);
90 if (candidates.empty()) {
93 float random = GetValue(random_noise, pos, config.randomness);
94 if (random < 0.0f) random += 1.0f;
95 float value = random * total;
96 // TODO: change to binary search
97 for (const Candidate &cand : candidates) {
98 if (value < cand.threshold) {
99 return Block(cand.type->id);
102 // theoretically, this should never happen
103 return Block(candidates.back().type->id);
106 float Generator::GetValue(
107 const SimplexNoise &noise,
108 const glm::vec3 &pos,
109 const Config::NoiseParam &conf