]> git.localhorst.tv Git - blobs.git/commitdiff
randomize creature properties a bit
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 26 Nov 2017 17:29:12 +0000 (18:29 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 26 Nov 2017 17:29:12 +0000 (18:29 +0100)
53 files changed:
assets
src/app/Assets.hpp
src/app/app.cpp
src/blobs.cpp
src/const.hpp [deleted file]
src/creature/Creature.hpp
src/creature/Genome.hpp [new file with mode: 0644]
src/creature/LocateResourceGoal.hpp
src/creature/Situation.hpp
src/creature/Steering.hpp
src/creature/creature.cpp
src/graphics/AlphaSprite.hpp
src/graphics/Camera.hpp
src/graphics/Canvas.hpp
src/graphics/CreatureSkin.hpp
src/graphics/Font.hpp
src/graphics/PlanetSurface.hpp
src/graphics/Program.hpp
src/graphics/SunSurface.hpp
src/graphics/gl_traits.hpp
src/graphics/glm.hpp [deleted file]
src/graphics/viewport.cpp
src/io/TokenStreamReader.hpp
src/math/Distribution.hpp [new file with mode: 0644]
src/math/GaloisLFSR.hpp [new file with mode: 0644]
src/math/OctaveNoise.hpp [new file with mode: 0644]
src/math/SimplexNoise.hpp [new file with mode: 0644]
src/math/WorleyNoise.hpp [new file with mode: 0644]
src/math/const.hpp [new file with mode: 0644]
src/math/glm.hpp [new file with mode: 0644]
src/math/noise.cpp [new file with mode: 0644]
src/rand/GaloisLFSR.hpp [deleted file]
src/rand/OctaveNoise.hpp [deleted file]
src/rand/SimplexNoise.hpp [deleted file]
src/rand/WorleyNoise.hpp [deleted file]
src/rand/noise.cpp [deleted file]
src/ui/Widget.hpp
src/ui/align.hpp
src/world/Body.hpp
src/world/Orbit.hpp
src/world/Planet.hpp
src/world/Resource.hpp
src/world/world.cpp
tst/assert.hpp
tst/math/GaloisLFSRTest.cpp [new file with mode: 0644]
tst/math/GaloisLFSRTest.hpp [new file with mode: 0644]
tst/math/StabilityTest.cpp [new file with mode: 0644]
tst/math/StabilityTest.hpp [new file with mode: 0644]
tst/rand/GaloisLFSRTest.cpp [deleted file]
tst/rand/GaloisLFSRTest.hpp [deleted file]
tst/rand/StabilityTest.cpp [deleted file]
tst/rand/StabilityTest.hpp [deleted file]
tst/world/OrbitTest.cpp

diff --git a/assets b/assets
index ce337a6b5afd87607a94f006631a390eefceeec1..7703c130c0be3b33f4f267d2662f36b999826f33 160000 (submodule)
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit ce337a6b5afd87607a94f006631a390eefceeec1
+Subproject commit 7703c130c0be3b33f4f267d2662f36b999826f33
index 22b60878da42ed6663d5735fa338b13e8f71d061..5f971c689ddba201d7cbc700a6b1c1e79c975692 100644 (file)
@@ -8,6 +8,7 @@
 #include "../graphics/Font.hpp"
 #include "../graphics/PlanetSurface.hpp"
 #include "../graphics/SunSurface.hpp"
+#include "../math/GaloisLFSR.hpp"
 #include "../world/Resource.hpp"
 #include "../world/Set.hpp"
 #include "../world/TileType.hpp"
@@ -29,6 +30,8 @@ struct Assets {
        std::string skin_path;
        std::string tile_path;
 
+       math::GaloisLFSR random;
+
        struct {
                world::Set<world::Resource> resources;
                world::Set<world::TileType> tile_types;
index e4dc1a58eef0de9166254142f5ea19073810c9e3..5a4cd67e0c2f1f0fee3275239b61b3af43fa9bac 100644 (file)
@@ -176,6 +176,7 @@ Assets::Assets()
 , font_path(path + "fonts/")
 , skin_path(path + "skins/")
 , tile_path(path + "tiles/")
+, random(0)
 , fonts{
        graphics::Font(font_path + "DejaVuSans.ttf", 32),
        graphics::Font(font_path + "DejaVuSans.ttf", 24),
@@ -251,6 +252,8 @@ void Assets::ReadResources(io::TokenStreamReader &in) {
                        in.Skip(io::Token::EQUALS);
                        if (name == "label") {
                                in.ReadString(data.resources[id].label);
+                       } else if (name == "density") {
+                               data.resources[id].density = in.GetDouble();
                        } else if (name == "state") {
                                in.ReadIdentifier(name);
                                if (name == "solid") {
index 006644b4342f9309342018c885508cd072519562..b32c4ab22e31a463c2f90e250bff482cd32172f5 100644 (file)
@@ -1,9 +1,9 @@
-#include "const.hpp"
 #include "app/Application.hpp"
 #include "app/Assets.hpp"
 #include "app/init.hpp"
 #include "app/MasterState.hpp"
 #include "creature/Creature.hpp"
+#include "math/const.hpp"
 #include "world/Planet.hpp"
 #include "world/Set.hpp"
 #include "world/Simulation.hpp"
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
                // sunset
                //.FirstPerson(3, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
                // from afar
-               .MapView(0, glm::vec3(0.0f, 0.0f, 31.0f), 0.0f)
+               .MapView(0, glm::vec3(0.0f, 0.0f, 10.0f), 0.0f)
                // from afar, rotating
                //.Orbital(glm::vec3(-60.0f, 0.0f, 0.0f))
        ;
diff --git a/src/const.hpp b/src/const.hpp
deleted file mode 100644 (file)
index edbbe7c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef BLOBS_CONST_HPP_
-#define BLOBS_CONST_HPP_
-
-
-namespace blobs {
-
-constexpr double PI = 3.141592653589793238462643383279502884;
-constexpr double PI_0p25 = PI * 0.25;
-constexpr double PI_0p5 = PI * 0.5;
-constexpr double PI_1p5 = PI * 1.5;
-constexpr double PI_2p0 = PI * 2.0;
-
-constexpr double PI_inv = 1.0 / PI;
-constexpr double PI_0p5_inv = 1.0 / PI_0p5;
-
-constexpr double G = 6.674e-11; // m³kg¯¹s¯²
-
-}
-
-#endif
index ce56dfbd56b072bd0bff1c62a1efebf09f423c7f..2a40d510407e4ff791a3e16c3d9b718066ca2d93 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef BLOBS_CREATURE_CREATURE_HPP_
 #define BLOBS_CREATURE_CREATURE_HPP_
 
+#include "Genome.hpp"
 #include "Goal.hpp"
 #include "Need.hpp"
 #include "Situation.hpp"
 #include "Steering.hpp"
-#include "../graphics/glm.hpp"
 #include "../graphics/SimpleVAO.hpp"
+#include "../math/glm.hpp"
 
 #include <memory>
 #include <string>
@@ -46,6 +47,12 @@ public:
        void Name(const std::string &n) noexcept { name = n; }
        const std::string &Name() const noexcept { return name; }
 
+       Genome &GetGenome() noexcept { return genome; }
+       const Genome &GetGenome() const noexcept { return genome; }
+
+       void Mass(double m) noexcept { mass = m; }
+       double Mass() const noexcept { return mass; }
+
        void Size(double s) noexcept { size = s; }
        double Size() const noexcept { return size; }
 
@@ -69,7 +76,7 @@ public:
 
        void Velocity(const glm::dvec3 &v) noexcept { vel = v; }
        const glm::dvec3 &Velocity() const noexcept { return vel; }
-       bool Moving() const noexcept { return !allzero(vel); }
+       bool Moving() const noexcept { return glm::length2(vel) < 0.000001; }
 
        glm::dmat4 LocalTransform() noexcept;
 
@@ -79,6 +86,10 @@ public:
 private:
        world::Simulation &sim;
        std::string name;
+
+       Genome genome;
+
+       double mass;
        double size;
        double health;
 
diff --git a/src/creature/Genome.hpp b/src/creature/Genome.hpp
new file mode 100644 (file)
index 0000000..4437150
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef BLOBS_CREATURE_GENOME_HPP_
+#define BLOBS_CREATURE_GENOME_HPP_
+
+#include "../math/Distribution.hpp"
+
+#include <vector>
+
+
+namespace blobs {
+namespace app {
+       struct Assets;
+}
+namespace creature {
+
+class Creature;
+
+struct Genome {
+
+       struct Composition {
+               // which resource
+               int resource;
+               // how much contained in the body
+               math::Distribution mass;
+               // how much to circulate
+               math::Distribution intake;
+               // how important for alive-being
+               math::Distribution penalty;
+       };
+       std::vector<Composition> composition;
+
+       void Configure(app::Assets &, Creature &) const;
+
+};
+
+}
+}
+
+#endif
index afa5b93d00ee6ef8d0b364cd4988c03d716803f1..a472fd5f9f16f8dc9864c9eb59b473b2d3df3e04 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_CREATURE_LOCATERESOURCEGOAL_HPP_
 #define BLOBS_CREATURE_LOCATERESOURCEGOAL_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 12b7490914783c6aac2bb9219d0bcd2f2f9c9c82..d421b690d694eb8fb0bac7d77c21bf87fccec57d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_CREATURE_SITUATION_HPP_
 #define BLOBS_CREATURE_SITUATION_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 6d5b40a2103e3d98cb8039c6010ac75e6fc85339..51f2c63db710bc098d689f540ef00801a050cadb 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_CREATURE_STEERING_HPP_
 #define BLOBS_CREATURE_STEERING_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 043aed7353cd66d4c2d6fbfff8eaf8e830f25031..0f25da8ab5bed76b10a28a2b821abf396023e61a 100644 (file)
@@ -1,4 +1,5 @@
 #include "Creature.hpp"
+#include "Genome.hpp"
 #include "Situation.hpp"
 #include "Steering.hpp"
 
@@ -25,6 +26,8 @@ namespace creature {
 Creature::Creature(world::Simulation &sim)
 : sim(sim)
 , name()
+, genome()
+, mass(1.0)
 , size(1.0)
 , health(1.0)
 , needs()
@@ -195,7 +198,6 @@ void Creature::Draw(app::Assets &assets, graphics::Viewport &viewport) {
 void Spawn(Creature &c, world::Planet &p, app::Assets &assets) {
        p.AddCreature(&c);
        c.GetSituation().SetPlanetSurface(p, 0, p.TileCenter(0, p.SideLength() / 2, p.SideLength() / 2));
-       c.Size(0.5);
 
        // probe surrounding area for common resources
        int start = p.SideLength() / 2 - 2;
@@ -223,33 +225,67 @@ void Spawn(Creature &c, world::Planet &p, app::Assets &assets) {
                }
        }
 
+       Genome genome;
        if (p.HasAtmosphere()) {
-               std::cout << "require breathing " << assets.data.resources[p.Atmosphere()].label << std::endl;
-               std::unique_ptr<Need> need(new InhaleNeed(p.Atmosphere(), 0.5, 0.1));
-               need->name = assets.data.resources[p.Atmosphere()].label;
-               need->gain = 0.2;
-               need->inconvenient = 0.4;
-               need->critical = 0.95;
-               c.AddNeed(std::move(need));
+               genome.composition.push_back({
+                       p.Atmosphere(),    // resource
+                       { 0.01, 0.00001 }, // mass
+                       { 0.5,  0.001 },   // intake
+                       { 0.1,  0.0005 }   // penalty
+               });
        }
        if (liquid > -1) {
-               std::cout << "require drinking " << assets.data.resources[liquid].label << std::endl;
-               std::unique_ptr<Need> need(new IngestNeed(liquid, 0.2, 0.01));
-               need->name = assets.data.resources[liquid].label;
-               need->gain = 0.02;
-               need->inconvenient = 0.6;
-               need->critical = 0.95;
-               c.AddNeed(std::move(need));
+               genome.composition.push_back({
+                       liquid,          // resource
+                       { 0.6,  0.01 },  // mass
+                       { 0.2,  0.001 }, // intake
+                       { 0.01, 0.002 }  // penalty
+               });
        }
        if (solid > -1) {
-               std::cout << "require eating " << assets.data.resources[solid].label << std::endl;
-               std::unique_ptr<Need> need(new IngestNeed(solid, 0.1, 0.001));
-               need->name = assets.data.resources[solid].label;
-               need->gain = 0.017;
-               need->inconvenient = 0.6;
+               genome.composition.push_back({
+                       solid,           // resource
+                       { 0.4,   0.01 },  // mass
+                       { 0.1,   0.001 }, // intake
+                       { 0.001, 0.0001 } // penalty
+               });
+       }
+
+       genome.Configure(assets, c);
+       c.GetSteering().MaxAcceleration(1.4);
+       c.GetSteering().MaxSpeed(4.4);
+}
+
+void Genome::Configure(app::Assets &assets, Creature &c) const {
+       c.GetGenome() = *this;
+       double mass = 0.0;
+       double volume = 0.0;
+       for (const auto &comp : composition) {
+               double comp_mass = comp.mass.FakeNormal(assets.random.SNorm());
+               double intake = comp.intake.FakeNormal(assets.random.SNorm());
+               double penalty = comp.intake.FakeNormal(assets.random.SNorm());
+
+               mass += comp_mass;
+               volume += comp_mass / assets.data.resources[comp.resource].density;
+
+               std::unique_ptr<Need> need;
+               if (assets.data.resources[comp.resource].state == world::Resource::SOLID) {
+                       need.reset(new IngestNeed(comp.resource, intake, penalty));
+                       need->gain = intake * 0.05;
+               } else if (assets.data.resources[comp.resource].state == world::Resource::LIQUID) {
+                       need.reset(new IngestNeed(comp.resource, intake, penalty));
+                       need->gain = intake * 0.1;
+               } else {
+                       need.reset(new InhaleNeed(comp.resource, intake, penalty));
+                       need->gain = intake * 0.5;
+               }
+               need->name = assets.data.resources[comp.resource].label;
+               need->inconvenient = 0.5;
                need->critical = 0.95;
                c.AddNeed(std::move(need));
        }
+       c.Mass(mass);
+       c.Size(std::cbrt(volume));
 }
 
 Situation::Situation()
index 3cc6a83a849ba948ebff81485534614d2946a506..c62150de5ab58ebbb2f7d8b3cfd6d00153fe9c2e 100644 (file)
@@ -4,8 +4,6 @@
 #include "Program.hpp"
 #include "SimpleVAO.hpp"
 
-#include "glm.hpp"
-
 #include <cstdint>
 
 
index f4a98d50cc0eefe80d5294f6f3c0c934c97c0377..51dd8f15c447e1a67731b816b78f7211f251179d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_GRAPHICS_CAMERA_HPP_
 #define BLOBS_GRAPHICS_CAMERA_HPP_
 
-#include "glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index bc2a47af4b815d7fe6f9797499c3389a65b0caa6..4e924f115ab24deb03ba60ed9fb8271179096b9c 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef BLOBS_GRAPHICS_CANVAS_HPP_
 #define BLOBS_GRAPHICS_CANVAS_HPP_
 
-#include "glm.hpp"
 #include "Program.hpp"
 #include "SimpleVAO.hpp"
+#include "../math/glm.hpp"
 
 #include <cstdint>
 
index 0d83563b2e4f35c8575389fdeadf6b6c2509a7cf..1b5b6b8bc47ae4dd625f0818dff28e2d5539b8e6 100644 (file)
@@ -3,8 +3,6 @@
 
 #include "Program.hpp"
 
-#include "glm.hpp"
-
 
 namespace blobs {
 namespace graphics {
index 6088d95b70a96f609899596ff2a8d6e84e5dd9cc..d7aa4fadeccc884797b87e030ab2e321fe634351 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_GRAPHICS_FONT_HPP_
 #define BLOBS_GRAPHICS_FONT_HPP_
 
-#include "glm.hpp"
+#include "../math/glm.hpp"
 
 #include <string>
 #include <SDL_ttf.h>
index 178fcabac98123ad6914a8e01b45e9079f3cac4b..a5f177da14e3a81a8b91deda99f2762ca1978040 100644 (file)
@@ -3,8 +3,6 @@
 
 #include "Program.hpp"
 
-#include "glm.hpp"
-
 
 namespace blobs {
 namespace graphics {
index 2add96c290066027544b48afb44a159b74df7b13..d06897231247b1f71bd9d64fe4b460772a3df248 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_GRAPHICS_PROGRAM_HPP_
 #define BLOBS_GRAPHICS_PROGRAM_HPP_
 
-#include "glm.hpp"
+#include "../math/glm.hpp"
 
 #include <iosfwd>
 #include <list>
index b5a056be3fe14dec0e69be7bc03d02ccbe207477..65727617996fc12212b7aa4a433fd75e0f314070 100644 (file)
@@ -4,8 +4,6 @@
 #include "Program.hpp"
 #include "SimpleVAO.hpp"
 
-#include "glm.hpp"
-
 #include <cstdint>
 
 
index a399893a17ab6c363c05c75bdc2380f5999f7a38..33b00690243faf2294cfe9c43115e63241b2bd29 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_GRAPHICS_GL_TRAITS_HPP_
 #define BLOBS_GRAPHICS_GL_TRAITS_HPP_
 
-#include "glm.hpp"
+#include "../math/glm.hpp"
 
 #include <GL/glew.h>
 
diff --git a/src/graphics/glm.hpp b/src/graphics/glm.hpp
deleted file mode 100644 (file)
index 8003f0b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef BLOBS_GRAPHICS_GLM_HPP_
-#define BLOBS_GRAPHICS_GLM_HPP_
-
-#ifndef GLM_FORCE_RADIANS
-#  define GLM_FORCE_RADIANS 1
-#endif
-
-#include <limits>
-#include <glm/glm.hpp>
-#include <glm/gtx/norm.hpp>
-#include <glm/gtx/component_wise.hpp>
-
-// GLM moved tvec[1234] from glm::detail to glm in 0.9.6
-
-#if GLM_VERSION < 96
-
-namespace glm {
-       using tvec1 = detail::tvec1;
-       using tvec2 = detail::tvec2;
-       using tvec3 = detail::tvec3;
-       using tvec4 = detail::tvec4;
-}
-
-#endif
-
-template <class T>
-inline bool allzero(const T &v) noexcept {
-       return glm::length2(v) <
-               std::numeric_limits<typename T::value_type>::epsilon()
-               * std::numeric_limits<typename T::value_type>::epsilon();
-}
-
-template <class T>
-inline bool anynan(const T &v) noexcept {
-       return glm::any(glm::isnan(v));
-}
-
-
-#endif
index 636f3c35c1015f9cc9612ef9d62c4f592d740692..ac0b9e5c5b7c1516ea2795f615f581bc50861c4a 100644 (file)
@@ -1,7 +1,7 @@
 #include "Camera.hpp"
 #include "Viewport.hpp"
 
-#include "../const.hpp"
+#include "../math/const.hpp"
 #include "../world/Body.hpp"
 
 #include <cmath>
index c9043d181b52ee477741d5c385105b1efec92f0f..ccdad90a376c66f321d08b3d92ead3bb8bd404b9 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "Token.hpp"
 #include "Tokenizer.hpp"
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 #include <iosfwd>
 #include <string>
diff --git a/src/math/Distribution.hpp b/src/math/Distribution.hpp
new file mode 100644 (file)
index 0000000..7f444f8
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef BLOBS_MATH_DISTRIBUTION_HPP_
+#define BLOBS_MATH_DISTRIBUTION_HPP_
+
+#include <cmath>
+
+
+namespace blobs {
+namespace math {
+
+class Distribution {
+
+public:
+       Distribution(double mean = 0.0, double stddev = 1.0) noexcept
+       : mean(mean)
+       , stddev(stddev)
+       { }
+
+public:
+       double Mean() const noexcept { return mean; }
+       double StandardDeviation() const noexcept { return stddev; }
+       double Variance() const noexcept { return stddev * stddev; }
+
+       /// convert uniform random value in [-1,1] to fake normal distribution
+       /// in [mean - 2 stdddev,mean + 2 stddev]
+       double FakeNormal(double uniform) const noexcept {
+               return mean + (uniform * uniform * stddev) + std::abs(uniform * uniform * uniform) * stddev;
+       }
+
+private:
+       double mean;
+       double stddev;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/math/GaloisLFSR.hpp b/src/math/GaloisLFSR.hpp
new file mode 100644 (file)
index 0000000..592c9af
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BLOBS_MATH_GALOISLFSR_HPP_
+#define BLOBS_MATH_GALOISLFSR_HPP_
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+
+
+namespace blobs {
+namespace math {
+
+class GaloisLFSR {
+
+public:
+       // seed should be non-zero
+       explicit GaloisLFSR(std::uint64_t seed) noexcept
+       : state(seed) {
+               if (state == 0) {
+                       state = 1;
+               }
+       }
+
+       // get the next bit
+       bool operator ()() noexcept {
+               bool result = state & 1;
+               state >>= 1;
+               if (result) {
+                       state |= 0x8000000000000000;
+                       state ^= mask;
+               } else {
+                       state &= 0x7FFFFFFFFFFFFFFF;
+               }
+               return result;
+       }
+
+       template<class T>
+       T operator ()(T &out) noexcept {
+               constexpr int num_bits =
+                       std::numeric_limits<T>::digits +
+                       std::numeric_limits<T>::is_signed;
+               for (int i = 0; i < num_bits; ++i) {
+                       operator ()();
+               }
+               return out = static_cast<T>(state);
+       }
+
+       /// special case for randrom(boolean), since static_cast<bool>(0b10) == true
+       bool operator ()(bool &out) noexcept {
+               return out = operator ()();
+       }
+
+       template<class T>
+       T Next() noexcept {
+               T next;
+               return (*this)(next);
+       }
+
+       double SNorm() noexcept {
+               return 2.0 * UNorm() - 1.0;
+       }
+
+       double UNorm() noexcept {
+               return double(Next<std::uint64_t>()) * (1.0 / double(std::numeric_limits<std::uint64_t>::max()));
+       }
+
+       template<class Container>
+       typename Container::reference From(Container &c) {
+               assert(c.size() > 0);
+               return c[Next<typename Container::size_type>() % c.size()];
+       }
+       template<class Container>
+       typename Container::const_reference From(const Container &c) {
+               assert(c.size() > 0);
+               return c[Next<typename Container::size_type>() % c.size()];
+       }
+
+private:
+       std::uint64_t state;
+       // bits 64, 63, 61, and 60 set to 1 (counting from 1 lo to hi)
+       static constexpr std::uint64_t mask = 0xD800000000000000;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/math/OctaveNoise.hpp b/src/math/OctaveNoise.hpp
new file mode 100644 (file)
index 0000000..1b2419e
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef BLOBS_MATH_OCTAVENOISE_HPP_
+#define BLOBS_MATH_OCTAVENOISE_HPP_
+
+#include "glm.hpp"
+
+
+namespace blobs {
+namespace math {
+
+template<class Noise>
+float OctaveNoise(
+       const Noise &noise,
+       const glm::vec3 &in,
+       int num,
+       float persistence,
+       float frequency = 1.0f,
+       float amplitude = 1.0f,
+       float growth = 2.0f
+) {
+       float total = 0.0f;
+       float max = 0.0f;
+       for (int i = 0; i < num; ++i) {
+               total += noise(in * frequency) * amplitude;
+               max += amplitude;
+               amplitude *= persistence;
+               frequency *= growth;
+       }
+
+       return total / max;
+}
+
+}
+}
+
+#endif
diff --git a/src/math/SimplexNoise.hpp b/src/math/SimplexNoise.hpp
new file mode 100644 (file)
index 0000000..cb9f07c
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef BLOBS_MATH_SIMPLEXNOISE_HPP_
+#define BLOBS_MATH_SIMPLEXNOISE_HPP_
+
+#include "glm.hpp"
+
+#include <cstdint>
+
+
+namespace blobs {
+namespace math {
+
+class SimplexNoise {
+
+public:
+       explicit SimplexNoise(std::uint64_t seed) noexcept;
+
+       float operator ()(const glm::vec3 &) const noexcept;
+
+private:
+       int Perm(int idx) const noexcept;
+       int Perm12(int idx) const noexcept;
+       const glm::vec3 &Grad(int idx) const noexcept;
+
+private:
+       int perm[512];
+       int perm12[512];
+       glm::vec3 grad[12];
+       glm::ivec3 second_ints[8];
+       glm::ivec3 third_ints[8];
+       glm::vec3 second_floats[8];
+       glm::vec3 third_floats[8];
+
+};
+
+}
+}
+
+#endif
diff --git a/src/math/WorleyNoise.hpp b/src/math/WorleyNoise.hpp
new file mode 100644 (file)
index 0000000..f585496
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef BLOBS_MATH_WORLEYNOISE_HPP_
+#define BLOBS_MATH_WORLEYNOISE_HPP_
+
+#include "glm.hpp"
+
+
+namespace blobs {
+namespace math {
+
+/// implementation of Worley noise (aka Cell or Voroni noise)
+class WorleyNoise {
+
+public:
+       explicit WorleyNoise(unsigned int seed) noexcept;
+
+       float operator ()(const glm::vec3 &) const noexcept;
+
+private:
+       const unsigned int seed;
+       const int num_points;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/math/const.hpp b/src/math/const.hpp
new file mode 100644 (file)
index 0000000..082cca1
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef BLOBS_MATH_CONST_HPP_
+#define BLOBS_MATH_CONST_HPP_
+
+
+namespace blobs {
+
+constexpr double PI = 3.141592653589793238462643383279502884;
+constexpr double PI_0p25 = PI * 0.25;
+constexpr double PI_0p5 = PI * 0.5;
+constexpr double PI_1p5 = PI * 1.5;
+constexpr double PI_2p0 = PI * 2.0;
+
+constexpr double PI_inv = 1.0 / PI;
+constexpr double PI_0p5_inv = 1.0 / PI_0p5;
+
+/// gravitational constant
+constexpr double G = 6.674e-11; // m³kg¯¹s¯²
+
+}
+
+#endif
diff --git a/src/math/glm.hpp b/src/math/glm.hpp
new file mode 100644 (file)
index 0000000..4b1bf33
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef BLOBS_MATH_GLM_HPP_
+#define BLOBS_MATH_GLM_HPP_
+
+#ifndef GLM_FORCE_RADIANS
+#  define GLM_FORCE_RADIANS 1
+#endif
+
+#include <limits>
+#include <glm/glm.hpp>
+#include <glm/gtx/norm.hpp>
+#include <glm/gtx/component_wise.hpp>
+
+// GLM moved tvec[1234] from glm::detail to glm in 0.9.6
+
+#if GLM_VERSION < 96
+
+namespace glm {
+       using tvec1 = detail::tvec1;
+       using tvec2 = detail::tvec2;
+       using tvec3 = detail::tvec3;
+       using tvec4 = detail::tvec4;
+}
+
+#endif
+
+template <class T>
+inline bool allzero(const T &v) noexcept {
+       return glm::length2(v) <
+               std::numeric_limits<typename T::value_type>::epsilon()
+               * std::numeric_limits<typename T::value_type>::epsilon();
+}
+
+template <class T>
+inline bool anynan(const T &v) noexcept {
+       return glm::any(glm::isnan(v));
+}
+
+
+#endif
diff --git a/src/math/noise.cpp b/src/math/noise.cpp
new file mode 100644 (file)
index 0000000..5c6f72d
--- /dev/null
@@ -0,0 +1,212 @@
+#include "GaloisLFSR.hpp"
+#include "SimplexNoise.hpp"
+#include "WorleyNoise.hpp"
+
+#include <cmath>
+#include <glm/gtx/norm.hpp>
+
+
+namespace {
+
+constexpr float one_third = 1.0f/3.0f;
+constexpr float one_sixth = 1.0f/6.0f;
+
+}
+
+namespace blobs {
+namespace math {
+
+SimplexNoise::SimplexNoise(std::uint64_t seed) noexcept
+: grad({
+       {  1.0f,  1.0f,  0.0f },
+       { -1.0f,  1.0f,  0.0f },
+       {  1.0f, -1.0f,  0.0f },
+       { -1.0f, -1.0f,  0.0f },
+       {  1.0f,  0.0f,  1.0f },
+       { -1.0f,  0.0f,  1.0f },
+       {  1.0f,  0.0f, -1.0f },
+       { -1.0f,  0.0f, -1.0f },
+       {  0.0f,  1.0f,  1.0f },
+       {  0.0f, -1.0f,  1.0f },
+       {  0.0f,  1.0f, -1.0f },
+       {  0.0f, -1.0f, -1.0f },
+})
+, second_ints({
+                    // x>y x>z y>z
+       { 0, 0, 1 }, //  0   0   0  ZYX
+       { 0, 1, 0 }, //  0   0   1  YZX
+       { 0, 0, 1 }, //  0   1   0  illogical, but ZYX
+       { 0, 1, 0 }, //  0   1   1  YXZ
+       { 0, 0, 1 }, //  1   0   0  ZXY
+       { 1, 0, 0 }, //  1   0   1  illogical, but XYZ
+       { 1, 0, 0 }, //  1   1   0  XZY
+       { 1, 0, 0 }, //  1   1   1  XYZ
+})
+, third_ints({
+                    // x>y x>z y>z
+       { 0, 1, 1 }, //  0   0   0  ZYX
+       { 0, 1, 1 }, //  0   0   1  YZX
+       { 0, 1, 1 }, //  0   1   0  illogical, but ZYX
+       { 1, 1, 0 }, //  0   1   1  YXZ
+       { 1, 0, 1 }, //  1   0   0  ZXY
+       { 1, 1, 0 }, //  1   0   1  illogical, but XYZ
+       { 1, 0, 1 }, //  1   1   0  XZY
+       { 1, 1, 0 }, //  1   1   1  XYZ
+})
+, second_floats({
+                             // x>y x>z y>z
+       { 0.0f, 0.0f, 1.0f }, //  0   0   0  ZYX
+       { 0.0f, 1.0f, 0.0f }, //  0   0   1  YZX
+       { 0.0f, 0.0f, 1.0f }, //  0   1   0  illogical, but ZYX
+       { 0.0f, 1.0f, 0.0f }, //  0   1   1  YXZ
+       { 0.0f, 0.0f, 1.0f }, //  1   0   0  ZXY
+       { 1.0f, 0.0f, 0.0f }, //  1   0   1  illogical, but XYZ
+       { 1.0f, 0.0f, 0.0f }, //  1   1   0  XZY
+       { 1.0f, 0.0f, 0.0f }, //  1   1   1  XYZ
+})
+, third_floats({
+                             // x>y x>z y>z
+       { 0.0f, 1.0f, 1.0f }, //  0   0   0  ZYX
+       { 0.0f, 1.0f, 1.0f }, //  0   0   1  YZX
+       { 0.0f, 1.0f, 1.0f }, //  0   1   0  illogical, but ZYX
+       { 1.0f, 1.0f, 0.0f }, //  0   1   1  YXZ
+       { 1.0f, 0.0f, 1.0f }, //  1   0   0  ZXY
+       { 1.0f, 1.0f, 0.0f }, //  1   0   1  illogical, but XYZ
+       { 1.0f, 0.0f, 1.0f }, //  1   1   0  XZY
+       { 1.0f, 1.0f, 0.0f }, //  1   1   1  XYZ
+}) {
+       GaloisLFSR random(seed ^ 0x0123456789ACBDEF);
+       unsigned char value;
+       for (size_t i = 0; i < 256; ++i) {
+               perm[i] = random(value);
+               perm[i] &= 0xFF;
+               perm[i + 256] = perm[i];
+               perm12[i] = perm[i] % 12;
+               perm12[i + 256] = perm12[i];
+       }
+}
+
+
+float SimplexNoise::operator ()(const glm::vec3 &in) const noexcept {
+       float skew = (in.x + in.y + in.z) * one_third;
+
+       glm::vec3 skewed(glm::floor(in + skew));
+       float tr = (skewed.x + skewed.y + skewed.z) * one_sixth;
+
+       glm::vec3 unskewed(skewed - tr);
+       glm::vec3 relative(in - unskewed);
+
+       bool x_ge_y = relative.x >= relative.y;
+       bool x_ge_z = relative.x >= relative.z;
+       bool y_ge_z = relative.y >= relative.z;
+       unsigned int st = (x_ge_y << 2) | (x_ge_z << 1) | y_ge_z;
+
+       glm::ivec3 second_int(second_ints[st]);
+       glm::ivec3 third_int(third_ints[st]);
+       glm::vec3 second_float(second_floats[st]);
+       glm::vec3 third_float(third_floats[st]);
+
+       glm::vec3 offset[4] = {
+               in - unskewed,
+               relative - second_float + one_sixth,
+               relative - third_float + one_third,
+               relative - 0.5f,
+       };
+
+       int index[3] = {
+               (int)(skewed.x) & 0xFF,
+               (int)(skewed.y) & 0xFF,
+               (int)(skewed.z) & 0xFF,
+       };
+
+       float n = 0.0f;
+
+       // I know 0.6 is wrong, but for some reason it looks better than 0.5
+
+       // 0
+       float t = glm::clamp(0.6f - glm::length2(offset[0]), 0.0f, 1.0f);
+       t *= t;
+       int corner = Perm12(index[0] + Perm(index[1] + Perm(index[2])));
+       n += t * t * glm::dot(Grad(corner), offset[0]);
+
+       // 1
+       t = glm::clamp(0.6f - glm::length2(offset[1]), 0.0f, 1.0f);
+       t *= t;
+       corner = Perm12(index[0] + second_int.x + Perm(index[1] + second_int.y + Perm(index[2] + second_int.z)));
+       n += t * t * glm::dot(Grad(corner), offset[1]);
+
+       // 2
+       t = glm::clamp(0.6f - glm::length2(offset[2]), 0.0f, 1.0f);
+       t *= t;
+       corner = Perm12(index[0] + third_int.x + Perm(index[1] + third_int.y + Perm(index[2] + third_int.z)));
+       n += t * t * glm::dot(Grad(corner), offset[2]);
+
+       // 3
+       t = glm::clamp(0.6f - glm::length2(offset[3]), 0.0f, 1.0f);
+       t *= t;
+       corner = Perm12(index[0] + 1 + Perm(index[1] + 1 + Perm(index[2] + 1)));
+       n += t * t * glm::dot(Grad(corner), offset[3]);
+
+       return 32.0f * n;
+}
+
+
+int SimplexNoise::Perm(int idx) const noexcept {
+       return perm[idx];
+}
+
+int SimplexNoise::Perm12(int idx) const noexcept {
+       return perm12[idx];
+}
+
+const glm::vec3 &SimplexNoise::Grad(int idx) const noexcept {
+       return grad[idx];
+}
+
+
+WorleyNoise::WorleyNoise(unsigned int seed) noexcept
+: seed(seed)
+, num_points(8) {
+
+}
+
+float WorleyNoise::operator ()(const glm::vec3 &in) const noexcept {
+       glm::vec3 center = glm::floor(in);
+
+       float closest = 1.0f;  // cannot be farther away than 1.0
+
+       for (int z = -1; z <= 1; ++z) {
+               for (int y = -1; y <= 1; ++y) {
+                       for (int x = -1; x <= 1; ++x) {
+                               glm::vec3 cube(center.x + x, center.y + y, center.z + z);
+                               unsigned int cube_rand =
+                                       (unsigned(cube.x) * 130223) ^
+                                       (unsigned(cube.y) * 159899) ^
+                                       (unsigned(cube.z) * 190717) ^
+                                       seed;
+
+                               for (int i = 0; i < num_points; ++i) {
+                                       glm::vec3 point(cube);
+                                       cube_rand = 190667 * cube_rand + 109807;
+                                       point.x += float(cube_rand % 262144) / 262144.0f;
+                                       cube_rand = 135899 * cube_rand + 189169;
+                                       point.y += float(cube_rand % 262144) / 262144.0f;
+                                       cube_rand = 159739 * cube_rand + 112139;
+                                       point.z += float(cube_rand % 262144) / 262144.0f;
+
+                                       float distance = glm::distance(in, point);
+                                       if (distance < closest) {
+                                               closest = distance;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // closest ranges (0, 1), so normalizing to (-1,1) is trivial
+       // though heavily biased towards lower numbers
+       return 2.0f * closest - 1.0f;
+}
+
+}
+}
diff --git a/src/rand/GaloisLFSR.hpp b/src/rand/GaloisLFSR.hpp
deleted file mode 100644 (file)
index 83dc0e5..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef BLOBS_RAND_GALOISLFSR_HPP_
-#define BLOBS_RAND_GALOISLFSR_HPP_
-
-#include <cassert>
-#include <cstdint>
-#include <limits>
-
-
-namespace blobs {
-namespace rand {
-
-class GaloisLFSR {
-
-public:
-       // seed should be non-zero
-       explicit GaloisLFSR(std::uint64_t seed) noexcept
-       : state(seed) {
-               if (state == 0) {
-                       state = 1;
-               }
-       }
-
-       // get the next bit
-       bool operator ()() noexcept {
-               bool result = state & 1;
-               state >>= 1;
-               if (result) {
-                       state |= 0x8000000000000000;
-                       state ^= mask;
-               } else {
-                       state &= 0x7FFFFFFFFFFFFFFF;
-               }
-               return result;
-       }
-
-       template<class T>
-       T operator ()(T &out) noexcept {
-               constexpr int num_bits =
-                       std::numeric_limits<T>::digits +
-                       std::numeric_limits<T>::is_signed;
-               for (int i = 0; i < num_bits; ++i) {
-                       operator ()();
-               }
-               return out = static_cast<T>(state);
-       }
-
-       /// special case for randrom(boolean), since static_cast<bool>(0b10) == true
-       bool operator ()(bool &out) noexcept {
-               return out = operator ()();
-       }
-
-       template<class T>
-       T Next() noexcept {
-               T next;
-               return (*this)(next);
-       }
-
-       float SNorm() noexcept {
-               return float(Next<std::uint32_t>()) * (1.0f / 2147483647.5f) - 1.0f;
-       }
-
-       float UNorm() noexcept {
-               return float(Next<std::uint32_t>()) * (1.0f / 4294967295.0f);
-       }
-
-       template<class Container>
-       typename Container::reference From(Container &c) {
-               assert(c.size() > 0);
-               return c[Next<typename Container::size_type>() % c.size()];
-       }
-       template<class Container>
-       typename Container::const_reference From(const Container &c) {
-               assert(c.size() > 0);
-               return c[Next<typename Container::size_type>() % c.size()];
-       }
-
-private:
-       std::uint64_t state;
-       // bits 64, 63, 61, and 60 set to 1 (counting from 1 lo to hi)
-       static constexpr std::uint64_t mask = 0xD800000000000000;
-
-};
-
-}
-}
-
-#endif
diff --git a/src/rand/OctaveNoise.hpp b/src/rand/OctaveNoise.hpp
deleted file mode 100644 (file)
index 6a91c85..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef BLOBS_RAND_OCTAVENOISE_HPP_
-#define BLOBS_RAND_OCTAVENOISE_HPP_
-
-#include "../graphics/glm.hpp"
-
-
-namespace blobs {
-namespace rand {
-
-template<class Noise>
-float OctaveNoise(
-       const Noise &noise,
-       const glm::vec3 &in,
-       int num,
-       float persistence,
-       float frequency = 1.0f,
-       float amplitude = 1.0f,
-       float growth = 2.0f
-) {
-       float total = 0.0f;
-       float max = 0.0f;
-       for (int i = 0; i < num; ++i) {
-               total += noise(in * frequency) * amplitude;
-               max += amplitude;
-               amplitude *= persistence;
-               frequency *= growth;
-       }
-
-       return total / max;
-}
-
-}
-}
-
-#endif
diff --git a/src/rand/SimplexNoise.hpp b/src/rand/SimplexNoise.hpp
deleted file mode 100644 (file)
index 9a72e64..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef BLOBS_RAND_SIMPLEXNOISE_HPP_
-#define BLOBS_RAND_SIMPLEXNOISE_HPP_
-
-#include "../graphics/glm.hpp"
-
-#include <cstdint>
-
-
-namespace blobs {
-namespace rand {
-
-class SimplexNoise {
-
-public:
-       explicit SimplexNoise(std::uint64_t seed) noexcept;
-
-       float operator ()(const glm::vec3 &) const noexcept;
-
-private:
-       int Perm(int idx) const noexcept;
-       int Perm12(int idx) const noexcept;
-       const glm::vec3 &Grad(int idx) const noexcept;
-
-private:
-       int perm[512];
-       int perm12[512];
-       glm::vec3 grad[12];
-       glm::ivec3 second_ints[8];
-       glm::ivec3 third_ints[8];
-       glm::vec3 second_floats[8];
-       glm::vec3 third_floats[8];
-
-};
-
-}
-}
-
-#endif
diff --git a/src/rand/WorleyNoise.hpp b/src/rand/WorleyNoise.hpp
deleted file mode 100644 (file)
index 34c4871..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef BLOBS_RAND_WORLEYNOISE_HPP_
-#define BLOBS_RAND_WORLEYNOISE_HPP_
-
-#include "../graphics/glm.hpp"
-
-
-namespace blobs {
-namespace rand {
-
-/// implementation of Worley noise (aka Cell or Voroni noise)
-class WorleyNoise {
-
-public:
-       explicit WorleyNoise(unsigned int seed) noexcept;
-
-       float operator ()(const glm::vec3 &) const noexcept;
-
-private:
-       const unsigned int seed;
-       const int num_points;
-
-};
-
-}
-}
-
-#endif
diff --git a/src/rand/noise.cpp b/src/rand/noise.cpp
deleted file mode 100644 (file)
index 07ab817..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-#include "GaloisLFSR.hpp"
-#include "SimplexNoise.hpp"
-#include "WorleyNoise.hpp"
-
-#include <cmath>
-#include <glm/gtx/norm.hpp>
-
-
-namespace {
-
-constexpr float one_third = 1.0f/3.0f;
-constexpr float one_sixth = 1.0f/6.0f;
-
-}
-
-namespace blobs {
-namespace rand {
-
-SimplexNoise::SimplexNoise(std::uint64_t seed) noexcept
-: grad({
-       {  1.0f,  1.0f,  0.0f },
-       { -1.0f,  1.0f,  0.0f },
-       {  1.0f, -1.0f,  0.0f },
-       { -1.0f, -1.0f,  0.0f },
-       {  1.0f,  0.0f,  1.0f },
-       { -1.0f,  0.0f,  1.0f },
-       {  1.0f,  0.0f, -1.0f },
-       { -1.0f,  0.0f, -1.0f },
-       {  0.0f,  1.0f,  1.0f },
-       {  0.0f, -1.0f,  1.0f },
-       {  0.0f,  1.0f, -1.0f },
-       {  0.0f, -1.0f, -1.0f },
-})
-, second_ints({
-                    // x>y x>z y>z
-       { 0, 0, 1 }, //  0   0   0  ZYX
-       { 0, 1, 0 }, //  0   0   1  YZX
-       { 0, 0, 1 }, //  0   1   0  illogical, but ZYX
-       { 0, 1, 0 }, //  0   1   1  YXZ
-       { 0, 0, 1 }, //  1   0   0  ZXY
-       { 1, 0, 0 }, //  1   0   1  illogical, but XYZ
-       { 1, 0, 0 }, //  1   1   0  XZY
-       { 1, 0, 0 }, //  1   1   1  XYZ
-})
-, third_ints({
-                    // x>y x>z y>z
-       { 0, 1, 1 }, //  0   0   0  ZYX
-       { 0, 1, 1 }, //  0   0   1  YZX
-       { 0, 1, 1 }, //  0   1   0  illogical, but ZYX
-       { 1, 1, 0 }, //  0   1   1  YXZ
-       { 1, 0, 1 }, //  1   0   0  ZXY
-       { 1, 1, 0 }, //  1   0   1  illogical, but XYZ
-       { 1, 0, 1 }, //  1   1   0  XZY
-       { 1, 1, 0 }, //  1   1   1  XYZ
-})
-, second_floats({
-                             // x>y x>z y>z
-       { 0.0f, 0.0f, 1.0f }, //  0   0   0  ZYX
-       { 0.0f, 1.0f, 0.0f }, //  0   0   1  YZX
-       { 0.0f, 0.0f, 1.0f }, //  0   1   0  illogical, but ZYX
-       { 0.0f, 1.0f, 0.0f }, //  0   1   1  YXZ
-       { 0.0f, 0.0f, 1.0f }, //  1   0   0  ZXY
-       { 1.0f, 0.0f, 0.0f }, //  1   0   1  illogical, but XYZ
-       { 1.0f, 0.0f, 0.0f }, //  1   1   0  XZY
-       { 1.0f, 0.0f, 0.0f }, //  1   1   1  XYZ
-})
-, third_floats({
-                             // x>y x>z y>z
-       { 0.0f, 1.0f, 1.0f }, //  0   0   0  ZYX
-       { 0.0f, 1.0f, 1.0f }, //  0   0   1  YZX
-       { 0.0f, 1.0f, 1.0f }, //  0   1   0  illogical, but ZYX
-       { 1.0f, 1.0f, 0.0f }, //  0   1   1  YXZ
-       { 1.0f, 0.0f, 1.0f }, //  1   0   0  ZXY
-       { 1.0f, 1.0f, 0.0f }, //  1   0   1  illogical, but XYZ
-       { 1.0f, 0.0f, 1.0f }, //  1   1   0  XZY
-       { 1.0f, 1.0f, 0.0f }, //  1   1   1  XYZ
-}) {
-       GaloisLFSR random(seed ^ 0x0123456789ACBDEF);
-       unsigned char value;
-       for (size_t i = 0; i < 256; ++i) {
-               perm[i] = random(value);
-               perm[i] &= 0xFF;
-               perm[i + 256] = perm[i];
-               perm12[i] = perm[i] % 12;
-               perm12[i + 256] = perm12[i];
-       }
-}
-
-
-float SimplexNoise::operator ()(const glm::vec3 &in) const noexcept {
-       float skew = (in.x + in.y + in.z) * one_third;
-
-       glm::vec3 skewed(glm::floor(in + skew));
-       float tr = (skewed.x + skewed.y + skewed.z) * one_sixth;
-
-       glm::vec3 unskewed(skewed - tr);
-       glm::vec3 relative(in - unskewed);
-
-       bool x_ge_y = relative.x >= relative.y;
-       bool x_ge_z = relative.x >= relative.z;
-       bool y_ge_z = relative.y >= relative.z;
-       unsigned int st = (x_ge_y << 2) | (x_ge_z << 1) | y_ge_z;
-
-       glm::ivec3 second_int(second_ints[st]);
-       glm::ivec3 third_int(third_ints[st]);
-       glm::vec3 second_float(second_floats[st]);
-       glm::vec3 third_float(third_floats[st]);
-
-       glm::vec3 offset[4] = {
-               in - unskewed,
-               relative - second_float + one_sixth,
-               relative - third_float + one_third,
-               relative - 0.5f,
-       };
-
-       int index[3] = {
-               (int)(skewed.x) & 0xFF,
-               (int)(skewed.y) & 0xFF,
-               (int)(skewed.z) & 0xFF,
-       };
-
-       float n = 0.0f;
-
-       // I know 0.6 is wrong, but for some reason it looks better than 0.5
-
-       // 0
-       float t = glm::clamp(0.6f - glm::length2(offset[0]), 0.0f, 1.0f);
-       t *= t;
-       int corner = Perm12(index[0] + Perm(index[1] + Perm(index[2])));
-       n += t * t * glm::dot(Grad(corner), offset[0]);
-
-       // 1
-       t = glm::clamp(0.6f - glm::length2(offset[1]), 0.0f, 1.0f);
-       t *= t;
-       corner = Perm12(index[0] + second_int.x + Perm(index[1] + second_int.y + Perm(index[2] + second_int.z)));
-       n += t * t * glm::dot(Grad(corner), offset[1]);
-
-       // 2
-       t = glm::clamp(0.6f - glm::length2(offset[2]), 0.0f, 1.0f);
-       t *= t;
-       corner = Perm12(index[0] + third_int.x + Perm(index[1] + third_int.y + Perm(index[2] + third_int.z)));
-       n += t * t * glm::dot(Grad(corner), offset[2]);
-
-       // 3
-       t = glm::clamp(0.6f - glm::length2(offset[3]), 0.0f, 1.0f);
-       t *= t;
-       corner = Perm12(index[0] + 1 + Perm(index[1] + 1 + Perm(index[2] + 1)));
-       n += t * t * glm::dot(Grad(corner), offset[3]);
-
-       return 32.0f * n;
-}
-
-
-int SimplexNoise::Perm(int idx) const noexcept {
-       return perm[idx];
-}
-
-int SimplexNoise::Perm12(int idx) const noexcept {
-       return perm12[idx];
-}
-
-const glm::vec3 &SimplexNoise::Grad(int idx) const noexcept {
-       return grad[idx];
-}
-
-
-WorleyNoise::WorleyNoise(unsigned int seed) noexcept
-: seed(seed)
-, num_points(8) {
-
-}
-
-float WorleyNoise::operator ()(const glm::vec3 &in) const noexcept {
-       glm::vec3 center = glm::floor(in);
-
-       float closest = 1.0f;  // cannot be farther away than 1.0
-
-       for (int z = -1; z <= 1; ++z) {
-               for (int y = -1; y <= 1; ++y) {
-                       for (int x = -1; x <= 1; ++x) {
-                               glm::vec3 cube(center.x + x, center.y + y, center.z + z);
-                               unsigned int cube_rand =
-                                       (unsigned(cube.x) * 130223) ^
-                                       (unsigned(cube.y) * 159899) ^
-                                       (unsigned(cube.z) * 190717) ^
-                                       seed;
-
-                               for (int i = 0; i < num_points; ++i) {
-                                       glm::vec3 point(cube);
-                                       cube_rand = 190667 * cube_rand + 109807;
-                                       point.x += float(cube_rand % 262144) / 262144.0f;
-                                       cube_rand = 135899 * cube_rand + 189169;
-                                       point.y += float(cube_rand % 262144) / 262144.0f;
-                                       cube_rand = 159739 * cube_rand + 112139;
-                                       point.z += float(cube_rand % 262144) / 262144.0f;
-
-                                       float distance = glm::distance(in, point);
-                                       if (distance < closest) {
-                                               closest = distance;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       // closest ranges (0, 1), so normalizing to (-1,1) is trivial
-       // though heavily biased towards lower numbers
-       return 2.0f * closest - 1.0f;
-}
-
-}
-}
index 0f9c8d9d3ad3a77ebadf3fffecd4d78bc312da39..a69defbcfc45a4cb1b2dcd510b9fb4a2cb540eb5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_UI_WIDGET_HPP_
 #define BLOBS_UI_WIDGET_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 15dce208a61b6995ae6551250b668dd3e05fe646..24fb9a21a84f8fb86dcc7ac6b7da3ab31e868c7a 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_UI_ALIGN_HPP_
 #define BLOBS_UI_ALIGN_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 3db5e37e362b3de7352dac22ee6a4a848dac5652..df68984915bdf8e22b375280c7df6a10f073a449 100644 (file)
@@ -2,7 +2,7 @@
 #define BLOBS_WORLD_BODY_HPP_
 
 #include "Orbit.hpp"
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 #include <vector>
 
index 7def521cc57bdbc79034fe95f4977ea1939cf353..8ed415ee2d77d5295a188745b2a9ed679edee696 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_WORLD_ORBIT_HPP_
 #define BLOBS_WORLD_ORBIT_HPP_
 
-#include "../graphics/glm.hpp"
+#include "../math/glm.hpp"
 
 
 namespace blobs {
index 2274d045aed749e9d4b65a4f0eceb075b508db34..28ecaa03cd206a0e254685928dabeb398203af07 100644 (file)
@@ -5,8 +5,8 @@
 
 #include "Set.hpp"
 #include "Tile.hpp"
-#include "../graphics/glm.hpp"
 #include "../graphics/SimpleVAO.hpp"
+#include "../math/glm.hpp"
 
 #include <cassert>
 #include <memory>
index 6250fc67ac4a9424cb305dc7e66b14f12538dfb5..492a7f81f1d21a5a4cb90cbf89cfefed02a2760f 100644 (file)
@@ -12,7 +12,9 @@ struct Resource {
        std::string name;
        std::string label;
 
-       int id;
+       double density = 1.0;
+
+       int id = -1;
 
        enum State {
                SOLID = 0,
@@ -22,7 +24,7 @@ struct Resource {
        };
        // the resource's natural state
        // TODO: something about temperature and pressure and stuff
-       int state;
+       int state = SOLID;
 
 };
 
index 0b1260f8673d8a0eb1b054bec81847b61602d711..4f98d9a63bdef3b241123e8cf2bbdf30b76ce3de 100644 (file)
@@ -8,12 +8,12 @@
 #include "Tile.hpp"
 #include "TileType.hpp"
 
-#include "../const.hpp"
 #include "../app/Assets.hpp"
 #include "../creature/Creature.hpp"
 #include "../graphics/Viewport.hpp"
-#include "../rand/OctaveNoise.hpp"
-#include "../rand/SimplexNoise.hpp"
+#include "../math/const.hpp"
+#include "../math/OctaveNoise.hpp"
+#include "../math/SimplexNoise.hpp"
 
 #include <algorithm>
 #include <cmath>
@@ -421,8 +421,8 @@ void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) {
 
 
 void GenerateEarthlike(const Set<TileType> &tiles, Planet &p) noexcept {
-       rand::SimplexNoise elevation_gen(0);
-       rand::SimplexNoise variation_gen(45623752346);
+       math::SimplexNoise elevation_gen(0);
+       math::SimplexNoise variation_gen(45623752346);
 
        const int ice = tiles["ice"].id;
        const int ocean = tiles["ocean"].id;
@@ -460,7 +460,7 @@ void GenerateEarthlike(const Set<TileType> &tiles, Planet &p) noexcept {
                                        p.TileAt(surface, x, y).type = ice;
                                        continue;
                                }
-                               float elevation = rand::OctaveNoise(
+                               float elevation = math::OctaveNoise(
                                        elevation_gen,
                                        to_tile / p.Radius(),
                                        3,   // octaves
@@ -469,7 +469,7 @@ void GenerateEarthlike(const Set<TileType> &tiles, Planet &p) noexcept {
                                        2,   // amplitude
                                        2    // growth
                                );
-                               float variation = rand::OctaveNoise(
+                               float variation = math::OctaveNoise(
                                        variation_gen,
                                        to_tile / p.Radius(),
                                        3,   // octaves
index 5042180915195538e0f5d6d0dde6ccb9e3471cb3..66a9704d13147703b5e43ae9a3af7db2cdc8355a 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BLOBS_TEST_ASSETS_HPP_
 #define BLOBS_TEST_ASSETS_HPP_
 
-#include "graphics/glm.hpp"
+#include "math/glm.hpp"
 
 #include <string>
 #include <limits>
diff --git a/tst/math/GaloisLFSRTest.cpp b/tst/math/GaloisLFSRTest.cpp
new file mode 100644 (file)
index 0000000..958ac76
--- /dev/null
@@ -0,0 +1,86 @@
+#include "GaloisLFSRTest.hpp"
+
+#include "math/GaloisLFSR.hpp"
+
+#include <algorithm>
+#include <sstream>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(blobs::math::test::GaloisLFSRTest);
+
+using namespace std;
+
+
+namespace blobs {
+namespace math {
+namespace test {
+
+void GaloisLFSRTest::setUp() {
+
+}
+
+void GaloisLFSRTest::tearDown() {
+
+}
+
+void GaloisLFSRTest::testFloatNorm() {
+       GaloisLFSR random(4);
+       for (int i = 0; i < 64; ++i) {
+               float value = random.SNorm();
+               AssertBetween(
+                       "random signed normal float",
+                       -1.0f, 1.0f, value);
+       }
+       for (int i = 0; i < 64; ++i) {
+               float value = random.UNorm();
+               AssertBetween(
+                       "random unsigned normal float",
+                       0.0f, 1.0f, value);
+       }
+}
+
+void GaloisLFSRTest::testFromContainer() {
+       GaloisLFSR random(5);
+       const vector<int> container({ 1, 2, 3, 4, 5 });
+       for (int i = 0; i < 64; ++i) {
+               int element = random.From(container);
+               AssertContains(
+                       "random element from container",
+                       container, element);
+       }
+}
+
+void GaloisLFSRTest::AssertBetween(
+       string message,
+       float minimum,
+       float maximum,
+       float actual
+) {
+       stringstream msg;
+       msg << message << ": " << actual << " not in ["
+               << minimum << ',' << maximum << ']';
+       CPPUNIT_ASSERT_MESSAGE(
+               msg.str(),
+               minimum <= actual && actual <= maximum);
+
+}
+
+void GaloisLFSRTest::AssertContains(
+       string message,
+       const vector<int> &container,
+       int element
+) {
+       stringstream msg;
+       msg << message << ": " << element << " not in { ";
+       for (int i : container) {
+               msg << i << ' ';
+       }
+       msg << '}';
+       CPPUNIT_ASSERT_MESSAGE(
+               msg.str(),
+               find(container.begin(), container.end(), element) != container.end());
+
+}
+
+}
+}
+}
diff --git a/tst/math/GaloisLFSRTest.hpp b/tst/math/GaloisLFSRTest.hpp
new file mode 100644 (file)
index 0000000..87c92d6
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef BLOBS_TEST_MATH_GALOISLFSRTEST_HPP
+#define BLOBS_TEST_MATH_GALOISLFSRTEST_HPP
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <string>
+#include <vector>
+
+
+namespace blobs {
+namespace math {
+namespace test {
+
+class GaloisLFSRTest
+: public CppUnit::TestFixture {
+
+CPPUNIT_TEST_SUITE(GaloisLFSRTest);
+
+CPPUNIT_TEST(testFloatNorm);
+CPPUNIT_TEST(testFromContainer);
+
+CPPUNIT_TEST_SUITE_END();
+
+public:
+       void setUp();
+       void tearDown();
+
+       void testFloatNorm();
+       void testFromContainer();
+
+       /// check if value is in range [minimum,maximum]
+       static void AssertBetween(
+               std::string message,
+               float minimum,
+               float maximum,
+               float actual);
+
+       static void AssertContains(
+               std::string message,
+               const std::vector<int> &container,
+               int element);
+
+};
+
+}
+}
+}
+
+#endif
diff --git a/tst/math/StabilityTest.cpp b/tst/math/StabilityTest.cpp
new file mode 100644 (file)
index 0000000..8b0011f
--- /dev/null
@@ -0,0 +1,305 @@
+#include "StabilityTest.hpp"
+
+#include "math/GaloisLFSR.hpp"
+#include "math/SimplexNoise.hpp"
+#include "math/WorleyNoise.hpp"
+
+#include <cstdint>
+#include <string>
+#include <sstream>
+#include <glm/gtx/io.hpp>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(blobs::math::test::StabilityTest);
+
+using namespace std;
+
+
+namespace blobs {
+namespace math {
+namespace test {
+
+void StabilityTest::setUp() {
+
+}
+
+void StabilityTest::tearDown() {
+
+}
+
+
+void StabilityTest::testRNG() {
+       GaloisLFSR random(0);
+       uint16_t value;
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #1 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #2 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #3 from RNG",
+               uint16_t(0xB000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #4 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #5 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #6 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #7 from RNG",
+               uint16_t(0x4500), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #8 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #9 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #10 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #11 from RNG",
+               uint16_t(0x2E70), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #12 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #13 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #14 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #15 from RNG",
+               uint16_t(0x1011), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #16 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #17 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #18 from RNG",
+               uint16_t(0xB000), value
+       );
+       value = random.Next<uint16_t>();
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #19 from RNG (using Next())",
+               uint16_t(0x0B0B), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #20 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #21 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #22 from RNG",
+               uint16_t(0x1500), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #23 from RNG",
+               uint16_t(0x0454), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #24 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #25 from RNG",
+               uint16_t(0x0000), value
+       );
+       value = random.Next<uint16_t>();
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #26 from RNG (using Next())",
+               uint16_t(0xC970), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #27 from RNG",
+               uint16_t(0x02E5), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #28 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #29 from RNG",
+               uint16_t(0x0000), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #30 from RNG",
+               uint16_t(0x0101), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #31 from RNG",
+               uint16_t(0x0100), value
+       );
+       random(value);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected value #32 from RNG",
+               uint16_t(0x0000), value
+       );
+
+       GaloisLFSR random1(1);
+       uint16_t value1;
+       for (int i = 0; i < 32; ++i) {
+               random1(value1);
+       }
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "RNG with seeds 0 and 1 differ",
+               value, value1
+       );
+
+       GaloisLFSR random_bool(0);
+       bool value_bool;
+       for (int i = 0; i < (16 * 32); ++i) {
+               random_bool(value_bool);
+       }
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected result for bool",
+               false, value_bool
+       );
+
+       GaloisLFSR random8(0);
+       uint8_t value8;
+       for (int i = 0; i < 31; ++i) {
+               random8(value8);
+       }
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected result for uint8",
+               uint8_t(0x10), value8
+       );
+
+       GaloisLFSR random32(0);
+       uint32_t value32;
+       for (int i = 0; i < 16; ++i) {
+               random32(value32);
+       }
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected result for uint32",
+               uint32_t(0xB0000000), value32
+       );
+}
+
+void StabilityTest::testSimplex() {
+       SimplexNoise noise(0);
+
+       Assert(noise, glm::vec3(0.0f, 0.0f, 0.0f),  0.0f);
+       Assert(noise, glm::vec3(0.0f, 0.0f, 1.0f),  0.652221322059631f);
+       Assert(noise, glm::vec3(0.0f, 1.0f, 0.0f),  0.867977976799011f);
+       Assert(noise, glm::vec3(0.0f, 1.0f, 1.0f), -0.107878111302853f);
+       Assert(noise, glm::vec3(1.0f, 0.0f, 0.0f), -0.107878260314465f);
+       Assert(noise, glm::vec3(1.0f, 0.0f, 1.0f), -6.31356940061778e-08f);
+       Assert(noise, glm::vec3(1.0f, 1.0f, 0.0f), -0.107878245413303f);
+       Assert(noise, glm::vec3(1.0f, 1.0f, 1.0f),  0.0f);
+
+       Assert(noise, glm::vec3( 0.0f,  0.0f, -1.0f), -0.107878483831882f);
+       Assert(noise, glm::vec3( 0.0f, -1.0f,  0.0f), -0.760099768638611f);
+       Assert(noise, glm::vec3( 0.0f, -1.0f, -1.0f),  0.0f);
+       Assert(noise, glm::vec3(-1.0f,  0.0f,  0.0f),  0.760099768638611f);
+       Assert(noise, glm::vec3(-1.0f,  0.0f, -1.0f),  0.0f);
+       Assert(noise, glm::vec3(-1.0f, -1.0f,  0.0f), -0.107878118753433f);
+       Assert(noise, glm::vec3(-1.0f, -1.0f, -1.0f),  0.0f);
+}
+
+void StabilityTest::testWorley() {
+       WorleyNoise noise(0);
+
+       Assert(noise, glm::vec3(0.0f, 0.0f, 0.0f), -0.117765009403229f);
+       Assert(noise, glm::vec3(0.0f, 0.0f, 1.0f), -0.209876894950867f);
+       Assert(noise, glm::vec3(0.0f, 1.0f, 0.0f), -0.290086328983307f);
+       Assert(noise, glm::vec3(0.0f, 1.0f, 1.0f), -0.332393705844879f);
+       Assert(noise, glm::vec3(1.0f, 0.0f, 0.0f), -0.621925830841064f);
+       Assert(noise, glm::vec3(1.0f, 0.0f, 1.0f), -0.338455379009247f);
+       Assert(noise, glm::vec3(1.0f, 1.0f, 0.0f), -0.386664032936096f);
+       Assert(noise, glm::vec3(1.0f, 1.0f, 1.0f), -0.533940434455872f);
+
+       Assert(noise, glm::vec3( 0.0f,  0.0f, -1.0f), -0.425480604171753f);
+       Assert(noise, glm::vec3( 0.0f, -1.0f,  0.0f), -0.189745843410492f);
+       Assert(noise, glm::vec3( 0.0f, -1.0f, -1.0f), -0.30408102273941f);
+       Assert(noise, glm::vec3(-1.0f,  0.0f,  0.0f), -0.618566155433655f);
+       Assert(noise, glm::vec3(-1.0f,  0.0f, -1.0f), -0.060045599937439f);
+       Assert(noise, glm::vec3(-1.0f, -1.0f,  0.0f), -0.366827547550201f);
+       Assert(noise, glm::vec3(-1.0f, -1.0f, -1.0f), -0.575981974601746f);
+}
+
+void StabilityTest::Assert(
+       const SimplexNoise &noise,
+       const glm::vec3 &position,
+       float expected
+) {
+       stringstream msg;
+       msg << "unexpected simplex noise value at " << position;
+       CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+               msg.str(),
+               expected, noise(position), numeric_limits<float>::epsilon()
+       );
+}
+
+void StabilityTest::Assert(
+       const WorleyNoise &noise,
+       const glm::vec3 &position,
+       float expected
+) {
+       stringstream msg;
+       msg << "unexpected worley noise value at " << position;
+       CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+               msg.str(),
+               expected, noise(position), numeric_limits<float>::epsilon()
+       );
+}
+
+}
+}
+}
diff --git a/tst/math/StabilityTest.hpp b/tst/math/StabilityTest.hpp
new file mode 100644 (file)
index 0000000..8b6409e
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef BLOBS_TEST_MATH_STABILITYTEST_HPP
+#define BLOBS_TEST_MATH_STABILITYTEST_HPP
+
+#include "math/glm.hpp"
+
+#include <cppunit/extensions/HelperMacros.h>
+
+
+
+namespace blobs {
+namespace math {
+
+class SimplexNoise;
+class WorleyNoise;
+
+namespace test {
+
+class StabilityTest
+: public CppUnit::TestFixture {
+
+CPPUNIT_TEST_SUITE(StabilityTest);
+
+CPPUNIT_TEST(testRNG);
+CPPUNIT_TEST(testSimplex);
+CPPUNIT_TEST(testWorley);
+
+CPPUNIT_TEST_SUITE_END();
+
+public:
+       void setUp();
+       void tearDown();
+
+       void testRNG();
+       void testSimplex();
+       void testWorley();
+
+       static void Assert(
+               const SimplexNoise &noise,
+               const glm::vec3 &position,
+               float expected);
+
+       static void Assert(
+               const WorleyNoise &noise,
+               const glm::vec3 &position,
+               float expected);
+
+};
+
+}
+}
+}
+
+#endif
diff --git a/tst/rand/GaloisLFSRTest.cpp b/tst/rand/GaloisLFSRTest.cpp
deleted file mode 100644 (file)
index 0078207..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "GaloisLFSRTest.hpp"
-
-#include "rand/GaloisLFSR.hpp"
-
-#include <algorithm>
-#include <sstream>
-
-CPPUNIT_TEST_SUITE_REGISTRATION(blobs::rand::test::GaloisLFSRTest);
-
-using namespace std;
-
-
-namespace blobs {
-namespace rand {
-namespace test {
-
-void GaloisLFSRTest::setUp() {
-
-}
-
-void GaloisLFSRTest::tearDown() {
-
-}
-
-void GaloisLFSRTest::testFloatNorm() {
-       GaloisLFSR random(4);
-       for (int i = 0; i < 64; ++i) {
-               float value = random.SNorm();
-               AssertBetween(
-                       "random signed normal float",
-                       -1.0f, 1.0f, value);
-       }
-       for (int i = 0; i < 64; ++i) {
-               float value = random.UNorm();
-               AssertBetween(
-                       "random unsigned normal float",
-                       0.0f, 1.0f, value);
-       }
-}
-
-void GaloisLFSRTest::testFromContainer() {
-       GaloisLFSR random(5);
-       const vector<int> container({ 1, 2, 3, 4, 5 });
-       for (int i = 0; i < 64; ++i) {
-               int element = random.From(container);
-               AssertContains(
-                       "random element from container",
-                       container, element);
-       }
-}
-
-void GaloisLFSRTest::AssertBetween(
-       string message,
-       float minimum,
-       float maximum,
-       float actual
-) {
-       stringstream msg;
-       msg << message << ": " << actual << " not in ["
-               << minimum << ',' << maximum << ']';
-       CPPUNIT_ASSERT_MESSAGE(
-               msg.str(),
-               minimum <= actual && actual <= maximum);
-
-}
-
-void GaloisLFSRTest::AssertContains(
-       string message,
-       const vector<int> &container,
-       int element
-) {
-       stringstream msg;
-       msg << message << ": " << element << " not in { ";
-       for (int i : container) {
-               msg << i << ' ';
-       }
-       msg << '}';
-       CPPUNIT_ASSERT_MESSAGE(
-               msg.str(),
-               find(container.begin(), container.end(), element) != container.end());
-
-}
-
-}
-}
-}
diff --git a/tst/rand/GaloisLFSRTest.hpp b/tst/rand/GaloisLFSRTest.hpp
deleted file mode 100644 (file)
index 512bb99..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef BLOBS_TEST_RAND_GALOISLFSRTEST_HPP
-#define BLOBS_TEST_RAND_GALOISLFSRTEST_HPP
-
-#include <cppunit/extensions/HelperMacros.h>
-
-#include <string>
-#include <vector>
-
-
-namespace blobs {
-namespace rand {
-namespace test {
-
-class GaloisLFSRTest
-: public CppUnit::TestFixture {
-
-CPPUNIT_TEST_SUITE(GaloisLFSRTest);
-
-CPPUNIT_TEST(testFloatNorm);
-CPPUNIT_TEST(testFromContainer);
-
-CPPUNIT_TEST_SUITE_END();
-
-public:
-       void setUp();
-       void tearDown();
-
-       void testFloatNorm();
-       void testFromContainer();
-
-       /// check if value is in range [minimum,maximum]
-       static void AssertBetween(
-               std::string message,
-               float minimum,
-               float maximum,
-               float actual);
-
-       static void AssertContains(
-               std::string message,
-               const std::vector<int> &container,
-               int element);
-
-};
-
-}
-}
-}
-
-#endif
diff --git a/tst/rand/StabilityTest.cpp b/tst/rand/StabilityTest.cpp
deleted file mode 100644 (file)
index c6c6339..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-#include "StabilityTest.hpp"
-
-#include "rand/GaloisLFSR.hpp"
-#include "rand/SimplexNoise.hpp"
-#include "rand/WorleyNoise.hpp"
-
-#include <cstdint>
-#include <string>
-#include <sstream>
-#include <glm/gtx/io.hpp>
-
-CPPUNIT_TEST_SUITE_REGISTRATION(blobs::rand::test::StabilityTest);
-
-using namespace std;
-
-
-namespace blobs {
-namespace rand {
-namespace test {
-
-void StabilityTest::setUp() {
-
-}
-
-void StabilityTest::tearDown() {
-
-}
-
-
-void StabilityTest::testRNG() {
-       GaloisLFSR random(0);
-       uint16_t value;
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #1 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #2 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #3 from RNG",
-               uint16_t(0xB000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #4 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #5 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #6 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #7 from RNG",
-               uint16_t(0x4500), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #8 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #9 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #10 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #11 from RNG",
-               uint16_t(0x2E70), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #12 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #13 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #14 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #15 from RNG",
-               uint16_t(0x1011), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #16 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #17 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #18 from RNG",
-               uint16_t(0xB000), value
-       );
-       value = random.Next<uint16_t>();
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #19 from RNG (using Next())",
-               uint16_t(0x0B0B), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #20 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #21 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #22 from RNG",
-               uint16_t(0x1500), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #23 from RNG",
-               uint16_t(0x0454), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #24 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #25 from RNG",
-               uint16_t(0x0000), value
-       );
-       value = random.Next<uint16_t>();
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #26 from RNG (using Next())",
-               uint16_t(0xC970), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #27 from RNG",
-               uint16_t(0x02E5), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #28 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #29 from RNG",
-               uint16_t(0x0000), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #30 from RNG",
-               uint16_t(0x0101), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #31 from RNG",
-               uint16_t(0x0100), value
-       );
-       random(value);
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected value #32 from RNG",
-               uint16_t(0x0000), value
-       );
-
-       GaloisLFSR random1(1);
-       uint16_t value1;
-       for (int i = 0; i < 32; ++i) {
-               random1(value1);
-       }
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "RNG with seeds 0 and 1 differ",
-               value, value1
-       );
-
-       GaloisLFSR random_bool(0);
-       bool value_bool;
-       for (int i = 0; i < (16 * 32); ++i) {
-               random_bool(value_bool);
-       }
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected result for bool",
-               false, value_bool
-       );
-
-       GaloisLFSR random8(0);
-       uint8_t value8;
-       for (int i = 0; i < 31; ++i) {
-               random8(value8);
-       }
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected result for uint8",
-               uint8_t(0x10), value8
-       );
-
-       GaloisLFSR random32(0);
-       uint32_t value32;
-       for (int i = 0; i < 16; ++i) {
-               random32(value32);
-       }
-       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected result for uint32",
-               uint32_t(0xB0000000), value32
-       );
-}
-
-void StabilityTest::testSimplex() {
-       SimplexNoise noise(0);
-
-       Assert(noise, glm::vec3(0.0f, 0.0f, 0.0f),  0.0f);
-       Assert(noise, glm::vec3(0.0f, 0.0f, 1.0f),  0.652221322059631f);
-       Assert(noise, glm::vec3(0.0f, 1.0f, 0.0f),  0.867977976799011f);
-       Assert(noise, glm::vec3(0.0f, 1.0f, 1.0f), -0.107878111302853f);
-       Assert(noise, glm::vec3(1.0f, 0.0f, 0.0f), -0.107878260314465f);
-       Assert(noise, glm::vec3(1.0f, 0.0f, 1.0f), -6.31356940061778e-08f);
-       Assert(noise, glm::vec3(1.0f, 1.0f, 0.0f), -0.107878245413303f);
-       Assert(noise, glm::vec3(1.0f, 1.0f, 1.0f),  0.0f);
-
-       Assert(noise, glm::vec3( 0.0f,  0.0f, -1.0f), -0.107878483831882f);
-       Assert(noise, glm::vec3( 0.0f, -1.0f,  0.0f), -0.760099768638611f);
-       Assert(noise, glm::vec3( 0.0f, -1.0f, -1.0f),  0.0f);
-       Assert(noise, glm::vec3(-1.0f,  0.0f,  0.0f),  0.760099768638611f);
-       Assert(noise, glm::vec3(-1.0f,  0.0f, -1.0f),  0.0f);
-       Assert(noise, glm::vec3(-1.0f, -1.0f,  0.0f), -0.107878118753433f);
-       Assert(noise, glm::vec3(-1.0f, -1.0f, -1.0f),  0.0f);
-}
-
-void StabilityTest::testWorley() {
-       WorleyNoise noise(0);
-
-       Assert(noise, glm::vec3(0.0f, 0.0f, 0.0f), -0.117765009403229f);
-       Assert(noise, glm::vec3(0.0f, 0.0f, 1.0f), -0.209876894950867f);
-       Assert(noise, glm::vec3(0.0f, 1.0f, 0.0f), -0.290086328983307f);
-       Assert(noise, glm::vec3(0.0f, 1.0f, 1.0f), -0.332393705844879f);
-       Assert(noise, glm::vec3(1.0f, 0.0f, 0.0f), -0.621925830841064f);
-       Assert(noise, glm::vec3(1.0f, 0.0f, 1.0f), -0.338455379009247f);
-       Assert(noise, glm::vec3(1.0f, 1.0f, 0.0f), -0.386664032936096f);
-       Assert(noise, glm::vec3(1.0f, 1.0f, 1.0f), -0.533940434455872f);
-
-       Assert(noise, glm::vec3( 0.0f,  0.0f, -1.0f), -0.425480604171753f);
-       Assert(noise, glm::vec3( 0.0f, -1.0f,  0.0f), -0.189745843410492f);
-       Assert(noise, glm::vec3( 0.0f, -1.0f, -1.0f), -0.30408102273941f);
-       Assert(noise, glm::vec3(-1.0f,  0.0f,  0.0f), -0.618566155433655f);
-       Assert(noise, glm::vec3(-1.0f,  0.0f, -1.0f), -0.060045599937439f);
-       Assert(noise, glm::vec3(-1.0f, -1.0f,  0.0f), -0.366827547550201f);
-       Assert(noise, glm::vec3(-1.0f, -1.0f, -1.0f), -0.575981974601746f);
-}
-
-void StabilityTest::Assert(
-       const SimplexNoise &noise,
-       const glm::vec3 &position,
-       float expected
-) {
-       stringstream msg;
-       msg << "unexpected simplex noise value at " << position;
-       CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
-               msg.str(),
-               expected, noise(position), numeric_limits<float>::epsilon()
-       );
-}
-
-void StabilityTest::Assert(
-       const WorleyNoise &noise,
-       const glm::vec3 &position,
-       float expected
-) {
-       stringstream msg;
-       msg << "unexpected worley noise value at " << position;
-       CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
-               msg.str(),
-               expected, noise(position), numeric_limits<float>::epsilon()
-       );
-}
-
-}
-}
-}
diff --git a/tst/rand/StabilityTest.hpp b/tst/rand/StabilityTest.hpp
deleted file mode 100644 (file)
index 8f38114..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef BLOBS_TEST_RAND_STABILITYTEST_HPP
-#define BLOBS_TEST_RAND_STABILITYTEST_HPP
-
-#include "graphics/glm.hpp"
-
-#include <cppunit/extensions/HelperMacros.h>
-
-
-
-namespace blobs {
-namespace rand {
-
-class SimplexNoise;
-class WorleyNoise;
-
-namespace test {
-
-class StabilityTest
-: public CppUnit::TestFixture {
-
-CPPUNIT_TEST_SUITE(StabilityTest);
-
-CPPUNIT_TEST(testRNG);
-CPPUNIT_TEST(testSimplex);
-CPPUNIT_TEST(testWorley);
-
-CPPUNIT_TEST_SUITE_END();
-
-public:
-       void setUp();
-       void tearDown();
-
-       void testRNG();
-       void testSimplex();
-       void testWorley();
-
-       static void Assert(
-               const SimplexNoise &noise,
-               const glm::vec3 &position,
-               float expected);
-
-       static void Assert(
-               const WorleyNoise &noise,
-               const glm::vec3 &position,
-               float expected);
-
-};
-
-}
-}
-}
-
-#endif
index ce1690902008155211af539cc8f5ee45a004e777..a7ef6817a7d7eb50c1c2db6eec3bedb65d31a2bd 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "../assert.hpp"
 
-#include "const.hpp"
+#include "math/const.hpp"
 #include "world/Orbit.hpp"
 
 CPPUNIT_TEST_SUITE_REGISTRATION(blobs::world::test::OrbitTest);