got movement and tile placing working

This commit is contained in:
Jay Robson 2024-07-08 01:37:55 +10:00
parent 4e3ab6460b
commit 799fd1c7dc
24 changed files with 451 additions and 147 deletions

View File

@ -17,6 +17,7 @@ void main() {
mat4 mat_mv = u_view * u_model; mat4 mat_mv = u_view * u_model;
vout.pos = mat_mv * vec4(v_pos, 1); vout.pos = mat_mv * vec4(v_pos, 1);
vout.colour = v_colour; 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);
} }

View File

@ -1,30 +1,49 @@
#include "context.hpp" #include "context.hpp"
#include "gl/uniform.hpp" #include "gl/uniform.hpp"
#include "window.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_float4x4.hpp> #include <glm/ext/matrix_float4x4.hpp>
#include <glm/trigonometric.hpp>
using Graphics::Context; using Graphics::Context;
Context::Context(unsigned int program) { Context::Context(GLFWwindow* window, unsigned int program) {
glUseProgram(program); glUseProgram(program);
m_u_model = glGetUniformLocation(program, "u_model"); m_u_model = glGetUniformLocation(program, "u_model");
m_u_view = glGetUniformLocation(program, "u_view"); m_u_view = glGetUniformLocation(program, "u_view");
m_u_projection = glGetUniformLocation(program, "u_projection"); m_u_projection = glGetUniformLocation(program, "u_projection");
m_u_colour = glGetUniformLocation(program, "u_colour"); m_u_colour = glGetUniformLocation(program, "u_colour");
m_program = program; 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); GL::Uniform::set_mat4(m_u_model, false, mat);
} }
void Context::set_view_matrix(glm::mat4 mat) { void Context::set_view_matrix(glm::mat4 mat) {
GL::Uniform::set_mat4(m_u_view, false, 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) const {
}
void Context::set_colour_matrix(glm::mat4 mat) {
GL::Uniform::set_mat4(m_u_colour, false, mat); 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;
}

View File

@ -2,21 +2,31 @@
#pragma once #pragma once
#include <glm/ext/matrix_float4x4.hpp> #include <glm/ext/matrix_float4x4.hpp>
#include <glm/ext/vector_float4.hpp> #include <glm/matrix.hpp>
#include "../world/player.hpp"
#include "window.hpp"
namespace Graphics { namespace Graphics {
struct Context { struct Context {
GLFWwindow* m_window;
unsigned int m_program; unsigned int m_program;
unsigned int m_u_model; unsigned int m_u_model;
unsigned int m_u_view; unsigned int m_u_view;
unsigned int m_u_projection; unsigned int m_u_projection;
unsigned int m_u_colour; 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_view_matrix(glm::mat4 mat);
void set_projection_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;
}; };
}; };

View File

@ -1,8 +1,6 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <iostream>
#include "model.hpp" #include "model.hpp"
#include "../../util/stream/vector.hpp"
using Graphics::GL::Model; 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_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); 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(); 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 { void Model::bind() const {

37
src/graphics/pipeline.cpp Normal file
View File

@ -0,0 +1,37 @@
#include <GL/glew.h>
#include <glm/ext/matrix_clip_space.hpp>
#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();
}

22
src/graphics/pipeline.hpp Normal file
View File

@ -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;
};
};

View File

@ -13,7 +13,7 @@ namespace Graphics {
constexpr Primitive with_colour(glm::vec4 colour) const { constexpr Primitive with_colour(glm::vec4 colour) const {
Primitive p = *this; Primitive p = *this;
for(Vertex& v : p.m_vertices) { for(Vertex& v : p.m_vertices) {
v.m_colour = colour; v.m_colour *= colour;
} }
return p; return p;
} }

View File

@ -105,9 +105,8 @@ static bool parse(std::vector<char>& source, const std::filesystem::path& path)
return true; 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<char> source; std::vector<char> source;
GL::Shader shader(type);
if(!parse(source, path)) { if(!parse(source, path)) {
throw std::runtime_error(std::format("File '{}' not found", path.string())); 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)); 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;
} }

