122 lines
2.7 KiB
C++
122 lines
2.7 KiB
C++
|
|
#include <GL/glew.h>
|
|
#include "chunk.hpp"
|
|
#include "tile/tile_base.hpp"
|
|
#include "../graphics/texture.hpp"
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/ext/quaternion_transform.hpp>
|
|
#include <glm/ext/scalar_constants.hpp>
|
|
#include <glm/ext/vector_float3.hpp>
|
|
#include <iterator>
|
|
#include <memory>
|
|
|
|
using World::Chunk;
|
|
using World::Tile::TileBase;
|
|
|
|
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].swap(v);
|
|
|
|
if(r && !v) {
|
|
m_used_tiles += 1;
|
|
}
|
|
else if(!r && v) {
|
|
m_used_tiles -= 1;
|
|
}
|
|
|
|
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++) {
|
|
glm::vec<2, int> t_off(x, y);
|
|
if(!get(t_off)) {
|
|
continue;
|
|
}
|
|
|
|
auto prim = PRIMITIVE_B;
|
|
prim.m_offset = {t_off, 0, 0};
|
|
prim.m_texid = Graphics::Texture::YELLOW_BRICK_FLOOR;
|
|
mesh.add_primitive(prim);
|
|
|
|
for(int i = 0; i < std::size(neighbours); i++) {
|
|
glm::vec<2, int> n_off = neighbours[i] + t_off;
|
|
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)) {
|
|
prim = PRIMITIVE_S[i];
|
|
prim.m_offset = {t_off, 0, 0};
|
|
prim.m_texid = Graphics::Texture::YELLOW_BRICK_WALL;
|
|
mesh.add_primitive(prim);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_model.set(mesh, GL_DYNAMIC_DRAW);
|
|
m_dirty = false;
|
|
}
|
|
|
|
void Chunk::render(const Graphics::Context& ctx) const {
|
|
ctx.set_model_matrix(glm::translate(glm::mat4(1), {glm::vec<2, double>(m_pos) - ctx.m_transform, 0}));
|
|
ctx.set_colour_matrix(glm::mat4(1));
|
|
m_model.render(GL_TRIANGLES);
|
|
|
|
for(auto& tile : m_tiles) {
|
|
if(tile) {
|
|
tile->render();
|
|
}
|
|
}
|
|
}
|
|
|