]> git.localhorst.tv Git - blobs.git/commitdiff
slightly better physics
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sat, 2 Dec 2017 18:10:06 +0000 (19:10 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sat, 2 Dec 2017 18:10:06 +0000 (19:10 +0100)
src/creature/Situation.hpp
src/creature/creature.cpp
src/ui/CreaturePanel.hpp
src/ui/ui.cpp
src/world/CreatureCreatureCollision.hpp
src/world/world.cpp

index 4205cff449c8e0f1d57cdaedd39c56662c62ddd2..3c4a28a567ef4877b09ad68c94575c12545179cf 100644 (file)
@@ -66,6 +66,8 @@ public:
        const glm::dvec3 &Velocity() const noexcept { return state.vel; }
        bool Moving() const noexcept { return glm::length2(state.vel) > 0.0000001; }
        void Move(const glm::dvec3 &dp) noexcept;
+       void Accelerate(const glm::dvec3 &dv) noexcept;
+       void EnforceConstraints(State &) noexcept;
 
        void Heading(const glm::dvec3 &h) noexcept { state.dir = h; }
        const glm::dvec3 &Heading() const noexcept { return state.dir; }
index dc857ceb08bd637460ee7b4954a95e7c17dd0275..b95b531a13097041c2b7e835d4d69483f3798446 100644 (file)
@@ -278,10 +278,11 @@ void Creature::TickState(double dt) {
        );
        state.pos += f.vel * dt;
        state.vel += f.acc * dt;
+       situation.EnforceConstraints(state);
        if (length2(state.vel) > 0.000001) {
                glm::dvec3 nvel(normalize(state.vel));
                double ang = angle(nvel, state.dir);
-               double turn_rate = PI * 0.5 * dt;
+               double turn_rate = PI * 0.75 * dt;
                if (ang < turn_rate) {
                        state.dir = normalize(state.vel);
                } else if (std::abs(ang - PI) < 0.001) {
@@ -291,16 +292,33 @@ void Creature::TickState(double dt) {
                }
        }
        situation.SetState(state);
-       stats.Exhaustion().Add(length(f.acc) * Mass() / Stamina() * dt);
+       stats.Exhaustion().Add(length(f.acc) * Mass() / Stamina() * 0.5 * 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;
+       glm::dvec3 force(steering.Force(s));
+       // gravity = antinormal * mass * Gm / r²
+       double elevation = s.pos[(situation.Surface() + 2) % 3];
+       glm::dvec3 normal(world::Planet::SurfaceNormal(situation.Surface()));
+       force += glm::dvec3(
+               -normal
+               * Mass() * situation.GetPlanet().GravitationalParameter()
+               / (elevation * elevation));
+       // if net force is applied and in contact with surface
+       if (!allzero(force) && std::abs(std::abs(elevation) - situation.GetPlanet().Radius()) < 0.001) {
+               // apply friction = -|normal force| * tangential force * coefficient
+               glm::dvec3 fn(normal * dot(force, normal));
+               glm::dvec3 ft(force - fn);
+               double u = 0.4;
+               glm::dvec3 friction(-length(fn) * ft * u);
+               force += friction;
+       }
        return {
                s.vel,
-               steering.Force(s) / Mass()
+               force / Mass()
        };
 }
 
@@ -576,7 +594,7 @@ void Split(Creature &c) {
        // TODO: duplicate situation somehow
        a->GetSituation().SetPlanetSurface(
                s.GetPlanet(), s.Surface(),
-               s.Position() + glm::dvec3(0.0, a->Size() + 0.1, 0.0));
+               s.Position() + glm::dvec3(0.0, 0.55 * a->Size(), 0.0));
        a->BuildVAO();
        std::cout << "[" << int(c.GetSimulation().Time()) << "s] "
                << a->Name() << " was born" << std::endl;
@@ -590,7 +608,7 @@ void Split(Creature &c) {
        s.GetPlanet().AddCreature(b);
        b->GetSituation().SetPlanetSurface(
                s.GetPlanet(), s.Surface(),
-               s.Position() + glm::dvec3(0.0, b->Size() - 0.1, 0.0));
+               s.Position() - glm::dvec3(0.0, 0.55 * b->Size(), 0.0));
        b->BuildVAO();
        std::cout << "[" << int(c.GetSimulation().Time()) << "s] "
                << b->Name() << " was born" << std::endl;
@@ -700,12 +718,26 @@ const world::TileType &Situation::GetTileType() const noexcept {
 
 void Situation::Move(const glm::dvec3 &dp) noexcept {
        state.pos += dp;
+       EnforceConstraints(state);
+}
+
+void Situation::Accelerate(const glm::dvec3 &dv) noexcept {
+       state.vel += dv;
+       EnforceConstraints(state);
+}
+
+void Situation::EnforceConstraints(State &s) noexcept {
        if (OnSurface()) {
-               // enforce ground constraint
                if (Surface() < 3) {
-                       state.pos[(Surface() + 2) % 3] = std::max(0.0, state.pos[(Surface() + 2) % 3]);
+                       if (s.pos[(Surface() + 2) % 3] < GetPlanet().Radius()) {
+                               s.pos[(Surface() + 2) % 3] = GetPlanet().Radius();
+                               s.vel[(Surface() + 2) % 3] = std::max(0.0, s.vel[(Surface() + 2) % 3]);
+                       }
                } else {
-                       state.pos[(Surface() + 2) % 3] = std::min(0.0, state.pos[(Surface() + 2) % 3]);
+                       if (s.pos[(Surface() + 2) % 3] > -GetPlanet().Radius()) {
+                               s.pos[(Surface() + 2) % 3] = -GetPlanet().Radius();
+                               s.vel[(Surface() + 2) % 3] = std::min(0.0, s.vel[(Surface() + 2) % 3]);
+                       }
                }
        }
 }
@@ -715,6 +747,7 @@ void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &po
        planet = &p;
        surface = srf;
        state.pos = pos;
+       EnforceConstraints(state);
 }
 
 
@@ -746,7 +779,7 @@ void Steering::DontSeparate() noexcept {
 }
 
 void Steering::ResumeSeparate() noexcept {
-       separating = false;
+       separating = true;
 }
 
 void Steering::Halt() noexcept {
index 864fede83c983756ad5f2af333b984bc37c62b53..967e03914a4c023fffb92eaefa907554b7452942 100644 (file)
@@ -52,6 +52,8 @@ private:
        Label *age;
        Label *mass;
        Label *pos;
+       Label *vel;
+       Label *dir;
        Label *tile;
        Label *goal;
        Meter *stats[7];
index 91ae1062fe4a176157ff5d7ee0e5d0505dd72710..becfb9813297002ac0d638b5d84e3bea2051f887 100644 (file)
@@ -24,6 +24,8 @@ CreaturePanel::CreaturePanel(const app::Assets &assets)
 , age(new Label(assets.fonts.medium))
 , mass(new Label(assets.fonts.medium))
 , pos(new Label(assets.fonts.medium))
+, vel(new Label(assets.fonts.medium))
+, dir(new Label(assets.fonts.medium))
 , tile(new Label(assets.fonts.medium))
 , goal(new Label(assets.fonts.medium))
 , stats{nullptr}
@@ -69,6 +71,26 @@ CreaturePanel::CreaturePanel(const app::Assets &assets)
                ->Spacing(10.0f)
                ->Direction(Panel::HORIZONTAL);
 
+       vel->Text("<00.0, 00.0, 00.0>");
+       Label *vel_label = new Label(assets.fonts.medium);
+       vel_label->Text("Vel");
+       Panel *vel_panel = new Panel;
+       vel_panel
+               ->Add(vel_label)
+               ->Add(vel)
+               ->Spacing(10.0f)
+               ->Direction(Panel::HORIZONTAL);
+
+       dir->Text("<0.00, 0.00, 0.00>");
+       Label *dir_label = new Label(assets.fonts.medium);
+       dir_label->Text("Dir");
+       Panel *dir_panel = new Panel;
+       dir_panel
+               ->Add(dir_label)
+               ->Add(dir)
+               ->Spacing(10.0f)
+               ->Direction(Panel::HORIZONTAL);
+
        tile->Text("<00, 00> (mountains)");
        Label *tile_label = new Label(assets.fonts.medium);
        tile_label->Text("Tile");
@@ -165,6 +187,8 @@ CreaturePanel::CreaturePanel(const app::Assets &assets)
                ->Add(born_panel)
                ->Add(mass_panel)
                ->Add(pos_panel)
+               ->Add(vel_panel)
+               ->Add(dir_panel)
                ->Add(tile_panel)
                ->Add(goal_panel)
                ->Add(stat_panel)
@@ -201,6 +225,20 @@ void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noex
                        << "<" << p.x << ", " << p.y << ", " << p.z << ">";
                pos->Text(ss.str());
        }
+       {
+               const glm::dvec3 &v = c->GetSituation().Velocity();
+               std::stringstream ss;
+               ss << std::fixed << std::setprecision(1)
+                       << "<" << v.x << ", " << v.y << ", " << v.z << ">";
+               vel->Text(ss.str());
+       }
+       {
+               const glm::dvec3 &d = c->GetSituation().GetState().dir;
+               std::stringstream ss;
+               ss << std::fixed << std::setprecision(2)
+                       << "<" << d.x << ", " << d.y << ", " << d.z << ">";
+               dir->Text(ss.str());
+       }
        {
                glm::ivec2 t = c->GetSituation().SurfacePosition();
                std::stringstream ss;
index 1a903ec54428b516eb59efe9224001fde2b8cdb5..a26b050a8b637a771114261cfa6e5afe4fa27ef3 100644 (file)
@@ -30,10 +30,12 @@ public:
        creature::Creature &A() noexcept { return *a; }
        const creature::Creature &A() const noexcept { return *a; }
        const glm::dvec3 &APos() const noexcept;
+       const glm::dvec3 &AVel() const noexcept;
 
        creature::Creature &B() noexcept { return *b; }
        const creature::Creature &B() const noexcept { return *b; }
        const glm::dvec3 &BPos() const noexcept;
+       const glm::dvec3 &BVel() const noexcept;
 
        const glm::dvec3 &Normal() const noexcept { return normal; }
        double Depth() const noexcept { return depth; }
index 9cd1e02df56a7f185a299f3337248cfbb22f417e..d7e293a5509d2d456c88cbca5b09daa44fdb49ba 100644 (file)
@@ -208,7 +208,8 @@ void Body::CheckCollision() noexcept {
        for (auto &c : collisions) {
                c.A().GetSituation().Move(c.Normal() * (c.Depth() * -0.5));
                c.B().GetSituation().Move(c.Normal() * (c.Depth() * 0.5));
-               // TODO: adjust velocities as well
+               c.A().GetSituation().Accelerate(c.Normal() * -dot(c.Normal(), c.AVel()));
+               c.B().GetSituation().Accelerate(c.Normal() * -dot(c.Normal(), c.BVel()));
                // TODO: notify participants so they can be annoyed
        }
 }
@@ -232,10 +233,18 @@ const glm::dvec3 &CreatureCreatureCollision::APos() const noexcept {
        return a->GetSituation().Position();
 }
 
+const glm::dvec3 &CreatureCreatureCollision::AVel() const noexcept {
+       return a->GetSituation().Velocity();
+}
+
 const glm::dvec3 &CreatureCreatureCollision::BPos() const noexcept {
        return b->GetSituation().Position();
 }
 
+const glm::dvec3 &CreatureCreatureCollision::BVel() const noexcept {
+       return b->GetSituation().Velocity();
+}
+
 
 Orbit::Orbit()
 : sma(1.0)