]> git.localhorst.tv Git - blank.git/blob - src/world/Entity.cpp
correct usage of quaternions :P
[blank.git] / src / world / Entity.cpp
1 #include "Entity.hpp"
2
3 #include "../model/Shape.hpp"
4
5 #include <cmath>
6 #include <glm/gtx/quaternion.hpp>
7 #include <glm/gtx/transform.hpp>
8
9 namespace {
10
11 blank::EntityModel::Buffer model_buffer;
12
13 }
14
15 namespace blank {
16
17 Entity::Entity() noexcept
18 : shape(nullptr)
19 , model()
20 , name("anonymous")
21 , bounds()
22 , velocity(0, 0, 0)
23 , position(0, 0, 0)
24 , chunk(0, 0, 0)
25 , angular_velocity(0.0f)
26 , rotation(1.0f, 0.0f, 0.0f, 0.0f)
27 , world_collision(false)
28 , remove(false) {
29
30 }
31
32
33 void Entity::SetShape(const Shape *s, const glm::vec3 &color) {
34         shape = s;
35         model_buffer.Clear();
36         shape->Vertices(model_buffer.vertices, model_buffer.normals, model_buffer.indices);
37         model_buffer.colors.resize(shape->VertexCount(), color);
38         model.Update(model_buffer);
39 }
40
41 void Entity::SetShapeless() noexcept {
42         shape = nullptr;
43 }
44
45
46 void Entity::Velocity(const glm::vec3 &vel) noexcept {
47         velocity = vel;
48 }
49
50 void Entity::Position(const Chunk::Pos &c, const Block::Pos &pos) noexcept {
51         chunk = c;
52         position = pos;
53 }
54
55 void Entity::Position(const Block::Pos &pos) noexcept {
56         position = pos;
57         while (position.x >= Chunk::width) {
58                 position.x -= Chunk::width;
59                 ++chunk.x;
60         }
61         while (position.x < 0) {
62                 position.x += Chunk::width;
63                 --chunk.x;
64         }
65         while (position.y >= Chunk::height) {
66                 position.y -= Chunk::height;
67                 ++chunk.y;
68         }
69         while (position.y < 0) {
70                 position.y += Chunk::height;
71                 --chunk.y;
72         }
73         while (position.z >= Chunk::depth) {
74                 position.z -= Chunk::depth;
75                 ++chunk.z;
76         }
77         while (position.z < 0) {
78                 position.z += Chunk::depth;
79                 --chunk.z;
80         }
81 }
82
83 void Entity::Move(const glm::vec3 &delta) noexcept {
84         Position(position + delta);
85 }
86
87 void Entity::AngularVelocity(const glm::vec3 &v) noexcept {
88         angular_velocity = v;
89 }
90
91 void Entity::Rotation(const glm::quat &rot) noexcept {
92         rotation = rot;
93 }
94
95 void Entity::Rotate(const glm::quat &delta) noexcept {
96         Rotation(delta * Rotation());
97 }
98
99 glm::mat4 Entity::Transform(const Chunk::Pos &chunk_offset) const noexcept {
100         const glm::vec3 translation = glm::vec3((chunk - chunk_offset) * Chunk::Extent()) + position;
101         glm::mat4 transform(toMat4(Rotation()));
102         transform[3].x = translation.x;
103         transform[3].y = translation.y;
104         transform[3].z = translation.z;
105         return transform;
106 }
107
108 Ray Entity::Aim(const Chunk::Pos &chunk_offset) const noexcept {
109         glm::mat4 transform = Transform(chunk_offset);
110         glm::vec4 from = transform * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
111         from /= from.w;
112         glm::vec4 to = transform * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f);
113         to /= to.w;
114         return Ray{ glm::vec3(from), glm::normalize(glm::vec3(to - from)) };
115 }
116
117 namespace {
118
119 glm::quat delta_rot(const glm::vec3 &av, float dt) {
120         glm::vec3 half(av * dt * 0.5f);
121         float mag = length(half);
122         if (mag > 0.0f) {
123                 float smag = std::sin(mag) / mag;
124                 return glm::quat(std::cos(mag), half * smag);
125         } else {
126                 return glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
127         }
128 }
129
130 }
131
132 void Entity::Update(int dt) noexcept {
133         float fdt = float(dt);
134         Move(velocity * fdt);
135         Rotate(delta_rot(angular_velocity, fdt));
136 }
137
138 }