]> git.lizzy.rs Git - dragonblocks3d.git/blob - src/dragonblocks/chunk.cpp
Added player, refactored mesh code
[dragonblocks3d.git] / src / dragonblocks / chunk.cpp
1 #include <stdexcept>
2 #include "block_def.hpp" 
3 #include "chunk.hpp" 
4 #include "cube.hpp"
5 #include "face_dir.hpp" 
6 #include "log.hpp" 
7 #include "map.hpp" 
8 #include "mesh.hpp" 
9 #include "texture.hpp" 
10
11 #include "scene.hpp"
12
13 #define SIZE DRAGONBLOCKS_CHUNK_SIZE
14
15 using namespace std;
16 using namespace glm;
17 using namespace dragonblocks;
18
19 void Chunk::checkPos(const ivec3 &pos)
20 {
21         if (pos.x < 0 || pos.y < 0 || pos.z < 0 || pos.x >= SIZE || pos.y >= SIZE || pos.z >= SIZE)
22                 throw out_of_range("Block position out of range");
23 }
24
25 const Block *Chunk::getBlock(const ivec3 &pos) const
26 {
27         Chunk::checkPos(pos);
28         return &data.blocks[pos.x][pos.y][pos.z];       
29 }
30
31 const Block *Chunk::getBlockNoEx(const ivec3 &pos) const
32 {
33         try {
34                 return getBlock(pos);
35         } catch (out_of_range &) {
36                 return nullptr;
37         }
38 }
39
40 void Chunk::setBlock(const ivec3 &pos, const Block &block)
41 {
42         Chunk::checkPos(pos);
43         data.blocks[pos.x][pos.y][pos.z] = block;
44 }
45
46 void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block)
47 {
48         try {
49                 setBlock(pos, block);
50         } catch (out_of_range &) {
51         }
52 }
53
54 void Chunk::addMeshUpdateTask()
55 {
56         mesh_gen_mgr->addTask(this);
57 }
58
59 void Chunk::addMeshUpdateTaskWithEdge()
60 {
61         addMeshUpdateTask();
62         for (int i = 0; i < 6; i++) {
63                 if (Chunk *neighbor = map->getChunk(pos + face_dir[i])) {
64                         neighbor->addMeshUpdateTask();
65                 }
66         }
67 }
68
69 void Chunk::updateMesh()
70 {
71         log(string("Update Chunk Mesh at ") + to_string(pos.x) + " " + to_string(pos.y) +  " " + to_string(pos.z));
72                 
73         if (mesh_created && ! animation_finished)
74                 return;
75         
76         bool mesh_created_before = mesh_created;
77         mesh_created = true;
78         
79         vector<GLfloat> vertices;
80         vector<Texture> textures;
81         bool any_drawable_block = false;
82         
83         for (int x = 0; x < SIZE; x++) {
84                 for (int y = 0; y < SIZE; y++) {
85                         for (int z = 0; z < SIZE; z++) {
86                                 Block *block = &data.blocks[x][y][z];
87                                 BlockDef *def = block->getDef();
88                                 if (! def->drawable)
89                                         continue;
90                                 ivec3 bpos(x, y, z);
91                                 vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
92                                 for (int facenr = 0; facenr < 6; facenr++) {
93                                         ivec3 npos = bpos + face_dir[facenr];
94                                         const Block *neighbor_own, *neighbor;
95                                         neighbor_own = neighbor = getBlockNoEx(npos);
96                                         if (! neighbor)
97                                                 neighbor = map->getBlock(pos * SIZE + npos);
98                                         if (neighbor && ! neighbor->getDef()->drawable)
99                                                 any_drawable_block = true;
100                                         if (! mesh_created_before)
101                                                 neighbor = neighbor_own;
102                                         if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
103                                                 textures.push_back(def->tiles[facenr]);
104                                                 for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
105                                                         for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
106                                                                 int index = facenr * 6 * 5 + vertex_index * 5 + attribute_index;
107                                                                 GLdouble value = cube[index];
108                                                                 switch (attribute_index) {
109                                                                         case 0:
110                                                                         value += pos_from_mesh_origin.x;
111                                                                         break;
112                                                                         case 1:
113                                                                         value += pos_from_mesh_origin.y;
114                                                                         break;
115                                                                         case 2:
116                                                                         value += pos_from_mesh_origin.z;
117                                                                         break;
118                                                                 }
119                                                                 vertices.push_back(value);
120                                                         }
121                                                 }
122                                         }
123                                 }
124                         }
125                 }
126         }
127         
128         if (! any_drawable_block) {
129                 if (! mesh_created_before) {
130                         afterAnimation();
131                 } else if (mesh) {
132                         delete mesh;
133                         mesh = nullptr;
134                 }
135                 return;
136         }
137         
138         Mesh *oldmesh = mesh;
139         
140         mesh = new Mesh(scene, &vertices[0], vertices.size() * sizeof(GLfloat));
141         mesh->pos = pos * SIZE + SIZE / 2;
142         mesh->textures = textures;
143         mesh->vertices_per_texture = 6;
144         if (! mesh_created_before) {
145                 mesh->animation = Mesh::Animation(Mesh::Animation::Type::FLYIN, Chunk::staticAfterAnimation, this);
146         }
147         
148         if (oldmesh) {
149                 oldmesh->die();
150         }
151 }
152
153 Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenMgr *mg, Scene *s) : map(m), data(d), pos(p), mesh_gen_mgr(mg), scene(s)
154 {
155         addMeshUpdateTask();
156 }
157
158 Chunk::~Chunk()
159 {
160         if (mesh) {
161                 delete mesh;
162         }
163 }
164
165 void Chunk::staticAfterAnimation(void *chunk)
166 {
167         if (chunk) {
168                 ((Chunk *)chunk)->afterAnimation();
169         }
170 }
171
172 void Chunk::afterAnimation()
173 {
174         animation_finished = true;
175         addMeshUpdateTaskWithEdge();
176 }