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, const BlockTypeRegistry &types) noexcept
29 , solidity_noise(config.seed ^ config.solidity.seed_mask)
30 , humidity_noise(config.seed ^ config.humidity.seed_mask)
31 , temperature_noise(config.seed ^ config.temperature.seed_mask)
32 , richness_noise(config.seed ^ config.richness.seed_mask)
33 , random_noise(config.seed ^ config.randomness.seed_mask) {
37 void Generator::Scan() {
39 for (size_t i = 0, end = types.Size(); i < end; ++i) {
40 if (types[i].generate) ++count;
42 candidates.reserve(count);
45 void Generator::operator ()(Chunk &chunk) const noexcept {
46 Chunk::Pos pos(chunk.Position());
47 glm::vec3 coords(pos * Chunk::Extent());
48 for (int z = 0; z < Chunk::depth; ++z) {
49 for (int y = 0; y < Chunk::height; ++y) {
50 for (int x = 0; x < Chunk::width; ++x) {
51 Block::Pos block_pos(x, y, z);
52 chunk.SetBlock(block_pos, Generate(coords + block_pos));
58 Block Generator::Generate(const glm::vec3 &pos) const noexcept {
59 float solidity = GetValue(solidity_noise, pos, config.solidity);
60 float humidity = GetValue(humidity_noise, pos, config.humidity);
61 float temperature = GetValue(temperature_noise, pos, config.temperature);
62 float richness = GetValue(richness_noise, pos, config.richness);
66 for (size_t i = 0, end = types.Size(); i < end; ++i) {
67 const BlockType &type = types[i];
68 if (!type.generate) continue;
69 if (solidity < type.min_solidity || solidity > type.max_solidity) continue;
70 if (humidity < type.min_humidity || humidity > type.max_humidity) continue;
71 if (temperature < type.min_temperature || temperature > type.max_temperature) continue;
72 if (richness < type.min_richness || richness > type.max_richness) continue;
73 float solidity_match = 4.0f - ((solidity - type.mid_solidity) * (solidity - type.mid_solidity));
74 float humidity_match = 4.0f - ((humidity - type.mid_humidity) * (humidity - type.mid_humidity));
75 float temperature_match = 4.0f - ((temperature - type.mid_temperature) * (temperature - type.mid_temperature));
76 float richness_match = 4.0f - ((richness - type.mid_richness) * (richness - type.mid_richness));
77 float chance = (solidity_match + humidity_match + temperature_match + richness_match) * type.commonness;
79 candidates.emplace_back(&type, total);
81 if (candidates.empty()) {
84 float random = GetValue(random_noise, pos, config.randomness);
85 if (random < 0.0f) random += 1.0f;
86 float value = random * total;
87 // TODO: change to binary search
88 for (const Candidate &cand : candidates) {
89 if (value < cand.threshold) {
90 return Block(cand.type->id);
93 // theoretically, this should never happen
94 return Block(candidates.back().type->id);
97 float Generator::GetValue(
98 const SimplexNoise &noise,
100 const Config::NoiseParam &conf