From 8e9e2bb4b2dd5a4100f4531628ab58002fe253c1 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Wed, 28 Oct 2015 14:52:24 +0100 Subject: [PATCH] cache some basic entity axes --- src/ai/AIController.hpp | 14 +++++------- src/ai/ai.cpp | 43 ++++++++++++++--------------------- src/client/net.cpp | 1 - src/world/Entity.hpp | 13 +++++++++-- src/world/world.cpp | 50 ++++++++++++++++++++++++----------------- 5 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/ai/AIController.hpp b/src/ai/AIController.hpp index bd88290..cda3e8a 100644 --- a/src/ai/AIController.hpp +++ b/src/ai/AIController.hpp @@ -28,8 +28,6 @@ public: glm::vec3 ControlForce(const Entity &, const EntityState &) const override; - static glm::vec3 Heading(const EntityState &) noexcept; - /// get the closest player that given entity can see /// returns nullptr if none are in sight Player *ClosestVisiblePlayer(const Entity &) noexcept; @@ -54,7 +52,7 @@ public: void ExitHalt() noexcept; bool IsHalted() const noexcept; void SetHaltSpeed(float) noexcept; - glm::vec3 GetHaltForce(const EntityState &) const noexcept; + glm::vec3 GetHaltForce(const Entity &, const EntityState &) const noexcept; void StartFleeing() noexcept; void StopFleeing() noexcept; @@ -63,7 +61,7 @@ public: void SetFleeSpeed(float) noexcept; Entity &GetFleeTarget() noexcept; const Entity &GetFleeTarget() const noexcept; - glm::vec3 GetFleeForce(const EntityState &) const noexcept; + glm::vec3 GetFleeForce(const Entity &, const EntityState &) const noexcept; void StartSeeking() noexcept; void StopSeeking() noexcept; @@ -72,7 +70,7 @@ public: void SetSeekSpeed(float) noexcept; Entity &GetSeekTarget() noexcept; const Entity &GetSeekTarget() const noexcept; - glm::vec3 GetSeekForce(const EntityState &) const noexcept; + glm::vec3 GetSeekForce(const Entity &, const EntityState &) const noexcept; void StartEvading() noexcept; void StopEvading() noexcept; @@ -81,7 +79,7 @@ public: void SetEvadeSpeed(float) noexcept; Entity &GetEvadeTarget() noexcept; const Entity &GetEvadeTarget() const noexcept; - glm::vec3 GetEvadeForce(const EntityState &) const noexcept; + glm::vec3 GetEvadeForce(const Entity &, const EntityState &) const noexcept; void StartPursuing() noexcept; void StopPursuing() noexcept; @@ -90,7 +88,7 @@ public: void SetPursuitSpeed(float) noexcept; Entity &GetPursuitTarget() noexcept; const Entity &GetPursuitTarget() const noexcept; - glm::vec3 GetPursuitForce(const EntityState &) const noexcept; + glm::vec3 GetPursuitForce(const Entity &, const EntityState &) const noexcept; /// start wandering randomly void StartWandering() noexcept; @@ -106,7 +104,7 @@ public: float radius = 1.0f, float displacement = 1.0f ) noexcept; - glm::vec3 GetWanderForce(const EntityState &) const noexcept; + glm::vec3 GetWanderForce(const Entity &, const EntityState &) const noexcept; private: World &world; diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 11add89..ff39127 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -86,7 +86,7 @@ void AIController::Update(Entity &e, float dt) { if (e.Moving()) { // orient head towards heading - glm::vec3 heading(Heading(e.GetState())); + glm::vec3 heading(e.Heading()); float tgt_pitch = std::atan(heading.y / length(glm::vec2(heading.x, heading.z))); float tgt_yaw = std::atan2(-heading.x, -heading.z); e.SetHead(tgt_pitch, tgt_yaw); @@ -95,46 +95,37 @@ void AIController::Update(Entity &e, float dt) { glm::vec3 AIController::ControlForce(const Entity &entity, const EntityState &state) const { if (IsHalted()) { - return GetHaltForce(state); + return GetHaltForce(entity, state); } glm::vec3 force(0.0f); if (IsFleeing()) { - if (MaxOutForce(force, GetFleeForce(state), entity.MaxControlForce())) { + if (MaxOutForce(force, GetFleeForce(entity, state), entity.MaxControlForce())) { return force; } } if (IsSeeking()) { - if (MaxOutForce(force, GetSeekForce(state), entity.MaxControlForce())) { + if (MaxOutForce(force, GetSeekForce(entity, state), entity.MaxControlForce())) { return force; } } if (IsEvading()) { - if (MaxOutForce(force, GetEvadeForce(state), entity.MaxControlForce())) { + if (MaxOutForce(force, GetEvadeForce(entity, state), entity.MaxControlForce())) { return force; } } if (IsPursuing()) { - if (MaxOutForce(force, GetPursuitForce(state), entity.MaxControlForce())) { + if (MaxOutForce(force, GetPursuitForce(entity, state), entity.MaxControlForce())) { return force; } } if (IsWandering()) { - if (MaxOutForce(force, GetWanderForce(state), entity.MaxControlForce())) { + if (MaxOutForce(force, GetWanderForce(entity, state), entity.MaxControlForce())) { return force; } } return force; } -glm::vec3 AIController::Heading(const EntityState &state) noexcept { - if (dot(state.velocity, state.velocity) > std::numeric_limits::epsilon()) { - return normalize(state.velocity); - } else { - float cp = std::cos(state.pitch); - return glm::vec3(std::cos(state.yaw) * cp, std::sin(state.yaw) * cp, std::sin(state.pitch)); - } -} - Player *AIController::ClosestVisiblePlayer(const Entity &e) noexcept { Player *target = nullptr; float distance = sight_dist; @@ -145,17 +136,17 @@ Player *AIController::ClosestVisiblePlayer(const Entity &e) noexcept { // distance test const glm::vec3 diff(pe.AbsoluteDifference(e)); - float dist = length_squared(diff); + float dist = length(diff); if (dist > distance) continue; // FOV test, 45° in each direction - if (dot(normalize(diff), aim.dir) < sight_angle) { + if (dot(diff / dist, aim.dir) < sight_angle) { continue; } // LOS test, assumes all entities are see-through WorldCollision col; - if (world.Intersection(aim, glm::mat4(1.0f), reference, col) && col.depth * col.depth < dist) { + if (world.Intersection(aim, glm::mat4(1.0f), reference, col) && col.depth < dist) { continue; } @@ -228,7 +219,7 @@ void AIController::SetHaltSpeed(float speed) noexcept { halt_speed = speed; } -glm::vec3 AIController::GetHaltForce(const EntityState &state) const noexcept { +glm::vec3 AIController::GetHaltForce(const Entity &, const EntityState &state) const noexcept { return Halt(state, halt_speed); } @@ -270,7 +261,7 @@ const Entity &AIController::GetFleeTarget() const noexcept { return *flee_target; } -glm::vec3 AIController::GetFleeForce(const EntityState &state) const noexcept { +glm::vec3 AIController::GetFleeForce(const Entity &, const EntityState &state) const noexcept { return Flee(state, GetFleeTarget().GetState(), flee_speed, 2.0f); } @@ -312,7 +303,7 @@ const Entity &AIController::GetSeekTarget() const noexcept { return *seek_target; } -glm::vec3 AIController::GetSeekForce(const EntityState &state) const noexcept { +glm::vec3 AIController::GetSeekForce(const Entity &, const EntityState &state) const noexcept { return Seek(state, GetSeekTarget().GetState(), seek_speed, 2.0f); } @@ -354,7 +345,7 @@ const Entity &AIController::GetEvadeTarget() const noexcept { return *evade_target; } -glm::vec3 AIController::GetEvadeForce(const EntityState &state) const noexcept{ +glm::vec3 AIController::GetEvadeForce(const Entity &, const EntityState &state) const noexcept{ glm::vec3 cur_diff(state.Diff(GetEvadeTarget().GetState())); float time_estimate = length(cur_diff) / evade_speed; EntityState pred_state(GetEvadeTarget().GetState()); @@ -400,7 +391,7 @@ const Entity &AIController::GetPursuitTarget() const noexcept { return *pursuit_target; } -glm::vec3 AIController::GetPursuitForce(const EntityState &state) const noexcept { +glm::vec3 AIController::GetPursuitForce(const Entity &, const EntityState &state) const noexcept { glm::vec3 cur_diff(state.Diff(GetPursuitTarget().GetState())); float time_estimate = length(cur_diff) / pursuit_speed; EntityState pred_state(GetPursuitTarget().GetState()); @@ -434,8 +425,8 @@ void AIController::SetWanderParams( wander_disp = displacement; } -glm::vec3 AIController::GetWanderForce(const EntityState &state) const noexcept { - glm::vec3 wander_target(normalize(Heading(state) * wander_dist + wander_pos) * wander_speed); +glm::vec3 AIController::GetWanderForce(const Entity &e, const EntityState &state) const noexcept { + glm::vec3 wander_target(normalize(e.Heading() * wander_dist + wander_pos) * wander_speed); return TargetVelocity(wander_target, state, 0.5f); } diff --git a/src/client/net.cpp b/src/client/net.cpp index 18f593a..aba3e76 100644 --- a/src/client/net.cpp +++ b/src/client/net.cpp @@ -398,7 +398,6 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr vector col; while (entry != end) { - replay.Velocity(entry->state.velocity); SetMovement(entry->movement); GetWorld().Update(replay, entry->delta_t); entry->state.chunk_pos = replay.GetState().chunk_pos; diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index 33eeb7d..efd9224 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -62,7 +62,6 @@ public: glm::vec3 ControlForce(const EntityState &) const noexcept; const glm::vec3 &Velocity() const noexcept { return state.velocity; } - void Velocity(const glm::vec3 &v) noexcept { state.velocity = v; } bool Moving() const noexcept { return dot(Velocity(), Velocity()) > std::numeric_limits::epsilon(); @@ -83,7 +82,6 @@ public: /// orientation of local coordinate system const glm::quat &Orientation() const noexcept { return state.orient; } - void Orientation(const glm::quat &o) noexcept { state.orient = o; } /// orientation of head within local coordinate system, in radians float Pitch() const noexcept { return state.pitch; } @@ -98,6 +96,8 @@ public: /// get a ray in entity's face direction originating from center of vision Ray Aim(const Chunk::Pos &chunk_offset) const noexcept; + const glm::vec3 &Heading() const noexcept { return heading; } + void SetState(const EntityState &s) noexcept { state = s; UpdateModel(); } const EntityState &GetState() const noexcept { return state; } @@ -116,6 +116,8 @@ public: private: void UpdateModel() noexcept; + void UpdateView() noexcept; + void UpdateHeading() noexcept; private: EntityController *ctrl; @@ -127,6 +129,13 @@ private: AABB bounds; EntityState state; + /// local transform of eyes + /// if this entity has no model, the eyes are assumed to + /// be at local origin and oriented towards -Z + glm::mat4 view_local; + /// normalized velocity or heading if standing still + glm::vec3 heading; + // TODO: I'd prefer a drag solution float max_vel; float max_force; diff --git a/src/world/world.cpp b/src/world/world.cpp index 925046c..4f73243 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -30,6 +30,7 @@ Entity::Entity() noexcept , name("anonymous") , bounds() , state() +, heading(0.0f, 0.0f, -1.0f) , max_vel(5.0f) , max_force(25.0f) , ref_count(0) @@ -112,20 +113,14 @@ glm::mat4 Entity::Transform(const glm::ivec3 &reference) const noexcept { } glm::mat4 Entity::ViewTransform(const glm::ivec3 &reference) const noexcept { - glm::mat4 transform = Transform(reference); - if (model) { - transform *= model.EyesTransform(); - } + glm::mat4 transform = view_local; + transform[3] += glm::vec4(state.RelativePosition(reference), 0.0f); return transform; } Ray Entity::Aim(const Chunk::Pos &chunk_offset) const noexcept { glm::mat4 transform = ViewTransform(chunk_offset); - glm::vec4 from = transform * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - from /= from.w; - glm::vec4 to = transform * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f); - to /= to.w; - return Ray{ glm::vec3(from), glm::normalize(glm::vec3(to - from)) }; + return Ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) }; } void Entity::UpdateModel() noexcept { @@ -143,11 +138,33 @@ void Entity::UpdateModel() noexcept { } void Entity::Update(float dt) { + UpdateView(); + UpdateHeading(); if (HasController()) { GetController().Update(*this, dt); } } +void Entity::UpdateView() noexcept { + // create local transform + view_local = Transform(ChunkCoords()); + // clear the translation part + view_local[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + // add the model's eyes translation, if any + if (model) { + view_local *= model.EyesTransform(); + } +} + +void Entity::UpdateHeading() noexcept { + if (Moving()) { + heading = normalize(Velocity()); + } else { + // use -Z (forward axis) of local view transform + heading = -glm::vec3(view_local[2]); + } +} + EntityController::~EntityController() { @@ -215,26 +232,19 @@ void EntityState::AdjustPosition() noexcept { } void EntityState::AdjustHeading() noexcept { - while (pitch > PI / 2) { - pitch = PI / 2; - } - while (pitch < -PI / 2) { - pitch = -PI / 2; - } + glm::clamp(pitch, -PI_0p5, PI_0p5); while (yaw > PI) { - yaw -= PI * 2; + yaw -= PI_2p0; } while (yaw < -PI) { - yaw += PI * 2; + yaw += PI_2p0; } } glm::mat4 EntityState::Transform(const glm::ivec3 &reference) const noexcept { const glm::vec3 translation = RelativePosition(reference); glm::mat4 transform(toMat4(orient)); - transform[3].x = translation.x; - transform[3].y = translation.y; - transform[3].z = translation.z; + transform[3] = glm::vec4(translation, 1.0f); return transform; } -- 2.39.2