diff --git a/assets/shader/model.vert b/assets/shader/model.vert index fafab62..9593bed 100644 --- a/assets/shader/model.vert +++ b/assets/shader/model.vert @@ -17,6 +17,7 @@ void main() { mat4 mat_mv = u_view * u_model; vout.pos = mat_mv * vec4(v_pos, 1); vout.colour = v_colour; - gl_Position = u_projection * vout.pos; + vec4 p = u_projection * vout.pos; + gl_Position = vec4(p.xy, 2 / (p.z + 2) - 1, p.w); } diff --git a/src/graphics/context.cpp b/src/graphics/context.cpp index b69362a..2323eee 100644 --- a/src/graphics/context.cpp +++ b/src/graphics/context.cpp @@ -1,30 +1,49 @@ #include "context.hpp" #include "gl/uniform.hpp" +#include "window.hpp" #include +#include #include +#include using Graphics::Context; -Context::Context(unsigned int program) { +Context::Context(GLFWwindow* window, unsigned int program) { glUseProgram(program); m_u_model = glGetUniformLocation(program, "u_model"); m_u_view = glGetUniformLocation(program, "u_view"); m_u_projection = glGetUniformLocation(program, "u_projection"); m_u_colour = glGetUniformLocation(program, "u_colour"); m_program = program; + m_window = window; } -void Context::set_model_matrix(glm::mat4 mat) { +void Context::set_model_matrix(glm::mat4 mat) const { GL::Uniform::set_mat4(m_u_model, false, mat); } + void Context::set_view_matrix(glm::mat4 mat) { GL::Uniform::set_mat4(m_u_view, false, mat); + m_view = mat; } -void Context::set_projection_matrix(glm::mat4 mat) { - GL::Uniform::set_mat4(m_u_projection, false, mat); -} -void Context::set_colour_matrix(glm::mat4 mat) { + +void Context::set_colour_matrix(glm::mat4 mat) const { GL::Uniform::set_mat4(m_u_colour, false, mat); } +void Context::set_projection_matrix(glm::mat4 mat) { + GL::Uniform::set_mat4(m_u_projection, false, mat); + m_projection = mat; +} + +void Context::set_player(const World::Player& player) { + set_projection_matrix(glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 10.f)); + set_view_matrix(player.get_view_matrix()); + m_transform = player.m_pos; +} + +glm::mat4 Context::get_vp() const { + return m_projection * m_view; +} + diff --git a/src/graphics/context.hpp b/src/graphics/context.hpp index 297c6ac..2541976 100644 --- a/src/graphics/context.hpp +++ b/src/graphics/context.hpp @@ -2,21 +2,31 @@ #pragma once #include -#include +#include +#include "../world/player.hpp" +#include "window.hpp" + namespace Graphics { struct Context { + GLFWwindow* m_window; unsigned int m_program; unsigned int m_u_model; unsigned int m_u_view; unsigned int m_u_projection; unsigned int m_u_colour; + glm::vec<2, double> m_transform; + glm::mat4 m_view; + glm::mat4 m_projection; - Context(unsigned int program); + Context(GLFWwindow* window, unsigned int program); - void set_model_matrix(glm::mat4 mat); + void set_model_matrix(glm::mat4 mat) const; void set_view_matrix(glm::mat4 mat); void set_projection_matrix(glm::mat4 mat); - void set_colour_matrix(glm::mat4 mat); + void set_colour_matrix(glm::mat4 mat) const; + void set_player(const World::Player& player); + + glm::mat4 get_vp() const; }; }; diff --git a/src/graphics/gl/model.cpp b/src/graphics/gl/model.cpp index 4a23506..089b9b5 100644 --- a/src/graphics/gl/model.cpp +++ b/src/graphics/gl/model.cpp @@ -1,8 +1,6 @@ #include -#include #include "model.hpp" -#include "../../util/stream/vector.hpp" using Graphics::GL::Model; @@ -10,16 +8,6 @@ void Model::set(const Mesh& mesh, int usage) { glBufferData(GL_ARRAY_BUFFER, mesh.m_vertices.size() * sizeof(mesh.m_vertices[0]), mesh.m_vertices.data(), usage); glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.m_indices.size() * sizeof(mesh.m_indices[0]), mesh.m_indices.data(), usage); m_size = mesh.m_indices.size(); - - std::cout << "Indices: "; - for(int i : mesh.m_indices) { - std::cout << i << ", "; - } - std::cout << "\nVertices:\n"; - for(const Vertex& v : mesh.m_vertices) { - std::cout << Util::Stream::Vector(v.m_pos) << ", "; - std::cout << Util::Stream::Vector(v.m_colour) << "\n"; - } } void Model::bind() const { diff --git a/src/graphics/pipeline.cpp b/src/graphics/pipeline.cpp new file mode 100644 index 0000000..e9d53a5 --- /dev/null +++ b/src/graphics/pipeline.cpp @@ -0,0 +1,37 @@ + +#include +#include +#include "pipeline.hpp" +#include "context.hpp" +#include "gl/shader.hpp" +#include "shader/compile.hpp" +#include "shader/link.hpp" + +using Graphics::Pipeline; + +Pipeline::Pipeline() { + Graphics::GL::Shader model_vert(GL_VERTEX_SHADER); + Graphics::GL::Shader model_frag(GL_FRAGMENT_SHADER); + Graphics::Shader::compile(model_vert, "../assets/shader/model.vert"); + Graphics::Shader::compile(model_frag, "../assets/shader/model.frag"); + Graphics::Shader::link(m_program_model, {model_vert, model_frag}); +} + +bool Pipeline::should_close() const { + return m_window.should_close(); +} + +void Pipeline::update() const { + m_window.update(); +} + +void Pipeline::render(const World::State& state, const Context& ctx) const { + + glUseProgram(m_program_model); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glClearColor(0.1, 0.1, 0.12, 1); + + state.render(ctx); + m_window.swap_buffers(); +} + diff --git a/src/graphics/pipeline.hpp b/src/graphics/pipeline.hpp new file mode 100644 index 0000000..2c5820d --- /dev/null +++ b/src/graphics/pipeline.hpp @@ -0,0 +1,22 @@ + +#pragma once + +#include "context.hpp" +#include "gl/program.hpp" +#include "window.hpp" +#include "../world/state.hpp" + +namespace Graphics { + struct Pipeline { + Window m_window; + GL::Program m_program_model; + + Pipeline(); + void update() const; + void render(const World::State& state, const Context& ctx) const; + bool should_close() const; + + operator unsigned int() const; + }; +}; + diff --git a/src/graphics/primitive.hpp b/src/graphics/primitive.hpp index 38bdb3c..746a1f2 100644 --- a/src/graphics/primitive.hpp +++ b/src/graphics/primitive.hpp @@ -13,7 +13,7 @@ namespace Graphics { constexpr Primitive with_colour(glm::vec4 colour) const { Primitive p = *this; for(Vertex& v : p.m_vertices) { - v.m_colour = colour; + v.m_colour *= colour; } return p; } diff --git a/src/graphics/shader/compile.cpp b/src/graphics/shader/compile.cpp index f66b5fd..6a1a786 100644 --- a/src/graphics/shader/compile.cpp +++ b/src/graphics/shader/compile.cpp @@ -105,9 +105,8 @@ static bool parse(std::vector& source, const std::filesystem::path& path) return true; } -Graphics::GL::Shader Graphics::Shader::compile(int type, const std::filesystem::path& path) { +void Graphics::Shader::compile(unsigned int shader, const std::filesystem::path& path) { std::vector source; - GL::Shader shader(type); if(!parse(source, path)) { throw std::runtime_error(std::format("File '{}' not found", path.string())); @@ -140,7 +139,5 @@ Graphics::GL::Shader Graphics::Shader::compile(int type, const std::filesystem:: throw std::runtime_error(std::format("OpenGL shader compilation error\n{}\nIn expanded source file '{}'\n{}", source_processed.str(), path.string(), info_log)); } - - return shader; } diff --git a/src/graphics/shader/compile.hpp b/src/graphics/shader/compile.hpp index 3ca386d..8064ce4 100644 --- a/src/graphics/shader/compile.hpp +++ b/src/graphics/shader/compile.hpp @@ -1,10 +1,9 @@ #pragma once -#include "../gl/shader.hpp" #include namespace Graphics::Shader { - GL::Shader compile(int type, const std::filesystem::path& path); + void compile(unsigned int shader, const std::filesystem::path& path); }; diff --git a/src/graphics/shader/link.cpp b/src/graphics/shader/link.cpp index 17bb610..b4de3b5 100644 --- a/src/graphics/shader/link.cpp +++ b/src/graphics/shader/link.cpp @@ -4,8 +4,7 @@ #include #include -Graphics::GL::Program Graphics::Shader::link(const std::vector& shaders) { - GL::Program program; +void Graphics::Shader::link(unsigned int program, const std::vector& shaders) { int success; for(unsigned int shader : shaders) { @@ -20,7 +19,5 @@ Graphics::GL::Program Graphics::Shader::link(const std::vector& sh glGetProgramInfoLog(program, sizeof(buff), nullptr, buff); throw std::runtime_error(std::format("OpenGL link error: {}", buff)); } - - return program; } diff --git a/src/graphics/shader/link.hpp b/src/graphics/shader/link.hpp index a4f6a37..da04451 100644 --- a/src/graphics/shader/link.hpp +++ b/src/graphics/shader/link.hpp @@ -1,10 +1,9 @@ #pragma once -#include "../gl/program.hpp" #include namespace Graphics::Shader { - GL::Program link(const std::vector& shaders); + void link(unsigned int program, const std::vector& shaders); } diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index b8b9b3e..8291f1f 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -1,12 +1,15 @@ #include #include +#include #include #include #include #include "window.hpp" #include "init.hpp" +using Graphics::Window; + static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { if(severity == GL_DEBUG_SEVERITY_HIGH) { throw std::runtime_error(message); @@ -16,11 +19,54 @@ static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, G } } -Graphics::Window::Window() { +static void cb_framebuffer_size(GLFWwindow* win, int w, int h) { + Window::size = {w, h}; +} + +static void cb_keypress(GLFWwindow* win, int key, int sc, int action, int mods) { + if(action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) { + if(Window::mouse_locked) { + Window::mouse_locked = false; + glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } else { + Window::mouse_locked = true; + glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + } + } +} + +static bool clicked_from_cb = false; + +void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) { + if(button == GLFW_MOUSE_BUTTON_RIGHT) { + if(action == GLFW_PRESS) { + Window::mouse_locked = true; + glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + } + else if(action == GLFW_RELEASE) { + Window::mouse_locked = false; + glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } + } + if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { + clicked_from_cb = true; + } +} + +float Window::get_aspect() { + return (float)Window::size.x / (float)Window::size.y; +} + +Window::Window() { init(); + Window::size = {800, 600}; m_handle = glfwCreateWindow(800, 600, "Window", nullptr, nullptr); glfwMakeContextCurrent(m_handle); + glfwSetInputMode(m_handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetFramebufferSizeCallback(m_handle, cb_framebuffer_size); + glfwSetMouseButtonCallback(m_handle, cb_mouse_button); + glfwSetKeyCallback(m_handle, cb_keypress); glfwSwapInterval(1); assert(glewInit() == GLEW_OK); @@ -32,30 +78,42 @@ Graphics::Window::Window() { glEnable(GL_BLEND); } -Graphics::Window::Window(Window&& o) { +Window::Window(Window&& o) { m_handle = o.m_handle; o.m_handle = nullptr; } -Graphics::Window::~Window() { +Window::~Window() { if(m_handle) { glfwDestroyWindow(m_handle); } } -void Graphics::Window::poll_events() { +void Window::update() const { glfwPollEvents(); + glViewport(0, 0, Window::size.x, Window::size.y); + + if(clicked_from_cb) { + Window::clicked = true; + clicked_from_cb = false; + } else { + Window::clicked = false; + } } -void Graphics::Window::swap_buffers() { +void Window::swap_buffers() const { glfwSwapBuffers(m_handle); } -bool Graphics::Window::should_close() { +bool Window::should_close() const { return glfwWindowShouldClose(m_handle); } -void Graphics::Window::make_current() { +void Window::make_current() const { glfwMakeContextCurrent(m_handle); } +Window::operator GLFWwindow*() const { + return m_handle; +} + diff --git a/src/graphics/window.hpp b/src/graphics/window.hpp index c8b9acf..d6b9f6e 100644 --- a/src/graphics/window.hpp +++ b/src/graphics/window.hpp @@ -1,8 +1,17 @@ +#pragma once + +#include + struct GLFWwindow; namespace Graphics { struct Window { + + inline static glm::vec<2, int> size; + inline static bool mouse_locked = false; + inline static bool clicked = false; + GLFWwindow* m_handle; Window(); @@ -10,10 +19,14 @@ namespace Graphics { Window(Window&& o); ~Window(); - void make_current(); - bool should_close(); - void swap_buffers(); - void poll_events(); + void make_current() const; + bool should_close() const; + void swap_buffers() const; + void update() const; + + static float get_aspect(); + + operator GLFWwindow*() const; }; }; diff --git a/src/main.cpp b/src/main.cpp index d34b05d..012402b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,62 +1,20 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include "graphics/context.hpp" -#include "graphics/gl/program.hpp" -#include "graphics/gl/shader.hpp" -#include "graphics/shader/compile.hpp" -#include "graphics/shader/link.hpp" -#include "graphics/window.hpp" -#include "world/map.hpp" -#include "world/player.hpp" -#include "world/tile/empty.hpp" +#include "graphics/pipeline.hpp" +#include "world/state.hpp" +#include int main() { - Graphics::Window window; - Graphics::GL::Shader model_vert = Graphics::Shader::compile(GL_VERTEX_SHADER, "../assets/shader/model.vert"); - Graphics::GL::Shader model_frag = Graphics::Shader::compile(GL_FRAGMENT_SHADER, "../assets/shader/model.frag"); - Graphics::GL::Program model_p = Graphics::Shader::link({model_vert, model_frag}); - Graphics::Context context(model_p); - World::Player player; - World::Map map; + Graphics::Pipeline pipeline; + World::State state; - map.set_tile({0, 0}, std::make_unique()); - map.set_tile({1, 0}, std::make_unique()); - map.set_tile({2, 1}, std::make_unique()); - map.set_tile({2, 2}, std::make_unique()); - map.set_tile({3, 2}, std::make_unique()); - map.set_tile({-1, -1}, std::make_unique()); - map.set_tile({-1, -2}, std::make_unique()); - map.set_tile({-2, -3}, std::make_unique()); - map.set_tile({-1, 0}, std::make_unique()); - map.set_tile({-3, 0}, std::make_unique()); - map.set_tile({-4, 0}, std::make_unique()); - map.set_tile({-5, 0}, std::make_unique()); - map.set_tile({-4, 1}, std::make_unique()); - map.set_tile({-4, -1}, std::make_unique()); - map.set_tile({0, -1}, std::make_unique()); - - glUseProgram(model_p); + while(!pipeline.should_close()) { + Graphics::Context ctx(pipeline.m_window, pipeline.m_program_model); + ctx.set_player(state.m_player); - context.set_projection_matrix(glm::perspective(glm::radians(90.0), 800.0 / 600.0, 0.1, 100.0)); - context.set_view_matrix(player.get_view_matrix()); - - while(!window.should_close()) { - map.update(); - window.poll_events(); - - glUseProgram(model_p); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - glClearColor(0.1, 0.1, 0.12, 1); - - map.render(context); - window.swap_buffers(); + pipeline.update(); + state.update(ctx); + pipeline.render(state, ctx); } } diff --git a/src/world/builder.cpp b/src/world/builder.cpp new file mode 100644 index 0000000..f9a3252 --- /dev/null +++ b/src/world/builder.cpp @@ -0,0 +1,85 @@ + +#include "builder.hpp" +#include "../graphics/window.hpp" +#include "chunk.hpp" +#include "map.hpp" +#include "tile/empty.hpp" +#include +#include +#include +#include +#include +#include + +using World::Builder; + +Builder::Builder() { + Graphics::Mesh mesh; + mesh.add_primitive(Chunk::PRIMITIVE_0); + + for(int i = 0; i < 4; i++) { + mesh.add_primitive(Chunk::PRIMITIVE_S[i]); + } + + m_model.bind(); + m_model.set(mesh, GL_STATIC_DRAW); + Graphics::Vertex::set_vertex_attribs(); +} + +void Builder::update(Map& map, const Graphics::Context& ctx) { + m_has_intersect = false; + if(Graphics::Window::mouse_locked) { + return; + } + + glm::vec<2, double> mpos; + glfwGetCursorPos(ctx.m_window, &mpos.x, &mpos.y); + mpos.y = Graphics::Window::size.y - mpos.y; + glm::vec<3, double> near = glm::unProject(glm::vec3(mpos, -1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size)); + glm::vec<3, double> far = glm::unProject(glm::vec3(mpos, 1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size)); + glm::vec<3, double> direction = far - near; + + if(direction.z >= 0) { + return; + } + + m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + ctx.m_transform); + + if(map.get_tile(m_intersect)) { + return; + } + + const glm::vec<2, double> CHECK_TILES[] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + bool found = false; + + for(const glm::vec<2, double>& off : CHECK_TILES) { + if(map.get_tile(m_intersect + off)) { + m_has_intersect = true; + break; + } + } + if(!m_has_intersect) { + return; + } + if(Graphics::Window::clicked) { + map.set_tile(m_intersect, std::make_unique()); + } +} + +void Builder::render(const Graphics::Context& ctx) const { + if(!m_has_intersect) { + return; + } + + glm::vec<2, double> pos = glm::round(m_intersect); + ctx.set_model_matrix(glm::translate(glm::mat4(1), {pos - ctx.m_transform, 0})); + ctx.set_colour_matrix({ + 0.5, 0.5, 0, 0, + 0, 1, 0, 0, + 0, 0.5, 0.5, 0, + 0, 0, 0, 1, + }); + m_model.bind(); + m_model.render(GL_TRIANGLES); +} + diff --git a/src/world/builder.hpp b/src/world/builder.hpp new file mode 100644 index 0000000..e8da2d0 --- /dev/null +++ b/src/world/builder.hpp @@ -0,0 +1,20 @@ + +#pragma once + +#include "../graphics/context.hpp" +#include "../graphics/gl/model.hpp" +#include "map.hpp" + +namespace World { + struct Builder { + Graphics::GL::Model m_model; + glm::vec<2, double> m_intersect; + bool m_has_intersect = false; + + Builder(); + + void update(Map& map, const Graphics::Context& ctx); + void render(const Graphics::Context& ctx) const; + }; +}; + diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index ea34ab1..9665119 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -13,44 +13,14 @@ using World::Chunk; using World::Tile::TileBase; -constexpr Graphics::Primitive<4, 6> PRIMITIVE_B = { - .m_vertices = { - {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 0, 0, 1}}, - {.m_pos = {-0.5, +0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, - {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 1, 0, 1}}, - {.m_pos = {+0.5, +0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, - }, - .m_indices = { - 0, 2, 3, - 0, 3, 1, - }, -}; -constexpr Graphics::Primitive<4, 6> PRIMITIVE_0 = { - .m_vertices = { - {.m_pos = {-0.5, -0.5, 0.5, 1}, .m_colour = {1, 0, 0, 1}}, - {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, - {.m_pos = {+0.5, -0.5, 0.5, 1}, .m_colour = {0, 1, 0, 1}}, - {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, - }, - .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() * 0.5f, {0, 0, 1})), - PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.0f, {0, 0, 1})), - PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.5f, {0, 0, 1})), - PRIMITIVE_0, -}; - constexpr glm::vec<2, int> get_pos_mod(glm::vec<2, int> pos) { return (pos % Chunk::N + Chunk::N) % Chunk::N; } Chunk::Chunk(glm::vec<2, int> pos) { m_pos = pos; + m_model.bind(); + Graphics::Vertex::set_vertex_attribs(); } TileBase* Chunk::get(glm::vec<2, int> p) { @@ -96,15 +66,15 @@ void Chunk::update(Map& map) { for(int x = 0; x < N; x++) { for(int y = 0; y < N; y++) { - if(!get({x, y})) { + glm::vec<2, int> t_off(x, y); + if(!get(t_off)) { continue; } - glm::vec<2, int> t_off(m_pos.x + x, m_pos.y + y); mesh.add_primitive(PRIMITIVE_B.with_translation({t_off, 0})); for(int i = 0; i < std::size(neighbours); i++) { - glm::vec<2, int> n_off = neighbours[i] + glm::vec<2, int>(x, y); + glm::vec<2, int> n_off = neighbours[i] + t_off; const Chunk* chunk_check = this; if(n_off.x == N) { chunk_check = chunks[0]; @@ -123,11 +93,12 @@ void Chunk::update(Map& map) { } m_model.bind(); m_model.set(mesh, GL_DYNAMIC_DRAW); - Graphics::Vertex::set_vertex_attribs(); m_dirty = false; } -void Chunk::render(Graphics::Context& ctx) const { +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_colour_matrix(glm::mat4(1)); m_model.bind(); m_model.render(GL_TRIANGLES); for(auto& tile : m_tiles) { diff --git a/src/world/chunk.hpp b/src/world/chunk.hpp index b57dc3a..56e4f98 100644 --- a/src/world/chunk.hpp +++ b/src/world/chunk.hpp @@ -1,6 +1,7 @@ #pragma once +#include namespace World { struct Chunk; }; @@ -16,6 +17,38 @@ namespace World { struct Chunk { static constexpr int N = 16; + static constexpr Graphics::Primitive<4, 6> PRIMITIVE_B = { + .m_vertices = { + {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 0, 0, 1}}, + {.m_pos = {-0.5, +0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, + {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 1, 0, 1}}, + {.m_pos = {+0.5, +0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, + }, + .m_indices = { + 0, 2, 3, + 0, 3, 1, + }, + }; + static constexpr Graphics::Primitive<4, 6> PRIMITIVE_0 = { + .m_vertices = { + {.m_pos = {-0.5, -0.5, 0.5, 1}, .m_colour = {1, 0, 0, 1}}, + {.m_pos = {-0.5, -0.5, 0, 1}, .m_colour = {1, 1, 0, 1}}, + {.m_pos = {+0.5, -0.5, 0.5, 1}, .m_colour = {0, 1, 0, 1}}, + {.m_pos = {+0.5, -0.5, 0, 1}, .m_colour = {0, 0, 1, 1}}, + }, + .m_indices = { + 0, 2, 3, + 0, 3, 1, + }, + }; + + static const inline Graphics::Primitive<4, 6> PRIMITIVE_S[4] = { + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 0.5f, {0, 0, 1})), + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.0f, {0, 0, 1})), + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.5f, {0, 0, 1})), + PRIMITIVE_0, + }; + std::unique_ptr m_tiles[N*N]; Graphics::GL::Model m_model; glm::vec<2, int> m_pos; @@ -24,7 +57,7 @@ namespace World { Chunk(glm::vec<2, int> pos); void update(Map& map); - void render(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; Tile::TileBase* set(glm::vec<2, int> p, std::unique_ptr v); diff --git a/src/world/map.cpp b/src/world/map.cpp index 00fc137..92516fa 100644 --- a/src/world/map.cpp +++ b/src/world/map.cpp @@ -70,7 +70,7 @@ void Map::update() { } } -void Map::render(Graphics::Context& ctx) const { +void Map::render(const Graphics::Context& ctx) const { for(auto& [cid, chunk] : m_chunks) { chunk.render(ctx); } diff --git a/src/world/map.hpp b/src/world/map.hpp index 073eb61..1e830f2 100644 --- a/src/world/map.hpp +++ b/src/world/map.hpp @@ -27,7 +27,7 @@ namespace World { Tile::TileBase* set_tile(glm::vec<2, int> pos, std::unique_ptr tile); void update(); - void render(Graphics::Context& ctx) const; + void render(const Graphics::Context& ctx) const; }; }; diff --git a/src/world/player.cpp b/src/world/player.cpp index 0b39c76..0c09108 100644 --- a/src/world/player.cpp +++ b/src/world/player.cpp @@ -1,20 +1,72 @@ #include "player.hpp" +#include "../graphics/window.hpp" +#include +#include +#include #include +#include +#include +#include using World::Player; +Player::Player() { + GLFWwindow* ctx = glfwGetCurrentContext(); + glfwGetCursorPos(ctx, &m_cursor_last.x, &m_cursor_last.y); +} + void Player::update() { + GLFWwindow* ctx = glfwGetCurrentContext(); + glm::vec<2, double> move = {0, 0}; + glm::vec<2, double> cursor; + + // keyboard input + + if(glfwGetKey(ctx, GLFW_KEY_W) == GLFW_PRESS) { + move.y += 1; + } + if(glfwGetKey(ctx, GLFW_KEY_S) == GLFW_PRESS) { + move.y -= 1; + } + if(glfwGetKey(ctx, GLFW_KEY_A) == GLFW_PRESS) { + move.x -= 1; + } + if(glfwGetKey(ctx, GLFW_KEY_D) == GLFW_PRESS) { + move.x += 1; + } + if(move.x != 0 || move.y != 0) { + glm::mat<2, 2, double> mat = { + std::cos(m_pitch), std::sin(m_pitch), + -std::sin(m_pitch), std::cos(m_pitch) + }; + move = glm::normalize(move); + if(glfwGetKey(ctx, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { + move *= 2; + } + m_accel += move * 0.0025 * mat; + } + + // mouse input + + glfwGetCursorPos(ctx, &cursor.x, &cursor.y); + glm::vec<2, double> cursor_diff = cursor - m_cursor_last; + m_cursor_last = cursor; + + if(Graphics::Window::mouse_locked) { + m_pitch += cursor_diff.x * 0.0025; + } + m_vel += m_accel; m_pos += m_vel; - m_accel -= m_vel * 0.01; + m_accel = -m_vel * 0.125; } glm::mat4 Player::get_view_matrix() const { glm::mat4 mat(1); mat = glm::translate(mat, {0, 0, -m_distance}); -// mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1}); mat = glm::rotate(mat, (float)m_yaw, {-1, 0, 0}); + mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1}); return mat; } diff --git a/src/world/player.hpp b/src/world/player.hpp index 4dc77b9..72400e6 100644 --- a/src/world/player.hpp +++ b/src/world/player.hpp @@ -7,13 +7,15 @@ namespace World { struct Player { - glm::vec<2, double> m_pos; - glm::vec<2, double> m_vel; - glm::vec<2, double> m_accel; - double m_distance = 4; + glm::vec<2, double> m_pos = {0, 0}; + glm::vec<2, double> m_vel = {0.01, 0}; + glm::vec<2, double> m_accel = {0, 0}; + glm::vec<2, double> m_cursor_last; + double m_distance = 2; double m_pitch = 0; - double m_yaw = glm::pi() * 0.25; + double m_yaw = glm::pi() * 5.0 / 16.0; + Player(); void update(); glm::mat4 get_view_matrix() const; }; diff --git a/src/world/state.cpp b/src/world/state.cpp new file mode 100644 index 0000000..5d2d145 --- /dev/null +++ b/src/world/state.cpp @@ -0,0 +1,22 @@ + +#include "state.hpp" +#include "tile/empty.hpp" +#include + +using World::State; + +State::State() { + m_map.set_tile({0, 0}, std::make_unique()); +} + +void State::update(const Graphics::Context& ctx) { + m_builder.update(m_map, ctx); + m_player.update(); + m_map.update(); +} + +void State::render(const Graphics::Context& ctx) const { + m_map.render(ctx); + m_builder.render(ctx); +} + diff --git a/src/world/state.hpp b/src/world/state.hpp new file mode 100644 index 0000000..a46c79e --- /dev/null +++ b/src/world/state.hpp @@ -0,0 +1,21 @@ + +#pragma once + +#include "../graphics/context.hpp" +#include "builder.hpp" +#include "player.hpp" +#include "map.hpp" + +namespace World { + struct State { + Builder m_builder; + Player m_player; + Map m_map; + + State(); + + void update(const Graphics::Context& ctx); + void render(const Graphics::Context& ctx) const; + }; +}; +