View File

@ -1,10 +1,9 @@
#pragma once #pragma once
#include "../gl/shader.hpp"
#include <filesystem> #include <filesystem>
namespace Graphics::Shader { namespace Graphics::Shader {
GL::Shader compile(int type, const std::filesystem::path& path); void compile(unsigned int shader, const std::filesystem::path& path);
}; };

View File

@ -4,8 +4,7 @@
#include <format> #include <format>
#include <stdexcept> #include <stdexcept>
Graphics::GL::Program Graphics::Shader::link(const std::vector<unsigned int>& shaders) { void Graphics::Shader::link(unsigned int program, const std::vector<unsigned int>& shaders) {
GL::Program program;
int success; int success;
for(unsigned int shader : shaders) { for(unsigned int shader : shaders) {
@ -20,7 +19,5 @@ Graphics::GL::Program Graphics::Shader::link(const std::vector<unsigned int>& sh
glGetProgramInfoLog(program, sizeof(buff), nullptr, buff); glGetProgramInfoLog(program, sizeof(buff), nullptr, buff);
throw std::runtime_error(std::format("OpenGL link error: {}", buff)); throw std::runtime_error(std::format("OpenGL link error: {}", buff));
} }
return program;
} }

View File

@ -1,10 +1,9 @@
#pragma once #pragma once
#include "../gl/program.hpp"
#include <vector> #include <vector>
namespace Graphics::Shader { namespace Graphics::Shader {
GL::Program link(const std::vector<unsigned int>& shaders); void link(unsigned int program, const std::vector<unsigned int>& shaders);
} }

View File

@ -1,12 +1,15 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glm/matrix.hpp>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include "window.hpp" #include "window.hpp"
#include "init.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) { 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) { if(severity == GL_DEBUG_SEVERITY_HIGH) {
throw std::runtime_error(message); 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(); init();
Window::size = {800, 600};
m_handle = glfwCreateWindow(800, 600, "Window", nullptr, nullptr); m_handle = glfwCreateWindow(800, 600, "Window", nullptr, nullptr);
glfwMakeContextCurrent(m_handle); 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); glfwSwapInterval(1);
assert(glewInit() == GLEW_OK); assert(glewInit() == GLEW_OK);
@ -32,30 +78,42 @@ Graphics::Window::Window() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
Graphics::Window::Window(Window&& o) { Window::Window(Window&& o) {
m_handle = o.m_handle; m_handle = o.m_handle;
o.m_handle = nullptr; o.m_handle = nullptr;
} }
Graphics::Window::~Window() { Window::~Window() {
if(m_handle) { if(m_handle) {
glfwDestroyWindow(m_handle); glfwDestroyWindow(m_handle);
} }
} }
void Graphics::Window::poll_events() { void Window::update() const {
glfwPollEvents(); 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); glfwSwapBuffers(m_handle);
} }
bool Graphics::Window::should_close() { bool Window::should_close() const {
return glfwWindowShouldClose(m_handle); return glfwWindowShouldClose(m_handle);
} }
void Graphics::Window::make_current() { void Window::make_current() const {
glfwMakeContextCurrent(m_handle); glfwMakeContextCurrent(m_handle);
} }
Window::operator GLFWwindow*() const {
return m_handle;
}

View File

