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