#include "Chunk.hpp" #include "BlockSide.hpp" namespace MC { void Chunk::set(uint32_t x, uint32_t y, uint32_t z, BlockType type) { m_blocks[x][y][z].type = type; } Mesh Chunk::mesh() { std::vector> positions{}; std::vector> tex_coords{}; std::vector indices{}; for (int x = 0; x < CHUNK_WIDTH; x++) { for (int y = 0; y < CHUNK_HEIGHT; y++) { for (int z = 0; z < CHUNK_WIDTH; z++) { auto type = m_blocks[x][y][z].type; if (type == BlockType::Air) { continue; } for (auto side: BlockSide::all()) { if (!is_face_visible(x, y, z, side)) { continue; } auto side_tex_coords = Chunk::face_tex_coords(type, side); auto side_positions = side.face(); for (auto& position : side_positions) { position = position + Vector<3>{static_cast(x), static_cast(y), static_cast(z)}; } uint32_t s = positions.size(); positions.insert(positions.end(), side_positions.begin(), side_positions.end()); tex_coords.insert(tex_coords.end(), side_tex_coords.begin(), side_tex_coords.end()); indices.insert(indices.end(), {s, s + 1, s + 3, s + 1, s + 2, s + 3}); } } } } return {positions, tex_coords, indices}; } bool Chunk::is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side) { Vector<3, int32_t> offset{}; switch (side) { case BlockSide::Front: offset[2] = 1; break; case BlockSide::Back: offset[2] = -1; break; case BlockSide::Top: offset[1] = 1; break; case BlockSide::Bottom: offset[1] = -1; break; case BlockSide::Left: offset[0] = -1; break; case BlockSide::Right: offset[0] = 1; break; } Vector<3, uint32_t> neighbor_pos{ x + offset.x(), y + offset.y(), z + offset.z(), }; if ( neighbor_pos.x() >= CHUNK_WIDTH || neighbor_pos.x() < 0 || neighbor_pos.y() >= CHUNK_HEIGHT || neighbor_pos.y() < 0 || neighbor_pos.z() >= CHUNK_WIDTH || neighbor_pos.z() < 0 ) { return true; } auto neighbor = m_blocks[neighbor_pos.x()][neighbor_pos.y()][neighbor_pos.z()]; if (neighbor.type == BlockType::Air) { return true; } return false; } std::array, 4> Chunk::face_tex_coords(BlockType type, BlockSide side) { switch (type) { case BlockType::Dirt: return {{ {0.5f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.5f}, {0.5f, 0.5f}, }}; case BlockType::Grass: switch (side) { case BlockSide::Front: case BlockSide::Back: case BlockSide::Left: case BlockSide::Right: return {{ {0.5f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.5f}, {0.5f, 0.5f}, }}; case BlockSide::Top: return {{ {0.0f, 0.0f}, {0.5f, 0.0f}, {0.5f, 0.5f}, {0.0f, 0.5f}, }}; case BlockSide::Bottom: return {{ {0.5f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.5f}, {0.5f, 0.5f}, }}; } default: return {}; } } }