From d02daa5a4805dc3184884f3a7cd7620e5787adcb Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Tue, 11 Aug 2015 15:17:54 +0200 Subject: [PATCH] allow multiple meshes per entity organized in a tree with each node haing its local position/orientation relative to the parent --- src/ai/Spawner.cpp | 12 +++++--- src/ai/Spawner.hpp | 3 ++ src/app/FPSController.cpp | 2 +- src/model/CompositeModel.cpp | 55 +++++++++++++++++++++++++++++++++++ src/model/CompositeModel.hpp | 56 ++++++++++++++++++++++++++++++++++++ src/world/Entity.cpp | 50 +++++++++----------------------- src/world/Entity.hpp | 38 +++++++++++------------- src/world/World.cpp | 5 +--- 8 files changed, 155 insertions(+), 66 deletions(-) create mode 100644 src/model/CompositeModel.cpp create mode 100644 src/model/CompositeModel.hpp diff --git a/src/ai/Spawner.cpp b/src/ai/Spawner.cpp index b0b9bcb..e5bc68f 100644 --- a/src/ai/Spawner.cpp +++ b/src/ai/Spawner.cpp @@ -18,6 +18,13 @@ Spawner::Spawner(World &world) , spawn_distance(16 * 16) , max_entities(16) , chunk_range(4) { + EntityModel::Buffer buf; + for (size_t i = 0; i < 14; ++i) { + world.BlockTypes()[i + 1].FillEntityModel(buf); + models[i].Update(buf); + buf.Clear(); + } + timer.Start(); Spawn(world.Player().ChunkCoords(), { 0.5f, 0.5f, 0.5f }); } @@ -92,9 +99,6 @@ void Spawner::TrySpawn() { } void Spawner::Spawn(const glm::ivec3 &chunk, const glm::vec3 &pos) { - glm::vec3 color(rand() % 6, rand() % 6, rand() % 6); - color = color * 0.15f + 0.25f; - glm::vec3 rot(0.000001f); rot.x *= (rand() % 1024); rot.y *= (rand() % 1024); @@ -105,7 +109,7 @@ void Spawner::Spawn(const glm::ivec3 &chunk, const glm::vec3 &pos) { e.Position(chunk, pos); e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } }); e.WorldCollidable(true); - e.SetShape(world.BlockTypes()[1].shape, color, 2); + e.GetModel().SetNodeModel(&models[rand() % 14]); e.AngularVelocity(rot); Controller *ctrl; if (rand() % 2) { diff --git a/src/ai/Spawner.hpp b/src/ai/Spawner.hpp index 127a860..b36e520 100644 --- a/src/ai/Spawner.hpp +++ b/src/ai/Spawner.hpp @@ -2,6 +2,7 @@ #define BLANK_AI_SPAWNER_HPP_ #include "../app/IntervalTimer.hpp" +#include "../model/EntityModel.hpp" #include #include @@ -29,6 +30,8 @@ private: World &world; std::vector controllers; + EntityModel models[14]; + IntervalTimer timer; float despawn_range; float spawn_distance; diff --git a/src/app/FPSController.cpp b/src/app/FPSController.cpp index 48e39dc..7f8c2c1 100644 --- a/src/app/FPSController.cpp +++ b/src/app/FPSController.cpp @@ -42,7 +42,7 @@ void FPSController::RotateYaw(float delta) noexcept { void FPSController::Update(int dt) noexcept { - entity.Rotation(glm::quat(glm::vec3(pitch, yaw, 0.0f))); + entity.Orientation(glm::quat(glm::vec3(pitch, yaw, 0.0f))); entity.Velocity(glm::rotateY(velocity, yaw)); } diff --git a/src/model/CompositeModel.cpp b/src/model/CompositeModel.cpp new file mode 100644 index 0000000..d5b25af --- /dev/null +++ b/src/model/CompositeModel.cpp @@ -0,0 +1,55 @@ +#include "CompositeModel.hpp" + +#include "EntityModel.hpp" +#include "../graphics/DirectionalLighting.hpp" + +#include + + +namespace blank { + +CompositeModel::CompositeModel() +: node_model(nullptr) +, position(0.0f) +, orientation(1.0f, 0.0f, 0.0f, 0.0f) +, parts() { + +} + + +CompositeModel &CompositeModel::AddPart() { + parts.emplace_back(); + parts.back().parent = this; + return parts.back(); +} + + +glm::mat4 CompositeModel::LocalTransform() const noexcept { + glm::mat4 transform(toMat4(orientation)); + transform[3].x = position.x; + transform[3].y = position.y; + transform[3].z = position.z; + return transform; +} + +glm::mat4 CompositeModel::GlobalTransform() const noexcept { + if (HasParent()) { + return Parent().GlobalTransform() * LocalTransform(); + } else { + return LocalTransform(); + } +} + + +void CompositeModel::Render(const glm::mat4 &M, DirectionalLighting &prog) const { + glm::mat4 transform(M * LocalTransform()); + if (HasNodeModel()) { + prog.SetM(transform); + NodeModel().Draw(); + } + for (const CompositeModel &part : parts) { + part.Render(transform, prog); + } +} + +} diff --git a/src/model/CompositeModel.hpp b/src/model/CompositeModel.hpp new file mode 100644 index 0000000..b548a9c --- /dev/null +++ b/src/model/CompositeModel.hpp @@ -0,0 +1,56 @@ +#ifndef BLANK_MODEL_COMPOSITEMODEL_HPP_ +#define BLANK_MODEL_COMPOSITEMODEL_HPP_ + +#include +#include +#include + + +namespace blank { + +class DirectionalLighting; +class EntityModel; + +class CompositeModel { + +public: + CompositeModel(); + + CompositeModel(const CompositeModel &) = delete; + CompositeModel &operator =(const CompositeModel &) = delete; + + const glm::vec3 &Position() const noexcept { return position; } + void Position(const glm::vec3 &p) noexcept { position = p; } + + const glm::quat &Orientation() const noexcept { return orientation; } + void Orientation(const glm::quat &o) noexcept { orientation = o; } + + bool HasNodeModel() const noexcept { return node_model; } + void SetNodeModel(const EntityModel *m) noexcept { node_model = m; } + + const EntityModel &NodeModel() const noexcept { return *node_model; } + + CompositeModel &AddPart(); + bool HasParent() const noexcept { return parent; } + CompositeModel &Parent() const noexcept { return *parent; } + bool IsRoot() const noexcept { return !HasParent(); } + + glm::mat4 LocalTransform() const noexcept; + glm::mat4 GlobalTransform() const noexcept; + + void Render(const glm::mat4 &, DirectionalLighting &) const; + +private: + CompositeModel *parent; + const EntityModel *node_model; + + glm::vec3 position; + glm::quat orientation; + + std::list parts; + +}; + +} + +#endif diff --git a/src/world/Entity.cpp b/src/world/Entity.cpp index 072bb38..fb62f27 100644 --- a/src/world/Entity.cpp +++ b/src/world/Entity.cpp @@ -15,45 +15,25 @@ blank::EntityModel::Buffer model_buffer; namespace blank { Entity::Entity() noexcept -: shape(nullptr) -, model() +: model() , name("anonymous") , bounds() , velocity(0, 0, 0) -, position(0, 0, 0) , chunk(0, 0, 0) , angular_velocity(0.0f) -, rotation(1.0f, 0.0f, 0.0f, 0.0f) , world_collision(false) , remove(false) { } -void Entity::SetShape(const Shape *s, const glm::vec3 &color, float texture) { - shape = s; - model_buffer.Clear(); - shape->Vertices(model_buffer, texture); - model_buffer.colors.resize(shape->VertexCount(), color); - model.Update(model_buffer); -} - -void Entity::SetShapeless() noexcept { - shape = nullptr; -} - - -void Entity::Velocity(const glm::vec3 &vel) noexcept { - velocity = vel; -} - -void Entity::Position(const Chunk::Pos &c, const Block::Pos &pos) noexcept { +void Entity::Position(const Chunk::Pos &c, const glm::vec3 &pos) noexcept { chunk = c; - position = pos; + model.Position(pos); } -void Entity::Position(const Block::Pos &pos) noexcept { - 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; @@ -78,27 +58,25 @@ void Entity::Position(const Block::Pos &pos) noexcept { position.z += Chunk::depth; --chunk.z; } + model.Position(position); } void Entity::Move(const glm::vec3 &delta) noexcept { - Position(position + delta); -} - -void Entity::AngularVelocity(const glm::vec3 &v) noexcept { - angular_velocity = v; + Position(Position() + delta); } -void Entity::Rotation(const glm::quat &rot) noexcept { - rotation = rot; +void Entity::Rotate(const glm::quat &delta) noexcept { + Orientation(delta * Orientation()); } -void Entity::Rotate(const glm::quat &delta) noexcept { - Rotation(delta * Rotation()); +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(Rotation())); + 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; diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index f60bf4c..ae14297 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -1,10 +1,9 @@ #ifndef BLANK_WORLD_ENTITY_HPP_ #define BLANK_WORLD_ENTITY_HPP_ -#include "Block.hpp" #include "Chunk.hpp" +#include "../model/CompositeModel.hpp" #include "../model/geometry.hpp" -#include "../model/EntityModel.hpp" #include #include @@ -13,6 +12,7 @@ namespace blank { +class DirectionalLighting; class Shape; class Entity { @@ -20,10 +20,8 @@ class Entity { public: Entity() noexcept; - bool HasShape() const noexcept { return shape; } - const Shape *GetShape() const noexcept { return shape; } - void SetShape(const Shape *, const glm::vec3 &color, float texture); - void SetShapeless() noexcept; + CompositeModel &GetModel() noexcept { return model; } + const CompositeModel &GetModel() const noexcept { return model; } const std::string &Name() const noexcept { return name; } void Name(const std::string &n) { name = n; } @@ -35,30 +33,31 @@ public: void WorldCollidable(bool b) noexcept { world_collision = b; } const glm::vec3 &Velocity() const noexcept { return velocity; } - void Velocity(const glm::vec3 &) noexcept; + void Velocity(const glm::vec3 &v) noexcept { velocity = v; } - const Block::Pos &Position() const noexcept { return position; } - void Position(const Chunk::Pos &, const Block::Pos &) noexcept; - void Position(const Block::Pos &) noexcept; + const glm::vec3 &Position() const noexcept { return model.Position(); } + void Position(const Chunk::Pos &, 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; } glm::vec3 AbsolutePosition() const noexcept { - return glm::vec3(chunk * Chunk::Extent()) + position; + return glm::vec3(chunk * Chunk::Extent()) + Position(); } glm::vec3 AbsoluteDifference(const Entity &other) const noexcept { - return glm::vec3((chunk - other.chunk) * Chunk::Extent()) + position - other.position; + return glm::vec3((chunk - other.chunk) * Chunk::Extent()) + Position() - other.Position(); } /// direction is rotation axis, magnitude is speed in rad/ms const glm::vec3 &AngularVelocity() const noexcept { return angular_velocity; } - void AngularVelocity(const glm::vec3 &) noexcept; + void AngularVelocity(const glm::vec3 &v) noexcept { angular_velocity = v; } - const glm::quat &Rotation() const noexcept { return rotation; } - void Rotation(const glm::quat &) noexcept; + 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; + glm::mat4 ChunkTransform(const Chunk::Pos &chunk_offset) const noexcept; glm::mat4 Transform(const Chunk::Pos &chunk_offset) const noexcept; Ray Aim(const Chunk::Pos &chunk_offset) const noexcept; @@ -67,24 +66,21 @@ public: void Update(int dt) noexcept; - void Draw() noexcept { - model.Draw(); + void Render(const glm::mat4 &M, DirectionalLighting &prog) noexcept { + model.Render(M, prog); } private: - const Shape *shape; - EntityModel model; + CompositeModel model; std::string name; AABB bounds; glm::vec3 velocity; - Block::Pos position; Chunk::Pos chunk; glm::vec3 angular_velocity; - glm::quat rotation; bool world_collision; bool remove; diff --git a/src/world/World.cpp b/src/world/World.cpp index aa347e7..19219e4 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -357,10 +357,7 @@ void World::Render(Viewport &viewport) { entity_prog.SetFogDensity(fog_density); for (Entity &entity : entities) { - if (entity.HasShape()) { - entity_prog.SetM(entity.Transform(player->ChunkCoords())); - entity.Draw(); - } + entity.Render(entity.ChunkTransform(player->ChunkCoords()), entity_prog); } } -- 2.39.2