added tile placement

This commit is contained in:
Jay Robson 2024-07-15 23:11:36 +10:00
parent ed761c82bc
commit bffeac4099
23 changed files with 305 additions and 219 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 B

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -5,6 +5,7 @@
#include "vertex.hpp" #include "vertex.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glm/ext/matrix_transform.hpp>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -82,7 +83,7 @@ void Particles::render(const Context& ctx) const {
} }
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
ctx.set_model_matrix(glm::mat4(1)); ctx.set_model_matrix(glm::translate(glm::mat4(1), {-ctx.m_transform, 0}));
ctx.set_colour_matrix(glm::mat4(1)); ctx.set_colour_matrix(glm::mat4(1));
glBindVertexArray(m_vao); glBindVertexArray(m_vao);

View File

@ -6,7 +6,7 @@
namespace Graphics::Texture { namespace Graphics::Texture {
inline Image MISSING {"missing.png", Image::Edge::REPEATING}; inline Image MISSING {"missing.png", Image::Edge::REPEATING};
inline Image WHITE {"white.png", Image::Edge::REPEATING}; inline Image WHITE {"white.png", Image::Edge::REPEATING};
inline Image CROSS {"cross.png", Image::Edge::CLAMP}; inline Image CROSS {"cross.png", Image::Edge::REPEATING};
inline Image YELLOW_BRICK_WALL {"yellow_brick_wall.png", Image::Edge::REPEATING}; inline Image YELLOW_BRICK_WALL {"yellow_brick_wall.png", Image::Edge::REPEATING};
inline Image YELLOW_BRICK_FLOOR {"yellow_brick_floor.png", Image::Edge::REPEATING}; inline Image YELLOW_BRICK_FLOOR {"yellow_brick_floor.png", Image::Edge::REPEATING};
inline Image BLUE_BRICK_WALL {"blue_brick_wall.png", Image::Edge::REPEATING}; inline Image BLUE_BRICK_WALL {"blue_brick_wall.png", Image::Edge::REPEATING};

View File

@ -37,7 +37,7 @@ static void cb_keypress(GLFWwindow* win, int key, int sc, int action, int mods)
static bool clicked_from_cb = false; static bool clicked_from_cb = false;
void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) { static void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) {
if(button == GLFW_MOUSE_BUTTON_RIGHT) { if(button == GLFW_MOUSE_BUTTON_RIGHT) {
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
Window::mouse_locked = true; Window::mouse_locked = true;
@ -53,6 +53,12 @@ void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) {
} }
} }
static double scroll_from_cb = 0;
static void cb_scroll(GLFWwindow* win, double x, double y) {
scroll_from_cb = y;
}
float Window::get_aspect() { float Window::get_aspect() {
return (float)Window::size.x / (float)Window::size.y; return (float)Window::size.x / (float)Window::size.y;
} }
@ -67,6 +73,7 @@ Window::Window() {
glfwSetFramebufferSizeCallback(m_handle, cb_framebuffer_size); glfwSetFramebufferSizeCallback(m_handle, cb_framebuffer_size);
glfwSetMouseButtonCallback(m_handle, cb_mouse_button); glfwSetMouseButtonCallback(m_handle, cb_mouse_button);
glfwSetKeyCallback(m_handle, cb_keypress); glfwSetKeyCallback(m_handle, cb_keypress);
glfwSetScrollCallback(m_handle, cb_scroll);
glfwSwapInterval(1); glfwSwapInterval(1);
assert(glewInit() == GLEW_OK); assert(glewInit() == GLEW_OK);
@ -100,6 +107,13 @@ void Window::update() const {
} else { } else {
Window::clicked = false; Window::clicked = false;
} }
if(scroll_from_cb) {
Window::scroll = scroll_from_cb;
scroll_from_cb = 0;
} else {
Window::scroll = 0;
}
} }
void Window::swap_buffers() const { void Window::swap_buffers() const {

View File

@ -11,6 +11,7 @@ namespace Graphics {
inline static glm::vec<2, int> size; inline static glm::vec<2, int> size;
inline static bool mouse_locked = false; inline static bool mouse_locked = false;
inline static bool clicked = false; inline static bool clicked = false;
inline static double scroll = 0;
GLFWwindow* m_handle; GLFWwindow* m_handle;

View File

@ -1,36 +1,34 @@
#include "builder.hpp" #include "builder.hpp"
#include "../graphics/window.hpp" #include "../graphics/window.hpp"
#include "../graphics/texture.hpp"
#include "map.hpp" #include "map.hpp"
#include "player.hpp" #include "player.hpp"
#include "state.hpp" #include "state.hpp"
#include "tile/blue_brick.hpp" #include "tile/blue_brick.hpp"
#include "tile/tile_base.hpp" #include "tile/tile_base.hpp"
#include "tile/white_brick.hpp"
#include "tile/yellow_brick.hpp"
#include "../util/math/mod.hpp"
#include "../graphics/texture.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <algorithm>
#include <glm/common.hpp> #include <glm/common.hpp>
#include <glm/ext/matrix_projection.hpp> #include <glm/ext/matrix_projection.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <memory>
using World::Builder; using World::Builder;
Builder::Builder() { Builder::Builder() {
const Tile::TileBase* neighbours[4] = {nullptr}; 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>());
Graphics::Mesh mesh; remesh_tool();
m_tool = std::make_unique<Tile::BlueBrick>();
m_tool->remesh(mesh, neighbours, {0, 0});
m_model.set(mesh, GL_STATIC_DRAW);
}
void Builder::update(State& state) {
m_has_intersect = false;
if(Graphics::Window::mouse_locked) {
return;
} }
void Builder::do_click(State& state) {
Player& player = state.m_player; Player& player = state.m_player;
Map& map = state.m_map; Map& map = state.m_map;
@ -40,7 +38,6 @@ void Builder::update(State& state) {
glm::vec<3, double> near = glm::unProject<float>(glm::vec3(mpos, -1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); glm::vec<3, double> near = glm::unProject<float>(glm::vec3(mpos, -1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size));
glm::vec<3, double> far = glm::unProject<float>(glm::vec3(mpos, 1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); glm::vec<3, double> far = glm::unProject<float>(glm::vec3(mpos, 1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size));
glm::vec<3, double> direction = far - near; glm::vec<3, double> direction = far - near;
const glm::vec<2, double> CHECK_TILES[] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
bool found = false; bool found = false;
if(direction.z >= 0) { if(direction.z >= 0) {
@ -48,32 +45,40 @@ void Builder::update(State& state) {
} }
m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos); m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos);
m_has_intersect = true;
const Tile::TileBase* tile_old = map.get_tile(m_intersect); const Tile::TileBase* tile_cur = map.get_tile(m_intersect);
unsigned int texid; const Tile::TileBase* tile_next = m_tools[m_tool_index].get();
if(tile_old) { if(tile_next && !tile_next->can_place(tile_cur) || !tile_next && !tile_cur) {
m_mode = Mode::CLEAR; return;
} else {
m_mode = Mode::SET;
} }
if(!m_has_intersect || !Graphics::Window::clicked) { m_has_intersect = true;
if(!Graphics::Window::clicked) {
return; return;
} }
std::unique_ptr<Tile::TileBase> tile; std::unique_ptr<Tile::TileBase> tile;
switch(m_mode) { unsigned int texid;
case Mode::SET: bool texid_use_old = false;
tile = m_tool->clone();
texid = tile->get_texid(); if(tile_next) {
break; tile = tile_next->clone();
default: texid = tile_next->get_break_texture();
texid = tile_old->get_texid(); } else {
tile = nullptr; texid_use_old = true;
}
tile = map.set_tile(m_intersect, std::move(tile));
if(texid_use_old) {
if(tile) {
texid = tile->get_break_texture();
} else {
return;
}
} }
map.set_tile(m_intersect, std::move(tile));
state.m_particles.add({ state.m_particles.add({
.m_pos = {m_intersect, 0.75/2}, .m_pos = {m_intersect, 0.75/2},
@ -86,6 +91,48 @@ void Builder::update(State& state) {
}); });
} }
void Builder::remesh_tool() {
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});
} 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_indices={
0, 3, 2,
0, 1, 3,
},
};
prim.m_texid = Graphics::Texture::CROSS;
mesh.add_primitive(prim);
}
m_model.set(mesh, GL_DYNAMIC_DRAW);
}
void Builder::select_tool() {
int offset = std::clamp((int)std::round(Graphics::Window::scroll), -1, 1);
if(offset == 0) {
return;
}
m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size());
remesh_tool();
}
void Builder::update(State& state) {
m_has_intersect = false;
if(!Graphics::Window::mouse_locked) {
select_tool();
do_click(state);
}
}
void Builder::render(const Graphics::Context& ctx) const { void Builder::render(const Graphics::Context& ctx) const {
if(!m_has_intersect) { if(!m_has_intersect) {
return; return;
@ -95,6 +142,5 @@ void Builder::render(const Graphics::Context& ctx) const {
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);
m_tool->render();
} }

View File

@ -14,16 +14,23 @@ namespace World {
CLEAR, CLEAR,
}; };
std::vector<std::unique_ptr<Tile::TileBase>> m_tools;
Graphics::GL::Model m_model; Graphics::GL::Model m_model;
glm::vec<2, double> m_intersect; glm::vec<2, double> m_intersect;
std::unique_ptr<Tile::TileBase> m_tool;
bool m_has_intersect = false; bool m_has_intersect = false;
Mode m_mode; int m_tool_index = 1;
Builder(); Builder();
void update(State& state); void update(State& state);
void render(const Graphics::Context& ctx) const; void render(const Graphics::Context& ctx) const;
private:
void do_click(State& state);
void select_tool();
void remesh_tool();
}; };
}; };

