added z index for tile placement

This commit is contained in:
Jay Robson 2024-07-19 14:27:41 +10:00
parent bffeac4099
commit dc8895b2dc
7 changed files with 128 additions and 91 deletions

View File

@ -20,12 +20,11 @@
using World::Builder; using World::Builder;
Builder::Builder() { Builder::Builder() {
m_tools.push_back(nullptr); m_tools.push_back({nullptr, 0});
m_tools.push_back(std::make_unique<Tile::YellowBrick>()); m_tools.push_back({nullptr, 1});
m_tools.push_back(std::make_unique<Tile::BlueBrick>()); m_tools.push_back({std::make_unique<Tile::YellowBrick>(), 0});
m_tools.push_back(std::make_unique<Tile::WhiteBrick>()); m_tools.push_back({std::make_unique<Tile::BlueBrick>(), 1});
m_tools.push_back({std::make_unique<Tile::WhiteBrick>(), 0});
remesh_tool();
} }
void Builder::do_click(State& state) { void Builder::do_click(State& state) {
@ -44,15 +43,20 @@ void Builder::do_click(State& state) {
return; 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_cur = map.get_tile({intersect, tool.m_zpos});
const Tile::TileBase* tile_next = m_tools[m_tool_index].get();
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; return;
} }
if(intersect != m_intersect) {
m_intersect = intersect;
m_remesh_needed = true;
}
m_has_intersect = true; m_has_intersect = true;
if(!Graphics::Window::clicked) { if(!Graphics::Window::clicked) {
@ -63,14 +67,14 @@ void Builder::do_click(State& state) {
unsigned int texid; unsigned int texid;
bool texid_use_old = false; bool texid_use_old = false;
if(tile_next) { if(tool.m_tile) {
tile = tile_next->clone(); tile = tool.m_tile->clone();
texid = tile_next->get_break_texture(); texid = tool.m_tile->get_break_texture();
} else { } else {
texid_use_old = true; 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(texid_use_old) {
if(tile) { 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; Graphics::Mesh mesh;
if(m_tools[m_tool_index]) {
const Tile::TileBase* neighbours[4] = {nullptr}; if(tool.m_tile) {
m_tools[m_tool_index]->remesh(mesh, neighbours, {0, 0}); 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 { } else {
Graphics::Primitive<4, 6> prim = { Graphics::Primitive<4, 6> prim = {
.m_vertices={ .m_vertices={
{.m_pos={-0.5, -0.5, 0.05, 1}, .m_uv={0, 0}}, {.m_pos={-0.25, -0.25, 0.05, 1}, .m_uv={0, 0}},
{.m_pos={+0.5, -0.5, 0.05, 1}, .m_uv={2, 0}}, {.m_pos={+0.25, -0.25, 0.05, 1}, .m_uv={1, 0}},
{.m_pos={-0.5, +0.5, 0.05, 1}, .m_uv={0, 2}}, {.m_pos={-0.25, +0.25, 0.05, 1}, .m_uv={0, 1}},
{.m_pos={+0.5, +0.5, 0.05, 1}, .m_uv={2, 2}}, {.m_pos={+0.25, +0.25, 0.05, 1}, .m_uv={1, 1}},
}, },
.m_indices={ .m_indices={
0, 3, 2, 0, 3, 2,
@ -112,17 +119,17 @@ void Builder::remesh_tool() {
prim.m_texid = Graphics::Texture::CROSS; prim.m_texid = Graphics::Texture::CROSS;
mesh.add_primitive(prim); mesh.add_primitive(prim);
} }
m_model.set(mesh, GL_DYNAMIC_DRAW); m_model.set(mesh, GL_DYNAMIC_DRAW);
m_remesh_needed = false;
} }
void Builder::select_tool() { void Builder::select_tool() {
int offset = std::clamp((int)std::round(Graphics::Window::scroll), -1, 1); int offset = std::clamp((int)std::round(Graphics::Window::scroll), -1, 1);
if(offset == 0) { if(offset) {
return;
}
m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size()); m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size());
remesh_tool(); m_remesh_needed = true;
}
} }
void Builder::update(State& state) { void Builder::update(State& state) {
@ -131,6 +138,9 @@ void Builder::update(State& state) {
select_tool(); select_tool();
do_click(state); do_click(state);
} }
if(m_remesh_needed) {
remesh_tool(state);
}
} }
void Builder::render(const Graphics::Context& ctx) const { void Builder::render(const Graphics::Context& ctx) const {
@ -138,7 +148,7 @@ void Builder::render(const Graphics::Context& ctx) const {
return; 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_model_matrix(glm::translate(glm::mat4(1), {pos - ctx.m_transform, 0}));
ctx.set_colour_matrix(glm::mat4(1)); ctx.set_colour_matrix(glm::mat4(1));
m_model.render(GL_TRIANGLES); m_model.render(GL_TRIANGLES);

View File

@ -14,11 +14,17 @@ namespace World {
CLEAR, CLEAR,
}; };
std::vector<std::unique_ptr<Tile::TileBase>> m_tools; struct ToolType {
std::unique_ptr<Tile::TileBase> m_tile;
int m_zpos;
};
std::vector<ToolType> m_tools;
Graphics::GL::Model m_model; Graphics::GL::Model m_model;
glm::vec<2, double> m_intersect; glm::vec<2, int> m_intersect;
bool m_has_intersect = false; bool m_has_intersect = false;
bool m_remesh_needed = true;
int m_tool_index = 1; int m_tool_index = 1;
Builder(); Builder();
@ -29,8 +35,8 @@ namespace World {
private: private:
void do_click(State& state); void do_click(State& state);
void remesh_tool(const State& state);
void select_tool(); void select_tool();
void remesh_tool();
}; };
}; };

View File

@ -19,21 +19,21 @@ Chunk::Chunk(glm::vec<2, int> pos) {
m_pos = pos; m_pos = pos;
} }
const TileBase* Chunk::get(glm::vec<2, int> p) const { const TileBase* Chunk::get(glm::vec<3, int> p) const {
p = get_pos_mod(p); p = {get_pos_mod(p), p.z};
return m_tiles[p.x * N + p.y].get(); return m_tiles[p.x + p.y * N + p.z * N * N].get();
} }
TileBase* Chunk::get(glm::vec<2, int> p) { TileBase* Chunk::get(glm::vec<3, int> p) {
p = get_pos_mod(p); p = {get_pos_mod(p), p.z};
return m_tiles[p.x * N + p.y].get(); return m_tiles[p.x + p.y * N + p.z * N * N].get();
} }
std::unique_ptr<TileBase> Chunk::set(glm::vec<2, int> p, std::unique_ptr<TileBase> v) { std::unique_ptr<TileBase> Chunk::set(glm::vec<3, int> p, std::unique_ptr<TileBase> v) {
p = get_pos_mod(p); p = {get_pos_mod(p), p.z};
bool is_empty_in = v == nullptr; 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) { if(is_empty_in && v) {
m_used_tiles -= 1; m_used_tiles -= 1;
@ -57,16 +57,16 @@ 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>(-N, 0)),
map.get_chunk(m_pos + glm::vec<2, int>(0, -N)), map.get_chunk(m_pos + glm::vec<2, int>(0, -N)),
}; };
const glm::vec<2, int> neighbours[4] = { const glm::vec<3, int> neighbours[4] = {
{1, 0}, {1, 0, 0},
{0, 1}, {0, 1, 0},
{-1, 0}, {-1, 0, 0},
{0, -1}, {0, -1, 0},
}; };
for(int x = 0; x < N; x++) { for(int x = 0; x < N; x++) for(int y = 0; y < N; y++) for(int z = 0; z < H; z++) {
for(int y = 0; y < N; y++) {
glm::vec<2, int> t_off(x, y); glm::vec<3, int> t_off(x, y, z);
const Tile::TileBase* tile = get(t_off); const Tile::TileBase* tile = get(t_off);
if(!tile) { if(!tile) {
@ -76,7 +76,7 @@ void Chunk::update(Map& map) {
const Tile::TileBase* tiles[4]; const Tile::TileBase* tiles[4];
for(int i = 0; i < std::size(neighbours); i++) { for(int i = 0; i < std::size(neighbours); i++) {
glm::vec<2, int> n_off = neighbours[i] + t_off; glm::vec<3, int> n_off = neighbours[i] + t_off;
const Chunk* chunk_check = this; const Chunk* chunk_check = this;
if(n_off.x == N) { if(n_off.x == N) {
chunk_check = chunks[0]; chunk_check = chunks[0];
@ -96,7 +96,6 @@ void Chunk::update(Map& map) {
tile->remesh(mesh, tiles, {x, y}); tile->remesh(mesh, tiles, {x, y});
} }
}
m_model.set(mesh, GL_DYNAMIC_DRAW); m_model.set(mesh, GL_DYNAMIC_DRAW);
m_dirty = false; m_dirty = false;
} }

View File

@ -15,8 +15,9 @@ namespace World {
namespace World { namespace World {
struct Chunk { struct Chunk {
static constexpr int N = 16; static constexpr int N = 16;
static constexpr int H = 2;
std::unique_ptr<Tile::TileBase> m_tiles[N*N] = {{}}; std::unique_ptr<Tile::TileBase> m_tiles[N*N*H] = {{}};
Graphics::GL::Model m_model; Graphics::GL::Model m_model;
glm::vec<2, int> m_pos; glm::vec<2, int> m_pos;
int m_used_tiles = 0; int m_used_tiles = 0;
@ -26,9 +27,9 @@ namespace World {
void update(Map& map); void update(Map& map);
void render(const Graphics::Context& ctx) const; void render(const Graphics::Context& ctx) const;
const Tile::TileBase* get(glm::vec<2, int> p) const; const Tile::TileBase* get(glm::vec<3, int> p) const;
Tile::TileBase* get(glm::vec<2, int> p); Tile::TileBase* get(glm::vec<3, int> p);
std::unique_ptr<Tile::TileBase> set(glm::vec<2, int> p, std::unique_ptr<Tile::TileBase> v); std::unique_ptr<Tile::TileBase> set(glm::vec<3, int> p, std::unique_ptr<Tile::TileBase> v);
}; };
}; };

View File

@ -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); const Chunk* c = get_chunk(pos);
return c ? c->get(pos) : nullptr; 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); Chunk* c = get_chunk(pos);
return c ? c->get(pos) : nullptr; return c ? c->get(pos) : nullptr;
} }
std::unique_ptr<TileBase> Map::set_tile(glm::vec<2, int> pos, std::unique_ptr<TileBase> 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<TileBase> Map::set_tile(glm::vec<3, int> pos, std::unique_ptr<TileBase> tile) {
uint64_t cid = get_chunk_id(pos); uint64_t cid = get_chunk_id(pos);
auto it = m_chunks.find(cid); auto it = m_chunks.find(cid);
glm::vec<2, int> pos_h = pos;
if(it == m_chunks.end()) { 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; Chunk& c = it->second;
tile = c.set(pos, std::move(tile)); tile = c.set(pos, std::move(tile));
mark_chunk_dirty(pos + glm::vec<2, int>(1, 0)); mark_chunk_dirty(pos_h + 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>(0, 1));
mark_chunk_dirty(pos + glm::vec<2, int>(-1, 0)); mark_chunk_dirty(pos_h + 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>(0, -1));
if(c.m_used_tiles <= 0) { if(c.m_used_tiles <= 0) {
m_chunks.erase(it); m_chunks.erase(it);

View File

@ -18,14 +18,15 @@ namespace World {
static constexpr int N = 16; static constexpr int N = 16;
std::map<uint64_t, Chunk> m_chunks; std::map<uint64_t, Chunk> m_chunks;
Tile::TileBase* get_tile(glm::vec<2, int> pos); Tile::TileBase* get_tile(glm::vec<3, int> pos);
const Tile::TileBase* get_tile(glm::vec<2, int> pos) const; 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<Tile::TileBase> set_tile(glm::vec<3, int> pos, std::unique_ptr<Tile::TileBase> tile);
Chunk* get_chunk(glm::vec<2, int> pos); Chunk* get_chunk(glm::vec<2, int> pos);
const Chunk* get_chunk(glm::vec<2, int> pos) const; const Chunk* get_chunk(glm::vec<2, int> pos) const;
Chunk* get_or_generate_chunk(glm::vec<2, int> pos); Chunk* get_or_generate_chunk(glm::vec<2, int> pos);
std::unique_ptr<Tile::TileBase> set_tile(glm::vec<2, int> pos, std::unique_ptr<Tile::TileBase> tile);
void update(); void update();
void render(const Graphics::Context& ctx) const; void render(const Graphics::Context& ctx) const;

View File

@ -5,7 +5,7 @@
using World::State; using World::State;
State::State() { State::State() {
m_map.set_tile({0, 0}, std::make_unique<Tile::YellowBrick>()); m_map.set_tile({0, 0, 0}, std::make_unique<Tile::YellowBrick>());
} }
void State::update() { void State::update() {