140 lines
3.4 KiB
C++
140 lines
3.4 KiB
C++
|
|
#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();
|
|
}
|
|
}
|
|
}
|
|
|