View File

@ -2,13 +2,11 @@
#include <GL/glew.h> #include <GL/glew.h>
#include "chunk.hpp" #include "chunk.hpp"
#include "tile/tile_base.hpp" #include "tile/tile_base.hpp"
#include "../graphics/texture.hpp"
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/ext/quaternion_transform.hpp> #include <glm/ext/quaternion_transform.hpp>
#include <glm/ext/scalar_constants.hpp> #include <glm/ext/scalar_constants.hpp>
#include <glm/ext/vector_float3.hpp> #include <glm/ext/vector_float3.hpp>
#include <iterator> #include <iterator>
#include <memory>
using World::Chunk; using World::Chunk;
using World::Tile::TileBase; using World::Tile::TileBase;
@ -21,38 +19,34 @@ Chunk::Chunk(glm::vec<2, int> pos) {
m_pos = pos; m_pos = pos;
} }
TileBase* Chunk::get(glm::vec<2, int> p) {
p = get_pos_mod(p);
return m_tiles[p.x * N + p.y].get();
}
const TileBase* Chunk::get(glm::vec<2, int> p) const { const TileBase* Chunk::get(glm::vec<2, int> p) const {
p = get_pos_mod(p); p = get_pos_mod(p);
return m_tiles[p.x * N + p.y].get(); return m_tiles[p.x * N + p.y].get();
} }
TileBase* Chunk::set(glm::vec<2, int> p, std::unique_ptr<TileBase> v) { TileBase* Chunk::get(glm::vec<2, int> p) {
TileBase* r = v.get();
p = get_pos_mod(p); p = get_pos_mod(p);
m_tiles[p.x * N + p.y].swap(v); return m_tiles[p.x * N + p.y].get();
if(r && !v) {
m_used_tiles += 1;
} }
else if(!r && v) {
std::unique_ptr<TileBase> Chunk::set(glm::vec<2, int> p, std::unique_ptr<TileBase> v) {
p = get_pos_mod(p);
bool is_empty_in = v == nullptr;
std::swap(m_tiles[p.x * N + p.y], v);
if(is_empty_in && v) {
m_used_tiles -= 1; m_used_tiles -= 1;
} }
else if(!is_empty_in && !v) {
m_used_tiles += 1;
}
m_dirty = true; m_dirty = true;
return r; return v;
} }
void Chunk::update(Map& map) { void Chunk::update(Map& map) {
for(auto& tile : m_tiles) {
if(tile) {
tile->update();
}
}
if(!m_dirty) { if(!m_dirty) {
return; return;
} }
@ -73,7 +67,8 @@ void Chunk::update(Map& map) {
for(int x = 0; x < N; x++) { for(int x = 0; x < N; x++) {
for(int y = 0; y < N; y++) { for(int y = 0; y < N; y++) {
glm::vec<2, int> t_off(x, y); glm::vec<2, int> t_off(x, y);
Tile::TileBase* tile = get(t_off); const Tile::TileBase* tile = get(t_off);
if(!tile) { if(!tile) {
continue; continue;
} }
@ -110,11 +105,5 @@ void Chunk::render(const Graphics::Context& ctx) const {
ctx.set_model_matrix(glm::translate(glm::mat4(1), {glm::vec<2, double>(m_pos) - ctx.m_transform, 0})); ctx.set_model_matrix(glm::translate(glm::mat4(1), {glm::vec<2, double>(m_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);
for(auto& tile : m_tiles) {
if(tile) {
tile->render();
}
}
} }

View File

@ -11,13 +11,12 @@ namespace World {
#include "tile/tile_base.hpp" #include "tile/tile_base.hpp"
#include "../graphics/gl/model.hpp" #include "../graphics/gl/model.hpp"
#include <glm/gtc/integer.hpp> #include <glm/gtc/integer.hpp>
#include <memory>
namespace World { namespace World {
struct Chunk { struct Chunk {
static constexpr int N = 16; static constexpr int N = 16;
std::unique_ptr<Tile::TileBase> m_tiles[N*N]; std::unique_ptr<Tile::TileBase> m_tiles[N*N] = {{}};
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;
@ -27,9 +26,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;
Tile::TileBase* get(glm::vec<2, int> p);
const Tile::TileBase* get(glm::vec<2, int> p) const; const Tile::TileBase* get(glm::vec<2, int> p) const;
Tile::TileBase* set(glm::vec<2, int> p, std::unique_ptr<Tile::TileBase> v); 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);
}; };
}; };

View File

@ -56,39 +56,37 @@ void Map::mark_chunk_dirty(glm::vec<2, int> pos) {
} }
} }
TileBase* Map::get_tile(glm::vec<2, int> pos) {
Chunk* c = get_chunk(pos);
return c ? c->get(pos) : nullptr;
}
const TileBase* Map::get_tile(glm::vec<2, int> pos) const { const TileBase* Map::get_tile(glm::vec<2, 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::set_tile(glm::vec<2, int> pos, std::unique_ptr<TileBase> tile) { TileBase* Map::get_tile(glm::vec<2, 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) {
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);
if(tile) {
tile->m_pos = 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 - get_pos_mod(pos)).first;
} }
} else if(it == m_chunks.end()) {
return nullptr; Chunk& c = it->second;
} tile = c.set(pos, std::move(tile));
Chunk* c = &it->second;
TileBase* tile_p = c->set(pos, std::move(tile));
mark_chunk_dirty(pos + glm::vec<2, int>(1, 0)); 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>(0, 1));
mark_chunk_dirty(pos + glm::vec<2, int>(-1, 0)); 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>(0, -1));
if(!tile_p && c->m_used_tiles == 0) { if(c.m_used_tiles <= 0) {
m_chunks.erase(it); m_chunks.erase(it);
} }
return tile_p; return tile;
} }
void Map::update() { void Map::update() {

View File

@ -11,7 +11,6 @@ namespace World {
#include <glm/gtc/integer.hpp> #include <glm/gtc/integer.hpp>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory>
namespace World { namespace World {
struct State; struct State;
@ -19,13 +18,14 @@ 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;
const Chunk* get_chunk(glm::vec<2, int> pos) const; Tile::TileBase* get_tile(glm::vec<2, int> pos);
const Tile::TileBase* get_tile(glm::vec<2, int> pos) const; const Tile::TileBase* get_tile(glm::vec<2, int> pos) const;
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;
Chunk* get_or_generate_chunk(glm::vec<2, int> pos); Chunk* get_or_generate_chunk(glm::vec<2, int> pos);
Tile::TileBase* get_tile(glm::vec<2, int> pos); std::unique_ptr<Tile::TileBase> set_tile(glm::vec<2, int> pos, std::unique_ptr<Tile::TileBase> tile);
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

@ -56,8 +56,9 @@ void Player::update() {
m_cursor_last = cursor; m_cursor_last = cursor;
if(Graphics::Window::mouse_locked) { if(Graphics::Window::mouse_locked) {
m_pitch = std::fmod(m_pitch + cursor_diff.x * 0.0025, glm::pi<double>() * 2); double pi = glm::pi<double>();
m_yaw = std::clamp(m_yaw - cursor_diff.y * 0.0025, 0.0, glm::pi<double>() * 0.5); m_pitch = std::fmod(m_pitch + cursor_diff.x * 0.0025, pi*2);
m_yaw = std::clamp(m_yaw - cursor_diff.y * 0.0025, 0.0, pi*0.5);
} }
m_vel += m_accel; m_vel += m_accel;
@ -68,8 +69,9 @@ void Player::update() {
mat = glm::translate(mat, {0, 0, -m_distance}); mat = glm::translate(mat, {0, 0, -m_distance});
mat = glm::rotate(mat, (float)m_yaw, {-1, 0, 0}); mat = glm::rotate(mat, (float)m_yaw, {-1, 0, 0});
mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1}); mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1});
mat = glm::translate(mat, {0, 0, -0.25});
m_view = mat; m_view = mat;
m_projection = glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 10.f); m_projection = glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 100.f);
} }

View File

@ -1,7 +1,6 @@
#include "state.hpp" #include "state.hpp"
#include "tile/yellow_brick.hpp" #include "tile/yellow_brick.hpp"
#include <memory>
using World::State; using World::State;

View File

@ -2,37 +2,23 @@
#include "blue_brick.hpp" #include "blue_brick.hpp"
#include "tile_base.hpp" #include "tile_base.hpp"
#include "../../graphics/texture.hpp" #include "../../graphics/texture.hpp"
#include <iterator>
using World::Tile::BlueBrick; using World::Tile::BlueBrick;
using World::Tile::TileBase;
void BlueBrick::update() { unsigned int BlueBrick::get_break_texture() const {
}
unsigned int BlueBrick::get_texid() const {
return Graphics::Texture::BLUE_BRICK_FLOOR; return Graphics::Texture::BLUE_BRICK_FLOOR;
} }
std::unique_ptr<World::Tile::TileBase> BlueBrick::clone() const { std::unique_ptr<TileBase> BlueBrick::clone() const {
return std::make_unique<BlueBrick>(*this); return std::make_unique<BlueBrick>(*this);
} }
void BlueBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { void BlueBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const {
auto p = TileBase::PRIMITIVE_B; remesh_room(mesh, neighbours, offset, Graphics::Texture::BLUE_BRICK_FLOOR, Graphics::Texture::BLUE_BRICK_WALL, Graphics::Texture::BLUE_BRICK_FLOOR, 0.75);
p.m_texid = Graphics::Texture::BLUE_BRICK_FLOOR;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) {
if(!neighbours[i]) {
p = TileBase::PRIMITIVE_S[i];
p.m_texid = Graphics::Texture::BLUE_BRICK_WALL;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
}
}
} }
void BlueBrick::render() const { bool BlueBrick::can_place(const TileBase* o) const {
return o == nullptr;
} }

