From: Daniel Karbach Date: Sun, 26 Nov 2017 17:29:12 +0000 (+0100) Subject: randomize creature properties a bit X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=8f6530c75730f901efd6708e4fde7e68a178adf1 randomize creature properties a bit --- diff --git a/assets b/assets index ce337a6..7703c13 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ce337a6b5afd87607a94f006631a390eefceeec1 +Subproject commit 7703c130c0be3b33f4f267d2662f36b999826f33 diff --git a/src/app/Assets.hpp b/src/app/Assets.hpp index 22b6087..5f971c6 100644 --- a/src/app/Assets.hpp +++ b/src/app/Assets.hpp @@ -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 resources; world::Set tile_types; diff --git a/src/app/app.cpp b/src/app/app.cpp index e4dc1a5..5a4cd67 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -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") { diff --git a/src/blobs.cpp b/src/blobs.cpp index 006644b..b32c4ab 100644 --- a/src/blobs.cpp +++ b/src/blobs.cpp @@ -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 index edbbe7c..0000000 --- a/src/const.hpp +++ /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 diff --git a/src/creature/Creature.hpp b/src/creature/Creature.hpp index ce56dfb..2a40d51 100644 --- a/src/creature/Creature.hpp +++ b/src/creature/Creature.hpp @@ -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 #include @@ -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 ∼ 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 index 0000000..4437150 --- /dev/null +++ b/src/creature/Genome.hpp @@ -0,0 +1,38 @@ +#ifndef BLOBS_CREATURE_GENOME_HPP_ +#define BLOBS_CREATURE_GENOME_HPP_ + +#include "../math/Distribution.hpp" + +#include + + +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; + + void Configure(app::Assets &, Creature &) const; + +}; + +} +} + +#endif diff --git a/src/creature/LocateResourceGoal.hpp b/src/creature/LocateResourceGoal.hpp index afa5b93..a472fd5 100644 --- a/src/creature/LocateResourceGoal.hpp +++ b/src/creature/LocateResourceGoal.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_CREATURE_LOCATERESOURCEGOAL_HPP_ #define BLOBS_CREATURE_LOCATERESOURCEGOAL_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/creature/Situation.hpp b/src/creature/Situation.hpp index 12b7490..d421b69 100644 --- a/src/creature/Situation.hpp +++ b/src/creature/Situation.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_CREATURE_SITUATION_HPP_ #define BLOBS_CREATURE_SITUATION_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/creature/Steering.hpp b/src/creature/Steering.hpp index 6d5b40a..51f2c63 100644 --- a/src/creature/Steering.hpp +++ b/src/creature/Steering.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_CREATURE_STEERING_HPP_ #define BLOBS_CREATURE_STEERING_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index 043aed7..0f25da8 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -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(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(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(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; + 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() diff --git a/src/graphics/AlphaSprite.hpp b/src/graphics/AlphaSprite.hpp index 3cc6a83..c62150d 100644 --- a/src/graphics/AlphaSprite.hpp +++ b/src/graphics/AlphaSprite.hpp @@ -4,8 +4,6 @@ #include "Program.hpp" #include "SimpleVAO.hpp" -#include "glm.hpp" - #include diff --git a/src/graphics/Camera.hpp b/src/graphics/Camera.hpp index f4a98d5..51dd8f1 100644 --- a/src/graphics/Camera.hpp +++ b/src/graphics/Camera.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_GRAPHICS_CAMERA_HPP_ #define BLOBS_GRAPHICS_CAMERA_HPP_ -#include "glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/graphics/Canvas.hpp b/src/graphics/Canvas.hpp index bc2a47a..4e924f1 100644 --- a/src/graphics/Canvas.hpp +++ b/src/graphics/Canvas.hpp @@ -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 diff --git a/src/graphics/CreatureSkin.hpp b/src/graphics/CreatureSkin.hpp index 0d83563..1b5b6b8 100644 --- a/src/graphics/CreatureSkin.hpp +++ b/src/graphics/CreatureSkin.hpp @@ -3,8 +3,6 @@ #include "Program.hpp" -#include "glm.hpp" - namespace blobs { namespace graphics { diff --git a/src/graphics/Font.hpp b/src/graphics/Font.hpp index 6088d95..d7aa4fa 100644 --- a/src/graphics/Font.hpp +++ b/src/graphics/Font.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_GRAPHICS_FONT_HPP_ #define BLOBS_GRAPHICS_FONT_HPP_ -#include "glm.hpp" +#include "../math/glm.hpp" #include #include diff --git a/src/graphics/PlanetSurface.hpp b/src/graphics/PlanetSurface.hpp index 178fcab..a5f177d 100644 --- a/src/graphics/PlanetSurface.hpp +++ b/src/graphics/PlanetSurface.hpp @@ -3,8 +3,6 @@ #include "Program.hpp" -#include "glm.hpp" - namespace blobs { namespace graphics { diff --git a/src/graphics/Program.hpp b/src/graphics/Program.hpp index 2add96c..d068972 100644 --- a/src/graphics/Program.hpp +++ b/src/graphics/Program.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_GRAPHICS_PROGRAM_HPP_ #define BLOBS_GRAPHICS_PROGRAM_HPP_ -#include "glm.hpp" +#include "../math/glm.hpp" #include #include diff --git a/src/graphics/SunSurface.hpp b/src/graphics/SunSurface.hpp index b5a056b..6572761 100644 --- a/src/graphics/SunSurface.hpp +++ b/src/graphics/SunSurface.hpp @@ -4,8 +4,6 @@ #include "Program.hpp" #include "SimpleVAO.hpp" -#include "glm.hpp" - #include diff --git a/src/graphics/gl_traits.hpp b/src/graphics/gl_traits.hpp index a399893..33b0069 100644 --- a/src/graphics/gl_traits.hpp +++ b/src/graphics/gl_traits.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_GRAPHICS_GL_TRAITS_HPP_ #define BLOBS_GRAPHICS_GL_TRAITS_HPP_ -#include "glm.hpp" +#include "../math/glm.hpp" #include diff --git a/src/graphics/glm.hpp b/src/graphics/glm.hpp deleted file mode 100644 index 8003f0b..0000000 --- a/src/graphics/glm.hpp +++ /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 -#include -#include -#include - -// 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 -inline bool allzero(const T &v) noexcept { - return glm::length2(v) < - std::numeric_limits::epsilon() - * std::numeric_limits::epsilon(); -} - -template -inline bool anynan(const T &v) noexcept { - return glm::any(glm::isnan(v)); -} - - -#endif diff --git a/src/graphics/viewport.cpp b/src/graphics/viewport.cpp index 636f3c3..ac0b9e5 100644 --- a/src/graphics/viewport.cpp +++ b/src/graphics/viewport.cpp @@ -1,7 +1,7 @@ #include "Camera.hpp" #include "Viewport.hpp" -#include "../const.hpp" +#include "../math/const.hpp" #include "../world/Body.hpp" #include diff --git a/src/io/TokenStreamReader.hpp b/src/io/TokenStreamReader.hpp index c9043d1..ccdad90 100644 --- a/src/io/TokenStreamReader.hpp +++ b/src/io/TokenStreamReader.hpp @@ -3,7 +3,7 @@ #include "Token.hpp" #include "Tokenizer.hpp" -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" #include #include diff --git a/src/math/Distribution.hpp b/src/math/Distribution.hpp new file mode 100644 index 0000000..7f444f8 --- /dev/null +++ b/src/math/Distribution.hpp @@ -0,0 +1,38 @@ +#ifndef BLOBS_MATH_DISTRIBUTION_HPP_ +#define BLOBS_MATH_DISTRIBUTION_HPP_ + +#include + + +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 index 0000000..592c9af --- /dev/null +++ b/src/math/GaloisLFSR.hpp @@ -0,0 +1,87 @@ +#ifndef BLOBS_MATH_GALOISLFSR_HPP_ +#define BLOBS_MATH_GALOISLFSR_HPP_ + +#include +#include +#include + + +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 + T operator ()(T &out) noexcept { + constexpr int num_bits = + std::numeric_limits::digits + + std::numeric_limits::is_signed; + for (int i = 0; i < num_bits; ++i) { + operator ()(); + } + return out = static_cast(state); + } + + /// special case for randrom(boolean), since static_cast(0b10) == true + bool operator ()(bool &out) noexcept { + return out = operator ()(); + } + + template + T Next() noexcept { + T next; + return (*this)(next); + } + + double SNorm() noexcept { + return 2.0 * UNorm() - 1.0; + } + + double UNorm() noexcept { + return double(Next()) * (1.0 / double(std::numeric_limits::max())); + } + + template + typename Container::reference From(Container &c) { + assert(c.size() > 0); + return c[Next() % c.size()]; + } + template + typename Container::const_reference From(const Container &c) { + assert(c.size() > 0); + return c[Next() % 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 index 0000000..1b2419e --- /dev/null +++ b/src/math/OctaveNoise.hpp @@ -0,0 +1,35 @@ +#ifndef BLOBS_MATH_OCTAVENOISE_HPP_ +#define BLOBS_MATH_OCTAVENOISE_HPP_ + +#include "glm.hpp" + + +namespace blobs { +namespace math { + +template +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 index 0000000..cb9f07c --- /dev/null +++ b/src/math/SimplexNoise.hpp @@ -0,0 +1,38 @@ +#ifndef BLOBS_MATH_SIMPLEXNOISE_HPP_ +#define BLOBS_MATH_SIMPLEXNOISE_HPP_ + +#include "glm.hpp" + +#include + + +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 index 0000000..f585496 --- /dev/null +++ b/src/math/WorleyNoise.hpp @@ -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 index 0000000..082cca1 --- /dev/null +++ b/src/math/const.hpp @@ -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 index 0000000..4b1bf33 --- /dev/null +++ b/src/math/glm.hpp @@ -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 +#include +#include +#include + +// 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 +inline bool allzero(const T &v) noexcept { + return glm::length2(v) < + std::numeric_limits::epsilon() + * std::numeric_limits::epsilon(); +} + +template +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 index 0000000..5c6f72d --- /dev/null +++ b/src/math/noise.cpp @@ -0,0 +1,212 @@ +#include "GaloisLFSR.hpp" +#include "SimplexNoise.hpp" +#include "WorleyNoise.hpp" + +#include +#include + + +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 index 83dc0e5..0000000 --- a/src/rand/GaloisLFSR.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef BLOBS_RAND_GALOISLFSR_HPP_ -#define BLOBS_RAND_GALOISLFSR_HPP_ - -#include -#include -#include - - -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 - T operator ()(T &out) noexcept { - constexpr int num_bits = - std::numeric_limits::digits + - std::numeric_limits::is_signed; - for (int i = 0; i < num_bits; ++i) { - operator ()(); - } - return out = static_cast(state); - } - - /// special case for randrom(boolean), since static_cast(0b10) == true - bool operator ()(bool &out) noexcept { - return out = operator ()(); - } - - template - T Next() noexcept { - T next; - return (*this)(next); - } - - float SNorm() noexcept { - return float(Next()) * (1.0f / 2147483647.5f) - 1.0f; - } - - float UNorm() noexcept { - return float(Next()) * (1.0f / 4294967295.0f); - } - - template - typename Container::reference From(Container &c) { - assert(c.size() > 0); - return c[Next() % c.size()]; - } - template - typename Container::const_reference From(const Container &c) { - assert(c.size() > 0); - return c[Next() % 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 index 6a91c85..0000000 --- a/src/rand/OctaveNoise.hpp +++ /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 -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 index 9a72e64..0000000 --- a/src/rand/SimplexNoise.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef BLOBS_RAND_SIMPLEXNOISE_HPP_ -#define BLOBS_RAND_SIMPLEXNOISE_HPP_ - -#include "../graphics/glm.hpp" - -#include - - -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 index 34c4871..0000000 --- a/src/rand/WorleyNoise.hpp +++ /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 index 07ab817..0000000 --- a/src/rand/noise.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "GaloisLFSR.hpp" -#include "SimplexNoise.hpp" -#include "WorleyNoise.hpp" - -#include -#include - - -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; -} - -} -} diff --git a/src/ui/Widget.hpp b/src/ui/Widget.hpp index 0f9c8d9..a69defb 100644 --- a/src/ui/Widget.hpp +++ b/src/ui/Widget.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_UI_WIDGET_HPP_ #define BLOBS_UI_WIDGET_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/ui/align.hpp b/src/ui/align.hpp index 15dce20..24fb9a2 100644 --- a/src/ui/align.hpp +++ b/src/ui/align.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_UI_ALIGN_HPP_ #define BLOBS_UI_ALIGN_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/world/Body.hpp b/src/world/Body.hpp index 3db5e37..df68984 100644 --- a/src/world/Body.hpp +++ b/src/world/Body.hpp @@ -2,7 +2,7 @@ #define BLOBS_WORLD_BODY_HPP_ #include "Orbit.hpp" -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" #include diff --git a/src/world/Orbit.hpp b/src/world/Orbit.hpp index 7def521..8ed415e 100644 --- a/src/world/Orbit.hpp +++ b/src/world/Orbit.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_WORLD_ORBIT_HPP_ #define BLOBS_WORLD_ORBIT_HPP_ -#include "../graphics/glm.hpp" +#include "../math/glm.hpp" namespace blobs { diff --git a/src/world/Planet.hpp b/src/world/Planet.hpp index 2274d04..28ecaa0 100644 --- a/src/world/Planet.hpp +++ b/src/world/Planet.hpp @@ -5,8 +5,8 @@ #include "Set.hpp" #include "Tile.hpp" -#include "../graphics/glm.hpp" #include "../graphics/SimpleVAO.hpp" +#include "../math/glm.hpp" #include #include diff --git a/src/world/Resource.hpp b/src/world/Resource.hpp index 6250fc6..492a7f8 100644 --- a/src/world/Resource.hpp +++ b/src/world/Resource.hpp @@ -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; }; diff --git a/src/world/world.cpp b/src/world/world.cpp index 0b1260f..4f98d9a 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -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 #include @@ -421,8 +421,8 @@ void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) { void GenerateEarthlike(const Set &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 &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 &tiles, Planet &p) noexcept { 2, // amplitude 2 // growth ); - float variation = rand::OctaveNoise( + float variation = math::OctaveNoise( variation_gen, to_tile / p.Radius(), 3, // octaves diff --git a/tst/assert.hpp b/tst/assert.hpp index 5042180..66a9704 100644 --- a/tst/assert.hpp +++ b/tst/assert.hpp @@ -1,7 +1,7 @@ #ifndef BLOBS_TEST_ASSETS_HPP_ #define BLOBS_TEST_ASSETS_HPP_ -#include "graphics/glm.hpp" +#include "math/glm.hpp" #include #include diff --git a/tst/math/GaloisLFSRTest.cpp b/tst/math/GaloisLFSRTest.cpp new file mode 100644 index 0000000..958ac76 --- /dev/null +++ b/tst/math/GaloisLFSRTest.cpp @@ -0,0 +1,86 @@ +#include "GaloisLFSRTest.hpp" + +#include "math/GaloisLFSR.hpp" + +#include +#include + +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 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 &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 index 0000000..87c92d6 --- /dev/null +++ b/tst/math/GaloisLFSRTest.hpp @@ -0,0 +1,49 @@ +#ifndef BLOBS_TEST_MATH_GALOISLFSRTEST_HPP +#define BLOBS_TEST_MATH_GALOISLFSRTEST_HPP + +#include + +#include +#include + + +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 &container, + int element); + +}; + +} +} +} + +#endif diff --git a/tst/math/StabilityTest.cpp b/tst/math/StabilityTest.cpp new file mode 100644 index 0000000..8b0011f --- /dev/null +++ b/tst/math/StabilityTest.cpp @@ -0,0 +1,305 @@ +#include "StabilityTest.hpp" + +#include "math/GaloisLFSR.hpp" +#include "math/SimplexNoise.hpp" +#include "math/WorleyNoise.hpp" + +#include +#include +#include +#include + +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(); + 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(); + 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::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::epsilon() + ); +} + +} +} +} diff --git a/tst/math/StabilityTest.hpp b/tst/math/StabilityTest.hpp new file mode 100644 index 0000000..8b6409e --- /dev/null +++ b/tst/math/StabilityTest.hpp @@ -0,0 +1,53 @@ +#ifndef BLOBS_TEST_MATH_STABILITYTEST_HPP +#define BLOBS_TEST_MATH_STABILITYTEST_HPP + +#include "math/glm.hpp" + +#include + + + +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 index 0078207..0000000 --- a/tst/rand/GaloisLFSRTest.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "GaloisLFSRTest.hpp" - -#include "rand/GaloisLFSR.hpp" - -#include -#include - -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 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 &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 index 512bb99..0000000 --- a/tst/rand/GaloisLFSRTest.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BLOBS_TEST_RAND_GALOISLFSRTEST_HPP -#define BLOBS_TEST_RAND_GALOISLFSRTEST_HPP - -#include - -#include -#include - - -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 &container, - int element); - -}; - -} -} -} - -#endif diff --git a/tst/rand/StabilityTest.cpp b/tst/rand/StabilityTest.cpp deleted file mode 100644 index c6c6339..0000000 --- a/tst/rand/StabilityTest.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#include "StabilityTest.hpp" - -#include "rand/GaloisLFSR.hpp" -#include "rand/SimplexNoise.hpp" -#include "rand/WorleyNoise.hpp" - -#include -#include -#include -#include - -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(); - 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(); - 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::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::epsilon() - ); -} - -} -} -} diff --git a/tst/rand/StabilityTest.hpp b/tst/rand/StabilityTest.hpp deleted file mode 100644 index 8f38114..0000000 --- a/tst/rand/StabilityTest.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef BLOBS_TEST_RAND_STABILITYTEST_HPP -#define BLOBS_TEST_RAND_STABILITYTEST_HPP - -#include "graphics/glm.hpp" - -#include - - - -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 diff --git a/tst/world/OrbitTest.cpp b/tst/world/OrbitTest.cpp index ce16909..a7ef681 100644 --- a/tst/world/OrbitTest.cpp +++ b/tst/world/OrbitTest.cpp @@ -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);