]> git.localhorst.tv Git - blank.git/commitdiff
smoother type selection during chunk generation
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 23 Dec 2015 12:31:47 +0000 (13:31 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 23 Dec 2015 12:31:47 +0000 (13:31 +0100)
Makefile
src/world/BlockType.hpp
src/world/Generator.cpp
src/world/block.cpp

index 42300ac6715eb1979460fb9b2fc4cdf418901872..156d5cb20d9dd64b0b64548b98b810e556cf23d6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,7 @@ CPPFLAGS ?=
 CPPFLAGS += $(PKGFLAGS)
 CXXFLAGS ?=
 CXXFLAGS += -Wall
+#CXXFLAGS += -march=native
 LDXXFLAGS ?=
 LDXXFLAGS += $(PKGLIBS)
 
index 3ca170a200ba65367ff604bfbada3645456714b1..f1b887d3eabc56e998fd64917c8a661df9df52b9 100644 (file)
@@ -9,6 +9,7 @@
 #include "../model/Shape.hpp"
 
 #include <glm/glm.hpp>
+#include <limits>
 #include <vector>
 
 
@@ -58,20 +59,58 @@ struct BlockType {
        // 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;
 
index b6d53ae4cf895c189941117bd1e7a9cab7638030..fa6e01e5920ed72a698d67c2ff7e60bc2cb4518b 100644 (file)
@@ -41,8 +41,8 @@ void Generator::LoadTypes(const BlockTypeRegistry &reg) {
        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();
                        }
                }
        }
@@ -160,14 +160,14 @@ Block Generator::Generate(const ValueField &field, const glm::ivec3 &pos) const
        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);
index f518b64aeabc96ad4a7cc8d8313582cb64348f8f..b0fdf61d71aee0a35adbfa9c82d5816b20fc4c0e 100644 (file)
@@ -89,18 +89,10 @@ BlockType::BlockType() noexcept
 , 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) {
 
 }
@@ -119,18 +111,10 @@ void BlockType::Copy(const BlockType &other) noexcept {
        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;
 }
 
@@ -193,29 +177,29 @@ void BlockType::Read(
                } 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") {