added z index for tile placement
This commit is contained in:
parent
bffeac4099
commit
dc8895b2dc
|
@ -20,12 +20,11 @@
|
|||
using World::Builder;
|
||||
|
||||
Builder::Builder() {
|
||||
m_tools.push_back(nullptr);
|
||||
m_tools.push_back(std::make_unique<Tile::YellowBrick>());
|
||||
m_tools.push_back(std::make_unique<Tile::BlueBrick>());
|
||||
m_tools.push_back(std::make_unique<Tile::WhiteBrick>());
|
||||
|
||||
remesh_tool();
|
||||
m_tools.push_back({nullptr, 0});
|
||||
m_tools.push_back({nullptr, 1});
|
||||
m_tools.push_back({std::make_unique<Tile::YellowBrick>(), 0});
|
||||
m_tools.push_back({std::make_unique<Tile::BlueBrick>(), 1});
|
||||
m_tools.push_back({std::make_unique<Tile::WhiteBrick>(), 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);
|
||||
|
|
|
@ -14,11 +14,17 @@ namespace World {
|
|||
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;
|
||||
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();
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TileBase> Chunk::set(glm::vec<2, int> p, std::unique_ptr<TileBase> v) {
|
||||
p = get_pos_mod(p);
|
||||
std::unique_ptr<TileBase> Chunk::set(glm::vec<3, int> p, std::unique_ptr<TileBase> 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;
|
||||
|
|
|
@ -15,8 +15,9 @@ namespace World {
|
|||
namespace World {
|
||||
struct Chunk {
|
||||
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;
|
||||
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<Tile::TileBase> set(glm::vec<2, int> p, std::unique_ptr<Tile::TileBase> v);
|
||||
const Tile::TileBase* get(glm::vec<3, int> p) const;
|
||||
Tile::TileBase* get(glm::vec<3, int> p);
|
||||
std::unique_ptr<Tile::TileBase> set(glm::vec<3, int> p, std::unique_ptr<Tile::TileBase> v);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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<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);
|
||||
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);
|
||||
|
|
|
@ -18,14 +18,15 @@ namespace World {
|
|||
static constexpr int N = 16;
|
||||
std::map<uint64_t, Chunk> 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<Tile::TileBase> set_tile(glm::vec<3, int> pos, std::unique_ptr<Tile::TileBase> 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<Tile::TileBase> set_tile(glm::vec<2, int> pos, std::unique_ptr<Tile::TileBase> tile);
|
||||
|
||||
void update();
|
||||
void render(const Graphics::Context& ctx) const;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
using World::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() {
|
||||
|
|
Loading…
Reference in New Issue