#include <GL/glew.h> #include "chunk.hpp" #include "tile/tile_base.hpp" #include <glm/detail/qualifier.hpp> #include <glm/ext/matrix_transform.hpp> #include <glm/ext/quaternion_transform.hpp> #include <glm/ext/scalar_constants.hpp> #include <iterator> #include <memory> #include <utility> using World::Chunk; using World::Tile::TileBase; constexpr Graphics::Primitive<4, 6> PRIMITIVE_B = { .m_vertices = { {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 0, 0, 1}}, {.m_pos = {-0.5, +0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 1, 0, 1}}, {.m_pos = {+0.5, +0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, }, .m_indices = { 0, 2, 3, 0, 3, 1, }, }; constexpr Graphics::Primitive<4, 6> PRIMITIVE_0 = { .m_vertices = { {.m_pos = {-0.5, -0.5, 0.5, 1}, .m_colour = {1, 0, 0, 1}}, {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, {.m_pos = {+0.5, -0.5, 0.5, 1}, .m_colour = {0, 1, 0, 1}}, {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, }, .m_indices = { 0, 2, 3, 0, 3, 1, }, }; static const Graphics::Primitive<4, 6> PRIMITIVE_S[4] = { PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 0.5f, {0, 0, 1})), PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.0f, {0, 0, 1})), PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.5f, {0, 0, 1})), PRIMITIVE_0, }; constexpr glm::vec<2, int> get_pos_mod(glm::vec<2, int> pos) { return (pos % Chunk::N + Chunk::N) % Chunk::N; } Chunk::Chunk(glm::vec<2, int> pos) { m_pos = pos; } TileBase* Chunk::get(glm::vec<2, int> p) { p = get_pos_mod(p); return m_tiles[p.x * N + p.y].get(); } const TileBase* Chunk::get(glm::vec<2, int> p) const { p = get_pos_mod(p); return m_tiles[p.x * N + p.y].get(); } TileBase* Chunk::set(glm::vec<2, int> p, std::unique_ptr<TileBase> v) { TileBase* r = v.get(); p = get_pos_mod(p); m_tiles[p.x * N + p.y] = std::move(v); m_dirty = true; return r; } void Chunk::update(Map& map) { for(auto& tile : m_tiles) { if(tile) { tile->update(); } } if(!m_dirty) { return; } Graphics::Mesh mesh; const Chunk* chunks[4] = { map.get_chunk(m_pos + glm::vec<2, int>(N, 0)), map.get_chunk(m_pos + glm::vec<2, int>(0, N)), map.get_chunk(m_pos + glm::vec<2, int>(-N, 0)), map.get_chunk(m_pos + glm::vec<2, int>(0, -N)), }; const glm::vec<2, int> neighbours[4] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1}, }; for(int x = 0; x < N; x++) { for(int y = 0; y < N; y++) { if(!get({x, y})) { continue; } glm::vec<2, int> t_off(m_pos.x + x, m_pos.y + y); mesh.add_primitive(PRIMITIVE_B.with_translation({t_off, 0})); for(int i = 0; i < std::size(neighbours); i++) { glm::vec<2, int> n_off = neighbours[i] + glm::vec<2, int>(x, y); const Chunk* chunk_check = this; if(n_off.x == N) { chunk_check = chunks[0]; } else if(n_off.y == N) { chunk_check = chunks[1]; } else if(n_off.x == -1) { chunk_check = chunks[2]; } else if(n_off.y == -1) { chunk_check = chunks[3]; } if(!chunk_check || !chunk_check->get(n_off)) { mesh.add_primitive(PRIMITIVE_S[i].with_translation({t_off, 0})); } } } } m_model.bind(); m_model.set(mesh, GL_DYNAMIC_DRAW); Graphics::Vertex::set_vertex_attribs(); m_dirty = false; } void Chunk::render(Graphics::Context& ctx) const { m_model.bind(); m_model.render(GL_TRIANGLES); for(auto& tile : m_tiles) { if(tile) { tile->render(); } } }