X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2Fworld.cpp;h=925046cbd0c9f4a2559822b34821498d362c2f9a;hb=1a237f316ee603e2130dc46b9f7d75a169763543;hp=a852038664a05410292a2e7bdd58ecfb0183f2de;hpb=33b37e7242e4cbfa76e4a0d6e5bb54223b541162;p=blank.git diff --git a/src/world/world.cpp b/src/world/world.cpp index a852038..925046c 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -1,4 +1,5 @@ #include "Entity.hpp" +#include "EntityController.hpp" #include "EntityDerivative.hpp" #include "EntityState.hpp" #include "Player.hpp" @@ -23,18 +24,68 @@ namespace blank { Entity::Entity() noexcept -: model() +: ctrl(nullptr) +, model() , id(-1) , name("anonymous") , bounds() , state() -, tgt_vel(0.0f) +, max_vel(5.0f) +, max_force(25.0f) , ref_count(0) , world_collision(false) -, dead(false) { +, dead(false) +, owns_controller(false) { } +Entity::~Entity() noexcept { + UnsetController(); +} + +Entity::Entity(const Entity &other) noexcept +: ctrl(other.ctrl) +, model(other.model) +, id(-1) +, name(other.name) +, bounds(other.bounds) +, state(other.state) +, max_vel(other.max_vel) +, max_force(other.max_force) +, ref_count(0) +, world_collision(other.world_collision) +, dead(other.dead) +, owns_controller(false) { + +} + +void Entity::SetController(EntityController *c) noexcept { + UnsetController(); + ctrl = c; + owns_controller = true; +} + +void Entity::SetController(EntityController &c) noexcept { + UnsetController(); + ctrl = &c; + owns_controller = false; +} + +void Entity::UnsetController() noexcept { + if (ctrl && owns_controller) { + delete ctrl; + } + ctrl = nullptr; +} + +glm::vec3 Entity::ControlForce(const EntityState &s) const noexcept { + if (HasController()) { + return GetController().ControlForce(*this, s); + } else { + return -s.velocity; + } +} + void Entity::Position(const glm::ivec3 &c, const glm::vec3 &b) noexcept { state.chunk_pos = c; state.block_pos = b; @@ -91,6 +142,40 @@ void Entity::UpdateModel() noexcept { } } +void Entity::Update(float dt) { + if (HasController()) { + GetController().Update(*this, dt); + } +} + + +EntityController::~EntityController() { + +} + +bool EntityController::MaxOutForce( + glm::vec3 &out, + const glm::vec3 &add, + float max +) noexcept { + if (iszero(add) || any(isnan(add))) { + return false; + } + float current = iszero(out) ? 0.0f : length(out); + float remain = max - current; + if (remain <= 0.0f) { + return true; + } + float additional = length(add); + if (additional > remain) { + out += normalize(add) * remain; + return true; + } else { + out += add; + return false; + } +} + EntityState::EntityState() : chunk_pos(0) @@ -396,6 +481,9 @@ bool World::Intersection(const Entity &e, const EntityState &s, std::vector entity.MaxVelocity() * entity.MaxVelocity()) { + next.velocity = normalize(next.velocity) * entity.MaxVelocity(); + } + EntityDerivative out; out.position = next.velocity; out.velocity = CalculateForce(entity, next); // by mass = 1kg @@ -452,18 +544,19 @@ glm::vec3 World::CalculateForce( const Entity &entity, const EntityState &state ) { - return ControlForce(entity, state) + CollisionForce(entity, state) + Gravity(entity, state); + glm::vec3 force(ControlForce(entity, state) + CollisionForce(entity, state) + Gravity(entity, state)); + if (dot(force, force) > entity.MaxControlForce() * entity.MaxControlForce()) { + return normalize(force) * entity.MaxControlForce(); + } else { + return force; + } } glm::vec3 World::ControlForce( const Entity &entity, const EntityState &state ) { - constexpr float k = 10.0f; // spring constant - constexpr float b = 10.0f; // damper constant - const glm::vec3 x(-entity.TargetVelocity()); // endpoint displacement from equilibrium, by 1s, in m - const glm::vec3 v(state.velocity); // relative velocity between endpoints in m/s - return ((-k) * x) - (b * v); // times 1kg/s, in kg*m/s² + return entity.ControlForce(state); } namespace {