]> git.localhorst.tv Git - blobs.git/commitdiff
use RK4 to integrate creature state
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 27 Nov 2017 21:05:20 +0000 (22:05 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 27 Nov 2017 21:05:20 +0000 (22:05 +0100)
src/creature/Creature.hpp
src/creature/Situation.hpp
src/creature/Steering.hpp
src/creature/creature.cpp
src/creature/goal.cpp

index 7c06cc81d876a1c1464552c4c38e1807db4bf221..e2f9b446ab010600a4541d78449d21f949aea168 100644 (file)
@@ -94,15 +94,14 @@ public:
        Steering &GetSteering() noexcept { return steering; }
        const Steering &GetSteering() const noexcept { return steering; }
 
-       void Velocity(const glm::dvec3 &v) noexcept { vel = v; }
-       const glm::dvec3 &Velocity() const noexcept { return vel; }
-       bool Moving() const noexcept { return glm::length2(vel) < 0.00000001; }
-
        glm::dmat4 LocalTransform() noexcept;
 
        void BuildVAO();
        void Draw(graphics::Viewport &);
 
+private:
+       Situation::Derivative Step(const Situation::Derivative &ds, double dt) const noexcept;
+
 private:
        world::Simulation &sim;
        std::string name;
@@ -127,8 +126,6 @@ private:
        Situation situation;
        Steering steering;
 
-       glm::dvec3 vel;
-
        struct Attributes {
                glm::vec3 position;
                glm::vec3 normal;
index a60aeb7aa27ee55595210ef8cf0924ebdd6fc319..a12f4224c64ca9d9dcb5d8ab6cd4bc4ddb1f13ab 100644 (file)
@@ -14,6 +14,24 @@ namespace creature {
 
 class Situation {
 
+public:
+       struct State {
+               glm::dvec3 pos;
+               glm::dvec3 vel;
+               State(
+                       const glm::dvec3 &pos = glm::dvec3(0.0),
+                       const glm::dvec3 &vel = glm::dvec3(0.0))
+               : pos(pos), vel(vel) { }
+       };
+       struct Derivative {
+               glm::dvec3 vel;
+               glm::dvec3 acc;
+               Derivative(
+                       const glm::dvec3 &vel = glm::dvec3(0.0),
+                       const glm::dvec3 &acc = glm::dvec3(0.0))
+               : vel(vel), acc(acc) { }
+       };
+
 public:
        Situation();
        ~Situation();
@@ -29,18 +47,22 @@ public:
        world::Planet &GetPlanet() const noexcept { return *planet; }
        bool OnSurface() const noexcept;
        int Surface() const noexcept { return surface; }
-       const glm::dvec3 &Position() const noexcept { return position; }
+       const glm::dvec3 &Position() const noexcept { return state.pos; }
        bool OnTile() const noexcept;
        glm::ivec2 SurfacePosition() const noexcept;
        world::Tile &GetTile() const noexcept;
        const world::TileType &GetTileType() const noexcept;
 
+       void SetState(const State &s) noexcept { state = s; }
+       const State &GetState() const noexcept { return state; }
+
+       bool Moving() const noexcept { return glm::length2(state.vel) < 0.00000001; }
        void Move(const glm::dvec3 &dp) noexcept;
        void SetPlanetSurface(world::Planet &, int srf, const glm::dvec3 &pos) noexcept;
 
 public:
        world::Planet *planet;
-       glm::dvec3 position;
+       State state;
        int surface;
        enum {
                LOST,
index 51f2c63db710bc098d689f540ef00801a050cadb..3ccf9e3d492dda6fa585849d0e393f7c81993ec9 100644 (file)
@@ -1,14 +1,13 @@
 #ifndef BLOBS_CREATURE_STEERING_HPP_
 #define BLOBS_CREATURE_STEERING_HPP_
 
+#include "Situation.hpp"
 #include "../math/glm.hpp"
 
 
 namespace blobs {
 namespace creature {
 
-class Creature;
-
 class Steering {
 
 public:
@@ -26,7 +25,7 @@ public:
        void Halt() noexcept;
        void GoTo(const glm::dvec3 &) noexcept;
 
-       glm::dvec3 Acceleration(Creature &) const noexcept;
+       glm::dvec3 Acceleration(const Situation::State &) const noexcept;
 
 private:
        bool SumForce(glm::dvec3 &out, const glm::dvec3 &in) const noexcept;
index f51f52ca4a16427cf75ab870577b8f5e71df45b6..d870755cfa8ae46607c62d7b4be120c5755b290c 100644 (file)
@@ -43,7 +43,6 @@ Creature::Creature(world::Simulation &sim)
 , goals()
 , situation()
 , steering()
-, vel(0.0)
 , vao() {
 }
 
@@ -106,10 +105,20 @@ bool GoalCompare(const std::unique_ptr<Goal> &a, const std::unique_ptr<Goal> &b)
 }
 
 void Creature::Tick(double dt) {
-       // TODO: better integration method
-       glm::dvec3 acc(steering.Acceleration(*this));
-       situation.Move(vel * dt);
-       vel += acc * dt;
+       {
+               Situation::State state(situation.GetState());
+               Situation::Derivative a(Step(Situation::Derivative(), 0.0));
+               Situation::Derivative b(Step(a, dt * 0.5));
+               Situation::Derivative c(Step(b, dt * 0.5));
+               Situation::Derivative d(Step(c, dt));
+               Situation::Derivative f(
+                       (1.0 / 6.0) * (a.vel + 2.0 * (b.vel + c.vel) + d.vel),
+                       (1.0 / 6.0) * (a.acc + 2.0 * (b.acc + c.acc) + d.acc)
+               );
+               state.pos += f.vel * dt;
+               state.vel += f.acc * dt;
+               situation.SetState(state);
+       }
 
        if (Age() > properties.death_age) {
                std::cout << "[" << int(sim.Time()) << "s] "
@@ -153,6 +162,13 @@ void Creature::Tick(double dt) {
        }
 }
 
+Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) const noexcept {
+       Situation::State s = situation.GetState();
+       s.pos += ds.vel * dt;
+       s.vel += ds.acc * dt;
+       return { s.vel, steering.Acceleration(s) };
+}
+
 glm::dmat4 Creature::LocalTransform() noexcept {
        // TODO: surface transform
        const double half_size = size * 0.5;
@@ -445,7 +461,7 @@ std::string NameGenerator::Sequential() {
 
 Situation::Situation()
 : planet(nullptr)
-, position(0.0)
+, state(glm::dvec3(0.0), glm::dvec3(0.0))
 , surface(0)
 , type(LOST) {
 }
@@ -462,34 +478,34 @@ bool Situation::OnSurface() const noexcept {
 }
 
 bool Situation::OnTile() const noexcept {
-       glm::ivec2 t(planet->SurfacePosition(surface, position));
+       glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
        return type == PLANET_SURFACE
                && t.x >= 0 && t.x < planet->SideLength()
                && t.y >= 0 && t.y < planet->SideLength();
 }
 
 glm::ivec2 Situation::SurfacePosition() const noexcept {
-       return planet->SurfacePosition(surface, position);
+       return planet->SurfacePosition(surface, state.pos);
 }
 
 world::Tile &Situation::GetTile() const noexcept {
-       glm::ivec2 t(planet->SurfacePosition(surface, position));
+       glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
        return planet->TileAt(surface, t.x, t.y);
 }
 
 const world::TileType &Situation::GetTileType() const noexcept {
-       glm::ivec2 t(planet->SurfacePosition(surface, position));
+       glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
        return planet->TypeAt(surface, t.x, t.y);
 }
 
 void Situation::Move(const glm::dvec3 &dp) noexcept {
-       position += dp;
+       state.pos += dp;
        if (OnSurface()) {
                // enforce ground constraint
                if (Surface() < 3) {
-                       position[(Surface() + 2) % 3] = std::max(0.0, position[(Surface() + 2) % 3]);
+                       state.pos[(Surface() + 2) % 3] = std::max(0.0, state.pos[(Surface() + 2) % 3]);
                } else {
-                       position[(Surface() + 2) % 3] = std::min(0.0, position[(Surface() + 2) % 3]);
+                       state.pos[(Surface() + 2) % 3] = std::min(0.0, state.pos[(Surface() + 2) % 3]);
                }
        }
 }
@@ -498,7 +514,7 @@ void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &po
        type = PLANET_SURFACE;
        planet = &p;
        surface = srf;
-       position = pos;
+       state.pos = pos;
 }
 
 
@@ -524,15 +540,15 @@ void Steering::GoTo(const glm::dvec3 &t) noexcept {
        seeking = true;
 }
 
-glm::dvec3 Steering::Acceleration(Creature &c) const noexcept {
+glm::dvec3 Steering::Acceleration(const Situation::State &s) const noexcept {
        glm::dvec3 acc(0.0);
        if (halting) {
-               SumForce(acc, c.Velocity() * -max_accel);
+               SumForce(acc, s.vel * -max_accel);
        }
        if (seeking) {
-               glm::dvec3 diff = seek_target - c.GetSituation().Position();
+               glm::dvec3 diff = seek_target - s.pos;
                if (!allzero(diff)) {
-                       SumForce(acc, ((normalize(diff) * max_speed) - c.Velocity()) * max_accel);
+                       SumForce(acc, ((normalize(diff) * max_speed) - s.vel) * max_accel);
                }
        }
        return acc;
index 8f8a3fa88f2911d2c6e0be6506cd43974df11d7e..ee51a919ba11a71ff7081262b4ebd3f9076c5d10 100644 (file)
@@ -138,7 +138,7 @@ void LocateResourceGoal::Action() {
                }
        } else if (OnTargetTile()) {
                GetSteering().Halt();
-               if (!GetCreature().Moving()) {
+               if (!GetSituation().Moving()) {
                        SetComplete();
                }
        } else {