From cf5ce8220483bb062740eeaedde6474928fd5e0e Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 14 Sep 2015 15:15:59 +0200 Subject: [PATCH] grouped entity physics state into a struct --- src/client/client.cpp | 4 +- src/net/Packet.hpp | 7 +- src/net/net.cpp | 104 +++++-------------------- src/world/Entity.cpp | 118 ----------------------------- src/world/Entity.hpp | 40 +++++----- src/world/EntityState.hpp | 50 ++++++++++++ src/world/{World.cpp => world.cpp} | 113 ++++++++++++++++++++++++++- 7 files changed, 204 insertions(+), 232 deletions(-) delete mode 100644 src/world/Entity.cpp create mode 100644 src/world/EntityState.hpp rename src/world/{World.cpp => world.cpp} (76%) diff --git a/src/client/client.cpp b/src/client/client.cpp index bd43635..8a3d1c8 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -212,7 +212,7 @@ void MasterState::On(const Packet::Join &pack) { pack.ReadPlayerID(player_id); state.reset(new InteractiveState(*this, player_id)); - pack.ReadPlayer(*state->GetInterface().GetPlayer().entity); + pack.ReadPlayerState(state->GetInterface().GetPlayer().entity->GetState()); env.state.PopAfter(this); env.state.Push(state.get()); @@ -293,7 +293,7 @@ void MasterState::On(const Packet::EntityUpdate &pack) { } if (world_iter->ID() == entity_id) { if (UpdateEntity(entity_id, pack.Seq())) { - pack.ReadEntity(*world_iter, i); + pack.ReadEntityState(world_iter->GetState(), i); } } } diff --git a/src/net/Packet.hpp b/src/net/Packet.hpp index 4742a45..232d0be 100644 --- a/src/net/Packet.hpp +++ b/src/net/Packet.hpp @@ -10,6 +10,7 @@ namespace blank { class Entity; +class EntityState; struct Packet { @@ -85,7 +86,7 @@ struct Packet { void WritePlayer(const Entity &) noexcept; void ReadPlayerID(std::uint32_t &) const noexcept; - void ReadPlayer(Entity &) const noexcept; + void ReadPlayerState(EntityState &) const noexcept; void WriteWorldName(const std::string &) noexcept; void ReadWorldName(std::string &) const noexcept; }; @@ -100,7 +101,7 @@ struct Packet { static constexpr std::size_t MAX_LEN = 64; void WritePlayer(const Entity &) noexcept; - void ReadPlayer(Entity &) const noexcept; + void ReadPlayerState(EntityState &) const noexcept; }; struct SpawnEntity : public Payload { @@ -135,7 +136,7 @@ struct Packet { void WriteEntity(const Entity &, std::uint32_t) noexcept; void ReadEntityID(std::uint32_t &, std::uint32_t) const noexcept; - void ReadEntity(Entity &, std::uint32_t) const noexcept; + void ReadEntityState(EntityState &, std::uint32_t) const noexcept; }; diff --git a/src/net/net.cpp b/src/net/net.cpp index 18abb92..13ea4d3 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -8,6 +8,8 @@ #include "../app/init.hpp" #include "../model/CompositeModel.hpp" +#include "../world/Entity.hpp" +#include "../world/EntityState.hpp" #include "../world/World.hpp" #include @@ -334,7 +336,8 @@ void ClientConnection::On(const Packet::PlayerUpdate &pack) { player_update_timer.Reset(); if (pack_diff > 0 || overdue) { player_update_pack = pack.Seq(); - pack.ReadPlayer(Player()); + // TODO: do client input validation here + pack.ReadPlayerState(Player().GetState()); } } @@ -542,34 +545,15 @@ void Packet::Login::ReadPlayerName(string &name) const noexcept { void Packet::Join::WritePlayer(const Entity &player) noexcept { Write(player.ID(), 0); - Write(player.ChunkCoords(), 4); - Write(player.Position(), 16); - Write(player.Velocity(), 28); - Write(player.Orientation(), 40); - Write(player.AngularVelocity(), 56); + Write(player.GetState(), 4); } void Packet::Join::ReadPlayerID(uint32_t &id) const noexcept { Read(id, 0); } -void Packet::Join::ReadPlayer(Entity &player) const noexcept { - glm::ivec3 chunk_coords(0); - glm::vec3 pos; - glm::vec3 vel; - glm::quat rot; - glm::vec3 ang; - - Read(chunk_coords, 4); - Read(pos, 16); - Read(vel, 28); - Read(rot, 40); - Read(ang, 56); - - player.Position(chunk_coords, pos); - player.Velocity(vel); - player.Orientation(rot); - player.AngularVelocity(ang); +void Packet::Join::ReadPlayerState(EntityState &state) const noexcept { + Read(state, 4); } void Packet::Join::WriteWorldName(const string &name) noexcept { @@ -581,30 +565,11 @@ void Packet::Join::ReadWorldName(string &name) const noexcept { } void Packet::PlayerUpdate::WritePlayer(const Entity &player) noexcept { - Write(player.ChunkCoords(), 0); - Write(player.Position(), 12); - Write(player.Velocity(), 24); - Write(player.Orientation(), 36); - Write(player.AngularVelocity(), 52); + Write(player.GetState(), 0); } -void Packet::PlayerUpdate::ReadPlayer(Entity &player) const noexcept { - glm::ivec3 chunk_coords(0); - glm::vec3 pos; - glm::vec3 vel; - glm::quat rot; - glm::vec3 ang; - - Read(chunk_coords, 0); - Read(pos, 12); - Read(vel, 24); - Read(rot, 36); - Read(ang, 52); - - player.Position(chunk_coords, pos); - player.Velocity(vel); - player.Orientation(rot); - player.AngularVelocity(ang); +void Packet::PlayerUpdate::ReadPlayerState(EntityState &state) const noexcept { + Read(state, 0); } void Packet::SpawnEntity::WriteEntity(const Entity &e) noexcept { @@ -614,11 +579,7 @@ void Packet::SpawnEntity::WriteEntity(const Entity &e) noexcept { } else { Write(uint32_t(0), 4); } - Write(e.ChunkCoords(), 8); - Write(e.Position(), 20); - Write(e.Velocity(), 32); - Write(e.Orientation(), 44); - Write(e.AngularVelocity(), 60); + Write(e.GetState(), 8); Write(e.Bounds(), 72); uint32_t flags = 0; if (e.WorldCollidable()) { @@ -637,28 +598,17 @@ void Packet::SpawnEntity::ReadSkeletonID(uint32_t &id) const noexcept { } void Packet::SpawnEntity::ReadEntity(Entity &e) const noexcept { - glm::ivec3 chunk_coords(0); - glm::vec3 pos; - glm::vec3 vel; - glm::quat rot; - glm::vec3 ang; + EntityState state; AABB bounds; uint32_t flags = 0; string name; - Read(chunk_coords, 8); - Read(pos, 20); - Read(vel, 32); - Read(rot, 44); - Read(ang, 60); + Read(state, 8); Read(bounds, 72); Read(flags, 96); ReadString(name, 100, 32); - e.Position(chunk_coords, pos); - e.Velocity(vel); - e.Orientation(rot); - e.AngularVelocity(ang); + e.SetState(state); e.Bounds(bounds); e.WorldCollidable(flags & 1); e.Name(name); @@ -684,36 +634,16 @@ void Packet::EntityUpdate::WriteEntity(const Entity &entity, uint32_t num) noexc uint32_t off = 4 + (num * 64); Write(entity.ID(), off); - Write(entity.ChunkCoords(), off + 4); - Write(entity.Position(), off + 16); - Write(entity.Velocity(), off + 28); - Write(entity.Orientation(), off + 40); - Write(entity.AngularVelocity(), off + 56); + Write(entity.GetState(), off + 4); } void Packet::EntityUpdate::ReadEntityID(uint32_t &id, uint32_t num) const noexcept { Read(id, 4 + (num * 64)); } -void Packet::EntityUpdate::ReadEntity(Entity &entity, uint32_t num) const noexcept { +void Packet::EntityUpdate::ReadEntityState(EntityState &state, uint32_t num) const noexcept { uint32_t off = 4 + (num * 64); - - glm::ivec3 chunk_coords(0); - glm::vec3 pos; - glm::vec3 vel; - glm::quat rot; - glm::vec3 ang; - - Read(chunk_coords, off + 4); - Read(pos, off + 16); - Read(vel, off + 28); - Read(rot, off + 40); - Read(ang, off + 56); - - entity.Position(chunk_coords, pos); - entity.Velocity(vel); - entity.Orientation(rot); - entity.AngularVelocity(ang); + Read(state, off + 4); } diff --git a/src/world/Entity.cpp b/src/world/Entity.cpp deleted file mode 100644 index b909603..0000000 --- a/src/world/Entity.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "Entity.hpp" - -#include "../model/Shape.hpp" - -#include -#include -#include - -namespace { - -blank::EntityModel::Buffer model_buffer; - -} - -namespace blank { - -Entity::Entity() noexcept -: model() -, id(-1) -, name("anonymous") -, bounds() -, velocity(0, 0, 0) -, chunk(0, 0, 0) -, angular_velocity(0.0f) -, ref_count(0) -, world_collision(false) -, dead(false) { - -} - - -void Entity::Position(const Chunk::Pos &c, const glm::vec3 &pos) noexcept { - chunk = c; - model.Position(pos); -} - -void Entity::Position(const glm::vec3 &pos) noexcept { - glm::vec3 position(pos); - while (position.x >= Chunk::width) { - position.x -= Chunk::width; - ++chunk.x; - } - while (position.x < 0) { - position.x += Chunk::width; - --chunk.x; - } - while (position.y >= Chunk::height) { - position.y -= Chunk::height; - ++chunk.y; - } - while (position.y < 0) { - position.y += Chunk::height; - --chunk.y; - } - while (position.z >= Chunk::depth) { - position.z -= Chunk::depth; - ++chunk.z; - } - while (position.z < 0) { - position.z += Chunk::depth; - --chunk.z; - } - model.Position(position); -} - -void Entity::Move(const glm::vec3 &delta) noexcept { - Position(Position() + delta); -} - -void Entity::Rotate(const glm::quat &delta) noexcept { - Orientation(delta * Orientation()); -} - -glm::mat4 Entity::ChunkTransform(const Chunk::Pos &chunk_offset) const noexcept { - const glm::vec3 translation = glm::vec3((chunk - chunk_offset) * Chunk::Extent()); - return glm::translate(translation); -} - -glm::mat4 Entity::Transform(const Chunk::Pos &chunk_offset) const noexcept { - const glm::vec3 translation = glm::vec3((chunk - chunk_offset) * Chunk::Extent()) + Position(); - glm::mat4 transform(toMat4(Orientation())); - transform[3].x = translation.x; - transform[3].y = translation.y; - transform[3].z = translation.z; - return transform; -} - -Ray Entity::Aim(const Chunk::Pos &chunk_offset) const noexcept { - glm::mat4 transform = Transform(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)) }; -} - -namespace { - -glm::quat delta_rot(const glm::vec3 &av, float dt) { - glm::vec3 half(av * dt * 0.5f); - float mag = length(half); - if (mag > 0.0f) { - float smag = std::sin(mag) / mag; - return glm::quat(std::cos(mag), half * smag); - } else { - return glm::quat(1.0f, 0.0f, 0.0f, 0.0f); - } -} - -} - -void Entity::Update(int dt) noexcept { - float fdt = float(dt); - Move(velocity * fdt); - Rotate(delta_rot(angular_velocity, fdt)); -} - -} diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index c0d9a0b..dcfb418 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -2,6 +2,7 @@ #define BLANK_WORLD_ENTITY_HPP_ #include "Chunk.hpp" +#include "EntityState.hpp" #include "../model/CompositeInstance.hpp" #include "../model/geometry.hpp" @@ -36,35 +37,38 @@ public: bool WorldCollidable() const noexcept { return world_collision; } void WorldCollidable(bool b) noexcept { world_collision = b; } - const glm::vec3 &Velocity() const noexcept { return velocity; } - void Velocity(const glm::vec3 &v) noexcept { velocity = v; } + const glm::vec3 &Velocity() const noexcept { return state.velocity; } + void Velocity(const glm::vec3 &v) noexcept { state.velocity = v; } - const glm::vec3 &Position() const noexcept { return model.Position(); } - void Position(const Chunk::Pos &, const glm::vec3 &) noexcept; + const glm::vec3 &Position() const noexcept { return state.block_pos; } + void Position(const glm::ivec3 &, const glm::vec3 &) noexcept; void Position(const glm::vec3 &) noexcept; - void Move(const glm::vec3 &delta) noexcept; - const Chunk::Pos ChunkCoords() const noexcept { return chunk; } + const glm::ivec3 ChunkCoords() const noexcept { return state.chunk_pos; } glm::vec3 AbsolutePosition() const noexcept { - return glm::vec3(chunk * Chunk::Extent()) + Position(); + return state.AbsolutePosition(); } glm::vec3 AbsoluteDifference(const Entity &other) const noexcept { - return glm::vec3((chunk - other.chunk) * Chunk::Extent()) + Position() - other.Position(); + return state.Diff(other.state); } /// direction is rotation axis, magnitude is speed in rad/ms - const glm::vec3 &AngularVelocity() const noexcept { return angular_velocity; } - void AngularVelocity(const glm::vec3 &v) noexcept { angular_velocity = v; } + const glm::vec3 &AngularVelocity() const noexcept { return state.ang_vel; } + void AngularVelocity(const glm::vec3 &v) noexcept { state.ang_vel = v; } - const glm::quat &Orientation() const noexcept { return model.Orientation(); } - void Orientation(const glm::quat &o) noexcept { model.Orientation(o); } - void Rotate(const glm::quat &delta) noexcept; + const glm::quat &Orientation() const noexcept { return state.orient; } + void Orientation(const glm::quat &o) noexcept { state.orient = o; } - glm::mat4 ChunkTransform(const Chunk::Pos &chunk_offset) const noexcept; - glm::mat4 Transform(const Chunk::Pos &chunk_offset) const noexcept; + glm::mat4 Transform(const glm::ivec3 &reference) const noexcept { + return state.Transform(reference); + } Ray Aim(const Chunk::Pos &chunk_offset) const noexcept; + void SetState(const EntityState &s) noexcept { state = s; } + EntityState &GetState() noexcept { return state; } + const EntityState &GetState() const noexcept { return state; } + void Ref() noexcept { ++ref_count; } void UnRef() noexcept { --ref_count; } void Kill() noexcept { dead = true; } @@ -85,11 +89,7 @@ private: std::string name; AABB bounds; - - glm::vec3 velocity; - Chunk::Pos chunk; - - glm::vec3 angular_velocity; + EntityState state; int ref_count; diff --git a/src/world/EntityState.hpp b/src/world/EntityState.hpp new file mode 100644 index 0000000..8f74114 --- /dev/null +++ b/src/world/EntityState.hpp @@ -0,0 +1,50 @@ +#ifndef BLANK_WORLD_ENTITYSTATE_HPP_ +#define BLANK_WORLD_ENTITYSTATE_HPP_ + +#include "Chunk.hpp" + +#include +#include + + +namespace blank { + +struct EntityState { + + glm::ivec3 chunk_pos; + glm::vec3 block_pos; + glm::vec3 velocity; + + glm::quat orient; + glm::vec3 ang_vel; + + EntityState(); + + /// make sure block_pos is within chunk bounds + void AdjustPosition() noexcept; + + /// do an integration step of dt milliseconds + void Update(int dt) noexcept; + + /// get a position vector relative to the (0,0,0) chunk + glm::vec3 AbsolutePosition() const noexcept { + return glm::vec3(chunk_pos * Chunk::Extent()) + block_pos; + } + /// get a position vector relative to given reference chunk + glm::vec3 RelativePosition(const glm::ivec3 &reference) const noexcept { + return glm::vec3((chunk_pos - reference) * Chunk::Extent()) + block_pos; + } + + /// get the difference between this and the given position + glm::vec3 Diff(const EntityState &other) const noexcept { + return RelativePosition(other.chunk_pos) - other.block_pos; + } + + /// get entity state as a matrix tranform relative to given reference chunk + glm::mat4 Transform(const glm::ivec3 &reference) const noexcept; + +}; + +} + +#endif diff --git a/src/world/World.cpp b/src/world/world.cpp similarity index 76% rename from src/world/World.cpp rename to src/world/world.cpp index 505cbbb..a35f76a 100644 --- a/src/world/World.cpp +++ b/src/world/world.cpp @@ -1,3 +1,5 @@ +#include "Entity.hpp" +#include "EntityState.hpp" #include "World.hpp" #include "ChunkIndex.hpp" @@ -8,13 +10,120 @@ #include "../graphics/Viewport.hpp" #include +#include #include #include +#include #include namespace blank { +Entity::Entity() noexcept +: model() +, id(-1) +, name("anonymous") +, bounds() +, state() +, ref_count(0) +, world_collision(false) +, dead(false) { + +} + + +void Entity::Position(const glm::ivec3 &c, const glm::vec3 &b) noexcept { + state.chunk_pos = c; + state.block_pos = b; +} + +void Entity::Position(const glm::vec3 &pos) noexcept { + state.block_pos = pos; + state.AdjustPosition(); +} + +Ray Entity::Aim(const Chunk::Pos &chunk_offset) const noexcept { + glm::mat4 transform = Transform(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)) }; +} + +namespace { + +glm::quat delta_rot(const glm::vec3 &av, float dt) { + glm::vec3 half(av * dt * 0.5f); + float mag = length(half); + if (mag > 0.0f) { + float smag = std::sin(mag) / mag; + return glm::quat(std::cos(mag), half * smag); + } else { + return glm::quat(1.0f, 0.0f, 0.0f, 0.0f); + } +} + +} + +void Entity::Update(int dt) noexcept { + state.Update(dt); +} + + +EntityState::EntityState() +: chunk_pos(0) +, block_pos(0.0f) +, velocity(0.0f) +, orient(1.0f, 0.0f, 0.0f, 0.0f) +, ang_vel(0.0f) { + +} + +void EntityState::Update(int dt) noexcept { + float fdt = float(dt); + block_pos += velocity * fdt; + orient = delta_rot(ang_vel, fdt) * orient; + AdjustPosition(); +} + +void EntityState::AdjustPosition() noexcept { + while (block_pos.x >= Chunk::width) { + block_pos.x -= Chunk::width; + ++chunk_pos.x; + } + while (block_pos.x < 0) { + block_pos.x += Chunk::width; + --chunk_pos.x; + } + while (block_pos.y >= Chunk::height) { + block_pos.y -= Chunk::height; + ++chunk_pos.y; + } + while (block_pos.y < 0) { + block_pos.y += Chunk::height; + --chunk_pos.y; + } + while (block_pos.z >= Chunk::depth) { + block_pos.z -= Chunk::depth; + ++chunk_pos.z; + } + while (block_pos.z < 0) { + block_pos.z += Chunk::depth; + --chunk_pos.z; + } +} + +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; + return transform; +} + + World::World(const BlockTypeRegistry &types, const Config &config) : config(config) , block_type(types) @@ -290,7 +399,7 @@ void World::Resolve(Entity &e, std::vector &col) { final_disp[axis] = max_disp[axis]; } } - e.Move(final_disp); + e.Position(e.Position() + final_disp); } World::EntityHandle World::RemoveEntity(EntityHandle &eh) { @@ -314,7 +423,7 @@ void World::Render(Viewport &viewport) { entity_prog.SetFogDensity(fog_density); for (Entity &entity : entities) { - entity.Render(entity.ChunkTransform(players[0].entity->ChunkCoords()), entity_prog); + entity.Render(entity.Transform(players[0].entity->ChunkCoords()), entity_prog); } } -- 2.39.2