, 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 });
}
}
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);
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) {
#define BLANK_AI_SPAWNER_HPP_
#include "../app/IntervalTimer.hpp"
+#include "../model/EntityModel.hpp"
#include <vector>
#include <glm/glm.hpp>
World &world;
std::vector<Controller *> controllers;
+ EntityModel models[14];
+
IntervalTimer timer;
float despawn_range;
float spawn_distance;
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));
}
--- /dev/null
+#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);
+ }
+}
+
+}
--- /dev/null
+#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
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;
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;
#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>
namespace blank {
+class DirectionalLighting;
class Shape;
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; }
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;
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;
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);
}
}