]> git.localhorst.tv Git - blank.git/commitdiff
allow multiple meshes per entity
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 11 Aug 2015 13:17:54 +0000 (15:17 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 11 Aug 2015 13:17:54 +0000 (15:17 +0200)
organized in a tree with each node haing its local
position/orientation relative to the parent

src/ai/Spawner.cpp
src/ai/Spawner.hpp
src/app/FPSController.cpp
src/model/CompositeModel.cpp [new file with mode: 0644]
src/model/CompositeModel.hpp [new file with mode: 0644]
src/world/Entity.cpp
src/world/Entity.hpp
src/world/World.cpp

index b0b9bcb5127575cc0b254105ec669ed80216d274..e5bc68f9d97461d2396de2076b338f025c0d967e 100644 (file)
@@ -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) {
index 127a8606dbdfbb8a2a6e491d75b632a8fb22ba99..b36e520f7d38cb7273e33109052bbc6435ea205b 100644 (file)
@@ -2,6 +2,7 @@
 #define BLANK_AI_SPAWNER_HPP_
 
 #include "../app/IntervalTimer.hpp"
+#include "../model/EntityModel.hpp"
 
 #include <vector>
 #include <glm/glm.hpp>
@@ -29,6 +30,8 @@ private:
        World &world;
        std::vector<Controller *> controllers;
 
+       EntityModel models[14];
+
        IntervalTimer timer;
        float despawn_range;
        float spawn_distance;
index 48e39dc8ba49bac7fc6071a9444da50a0bbed044..7f8c2c197b955c40e437b40f8911c69dd2b89158 100644 (file)
@@ -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 (file)
index 0000000..d5b25af
--- /dev/null
@@ -0,0 +1,55 @@
+#include "CompositeModel.hpp"
+
+#include "EntityModel.hpp"
+#include "../graphics/DirectionalLighting.hpp"
+
+#include <glm/gtx/quaternion.hpp>
+
+
+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 (file)
index 0000000..b548a9c
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef BLANK_MODEL_COMPOSITEMODEL_HPP_
+#define BLANK_MODEL_COMPOSITEMODEL_HPP_
+
+#include <list>
+#include <glm/glm.hpp>
+#include <glm/gtc/quaternion.hpp>
+
+
+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<CompositeModel> parts;
+
+};
+
+}
+
+#endif
index 072bb38d38ab2350c2da582c6946fe86c80b33ac..fb62f2757d545757f35fcff11132295e4b33e6fd 100644 (file)
@@ -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;
index f60bf4cc6e01c2537a8c3c0927292e867a743e79..ae14297bb0baf282a3ddef142285a262a95c11b6 100644 (file)
@@ -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 <string>
 #include <glm/glm.hpp>
@@ -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;
index aa347e7f654d5e374b621ad1e4efe55a3419fd43..19219e4dd9360a85b68c69cc81b9f982fd94eb54 100644 (file)
@@ -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);
        }
 }