diff options
Diffstat (limited to 'game/client/chunk_mesher.cc')
| -rw-r--r-- | game/client/chunk_mesher.cc | 252 |
1 files changed, 160 insertions, 92 deletions
diff --git a/game/client/chunk_mesher.cc b/game/client/chunk_mesher.cc index 7e185f1..962997c 100644 --- a/game/client/chunk_mesher.cc +++ b/game/client/chunk_mesher.cc @@ -1,4 +1,5 @@ #include "client/pch.hh" + #include "client/chunk_mesher.hh" #include "core/crc64.hh" @@ -18,19 +19,19 @@ using QuadBuilder = std::vector<ChunkQuad>; using CachedChunkCoord = unsigned short; constexpr static CachedChunkCoord CPOS_ITSELF = 0x0000; -constexpr static CachedChunkCoord CPOS_NORTH = 0x0001; -constexpr static CachedChunkCoord CPOS_SOUTH = 0x0002; -constexpr static CachedChunkCoord CPOS_EAST = 0x0003; -constexpr static CachedChunkCoord CPOS_WEST = 0x0004; -constexpr static CachedChunkCoord CPOS_TOP = 0x0005; +constexpr static CachedChunkCoord CPOS_NORTH = 0x0001; +constexpr static CachedChunkCoord CPOS_SOUTH = 0x0002; +constexpr static CachedChunkCoord CPOS_EAST = 0x0003; +constexpr static CachedChunkCoord CPOS_WEST = 0x0004; +constexpr static CachedChunkCoord CPOS_TOP = 0x0005; constexpr static CachedChunkCoord CPOS_BOTTOM = 0x0006; constexpr static const size_t NUM_CACHED_CPOS = 7; -static const CachedChunkCoord get_cached_cpos(const chunk_pos &pivot, const chunk_pos &cpos) +static const CachedChunkCoord get_cached_cpos(const chunk_pos& pivot, const chunk_pos& cpos) { - static const CachedChunkCoord nx[3] = {CPOS_WEST, 0, CPOS_EAST}; - static const CachedChunkCoord ny[3] = {CPOS_BOTTOM, 0, CPOS_TOP}; - static const CachedChunkCoord nz[3] = {CPOS_NORTH, 0, CPOS_SOUTH}; + static const CachedChunkCoord nx[3] = { CPOS_WEST, 0, CPOS_EAST }; + static const CachedChunkCoord ny[3] = { CPOS_BOTTOM, 0, CPOS_TOP }; + static const CachedChunkCoord nz[3] = { CPOS_NORTH, 0, CPOS_SOUTH }; if(pivot != cpos) { chunk_pos delta = pivot - cpos; @@ -38,11 +39,13 @@ static const CachedChunkCoord get_cached_cpos(const chunk_pos &pivot, const chun delta[1] = cxpr::clamp<std::int64_t>(delta[1], -1, 1); delta[2] = cxpr::clamp<std::int64_t>(delta[2], -1, 1); - if(delta[0]) + if(delta[0]) { return nx[delta[0] + 1]; - if(delta[1]) + } else if(delta[1]) { return ny[delta[1] + 1]; - return nz[delta[2] + 1]; + } else { + return nz[delta[2] + 1]; + } } return CPOS_ITSELF; @@ -52,36 +55,46 @@ static voxel_facing get_facing(voxel_face face, voxel_type type) { if(type == voxel_type::CROSS) { switch(face) { - case voxel_face::CROSS_NESW: return voxel_facing::NESW; - case voxel_face::CROSS_NWSE: return voxel_facing::NWSE; - default: return voxel_facing::NORTH; + case voxel_face::CROSS_NESW: + return voxel_facing::NESW; + case voxel_face::CROSS_NWSE: + return voxel_facing::NWSE; + default: + return voxel_facing::NORTH; } } switch(face) { - case voxel_face::CUBE_NORTH: return voxel_facing::NORTH; - case voxel_face::CUBE_SOUTH: return voxel_facing::SOUTH; - case voxel_face::CUBE_EAST: return voxel_facing::EAST; - case voxel_face::CUBE_WEST: return voxel_facing::WEST; - case voxel_face::CUBE_TOP: return voxel_facing::UP; - case voxel_face::CUBE_BOTTOM: return voxel_facing::DOWN; - default: return voxel_facing::NORTH; + case voxel_face::CUBE_NORTH: + return voxel_facing::NORTH; + case voxel_face::CUBE_SOUTH: + return voxel_facing::SOUTH; + case voxel_face::CUBE_EAST: + return voxel_facing::EAST; + case voxel_face::CUBE_WEST: + return voxel_facing::WEST; + case voxel_face::CUBE_TOP: + return voxel_facing::UP; + case voxel_face::CUBE_BOTTOM: + return voxel_facing::DOWN; + default: + return voxel_facing::NORTH; } } class GL_MeshingTask final : public Task { public: - explicit GL_MeshingTask(entt::entity entity, const chunk_pos &cpos); + explicit GL_MeshingTask(entt::entity entity, const chunk_pos& cpos); virtual ~GL_MeshingTask(void) = default; virtual void process(void) override; virtual void finalize(void) override; private: - bool vis_test(voxel_id voxel, const VoxelInfo *info, const local_pos &lpos) const; - void push_quad_a(const VoxelInfo *info, const glm::fvec3 &pos, const glm::fvec2 &size, voxel_face face); - void push_quad_v(const VoxelInfo *info, const glm::fvec3 &pos, const glm::fvec2 &size, voxel_face face, std::size_t entropy); - void make_cube(voxel_id voxel, const VoxelInfo *info, const local_pos &lpos, voxel_vis vis, std::size_t entropy); - void cache_chunk(const chunk_pos &cpos); + bool vis_test(voxel_id voxel, const VoxelInfo* info, const local_pos& lpos) const; + void push_quad_a(const VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, voxel_face face); + void push_quad_v(const VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, voxel_face face, std::size_t entropy); + void make_cube(voxel_id voxel, const VoxelInfo* info, const local_pos& lpos, voxel_vis vis, std::size_t entropy); + void cache_chunk(const chunk_pos& cpos); private: std::array<VoxelStorage, NUM_CACHED_CPOS> m_cache; @@ -91,7 +104,7 @@ private: chunk_pos m_cpos; }; -GL_MeshingTask::GL_MeshingTask(entt::entity entity, const chunk_pos &cpos) +GL_MeshingTask::GL_MeshingTask(entt::entity entity, const chunk_pos& cpos) { m_entity = entity; m_cpos = cpos; @@ -110,7 +123,7 @@ void GL_MeshingTask::process(void) m_quads_b.resize(voxel_atlas::plane_count()); m_quads_s.resize(voxel_atlas::plane_count()); - const auto &voxels = m_cache.at(CPOS_ITSELF); + const auto& voxels = m_cache.at(CPOS_ITSELF); for(std::size_t i = 0; i < CHUNK_VOLUME; ++i) { if(m_status == task_status::CANCELLED) { @@ -131,18 +144,30 @@ void GL_MeshingTask::process(void) } voxel_vis vis = 0; - if(vis_test(voxel, info, lpos + DIR_NORTH<local_pos::value_type>)) + + if(vis_test(voxel, info, lpos + DIR_NORTH<local_pos::value_type>)) { vis |= VIS_NORTH; - if(vis_test(voxel, info, lpos + DIR_SOUTH<local_pos::value_type>)) + } + + if(vis_test(voxel, info, lpos + DIR_SOUTH<local_pos::value_type>)) { vis |= VIS_SOUTH; - if(vis_test(voxel, info, lpos + DIR_EAST<local_pos::value_type>)) + } + + if(vis_test(voxel, info, lpos + DIR_EAST<local_pos::value_type>)) { vis |= VIS_EAST; - if(vis_test(voxel, info, lpos + DIR_WEST<local_pos::value_type>)) + } + + if(vis_test(voxel, info, lpos + DIR_WEST<local_pos::value_type>)) { vis |= VIS_WEST; - if(vis_test(voxel, info, lpos + DIR_UP<local_pos::value_type>)) + } + + if(vis_test(voxel, info, lpos + DIR_UP<local_pos::value_type>)) { vis |= VIS_UP; - if(vis_test(voxel, info, lpos + DIR_DOWN<local_pos::value_type>)) + } + + if(vis_test(voxel, info, lpos + DIR_DOWN<local_pos::value_type>)) { vis |= VIS_DOWN; + } const auto vpos = coord::to_voxel(m_cpos, lpos); const auto entropy_src = vpos[0] * vpos[1] * vpos[2]; @@ -161,7 +186,7 @@ void GL_MeshingTask::finalize(void) return; } - auto &component = globals::dimension->chunks.emplace_or_replace<ChunkMeshComponent>(m_entity); + auto& component = globals::dimension->chunks.emplace_or_replace<ChunkMeshComponent>(m_entity); const std::size_t plane_count_nb = m_quads_s.size(); const std::size_t plane_count_b = m_quads_b.size(); @@ -173,8 +198,8 @@ void GL_MeshingTask::finalize(void) component.quad_b.resize(plane_count_b); for(std::size_t plane = 0; plane < plane_count_nb; ++plane) { - QuadBuilder &builder = m_quads_s[plane]; - ChunkVBO &buffer = component.quad_nb[plane]; + QuadBuilder& builder = m_quads_s[plane]; + ChunkVBO& buffer = component.quad_nb[plane]; if(builder.empty()) { if(buffer.handle) { @@ -182,20 +207,21 @@ void GL_MeshingTask::finalize(void) buffer.handle = 0; buffer.size = 0; } - } - else { - if(!buffer.handle) + } else { + if(!buffer.handle) { glGenBuffers(1, &buffer.handle); + } + glBindBuffer(GL_ARRAY_BUFFER, buffer.handle); glBufferData(GL_ARRAY_BUFFER, sizeof(ChunkQuad) * builder.size(), builder.data(), GL_STATIC_DRAW); buffer.size = builder.size(); has_no_submeshes_nb = false; - } + } } for(std::size_t plane = 0; plane < plane_count_b; ++plane) { - QuadBuilder &builder = m_quads_b[plane]; - ChunkVBO &buffer = component.quad_b[plane]; + QuadBuilder& builder = m_quads_b[plane]; + ChunkVBO& buffer = component.quad_b[plane]; if(builder.empty()) { if(buffer.handle) { @@ -203,15 +229,16 @@ void GL_MeshingTask::finalize(void) buffer.handle = 0; buffer.size = 0; } - } - else { - if(!buffer.handle) + } else { + if(!buffer.handle) { glGenBuffers(1, &buffer.handle); + } + glBindBuffer(GL_ARRAY_BUFFER, buffer.handle); glBufferData(GL_ARRAY_BUFFER, sizeof(ChunkQuad) * builder.size(), builder.data(), GL_STATIC_DRAW); buffer.size = builder.size(); has_no_submeshes_b = false; - } + } } if(has_no_submeshes_b && has_no_submeshes_nb) { @@ -219,7 +246,7 @@ void GL_MeshingTask::finalize(void) } } -bool GL_MeshingTask::vis_test(voxel_id voxel, const VoxelInfo *info, const local_pos &lpos) const +bool GL_MeshingTask::vis_test(voxel_id voxel, const VoxelInfo* info, const local_pos& lpos) const { const auto pvpos = coord::to_voxel(m_cpos, lpos); const auto pcpos = coord::to_chunk(pvpos); @@ -227,71 +254,113 @@ bool GL_MeshingTask::vis_test(voxel_id voxel, const VoxelInfo *info, const local const auto index = coord::to_index(plpos); const auto cached_cpos = get_cached_cpos(m_cpos, pcpos); - const auto &voxels = m_cache.at(cached_cpos); + const auto& voxels = m_cache.at(cached_cpos); const auto neighbour = voxels[index]; - if(neighbour == NULL_VOXEL_ID) - return true; - if(neighbour == voxel) - return false; + bool result; - if(const VoxelInfo *neighbour_info = voxel_registry::find(neighbour)) { + if(neighbour == NULL_VOXEL_ID) { + result = true; + } else if(neighbour == voxel) { + result = false; + } else if(auto neighbour_info = voxel_registry::find(neighbour)) { if(neighbour_info->blending != info->blending) { // Voxel types that use blending are semi-transparent; // this means they're rendered using a different setup // and they must have visible faces with opaque voxels - return neighbour_info->blending; + result = neighbour_info->blending; + } else { + result = false; } + } else { + result = false; } - return false; + return result; } -void GL_MeshingTask::push_quad_a(const VoxelInfo *info, const glm::fvec3 &pos, const glm::fvec2 &size, voxel_face face) +void GL_MeshingTask::push_quad_a(const VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, voxel_face face) { const voxel_facing facing = get_facing(face, info->type); - const VoxelTexture &vtex = info->textures[static_cast<std::size_t>(face)]; + const VoxelTexture& vtex = info->textures[static_cast<std::size_t>(face)]; - if(info->blending) + if(info->blending) { m_quads_b[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset, vtex.paths.size())); - else m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset, vtex.paths.size())); + } else { + m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset, vtex.paths.size())); + } } -void GL_MeshingTask::push_quad_v(const VoxelInfo *info, const glm::fvec3 &pos, const glm::fvec2 &size, voxel_face face, std::size_t entropy) +void GL_MeshingTask::push_quad_v(const VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, voxel_face face, std::size_t entropy) { const voxel_facing facing = get_facing(face, info->type); - const VoxelTexture &vtex = info->textures[static_cast<std::size_t>(face)]; + const VoxelTexture& vtex = info->textures[static_cast<std::size_t>(face)]; const std::size_t entropy_mod = entropy % vtex.paths.size(); - if(info->blending) + if(info->blending) { m_quads_b[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset + entropy_mod, 0)); - else m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset + entropy_mod, 0)); + } else { + m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset + entropy_mod, 0)); + } } -void GL_MeshingTask::make_cube(voxel_id voxel, const VoxelInfo *info, const local_pos &lpos, voxel_vis vis, std::size_t entropy) +void GL_MeshingTask::make_cube(voxel_id voxel, const VoxelInfo* info, const local_pos& lpos, voxel_vis vis, std::size_t entropy) { const glm::fvec3 fpos = glm::fvec3(lpos); const glm::fvec2 fsize = glm::fvec2(1.0f, 1.0f); if(info->animated) { - if(vis & VIS_NORTH) push_quad_a(info, fpos, fsize, voxel_face::CUBE_NORTH); - if(vis & VIS_SOUTH) push_quad_a(info, fpos, fsize, voxel_face::CUBE_SOUTH); - if(vis & VIS_EAST) push_quad_a(info, fpos, fsize, voxel_face::CUBE_EAST); - if(vis & VIS_WEST) push_quad_a(info, fpos, fsize, voxel_face::CUBE_WEST); - if(vis & VIS_UP) push_quad_a(info, fpos, fsize, voxel_face::CUBE_TOP); - if(vis & VIS_DOWN) push_quad_a(info, fpos, fsize, voxel_face::CUBE_BOTTOM); - } - else { - if(vis & VIS_NORTH) push_quad_v(info, fpos, fsize, voxel_face::CUBE_NORTH, entropy); - if(vis & VIS_SOUTH) push_quad_v(info, fpos, fsize, voxel_face::CUBE_SOUTH, entropy); - if(vis & VIS_EAST) push_quad_v(info, fpos, fsize, voxel_face::CUBE_EAST, entropy); - if(vis & VIS_WEST) push_quad_v(info, fpos, fsize, voxel_face::CUBE_WEST, entropy); - if(vis & VIS_UP) push_quad_v(info, fpos, fsize, voxel_face::CUBE_TOP, entropy); - if(vis & VIS_DOWN) push_quad_v(info, fpos, fsize, voxel_face::CUBE_BOTTOM, entropy); + if(vis & VIS_NORTH) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_NORTH); + } + + if(vis & VIS_SOUTH) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_SOUTH); + } + + if(vis & VIS_EAST) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_EAST); + } + + if(vis & VIS_WEST) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_WEST); + } + + if(vis & VIS_UP) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_TOP); + } + + if(vis & VIS_DOWN) { + push_quad_a(info, fpos, fsize, voxel_face::CUBE_BOTTOM); + } + } else { + if(vis & VIS_NORTH) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_NORTH, entropy); + } + + if(vis & VIS_SOUTH) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_SOUTH, entropy); + } + + if(vis & VIS_EAST) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_EAST, entropy); + } + + if(vis & VIS_WEST) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_WEST, entropy); + } + + if(vis & VIS_UP) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_TOP, entropy); + } + + if(vis & VIS_DOWN) { + push_quad_v(info, fpos, fsize, voxel_face::CUBE_BOTTOM, entropy); + } } } -void GL_MeshingTask::cache_chunk(const chunk_pos &cpos) +void GL_MeshingTask::cache_chunk(const chunk_pos& cpos) { const auto index = get_cached_cpos(m_cpos, cpos); @@ -304,7 +373,7 @@ void GL_MeshingTask::cache_chunk(const chunk_pos &cpos) // Bogus internal flag component struct NeedsMeshingComponent final {}; -static void on_chunk_create(const ChunkCreateEvent &event) +static void on_chunk_create(const ChunkCreateEvent& event) { const std::array<chunk_pos, 6> neighbours = { event.cpos + DIR_NORTH<chunk_pos::value_type>, @@ -317,15 +386,15 @@ static void on_chunk_create(const ChunkCreateEvent &event) globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(event.chunk->get_entity()); - for(const chunk_pos &cpos : neighbours) { - if(const Chunk *chunk = globals::dimension->find_chunk(cpos)) { + for(const chunk_pos& cpos : neighbours) { + if(const Chunk* chunk = globals::dimension->find_chunk(cpos)) { globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(chunk->get_entity()); continue; } } } -static void on_chunk_update(const ChunkUpdateEvent &event) +static void on_chunk_update(const ChunkUpdateEvent& event) { const std::array<chunk_pos, 6> neighbours = { event.cpos + DIR_NORTH<chunk_pos::value_type>, @@ -338,15 +407,15 @@ static void on_chunk_update(const ChunkUpdateEvent &event) globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(event.chunk->get_entity()); - for(const chunk_pos &cpos : neighbours) { - if(const Chunk *chunk = globals::dimension->find_chunk(cpos)) { + for(const chunk_pos& cpos : neighbours) { + if(const Chunk* chunk = globals::dimension->find_chunk(cpos)) { globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(chunk->get_entity()); continue; } } } -static void on_voxel_set(const VoxelSetEvent &event) +static void on_voxel_set(const VoxelSetEvent& event) { globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(event.chunk->get_entity()); @@ -367,8 +436,8 @@ static void on_voxel_set(const VoxelSetEvent &event) } } - for(const chunk_pos &cpos : neighbours) { - if(const Chunk *chunk = globals::dimension->find_chunk(cpos)) { + for(const chunk_pos& cpos : neighbours) { + if(const Chunk* chunk = globals::dimension->find_chunk(cpos)) { globals::dimension->chunks.emplace_or_replace<NeedsMeshingComponent>(chunk->get_entity()); continue; } @@ -384,7 +453,6 @@ void chunk_mesher::init(void) void chunk_mesher::deinit(void) { - } void chunk_mesher::update(void) |
