]> git.localhorst.tv Git - blank.git/blob - src/chunk.cpp
483a4e5cd78ccea1f4722deb31ead2f3cfff0e4a
[blank.git] / src / chunk.cpp
1 #include "chunk.hpp"
2
3 #include <limits>
4 #include <glm/gtx/transform.hpp>
5
6
7 namespace blank {
8
9 Chunk::Chunk()
10 : blocks()
11 , model()
12 , position(0, 0, 0)
13 , dirty(false) {
14
15 }
16
17 Chunk::Chunk(Chunk &&other)
18 : blocks(std::move(other.blocks))
19 , model(std::move(other.model))
20 , dirty(other.dirty) {
21
22 }
23
24 Chunk &Chunk::operator =(Chunk &&other) {
25         blocks = std::move(other.blocks);
26         model = std::move(other.model);
27         dirty = other.dirty;
28         return *this;
29 }
30
31
32 void Chunk::Allocate() {
33         blocks.resize(Size());
34 }
35
36
37 void Chunk::Draw() {
38         if (dirty) {
39                 Update();
40         }
41         model.Draw();
42 }
43
44
45 bool Chunk::Intersection(
46         const Ray &ray,
47         const glm::mat4 &M,
48         int *blkid,
49         float *dist,
50         glm::vec3 *normal) const {
51         { // rough check
52                 if (!blank::Intersection(ray, Bounds(), M)) {
53                         return false;
54                 }
55         }
56
57         if (!blkid && !dist && !normal) {
58                 return true;
59         }
60
61         // TODO: should be possible to heavily optimize this
62         int id = 0;
63         int closest_id = -1;
64         float closest_dist = std::numeric_limits<float>::infinity();
65         glm::vec3 closest_normal(0, 1, 0);
66         for (int z = 0; z < Depth(); ++z) {
67                 for (int y = 0; y < Height(); ++y) {
68                         for (int x = 0; x < Width(); ++x, ++id) {
69                                 if (!blocks[id].type->visible) {
70                                         continue;
71                                 }
72                                 float cur_dist;
73                                 glm::vec3 cur_norm;
74                                 glm::vec3 pos(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f);
75                                 if (blocks[id].type->shape->Intersects(ray, glm::translate(M, pos), cur_dist, cur_norm)) {
76                                         if (cur_dist < closest_dist) {
77                                                 closest_id = id;
78                                                 closest_dist = cur_dist;
79                                                 closest_normal = cur_norm;
80                                         }
81                                 }
82                         }
83                 }
84         }
85
86         if (closest_id < 0) {
87                 return false;
88         }
89
90         if (blkid) {
91                 *blkid = closest_id;
92         }
93         if (dist) {
94                 *dist = closest_dist;
95         }
96         if (normal) {
97                 *normal = closest_normal;
98         }
99         return true;
100 }
101
102 void Chunk::Position(const glm::tvec3<int> &pos) {
103         position = pos;
104 }
105
106 glm::mat4 Chunk::Transform(const glm::tvec3<int> &offset) const {
107         return glm::translate((position - offset) * Extent());
108 }
109
110
111 int Chunk::VertexCount() const {
112         int count = 0;
113         for (const auto &block : blocks) {
114                 count += block.type->shape->VertexCount();
115         }
116         return count;
117 }
118
119 void Chunk::Update() {
120         model.Clear();
121         model.Reserve(VertexCount());
122
123         for (size_t i = 0; i < Size(); ++i) {
124                 blocks[i].type->FillModel(ToCoords(i), model);
125         }
126
127         model.Invalidate();
128         dirty = false;
129 }
130
131
132 }