nuclear-plant-sim/src/world/chunk.cpp

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();
}
}
}