2 #include "block_def.hpp"
5 #include "face_dir.hpp"
11 #define SIZE DRAGONBLOCKS_CHUNK_SIZE
15 using namespace dragonblocks;
17 void Chunk::checkPos(const ivec3 &pos)
19 if (pos.x < 0 || pos.y < 0 || pos.z < 0 || pos.x >= SIZE || pos.y >= SIZE || pos.z >= SIZE)
20 throw out_of_range("Block position out of range");
23 const Block *Chunk::getBlock(const ivec3 &pos) const
26 return &data.blocks[pos.x][pos.y][pos.z];
29 const Block *Chunk::getBlockNoEx(const ivec3 &pos) const
33 } catch (out_of_range &) {
38 void Chunk::setBlock(const ivec3 &pos, const Block &block)
41 data.blocks[pos.x][pos.y][pos.z] = block;
44 void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block)
48 } catch (out_of_range &) {
52 void Chunk::addMeshUpdateTask()
54 mesh_gen_mgr->addTask(this);
57 void Chunk::addMeshUpdateTaskWithEdge()
60 for (int i = 0; i < 6; i++) {
61 if (Chunk *neighbor = map->getChunk(pos + face_dir[i])) {
62 neighbor->addMeshUpdateTask();
67 void Chunk::updateMesh()
69 log(string("Update Chunk Mesh at ") + to_string(pos.x) + " " + to_string(pos.y) + " " + to_string(pos.z));
71 if (mesh_created && ! effect_finished)
74 bool mesh_created_before = mesh_created;
77 vector<GLfloat> vertices;
78 vector<Texture> textures;
79 bool any_drawable_block = false;
81 for (int x = 0; x < SIZE; x++) {
82 for (int y = 0; y < SIZE; y++) {
83 for (int z = 0; z < SIZE; z++) {
84 Block *block = &data.blocks[x][y][z];
85 BlockDef *def = block->getDef();
89 vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
90 for (int facenr = 0; facenr < 6; facenr++) {
91 ivec3 npos = bpos + face_dir[facenr];
92 const Block *neighbor_own, *neighbor;
93 neighbor_own = neighbor = getBlockNoEx(npos);
95 neighbor = map->getBlock(pos * SIZE + npos);
96 if (neighbor && ! neighbor->getDef()->drawable)
97 any_drawable_block = true;
98 if (! mesh_created_before)
99 neighbor = neighbor_own;
100 if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
101 textures.push_back(def->tiles[facenr]);
102 for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
103 for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
104 int index = facenr * 6 * 5 + vertex_index * 5 + attribute_index;
105 GLdouble value = cube[index];
106 switch (attribute_index) {
108 value += pos_from_mesh_origin.x;
111 value += pos_from_mesh_origin.y;
114 value += pos_from_mesh_origin.z;
117 vertices.push_back(value);
126 if (! any_drawable_block) {
127 if (! mesh_created_before) {
136 mesh = new Mesh(scene);
140 mesh->pos = pos * SIZE + SIZE / 2;
141 mesh->vertexConfig(&vertices[0], vertices.size() * sizeof(GLfloat));
142 mesh->textures = textures;
143 mesh->vertices_per_texture = 6;
144 if (! mesh_created_before) {
145 mesh->effect = Mesh::Effect(Mesh::Effect::Type::FLYIN, Chunk::staticAfterEffect, this);
150 Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenMgr *mgt, Scene *s) : map(m), data(d), pos(p), mesh_gen_mgr(mgt), scene(s)
158 mesh->removeFromScene();
163 void Chunk::staticAfterEffect(void *chunk)
166 ((Chunk *)chunk)->afterEffect();
170 void Chunk::afterEffect()
172 effect_finished = true;
173 addMeshUpdateTaskWithEdge();