]> git.lizzy.rs Git - dragonblocks3d.git/blob - src/dragonblocks/chunk.cpp
Initial Commit
[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 "map.hpp" 
7 #include "mesh.hpp" 
8 #include "texture.hpp" 
9
10 #define SIZE DRAGONBLOCKS_CHUNK_SIZE
11
12 using namespace std;
13 using namespace glm;
14 using namespace dragonblocks;
15
16 void Chunk::checkPos(const ivec3 &pos)
17 {
18         if (pos.x < 0 || pos.y < 0 || pos.z < 0 || pos.x >= SIZE || pos.y >= SIZE || pos.z >= SIZE)
19                 throw out_of_range("Block position out of range");
20 }
21
22 const Block *Chunk::getBlock(const ivec3 &pos) const
23 {
24         Chunk::checkPos(pos);
25         return &data.blocks[pos.x][pos.y][pos.z];       
26 }
27
28 const Block *Chunk::getBlockNoEx(const ivec3 &pos) const
29 {
30         try {
31                 return getBlock(pos);
32         } catch (std::out_of_range &) {
33                 return nullptr;
34         }
35 }
36
37 void Chunk::setBlock(const ivec3 &pos, const Block &block)
38 {
39         Chunk::checkPos(pos);
40         data.blocks[pos.x][pos.y][pos.z] = block;
41 }
42
43 void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block)
44 {
45         try {
46                 setBlock(pos, block);
47         } catch (std::out_of_range &) {
48         }
49 }
50
51 void Chunk::updateMesh()
52 {
53         std::vector<GLfloat> vertices;
54         std::vector<Texture> textures;
55         
56         for (int x = 0; x < SIZE; x++) {
57                 for (int y = 0; y < SIZE; y++) {
58                         for (int z = 0; z < SIZE; z++) {
59                                 Block *block = &data.blocks[x][y][z];
60                                 BlockDef *def = block->getDef();
61                                 if (! def->drawable)
62                                         continue;
63                                 vec3 pos(x, y, z);
64                                 vec3 pos_from_mesh_origin = pos - vec3(SIZE / 2 + 0.5);
65                                 for (int facenr = 0; facenr < 6; facenr++) {
66                                         const Block *neighbor = map->getBlockRelativePos(this, pos + (vec3)face_dir[facenr]);
67                                         if (neighbor && ! neighbor->getDef()->drawable) {
68                                                 textures.push_back(def->tiles[facenr]);
69                                                 for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
70                                                         for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
71                                                                 int index = facenr * 6 * 5 + vertex_index * 5 + attribute_index;
72                                                                 GLdouble value = cube[index];
73                                                                 switch (attribute_index) {
74                                                                         case 0:
75                                                                         value += pos_from_mesh_origin.x;
76                                                                         break;
77                                                                         case 1:
78                                                                         value += pos_from_mesh_origin.y;
79                                                                         break;
80                                                                         case 2:
81                                                                         value += pos_from_mesh_origin.z;
82                                                                         break;
83                                                                 }
84                                                                 vertices.push_back(value);
85                                                         }
86                                                 }
87                                         }
88                                 }
89                         }
90                 }
91         }
92
93         bool is_new = ! deleteMesh();
94         
95         if (textures.size() == 0) {
96                 return;
97         }
98
99         mesh = new Mesh(scene);
100         mesh->pos = pos * SIZE + SIZE / 2;
101         mesh->size = vec3(1.0);
102         mesh->configureVertexObjects(&vertices[0], vertices.size() * sizeof(GLfloat));
103         mesh->textures = textures;
104         mesh->vertices_per_texture = 6;
105         if (is_new)
106                 mesh->effect = Mesh::Effect::Type::FLYIN;
107         mesh->addToScene();
108 }
109
110 void Chunk::addMeshUpdateTask()
111 {
112         mesh_gen_thread->addTask(this);
113 }
114
115 bool Chunk::deleteMesh()
116 {
117         if (mesh) {
118                 mesh->removeFromScene();
119                 delete mesh;
120                 mesh = nullptr;
121                 return true;
122         }
123         return false;
124 }
125
126 Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenThread *mgt, Scene *s) : map(m), data(d), pos(p), mesh_gen_thread(mgt), scene(s)
127 {
128         addMeshUpdateTask();
129 }
130
131 Chunk::~Chunk()
132 {
133         deleteMesh();
134 }