View File

@ -1,15 +1,14 @@
#pragma once #pragma once
#include "tile_base.hpp" #include "tile_room.hpp"
namespace World::Tile { namespace World::Tile {
struct BlueBrick : TileBase { struct BlueBrick : TileRoom {
void update() override; unsigned int get_break_texture() const override;
unsigned int get_texid() const override;
std::unique_ptr<TileBase> clone() const override;
void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override;
void render() const override; std::unique_ptr<TileBase> clone() const override;
bool can_place(const TileBase* o) const override;
}; };
}; };

View File

@ -0,0 +1,12 @@
#include "tile_base.hpp"
using World::Tile::TileBase;
unsigned int TileBase::get_break_texture() const {
return 0;
}
void TileBase::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const {
}

View File

@ -10,49 +10,12 @@
namespace World::Tile { namespace World::Tile {
struct TileBase { struct TileBase {
static const inline Graphics::Primitive<4, 6> PRIMITIVE_B = {
.m_vertices={
{.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}},
{.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}},
{.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}},
{.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}},
},
.m_indices={
0, 2, 3,
0, 3, 1,
},
};
private:
static const inline Graphics::Primitive<4, 6> PRIMITIVE_0 = {
.m_vertices={
{.m_pos={-0.5, -0.5, 0.75, 1}, .m_uv={0, 0}},
{.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 1.5}},
{.m_pos={+0.5, -0.5, 0.75, 1}, .m_uv={2, 0}},
{.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 1.5}},
},
.m_indices={
0, 2, 3,
0, 3, 1,
},
};
public:
static const inline Graphics::Primitive<4, 6> PRIMITIVE_S[4] = {
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 0.5f, {0, 0, 1})),
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.0f, {0, 0, 1})),
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.5f, {0, 0, 1})),
PRIMITIVE_0,
};
int m_facing = 0;
glm::vec<2, int> m_pos;
virtual ~TileBase() = default; virtual ~TileBase() = default;
virtual void update() = 0; virtual unsigned int get_break_texture() const = 0;
virtual unsigned int get_texid() const = 0; virtual void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const = 0;
virtual std::unique_ptr<TileBase> clone() const = 0; virtual std::unique_ptr<TileBase> clone() const = 0;
virtual void remesh(Graphics::Mesh& mesh, TileBase const* const* neighbours, glm::vec<2, int> offset) const = 0; virtual bool can_place(const TileBase* o) const = 0;
virtual void render() const = 0;
}; };
}; };

