From: Daniel Karbach Date: Wed, 23 Dec 2015 12:31:47 +0000 (+0100) Subject: smoother type selection during chunk generation X-Git-Url: http://git.localhorst.tv/?p=blank.git;a=commitdiff_plain;h=fda38181732e58537331c919dd699eaa830ead50 smoother type selection during chunk generation --- diff --git a/Makefile b/Makefile index 42300ac..156d5cb 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ CPPFLAGS ?= CPPFLAGS += $(PKGFLAGS) CXXFLAGS ?= CXXFLAGS += -Wall +#CXXFLAGS += -march=native LDXXFLAGS ?= LDXXFLAGS += $(PKGLIBS) diff --git a/src/world/BlockType.hpp b/src/world/BlockType.hpp index 3ca170a..f1b887d 100644 --- a/src/world/BlockType.hpp +++ b/src/world/BlockType.hpp @@ -9,6 +9,7 @@ #include "../model/Shape.hpp" #include +#include #include @@ -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::epsilon() ? 0.0f : 1.0f / abs_min; + float abs_max = std::abs(xmax - xmid); + inv_pos = abs_max < std::numeric_limits::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; diff --git a/src/world/Generator.cpp b/src/world/Generator.cpp index b6d53ae..fa6e01e 100644 --- a/src/world/Generator.cpp +++ b/src/world/Generator.cpp @@ -41,8 +41,8 @@ void Generator::LoadTypes(const BlockTypeRegistry ®) { 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); diff --git a/src/world/block.cpp b/src/world/block.cpp index f518b64..b0fdf61 100644 --- a/src/world/block.cpp +++ b/src/world/block.cpp @@ -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") {