X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2Fworld.cpp;h=08ee294fca5e5a8b72351be8bb3ff3e3e40abdd2;hb=be06fbd6c75dabf411f33ebdeed29e60fb639694;hp=ee5bf02c191ffcf3be293d0a4acda9b31289f751;hpb=d122d3e445d64f7d710c1cfaf285ff01bbe955b9;p=blank.git diff --git a/src/world/world.cpp b/src/world/world.cpp index ee5bf02..08ee294 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,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) @@ -50,6 +52,10 @@ Entity::Entity(const Entity &other) noexcept , name(other.name) , bounds(other.bounds) , state(other.state) +, model_transform(1.0f) +, view_transform(1.0f) +, speed(0.0f) +, heading(0.0f, 0.0f, -1.0f) , max_vel(other.max_vel) , max_force(other.max_force) , ref_count(0) @@ -80,7 +86,7 @@ void Entity::UnsetController() noexcept { glm::vec3 Entity::ControlForce(const EntityState &s) const noexcept { if (HasController()) { - return GetController().ControlForce(s); + return GetController().ControlForce(*this, s); } else { return -s.velocity; } @@ -108,51 +114,86 @@ void Entity::SetHead(float p, float y) noexcept { } glm::mat4 Entity::Transform(const glm::ivec3 &reference) const noexcept { - return state.Transform(reference); + return glm::translate(glm::vec3((state.chunk_pos - reference) * Chunk::Extent())) * model_transform; } glm::mat4 Entity::ViewTransform(const glm::ivec3 &reference) const noexcept { - glm::mat4 transform = Transform(reference); - if (model) { - transform *= model.EyesTransform(); - } - return transform; + return Transform(reference) * view_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 { state.AdjustHeading(); + state.orient = glm::quat(glm::vec3(0.0f, state.yaw, 0.0f)); if (model) { - Part::State &body_state = model.BodyState(); - Part::State &eyes_state = model.EyesState(); - if (&body_state != &eyes_state) { - body_state.orientation = glm::quat(glm::vec3(0.0f, state.yaw, 0.0f)); - eyes_state.orientation = glm::quat(glm::vec3(state.pitch, 0.0f, 0.0f)); - } else { - eyes_state.orientation = glm::quat(glm::vec3(state.pitch, state.yaw, 0.0f)); - } + model.EyesState().orientation = glm::quat(glm::vec3(state.pitch, 0.0f, 0.0f)); } } void Entity::Update(float dt) { + UpdateTransforms(); + UpdateHeading(); if (HasController()) { GetController().Update(*this, dt); } } +void Entity::UpdateTransforms() noexcept { + // model transform is the one given by current state + model_transform = state.Transform(state.chunk_pos); + // view transform is either the model's eyes transform or, + // should the entity have no model, the pitch (yaw already is + // in model transform) + if (model) { + view_transform = model.EyesTransform(); + } else { + view_transform = glm::eulerAngleX(state.pitch); + } +} + +void Entity::UpdateHeading() noexcept { + speed = length(Velocity()); + if (speed > std::numeric_limits::epsilon()) { + heading = Velocity() / speed; + } else { + speed = 0.0f; + // use -Z (forward axis) of local view transform + heading = -glm::vec3(view_transform[2]); + } +} + 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) @@ -192,26 +233,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; } @@ -441,6 +475,15 @@ bool World::Intersection(const Entity &e, const EntityState &s, std::vector &col +) { bool any = false; for (Chunk &cur_chunk : chunks) { if (manhattan_radius(cur_chunk.Position() - reference) > 1) { @@ -455,14 +498,13 @@ bool World::Intersection(const Entity &e, const EntityState &s, std::vector