From dc8895b2dccc1279e4108911bb55156ce95df622 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Fri, 19 Jul 2024 14:27:41 +1000 Subject: [PATCH] added z index for tile placement --- src/world/builder.cpp | 66 +++++++++++++++++++-------------- src/world/builder.hpp | 12 ++++-- src/world/chunk.cpp | 85 +++++++++++++++++++++---------------------- src/world/chunk.hpp | 9 +++-- src/world/map.cpp | 36 ++++++++++++++---- src/world/map.hpp | 9 +++-- src/world/state.cpp | 2 +- 7 files changed, 128 insertions(+), 91 deletions(-) diff --git a/src/world/builder.cpp b/src/world/builder.cpp index d0bc67d..dff9e7f 100644 --- a/src/world/builder.cpp +++ b/src/world/builder.cpp @@ -20,12 +20,11 @@ using World::Builder; Builder::Builder() { - m_tools.push_back(nullptr); - m_tools.push_back(std::make_unique()); - m_tools.push_back(std::make_unique()); - m_tools.push_back(std::make_unique()); - - remesh_tool(); + m_tools.push_back({nullptr, 0}); + m_tools.push_back({nullptr, 1}); + m_tools.push_back({std::make_unique(), 0}); + m_tools.push_back({std::make_unique(), 1}); + m_tools.push_back({std::make_unique(), 0}); } void Builder::do_click(State& state) { @@ -44,14 +43,19 @@ void Builder::do_click(State& state) { return; } - m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos); + glm::vec<2, int> intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos); + const auto& tool = m_tools[m_tool_index]; - const Tile::TileBase* tile_cur = map.get_tile(m_intersect); - const Tile::TileBase* tile_next = m_tools[m_tool_index].get(); + const Tile::TileBase* tile_cur = map.get_tile({intersect, tool.m_zpos}); - if(tile_next && !tile_next->can_place(tile_cur) || !tile_next && !tile_cur) { + if(tool.m_tile && !tool.m_tile->can_place(tile_cur) || !tool.m_tile && !tile_cur) { return; } + + if(intersect != m_intersect) { + m_intersect = intersect; + m_remesh_needed = true; + } m_has_intersect = true; @@ -63,14 +67,14 @@ void Builder::do_click(State& state) { unsigned int texid; bool texid_use_old = false; - if(tile_next) { - tile = tile_next->clone(); - texid = tile_next->get_break_texture(); + if(tool.m_tile) { + tile = tool.m_tile->clone(); + texid = tool.m_tile->get_break_texture(); } else { texid_use_old = true; } - tile = map.set_tile(m_intersect, std::move(tile)); + tile = map.set_tile({m_intersect, tool.m_zpos}, std::move(tile)); if(texid_use_old) { if(tile) { @@ -91,18 +95,21 @@ void Builder::do_click(State& state) { }); } -void Builder::remesh_tool() { +void Builder::remesh_tool(const State& state) { + const auto& tool = m_tools[m_tool_index]; Graphics::Mesh mesh; - if(m_tools[m_tool_index]) { - const Tile::TileBase* neighbours[4] = {nullptr}; - m_tools[m_tool_index]->remesh(mesh, neighbours, {0, 0}); + + if(tool.m_tile) { + const Tile::TileBase* neighbours[4]; + state.m_map.get_tile_neighbours(neighbours, glm::vec<3, int>{m_intersect, tool.m_zpos}); + tool.m_tile->remesh(mesh, neighbours, {0, 0}); } else { Graphics::Primitive<4, 6> prim = { .m_vertices={ - {.m_pos={-0.5, -0.5, 0.05, 1}, .m_uv={0, 0}}, - {.m_pos={+0.5, -0.5, 0.05, 1}, .m_uv={2, 0}}, - {.m_pos={-0.5, +0.5, 0.05, 1}, .m_uv={0, 2}}, - {.m_pos={+0.5, +0.5, 0.05, 1}, .m_uv={2, 2}}, + {.m_pos={-0.25, -0.25, 0.05, 1}, .m_uv={0, 0}}, + {.m_pos={+0.25, -0.25, 0.05, 1}, .m_uv={1, 0}}, + {.m_pos={-0.25, +0.25, 0.05, 1}, .m_uv={0, 1}}, + {.m_pos={+0.25, +0.25, 0.05, 1}, .m_uv={1, 1}}, }, .m_indices={ 0, 3, 2, @@ -112,17 +119,17 @@ void Builder::remesh_tool() { prim.m_texid = Graphics::Texture::CROSS; mesh.add_primitive(prim); } + m_model.set(mesh, GL_DYNAMIC_DRAW); + m_remesh_needed = false; } void Builder::select_tool() { int offset = std::clamp((int)std::round(Graphics::Window::scroll), -1, 1); - if(offset == 0) { - return; + if(offset) { + m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size()); + m_remesh_needed = true; } - - m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size()); - remesh_tool(); } void Builder::update(State& state) { @@ -131,6 +138,9 @@ void Builder::update(State& state) { select_tool(); do_click(state); } + if(m_remesh_needed) { + remesh_tool(state); + } } void Builder::render(const Graphics::Context& ctx) const { @@ -138,7 +148,7 @@ void Builder::render(const Graphics::Context& ctx) const { return; } - glm::vec<2, double> pos = glm::round(m_intersect); + glm::vec<2, double> pos = m_intersect; ctx.set_model_matrix(glm::translate(glm::mat4(1), {pos - ctx.m_transform, 0})); ctx.set_colour_matrix(glm::mat4(1)); m_model.render(GL_TRIANGLES); diff --git a/src/world/builder.hpp b/src/world/builder.hpp index 3f3f24a..f7bce92 100644 --- a/src/world/builder.hpp +++ b/src/world/builder.hpp @@ -14,11 +14,17 @@ namespace World { CLEAR, }; - std::vector> m_tools; + struct ToolType { + std::unique_ptr m_tile; + int m_zpos; + }; + + std::vector m_tools; Graphics::GL::Model m_model; - glm::vec<2, double> m_intersect; + glm::vec<2, int> m_intersect; bool m_has_intersect = false; + bool m_remesh_needed = true; int m_tool_index = 1; Builder(); @@ -29,8 +35,8 @@ namespace World { private: void do_click(State& state); + void remesh_tool(const State& state); void select_tool(); - void remesh_tool(); }; }; diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index ee04277..81043e6 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -19,21 +19,21 @@ Chunk::Chunk(glm::vec<2, int> pos) { m_pos = pos; } -const TileBase* Chunk::get(glm::vec<2, int> p) const { - p = get_pos_mod(p); - return m_tiles[p.x * N + p.y].get(); +const TileBase* Chunk::get(glm::vec<3, int> p) const { + p = {get_pos_mod(p), p.z}; + return m_tiles[p.x + p.y * N + p.z * N * N].get(); } -TileBase* Chunk::get(glm::vec<2, int> p) { - p = get_pos_mod(p); - return m_tiles[p.x * N + p.y].get(); +TileBase* Chunk::get(glm::vec<3, int> p) { + p = {get_pos_mod(p), p.z}; + return m_tiles[p.x + p.y * N + p.z * N * N].get(); } -std::unique_ptr Chunk::set(glm::vec<2, int> p, std::unique_ptr v) { - p = get_pos_mod(p); +std::unique_ptr Chunk::set(glm::vec<3, int> p, std::unique_ptr v) { + p = {get_pos_mod(p), p.z}; bool is_empty_in = v == nullptr; - std::swap(m_tiles[p.x * N + p.y], v); + std::swap(m_tiles[p.x + p.y * N + p.z * N * N], v); if(is_empty_in && v) { m_used_tiles -= 1; @@ -57,45 +57,44 @@ void Chunk::update(Map& map) { 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}, + const glm::vec<3, int> neighbours[4] = { + {1, 0, 0}, + {0, 1, 0}, + {-1, 0, 0}, + {0, -1, 0}, }; - for(int x = 0; x < N; x++) { - for(int y = 0; y < N; y++) { - glm::vec<2, int> t_off(x, y); - const Tile::TileBase* tile = get(t_off); + for(int x = 0; x < N; x++) for(int y = 0; y < N; y++) for(int z = 0; z < H; z++) { - if(!tile) { - continue; - } + glm::vec<3, int> t_off(x, y, z); + const Tile::TileBase* tile = get(t_off); - const Tile::TileBase* tiles[4]; - - 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) { - tiles[i] = chunk_check->get(n_off); - } else { - tiles[i] = nullptr; - } - } - - tile->remesh(mesh, tiles, {x, y}); + if(!tile) { + continue; } + + const Tile::TileBase* tiles[4]; + + for(int i = 0; i < std::size(neighbours); i++) { + glm::vec<3, 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) { + tiles[i] = chunk_check->get(n_off); + } else { + tiles[i] = nullptr; + } + } + + tile->remesh(mesh, tiles, {x, y}); } m_model.set(mesh, GL_DYNAMIC_DRAW); m_dirty = false; diff --git a/src/world/chunk.hpp b/src/world/chunk.hpp index fe6d15d..bf551ea 100644 --- a/src/world/chunk.hpp +++ b/src/world/chunk.hpp @@ -15,8 +15,9 @@ namespace World { namespace World { struct Chunk { static constexpr int N = 16; + static constexpr int H = 2; - std::unique_ptr m_tiles[N*N] = {{}}; + std::unique_ptr m_tiles[N*N*H] = {{}}; Graphics::GL::Model m_model; glm::vec<2, int> m_pos; int m_used_tiles = 0; @@ -26,9 +27,9 @@ namespace World { void update(Map& map); void render(const Graphics::Context& ctx) const; - const Tile::TileBase* get(glm::vec<2, int> p) const; - Tile::TileBase* get(glm::vec<2, int> p); - std::unique_ptr set(glm::vec<2, int> p, std::unique_ptr v); + const Tile::TileBase* get(glm::vec<3, int> p) const; + Tile::TileBase* get(glm::vec<3, int> p); + std::unique_ptr set(glm::vec<3, int> p, std::unique_ptr v); }; }; diff --git a/src/world/map.cpp b/src/world/map.cpp index d63adc8..5ebdd68 100644 --- a/src/world/map.cpp +++ b/src/world/map.cpp @@ -56,31 +56,51 @@ void Map::mark_chunk_dirty(glm::vec<2, int> pos) { } } -const TileBase* Map::get_tile(glm::vec<2, int> pos) const { +const TileBase* Map::get_tile(glm::vec<3, int> pos) const { const Chunk* c = get_chunk(pos); return c ? c->get(pos) : nullptr; } -TileBase* Map::get_tile(glm::vec<2, int> pos) { +TileBase* Map::get_tile(glm::vec<3, int> pos) { Chunk* c = get_chunk(pos); return c ? c->get(pos) : nullptr; } -std::unique_ptr Map::set_tile(glm::vec<2, int> pos, std::unique_ptr tile) { +static const glm::vec<3, int> NEIGHBOURS[4] = { + {1, 0, 0}, + {0, 1, 0}, + {-1, 0, 0}, + {0, -1, 0}, +}; + +void Map::get_tile_neighbours(Tile::TileBase** neighbours, glm::vec<3, int> pos) { + for(int i = 0; i < std::size(NEIGHBOURS); i++) { + neighbours[i] = get_tile(pos + NEIGHBOURS[i]); + } +} + +void Map::get_tile_neighbours(const Tile::TileBase** neighbours, glm::vec<3, int> pos) const { + for(int i = 0; i < std::size(NEIGHBOURS); i++) { + neighbours[i] = get_tile(pos + NEIGHBOURS[i]); + } +} + +std::unique_ptr Map::set_tile(glm::vec<3, int> pos, std::unique_ptr tile) { uint64_t cid = get_chunk_id(pos); auto it = m_chunks.find(cid); + glm::vec<2, int> pos_h = pos; if(it == m_chunks.end()) { - it = m_chunks.try_emplace(cid, pos - get_pos_mod(pos)).first; + it = m_chunks.try_emplace(cid, pos_h - get_pos_mod(pos_h)).first; } Chunk& c = it->second; tile = c.set(pos, std::move(tile)); - mark_chunk_dirty(pos + glm::vec<2, int>(1, 0)); - mark_chunk_dirty(pos + glm::vec<2, int>(0, 1)); - mark_chunk_dirty(pos + glm::vec<2, int>(-1, 0)); - mark_chunk_dirty(pos + glm::vec<2, int>(0, -1)); + mark_chunk_dirty(pos_h + glm::vec<2, int>(1, 0)); + mark_chunk_dirty(pos_h + glm::vec<2, int>(0, 1)); + mark_chunk_dirty(pos_h + glm::vec<2, int>(-1, 0)); + mark_chunk_dirty(pos_h + glm::vec<2, int>(0, -1)); if(c.m_used_tiles <= 0) { m_chunks.erase(it); diff --git a/src/world/map.hpp b/src/world/map.hpp index 864d141..5e05674 100644 --- a/src/world/map.hpp +++ b/src/world/map.hpp @@ -18,14 +18,15 @@ namespace World { static constexpr int N = 16; std::map m_chunks; - Tile::TileBase* get_tile(glm::vec<2, int> pos); - const Tile::TileBase* get_tile(glm::vec<2, int> pos) const; + Tile::TileBase* get_tile(glm::vec<3, int> pos); + const Tile::TileBase* get_tile(glm::vec<3, int> pos) const; + void get_tile_neighbours(Tile::TileBase** neighbours, glm::vec<3, int> pos); + void get_tile_neighbours(const Tile::TileBase** neighbours, glm::vec<3, int> pos) const; + std::unique_ptr set_tile(glm::vec<3, int> pos, std::unique_ptr tile); Chunk* get_chunk(glm::vec<2, int> pos); const Chunk* get_chunk(glm::vec<2, int> pos) const; - Chunk* get_or_generate_chunk(glm::vec<2, int> pos); - std::unique_ptr set_tile(glm::vec<2, int> pos, std::unique_ptr tile); void update(); void render(const Graphics::Context& ctx) const; diff --git a/src/world/state.cpp b/src/world/state.cpp index 82cac6a..dbdde4a 100644 --- a/src/world/state.cpp +++ b/src/world/state.cpp @@ -5,7 +5,7 @@ using World::State; State::State() { - m_map.set_tile({0, 0}, std::make_unique()); + m_map.set_tile({0, 0, 0}, std::make_unique()); } void State::update() {