#include "../model/Shape.hpp"
#include <glm/glm.hpp>
+#include <limits>
#include <vector>
// generation properties
/// whether to use this block in generation at all
bool generate;
+
// min/mid/max points for the respective properties
// should all be in the (-1,1) range
- float min_solidity;
- float mid_solidity;
- float max_solidity;
- float min_humidity;
- float mid_humidity;
- float max_humidity;
- float min_temperature;
- float mid_temperature;
- float max_temperature;
- float min_richness;
- float mid_richness;
- float max_richness;
+ class Distribution {
+
+ public:
+ Distribution(float min, float mid, float max)
+ : xmin(min), xmid(mid), xmax(max) { Update(); }
+
+ bool Valid(float x) const noexcept {
+ return x >= xmin && x <= xmax;
+ }
+ float Map(float x) const noexcept {
+ // previous algo as was used by Generator
+ //return 4.0f - ((x - xmid) * (x - xmid));
+
+ // linear mapping of [min,mid,max] to [-1,0,1]
+ x -= xmid;
+ x *= (x < 0) ? inv_neg : inv_pos;
+
+ // smoothing: x^4 - 2x^2 + 1
+ x *= x;
+ return x * x - 2.0f * x + 1.0f;
+ }
+
+ void Min(float m) noexcept { xmin = m; Update(); }
+ float Min() const noexcept { return xmin; }
+ void Mid(float m) noexcept { xmid = m; Update(); }
+ float Mid() const noexcept { return xmid; }
+ void Max(float m) noexcept { xmax = m; Update(); }
+ float Max() const noexcept { return xmax; }
+
+ private:
+ void Update() {
+ float abs_min = std::abs(xmin - xmid);
+ inv_neg = abs_min < std::numeric_limits<float>::epsilon() ? 0.0f : 1.0f / abs_min;
+ float abs_max = std::abs(xmax - xmid);
+ inv_pos = abs_max < std::numeric_limits<float>::epsilon() ? 0.0f : 1.0f / abs_max;
+ }
+
+ float xmin;
+ float xmid;
+ float xmax;
+ float inv_neg;
+ float inv_pos;
+
+ };
+
+ Distribution solidity;
+ Distribution humidity;
+ Distribution temperature;
+ Distribution richness;
/// commonness factor, random chance is multiplied by this
float commonness;
for (const BlockType &type : reg) {
if (type.generate) {
types.push_back(&type);
- if (type.min_solidity < min_solidity) {
- min_solidity = type.min_solidity;
+ if (type.solidity.Min() < min_solidity) {
+ min_solidity = type.solidity.Min();
}
}
}
candidates.clear();
float total = 0.0f;
for (const BlockType *type : types) {
- if (solidity < type->min_solidity || solidity > type->max_solidity) continue;
- if (humidity < type->min_humidity || humidity > type->max_humidity) continue;
- if (temperature < type->min_temperature || temperature > type->max_temperature) continue;
- if (richness < type->min_richness || richness > type->max_richness) continue;
- float solidity_match = 4.0f - ((solidity - type->mid_solidity) * (solidity - type->mid_solidity));
- float humidity_match = 4.0f - ((humidity - type->mid_humidity) * (humidity - type->mid_humidity));
- float temperature_match = 4.0f - ((temperature - type->mid_temperature) * (temperature - type->mid_temperature));
- float richness_match = 4.0f - ((richness - type->mid_richness) * (richness - type->mid_richness));
+ if (!type->solidity.Valid(solidity)) continue;
+ if (!type->humidity.Valid(humidity)) continue;
+ if (!type->temperature.Valid(temperature)) continue;
+ if (!type->richness.Valid(richness)) continue;
+ float solidity_match = type->solidity.Map(solidity);
+ float humidity_match = type->humidity.Map(humidity);
+ float temperature_match = type->temperature.Map(temperature);
+ float richness_match = type->richness.Map(richness);
float chance = (solidity_match + humidity_match + temperature_match + richness_match) * type->commonness;
total += chance;
candidates.emplace_back(type, total);
, collision(true)
, collide_block(true)
, generate(false)
-, min_solidity(0.5f)
-, mid_solidity(0.75f)
-, max_solidity(1.0f)
-, min_humidity(-1.0f)
-, mid_humidity(0.0f)
-, max_humidity(1.0f)
-, min_temperature(-1.0f)
-, mid_temperature(0.0f)
-, max_temperature(1.0f)
-, min_richness(-1.0f)
-, mid_richness(0.0f)
-, max_richness(1.0f)
+, solidity(0.5f, 0.75f, 1.0f)
+, humidity(-1.0f, 0.0f, 1.0f)
+, temperature(-1.0f, 0.0f, 1.0f)
+, richness(-1.0f, 0.0f, 1.0f)
, commonness(1.0f) {
}
collision = other.collision;
collide_block = collide_block;
generate = other.generate;
- min_solidity = other.min_solidity;
- mid_solidity = other.mid_solidity;
- max_solidity = other.max_solidity;
- min_humidity = other.min_humidity;
- mid_humidity = other.mid_humidity;
- max_humidity = other.max_humidity;
- min_temperature = other.min_temperature;
- mid_temperature = other.mid_temperature;
- max_temperature = other.max_temperature;
- min_richness = other.min_richness;
- mid_richness = other.mid_richness;
- max_richness = other.max_richness;
+ solidity = other.solidity;
+ humidity = other.humidity;
+ temperature = other.temperature;
+ richness = other.richness;
commonness = other.commonness;
}
} else if (name == "generate") {
generate = in.GetBool();
} else if (name == "min_solidity") {
- min_solidity = in.GetFloat();
+ solidity.Min(in.GetFloat());
} else if (name == "mid_solidity") {
- mid_solidity = in.GetFloat();
+ solidity.Mid(in.GetFloat());
} else if (name == "max_solidity") {
- max_solidity = in.GetFloat();
+ solidity.Max(in.GetFloat());
} else if (name == "min_humidity") {
- min_humidity = in.GetFloat();
+ humidity.Min(in.GetFloat());
} else if (name == "mid_humidity") {
- mid_humidity = in.GetFloat();
+ humidity.Mid(in.GetFloat());
} else if (name == "max_humidity") {
- max_humidity = in.GetFloat();
+ humidity.Max(in.GetFloat());
} else if (name == "min_temperature") {
- min_temperature = in.GetFloat();
+ temperature.Min(in.GetFloat());
} else if (name == "mid_temperature") {
- mid_temperature = in.GetFloat();
+ temperature.Mid(in.GetFloat());
} else if (name == "max_temperature") {
- max_temperature = in.GetFloat();
+ temperature.Max(in.GetFloat());
} else if (name == "min_richness") {
- min_richness = in.GetFloat();
+ richness.Min(in.GetFloat());
} else if (name == "mid_richness") {
- mid_richness = in.GetFloat();
+ richness.Mid(in.GetFloat());
} else if (name == "max_richness") {
- max_richness = in.GetFloat();
+ richness.Max(in.GetFloat());
} else if (name == "commonness") {
commonness = in.GetFloat();
} else if (name == "shape") {