@ -1,8 +1,17 @@
#pragma once
#include <glm/matrix.hpp>
struct GLFWwindow; struct GLFWwindow;
namespace Graphics { namespace Graphics {
struct Window { struct Window {
inline static glm::vec<2, int> size;
inline static bool mouse_locked = false;
inline static bool clicked = false;
GLFWwindow* m_handle; GLFWwindow* m_handle;
Window(); Window();
@ -10,10 +19,14 @@ namespace Graphics {
Window(Window&& o); Window(Window&& o);
~Window(); ~Window();
void make_current(); void make_current() const;
bool should_close(); bool should_close() const;
void swap_buffers(); void swap_buffers() const;
void poll_events(); void update() const;
static float get_aspect();
operator GLFWwindow*() const;
}; };
}; };

View File

@ -1,62 +1,20 @@
#include <GL/glew.h>
#include <glm/ext.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_float2x3.hpp>
#include <glm/ext/matrix_projection.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/trigonometric.hpp>
#include <memory>
#include "graphics/context.hpp" #include "graphics/context.hpp"
#include "graphics/gl/program.hpp" #include "graphics/pipeline.hpp"
#include "graphics/gl/shader.hpp" #include "world/state.hpp"
#include "graphics/shader/compile.hpp" #include <glm/ext/matrix_clip_space.hpp>
#include "graphics/shader/link.hpp"
#include "graphics/window.hpp"
#include "world/map.hpp"
#include "world/player.hpp"
#include "world/tile/empty.hpp"
int main() { int main() {
Graphics::Window window; Graphics::Pipeline pipeline;
Graphics::GL::Shader model_vert = Graphics::Shader::compile(GL_VERTEX_SHADER, "../assets/shader/model.vert"); World::State state;
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;
map.set_tile({0, 0}, std::make_unique<World::Tile::Empty>()); while(!pipeline.should_close()) {
map.set_tile({1, 0}, std::make_unique<World::Tile::Empty>()); Graphics::Context ctx(pipeline.m_window, pipeline.m_program_model);
map.set_tile({2, 1}, std::make_unique<World::Tile::Empty>()); ctx.set_player(state.m_player);
map.set_tile({2, 2}, std::make_unique<World::Tile::Empty>());
map.set_tile({3, 2}, std::make_unique<World::Tile::Empty>());
map.set_tile({-1, -1}, std::make_unique<World::Tile::Empty>());
map.set_tile({-1, -2}, std::make_unique<World::Tile::Empty>());
map.set_tile({-2, -3}, std::make_unique<World::Tile::Empty>());
map.set_tile({-1, 0}, std::make_unique<World::Tile::Empty>());
map.set_tile({-3, 0}, std::make_unique<World::Tile::Empty>());
map.set_tile({-4, 0}, std::make_unique<World::Tile::Empty>());
map.set_tile({-5, 0}, std::make_unique<World::Tile::Empty>());
map.set_tile({-4, 1}, std::make_unique<World::Tile::Empty>());
map.set_tile({-4, -1}, std::make_unique<World::Tile::Empty>());
map.set_tile({0, -1}, std::make_unique<World::Tile::Empty>());
glUseProgram(model_p); pipeline.update();
state.update(ctx);
context.set_projection_matrix(glm::perspective(glm::radians(90.0), 800.0 / 600.0, 0.1, 100.0)); pipeline.render(state, ctx);
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();
} }
} }

85
src/world/builder.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "builder.hpp"
#include "../graphics/window.hpp"
#include "chunk.hpp"
#include "map.hpp"
#include "tile/empty.hpp"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include <glm/ext/matrix_projection.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <memory>
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<float>(glm::vec3(mpos, -1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size));
glm::vec<3, double> far = glm::unProject<float>(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<Tile::Empty>());
}
}
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);
}

20
src/world/builder.hpp Normal file
View File

@ -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;
};
};

View File