View File

@ -0,0 +1,84 @@
#include "tile_room.hpp"
#include "tile_base.hpp"
using World::Tile::TileBase;
using World::Tile::TileRoom;
static const Graphics::Primitive<4, 6> PRIMITIVE_0 = {
.m_vertices={
{.m_pos={-0.5, -0.5, 1, 1}, .m_uv={0, 0}},
{.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 2}},
{.m_pos={+0.5, -0.5, 1, 1}, .m_uv={2, 0}},
{.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 2}},
},
.m_indices={
0, 2, 3,
0, 3, 1,
},
};
static const Graphics::Primitive<4, 6> PRIMITIVE_B = {
.m_vertices={
{.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}},
{.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}},
{.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}},
{.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}},
},
.m_indices={
0, 2, 3,
0, 3, 1,
},
};
static const Graphics::Primitive<4, 6> PRIMITIVE_T = {
.m_vertices={
{.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}},
{.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}},
{.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}},
{.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}},
},
.m_indices={
0, 2, 3,
0, 3, 1,
},
};
static const Graphics::Primitive<4, 6> PRIMITIVE_S[4] = {
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 0.5f, {0, 0, 1})),
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.0f, {0, 0, 1})),
PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi<float>() * 1.5f, {0, 0, 1})),
PRIMITIVE_0,
};
void TileRoom::remesh_room(
Graphics::Mesh& mesh,
const TileBase* const* neighbours,
glm::vec<2, int> offset,
unsigned int texid_floor,
unsigned int texid_walls,
unsigned int texid_ceiling,
double height) const
{
auto p = PRIMITIVE_B;
p.m_texid = texid_floor;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
p = PRIMITIVE_T;
p.m_texid = texid_ceiling;
p.m_offset = {offset, height};
mesh.add_primitive(p);
for(int i = 0; i < std::size(PRIMITIVE_S); i++) {
if(!neighbours[i]) {
p = PRIMITIVE_S[i];
p.m_texid = texid_walls;
p.m_offset = {offset, 0};
for(Graphics::Vertex& v : p.m_vertices) {
v.m_pos.z *= height;
v.m_uv.y *= height;
}
mesh.add_primitive(p);
}
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "tile_base.hpp"
namespace World::Tile {
struct TileRoom : TileBase {
void remesh_room(
Graphics::Mesh& mesh,
const TileBase* const* neighbours,
glm::vec<2, int> offset,
unsigned int texid_floor,
unsigned int texid_walls,
unsigned int texid_ceiling,
double height) const;
};
};

View File

@ -2,37 +2,22 @@
#include "white_brick.hpp" #include "white_brick.hpp"
#include "tile_base.hpp" #include "tile_base.hpp"
#include "../../graphics/texture.hpp" #include "../../graphics/texture.hpp"
#include <iterator>
using World::Tile::WhiteBrick; using World::Tile::WhiteBrick;
using World::Tile::TileBase;
void WhiteBrick::update() { unsigned int WhiteBrick::get_break_texture() const {
}
unsigned int WhiteBrick::get_texid() const {
return Graphics::Texture::WHITE_BRICK_FLOOR; return Graphics::Texture::WHITE_BRICK_FLOOR;
} }
std::unique_ptr<World::Tile::TileBase> WhiteBrick::clone() const { std::unique_ptr<TileBase> WhiteBrick::clone() const {
return std::make_unique<WhiteBrick>(*this); return std::make_unique<WhiteBrick>(*this);
} }
void WhiteBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { void WhiteBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const {
auto p = TileBase::PRIMITIVE_B; remesh_room(mesh, neighbours, offset, Graphics::Texture::WHITE_BRICK_FLOOR, Graphics::Texture::WHITE_BRICK_WALL, Graphics::Texture::WHITE_BRICK_FLOOR, 0.75);
p.m_texid = Graphics::Texture::WHITE_BRICK_FLOOR;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) {
if(!neighbours[i]) {
p = TileBase::PRIMITIVE_S[i];
p.m_texid = Graphics::Texture::WHITE_BRICK_WALL;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
}
}
} }
void WhiteBrick::render() const { bool WhiteBrick::can_place(const TileBase* o) const {
return o == nullptr;
} }

View File

@ -1,16 +1,14 @@
#pragma once #pragma once
#include "tile_base.hpp" #include "tile_room.hpp"
namespace World::Tile { namespace World::Tile {
struct WhiteBrick : TileBase { struct WhiteBrick : TileRoom {
void update() override; unsigned int get_break_texture() const override;
unsigned int get_texid() const override;
std::unique_ptr<TileBase> clone() const override;
void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override;
void render() const override; std::unique_ptr<TileBase> clone() const override;
bool can_place(const TileBase* o) const override;
}; };
}; };

View File

@ -2,37 +2,23 @@
#include "yellow_brick.hpp" #include "yellow_brick.hpp"
#include "tile_base.hpp" #include "tile_base.hpp"
#include "../../graphics/texture.hpp" #include "../../graphics/texture.hpp"
#include <iterator>
using World::Tile::YellowBrick; using World::Tile::YellowBrick;
using World::Tile::TileBase;
void YellowBrick::update() { unsigned int YellowBrick::get_break_texture() const {
}
unsigned int YellowBrick::get_texid() const {
return Graphics::Texture::YELLOW_BRICK_FLOOR; return Graphics::Texture::YELLOW_BRICK_FLOOR;
} }
std::unique_ptr<World::Tile::TileBase> YellowBrick::clone() const { std::unique_ptr<TileBase> YellowBrick::clone() const {
return std::make_unique<YellowBrick>(*this); return std::make_unique<YellowBrick>(*this);
} }
void YellowBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { void YellowBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const {
auto p = TileBase::PRIMITIVE_B; remesh_room(mesh, neighbours, offset, Graphics::Texture::YELLOW_BRICK_FLOOR, Graphics::Texture::YELLOW_BRICK_WALL, Graphics::Texture::YELLOW_BRICK_FLOOR, 0.75);
p.m_texid = Graphics::Texture::YELLOW_BRICK_FLOOR;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) {
if(!neighbours[i]) {
p = TileBase::PRIMITIVE_S[i];
p.m_texid = Graphics::Texture::YELLOW_BRICK_WALL;
p.m_offset = {offset, 0};
mesh.add_primitive(p);
}
}
} }
void YellowBrick::render() const { bool YellowBrick::can_place(const TileBase* o) const {
return o == nullptr;
} }

View File

@ -1,16 +1,14 @@
#pragma once #pragma once
#include "tile_base.hpp" #include "tile_room.hpp"
namespace World::Tile { namespace World::Tile {
struct YellowBrick : TileBase { struct YellowBrick : TileRoom {
void update() override; unsigned int get_break_texture() const override;
unsigned int get_texid() const override;
std::unique_ptr<TileBase> clone() const override;
void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override;
void render() const override; std::unique_ptr<TileBase> clone() const override;
bool can_place(const TileBase* o) const override;
}; };
}; };