3 #include "animations.hpp"
4 #include "block_def.hpp"
5 #include "box_vertices.hpp"
7 #include "face_dir.hpp"
10 #include "texture.hpp"
12 #define SIZE DRAGONBLOCKS_CHUNK_SIZE
16 using namespace dragonblocks;
18 bool Chunk::checkPos(const ivec3 &pos)
20 return pos.x >= 0 && pos.y >= 0 && pos.z >= 0 && pos.x < SIZE && pos.y < SIZE && pos.z < SIZE;
23 const Block *Chunk::getBlock(const ivec3 &pos) const
25 const Block *b = getBlockNoEx(pos);
27 throw out_of_range("Block position out of range");
32 const Block *Chunk::getBlockNoEx(const ivec3 &pos) const
34 return Chunk::checkPos(pos) ? &data.blocks[pos.x][pos.y][pos.z] : nullptr;
37 void Chunk::setBlock(const ivec3 &pos, const Block &block)
39 if (! Chunk::checkPos(pos)) {
40 throw out_of_range("Block position out of range");
42 data.blocks[pos.x][pos.y][pos.z] = block;
45 void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block)
49 } catch (out_of_range &) {
53 void Chunk::addMeshUpdateTask()
55 async_mgr->addTask(this);
58 void Chunk::addMeshUpdateTaskWithEdge()
61 for (int i = 0; i < 6; i++) {
62 if (Chunk *neighbor = map->getChunk(pos + face_dir[i])) {
63 neighbor->addMeshUpdateTask();
68 void Chunk::updateMesh()
70 cout << "Update Chunk Mesh at " << pos.x << " " << pos.y << " " << pos.z << endl;
72 if (mesh_created && ! animation_finished)
75 bool mesh_created_before = mesh_created;
78 vector<GLfloat> vertices;
79 vector<Texture> textures;
80 bool any_drawable_block = false;
82 for (int x = 0; x < SIZE; x++) {
83 for (int y = 0; y < SIZE; y++) {
84 for (int z = 0; z < SIZE; z++) {
85 Block *block = &data.blocks[x][y][z];
86 BlockDef *def = block->getDef();
90 vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
91 for (int facenr = 0; facenr < 6; facenr++) {
92 ivec3 npos = bpos + face_dir[facenr];
93 const Block *neighbor_own, *neighbor;
94 neighbor_own = neighbor = getBlockNoEx(npos);
96 neighbor = map->getBlock(pos * SIZE + npos);
97 if (neighbor && ! neighbor->getDef()->drawable)
98 any_drawable_block = true;
99 if (! mesh_created_before)
100 neighbor = neighbor_own;
101 if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
102 textures.push_back(def->tile_def.get(facenr));
103 for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
104 for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
105 GLdouble value = box_vertices[facenr][vertex_index][attribute_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 *oldmesh = mesh;
138 mesh = new Mesh(scene, shader_program, &vertices[0], vertices.size());
139 mesh->pos = pos * SIZE + SIZE / 2;
140 mesh->minp = vec3(- SIZE / 2);
141 mesh->maxp = vec3(+ SIZE / 2);
142 mesh->textures = textures;
143 mesh->vertices_per_texture = 6;
144 if (! mesh_created_before) {
145 mesh->animation = new GrowAnimation(0.25, Chunk::staticAfterAnimation, this);
153 void Chunk::doAsyncTask()
158 Chunk::Chunk(Map *m, const ivec3 &p, const Data &d, AsyncMgr *a, Scene *s, ShaderProgram *sh) : map(m), data(d), pos(p), async_mgr(a), scene(s), shader_program(sh)
170 void Chunk::staticAfterAnimation(void *chunk)
173 ((Chunk *)chunk)->afterAnimation();
177 void Chunk::afterAnimation()
179 animation_finished = true;
180 addMeshUpdateTaskWithEdge();