]> git.localhorst.tv Git - blobs.git/blobdiff - src/creature/creature.cpp
color conversion tests
[blobs.git] / src / creature / creature.cpp
index 0a8b460c09e8b568af1e138ae7ae962386fc98ca..e118451147fa0e3d88919ecd2a4b96e96698924d 100644 (file)
@@ -11,6 +11,7 @@
 #include "Goal.hpp"
 #include "IdleGoal.hpp"
 #include "../app/Assets.hpp"
+#include "../graphics/color.hpp"
 #include "../math/const.hpp"
 #include "../ui/string.hpp"
 #include "../world/Body.hpp"
@@ -26,6 +27,9 @@
 #include <iostream>
 #include <glm/gtx/io.hpp>
 
+using blobs::graphics::hsl2rgb;
+using blobs::graphics::rgb2hsl;
+
 
 namespace blobs {
 namespace creature {
@@ -182,17 +186,17 @@ void Creature::Ingest(int res, double amount) noexcept {
                // 30% of solids stays in body
                AddMass(res, amount * 0.3 * composition.Compatibility(res));
        } else {
-               // 5% of fluids stays in body
-               AddMass(res, amount * 0.05 * composition.Compatibility(res));
+               // 10% of fluids stays in body
+               AddMass(res, amount * 0.1 * composition.Compatibility(res));
        }
        math::GaloisLFSR &random = sim.Assets().random;
        if (random.UNorm() < AdaptChance()) {
                // change color to be slightly more like resource
                glm::dvec3 color(rgb2hsl(sim.Resources()[res].base_color));
                // solids affect base color, others highlight
-               double p = sim.Resources()[res].state == world::Resource::SOLID ? 0 : 1;
-               double q = random.UInt(3); // hue, sat, or val
-               double r = random.UInt(2); // mean or deviation
+               int p = sim.Resources()[res].state == world::Resource::SOLID ? 0 : 1;
+               int q = random.UInt(3); // hue, sat, or val
+               int r = random.UInt(2); // mean or deviation
                math::Distribution *d = nullptr;
                double ref = 0.0;
                if (p == 0) {
@@ -236,6 +240,20 @@ void Creature::Ingest(int res, double amount) noexcept {
                        d->StandardDeviation(glm::clamp(d->StandardDeviation() * (1.0 + random.SNorm() * 0.15), 0.0001, 0.5));
                }
        }
+       if (sim.Resources()[res].state == world::Resource::LIQUID && random.UNorm() < AdaptChance()) {
+               // change texture randomly
+               // TODO: make change depending on surroundings and/or resource
+               int p = random.UInt(2); // back or side
+               int q = random.UInt(2); // mean or deviation
+               math::Distribution &d = p ? genome.skin_side : genome.skin_back;
+               if (q == 0) {
+                       // move ± one standard deviation
+                       d.Mean(d.Mean() + (random.SNorm() * d.StandardDeviation()));
+               } else {
+                       // scale by ±10%, enforce bounds
+                       d.StandardDeviation(glm::clamp(d.StandardDeviation() * (1.0 + random.SNorm() * 0.1), 0.0001, 0.5));
+               }
+       }
 }
 
 void Creature::DoWork(double amount) noexcept {
@@ -631,7 +649,16 @@ void Creature::BuildVAO() {
        vao->ReserveAttributes(6 * 4, GL_STATIC_DRAW);
        {
                auto attrib = vao->MapAttributes(GL_WRITE_ONLY);
-               const float offset = 1.0f;
+               constexpr float offset = 1.0f;
+               constexpr float max_tex = 5.999f;
+               const float tex[6] = {
+                       0.0f, // face
+                       float(std::floor(skin_side * max_tex)), // left
+                       float(std::floor(skin_back * max_tex)), // top
+                       float(std::floor(skin_back * max_tex)), // back
+                       float(std::floor(skin_side * max_tex)), // right
+                       0.0f, // bottom
+               };
                for (int surface = 0; surface < 6; ++surface) {
                        const float tex_u_begin = surface < 3 ? 1.0f : 0.0f;
                        const float tex_u_end = surface < 3 ? 0.0f : 1.0f;
@@ -644,7 +671,7 @@ void Creature::BuildVAO() {
                        attrib[4 * surface + 0].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
                        attrib[4 * surface + 0].texture.x = tex_u_begin;
                        attrib[4 * surface + 0].texture.y = 1.0f;
-                       attrib[4 * surface + 0].texture.z = surface;
+                       attrib[4 * surface + 0].texture.z = tex[surface];
 
                        attrib[4 * surface + 1].position[(surface + 0) % 3] = -offset;
                        attrib[4 * surface + 1].position[(surface + 1) % 3] =  offset;
@@ -654,7 +681,7 @@ void Creature::BuildVAO() {
                        attrib[4 * surface + 1].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
                        attrib[4 * surface + 1].texture.x = tex_u_end;
                        attrib[4 * surface + 1].texture.y = 1.0f;
-                       attrib[4 * surface + 1].texture.z = surface;
+                       attrib[4 * surface + 1].texture.z = tex[surface];
 
                        attrib[4 * surface + 2].position[(surface + 0) % 3] =  offset;
                        attrib[4 * surface + 2].position[(surface + 1) % 3] = -offset;
@@ -664,7 +691,7 @@ void Creature::BuildVAO() {
                        attrib[4 * surface + 2].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
                        attrib[4 * surface + 2].texture.x = tex_u_begin;
                        attrib[4 * surface + 2].texture.y = 0.0f;
-                       attrib[4 * surface + 2].texture.z = surface;
+                       attrib[4 * surface + 2].texture.z = tex[surface];
 
                        attrib[4 * surface + 3].position[(surface + 0) % 3] = offset;
                        attrib[4 * surface + 3].position[(surface + 1) % 3] = offset;
@@ -674,7 +701,7 @@ void Creature::BuildVAO() {
                        attrib[4 * surface + 3].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
                        attrib[4 * surface + 3].texture.x = tex_u_end;
                        attrib[4 * surface + 3].texture.y = 0.0f;
-                       attrib[4 * surface + 3].texture.z = surface;
+                       attrib[4 * surface + 3].texture.z = tex[surface];
                }
        }
        vao->BindElements();
@@ -759,7 +786,7 @@ void Spawn(Creature &c, world::Planet &p) {
        double color_divisor = 0.0;
 
        if (p.HasAtmosphere()) {
-               c.AddMass(p.Atmosphere(), 0.01);
+               c.AddMass(p.Atmosphere(), 0.005);
                color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color * 0.1;
                color_divisor += 0.1;
        }
@@ -786,6 +813,9 @@ void Spawn(Creature &c, world::Planet &p) {
        genome.highlight_saturation = { 1.0 - hsl.y, 0.01 };
        genome.highlight_lightness = { 1.0 - hsl.z, 0.01 };
 
+       genome.skin_side = { 0.5, 0.01 };
+       genome.skin_back = { 0.5, 0.01 };
+
        genome.Configure(c);
 }
 
@@ -817,6 +847,8 @@ void Genome::Configure(Creature &c) const {
        );
        c.BaseColor(hsl2rgb(base_color));
        c.HighlightColor(hsl2rgb(highlight_color));
+       c.BackSkin(glm::clamp(skin_back.FakeNormal(random.SNorm()), 0.0, 1.0));
+       c.SideSkin(glm::clamp(skin_side.FakeNormal(random.SNorm()), 0.0, 1.0));
        c.SetBackgroundTask(std::unique_ptr<Goal>(new BlobBackgroundTask(c)));
        c.AddGoal(std::unique_ptr<Goal>(new IdleGoal(c)));
 }
@@ -829,7 +861,10 @@ void Split(Creature &c) {
        a->Name(c.GetSimulation().Assets().name.Sequential());
        c.GetGenome().Configure(*a);
        for (const auto &cmp : c.GetComposition()) {
-               a->AddMass(cmp.resource, cmp.value * 0.5);
+               // require at least 0.1%
+               if (cmp.value > 0.002) {
+                       a->AddMass(cmp.resource, cmp.value * 0.5);
+               }
        }
        s.GetPlanet().AddCreature(a);
        // TODO: duplicate situation somehow
@@ -844,7 +879,10 @@ void Split(Creature &c) {
        b->Name(c.GetSimulation().Assets().name.Sequential());
        c.GetGenome().Configure(*b);
        for (const auto &cmp : c.GetComposition()) {
-               b->AddMass(cmp.resource, cmp.value * 0.5);
+               // require at least 0.1%
+               if (cmp.value > 0.002) {
+                       b->AddMass(cmp.resource, cmp.value * 0.5);
+               }
        }
        s.GetPlanet().AddCreature(b);
        b->GetSituation().SetPlanetSurface(