@ -13,44 +13,14 @@
using World::Chunk; using World::Chunk;
using World::Tile::TileBase; 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<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,
};
constexpr glm::vec<2, int> get_pos_mod(glm::vec<2, int> pos) { constexpr glm::vec<2, int> get_pos_mod(glm::vec<2, int> pos) {
return (pos % Chunk::N + Chunk::N) % Chunk::N; return (pos % Chunk::N + Chunk::N) % Chunk::N;
} }
Chunk::Chunk(glm::vec<2, int> pos) { Chunk::Chunk(glm::vec<2, int> pos) {
m_pos = pos; m_pos = pos;
m_model.bind();
Graphics::Vertex::set_vertex_attribs();
} }
TileBase* Chunk::get(glm::vec<2, int> p) { 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 x = 0; x < N; x++) {
for(int y = 0; y < N; y++) { for(int y = 0; y < N; y++) {
if(!get({x, y})) { glm::vec<2, int> t_off(x, y);
if(!get(t_off)) {
continue; 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})); mesh.add_primitive(PRIMITIVE_B.with_translation({t_off, 0}));
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] + glm::vec<2, int>(x, y); glm::vec<2, 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];
@ -123,11 +93,12 @@ void Chunk::update(Map& map) {
} }
m_model.bind(); m_model.bind();
m_model.set(mesh, GL_DYNAMIC_DRAW); m_model.set(mesh, GL_DYNAMIC_DRAW);
Graphics::Vertex::set_vertex_attribs();
m_dirty = false; 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.bind();
m_model.render(GL_TRIANGLES); m_model.render(GL_TRIANGLES);
for(auto& tile : m_tiles) { for(auto& tile : m_tiles) {

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <glm/ext/matrix_transform.hpp>
namespace World { namespace World {
struct Chunk; struct Chunk;
}; };
@ -16,6 +17,38 @@ namespace World {
struct Chunk { struct Chunk {
static constexpr int N = 16; 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<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,
};
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;
@ -24,7 +57,7 @@ namespace World {
Chunk(glm::vec<2, int> pos); Chunk(glm::vec<2, int> pos);
void update(Map& map); 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); 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* set(glm::vec<2, int> p, std::unique_ptr<Tile::TileBase> v);

View File

@ -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) { for(auto& [cid, chunk] : m_chunks) {
chunk.render(ctx); chunk.render(ctx);
} }

View File

@ -27,7 +27,7 @@ namespace World {
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(Graphics::Context& ctx) const; void render(const Graphics::Context& ctx) const;
}; };
}; };

View File

@ -1,20 +1,72 @@
#include "player.hpp" #include "player.hpp"
#include "../graphics/window.hpp"
#include <GLFW/glfw3.h>
#include <glm/detail/qualifier.hpp>
#include <glm/detail/type_quat.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/ext/quaternion_transform.hpp>
#include <glm/fwd.hpp>
#include <glm/geometric.hpp>
using World::Player; using World::Player;
Player::Player() {
GLFWwindow* ctx = glfwGetCurrentContext();
glfwGetCursorPos(ctx, &m_cursor_last.x, &m_cursor_last.y);
}
void Player::update() { 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_vel += m_accel;
m_pos += m_vel; 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 Player::get_view_matrix() const {
glm::mat4 mat(1); glm::mat4 mat(1);
mat = glm::translate(mat, {0, 0, -m_distance}); 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_yaw, {-1, 0, 0});
mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1});
return mat; return mat;
} }

View File

@ -7,13 +7,15 @@
namespace World { namespace World {
struct Player { struct Player {
glm::vec<2, double> m_pos; glm::vec<2, double> m_pos = {0, 0};
glm::vec<2, double> m_vel; glm::vec<2, double> m_vel = {0.01, 0};
glm::vec<2, double> m_accel; glm::vec<2, double> m_accel = {0, 0};
double m_distance = 4; glm::vec<2, double> m_cursor_last;
double m_distance = 2;
double m_pitch = 0; double m_pitch = 0;
double m_yaw = glm::pi<double>() * 0.25; double m_yaw = glm::pi<double>() * 5.0 / 16.0;
Player();
void update(); void update();
glm::mat4 get_view_matrix() const; glm::mat4 get_view_matrix() const;
}; };

22
src/world/state.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "state.hpp"
#include "tile/empty.hpp"
#include <memory>
using World::State;
State::State() {
m_map.set_tile({0, 0}, std::make_unique<Tile::Empty>());
}
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);
}

21
src/world/state.hpp Normal file
View File

@ -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;
};
};