From 4e3ab6460b44466c7a66a6dac04d62467bfe6788 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Sun, 7 Jul 2024 18:30:53 +1000 Subject: [PATCH] initial commit --- .gitignore | 3 + CMakeLists.txt | 38 ++++++++ assets/shader/math.glsl | 5 + assets/shader/model.frag | 16 ++++ assets/shader/model.vert | 22 +++++ assets/shader/version.glsl | 3 + src/files.cmake | 7 ++ src/graphics/context.cpp | 30 ++++++ src/graphics/context.hpp | 22 +++++ src/graphics/files.cmake | 6 ++ src/graphics/gl/array_buffer.cpp | 21 +++++ src/graphics/gl/array_buffer.hpp | 12 +++ src/graphics/gl/buffer_base.cpp | 14 +++ src/graphics/gl/buffer_base.hpp | 16 ++++ src/graphics/gl/files.cmake | 3 + src/graphics/gl/frame_buffer.cpp | 20 ++++ src/graphics/gl/frame_buffer.hpp | 11 +++ src/graphics/gl/model.cpp | 34 +++++++ src/graphics/gl/model.hpp | 20 ++++ src/graphics/gl/program.cpp | 20 ++++ src/graphics/gl/program.hpp | 11 +++ src/graphics/gl/render_buffer.cpp | 20 ++++ src/graphics/gl/render_buffer.hpp | 11 +++ src/graphics/gl/shader.cpp | 20 ++++ src/graphics/gl/shader.hpp | 11 +++ src/graphics/gl/texture.cpp | 20 ++++ src/graphics/gl/texture.hpp | 11 +++ src/graphics/gl/uniform.cpp | 30 ++++++ src/graphics/gl/uniform.hpp | 14 +++ src/graphics/gl/vertex_array.cpp | 20 ++++ src/graphics/gl/vertex_array.hpp | 11 +++ src/graphics/init.cpp | 19 ++++ src/graphics/init.hpp | 7 ++ src/graphics/mesh.hpp | 25 +++++ src/graphics/primitive.hpp | 38 ++++++++ src/graphics/shader/compile.cpp | 146 ++++++++++++++++++++++++++++++ src/graphics/shader/compile.hpp | 10 ++ src/graphics/shader/files.cmake | 3 + src/graphics/shader/link.cpp | 26 ++++++ src/graphics/shader/link.hpp | 10 ++ src/graphics/vertex.cpp | 18 ++++ src/graphics/vertex.hpp | 14 +++ src/graphics/window.cpp | 61 +++++++++++++ src/graphics/window.hpp | 19 ++++ src/main.cpp | 62 +++++++++++++ src/util/file/files.cmake | 3 + src/util/file/load.cpp | 17 ++++ src/util/file/load.hpp | 10 ++ src/util/files.cmake | 7 ++ src/util/math/files.cmake | 3 + src/util/pointer_diff.cpp | 9 ++ src/util/pointer_diff.hpp | 7 ++ src/util/stream/files.cmake | 3 + src/util/stream/matrix.hpp | 27 ++++++ src/util/stream/vector.hpp | 26 ++++++ src/world/chunk.cpp | 139 ++++++++++++++++++++++++++++ src/world/chunk.hpp | 33 +++++++ src/world/files.cmake | 5 + src/world/map.cpp | 78 ++++++++++++++++ src/world/map.hpp | 33 +++++++ src/world/player.cpp | 20 ++++ src/world/player.hpp | 21 +++++ src/world/tile/empty.cpp | 11 +++ src/world/tile/empty.hpp | 11 +++ src/world/tile/files.cmake | 3 + src/world/tile/tile_base.hpp | 17 ++++ 66 files changed, 1443 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 assets/shader/math.glsl create mode 100644 assets/shader/model.frag create mode 100644 assets/shader/model.vert create mode 100644 assets/shader/version.glsl create mode 100644 src/files.cmake create mode 100644 src/graphics/context.cpp create mode 100644 src/graphics/context.hpp create mode 100644 src/graphics/files.cmake create mode 100644 src/graphics/gl/array_buffer.cpp create mode 100644 src/graphics/gl/array_buffer.hpp create mode 100644 src/graphics/gl/buffer_base.cpp create mode 100644 src/graphics/gl/buffer_base.hpp create mode 100644 src/graphics/gl/files.cmake create mode 100644 src/graphics/gl/frame_buffer.cpp create mode 100644 src/graphics/gl/frame_buffer.hpp create mode 100644 src/graphics/gl/model.cpp create mode 100644 src/graphics/gl/model.hpp create mode 100644 src/graphics/gl/program.cpp create mode 100644 src/graphics/gl/program.hpp create mode 100644 src/graphics/gl/render_buffer.cpp create mode 100644 src/graphics/gl/render_buffer.hpp create mode 100644 src/graphics/gl/shader.cpp create mode 100644 src/graphics/gl/shader.hpp create mode 100644 src/graphics/gl/texture.cpp create mode 100644 src/graphics/gl/texture.hpp create mode 100644 src/graphics/gl/uniform.cpp create mode 100644 src/graphics/gl/uniform.hpp create mode 100644 src/graphics/gl/vertex_array.cpp create mode 100644 src/graphics/gl/vertex_array.hpp create mode 100644 src/graphics/init.cpp create mode 100644 src/graphics/init.hpp create mode 100644 src/graphics/mesh.hpp create mode 100644 src/graphics/primitive.hpp create mode 100644 src/graphics/shader/compile.cpp create mode 100644 src/graphics/shader/compile.hpp create mode 100644 src/graphics/shader/files.cmake create mode 100644 src/graphics/shader/link.cpp create mode 100644 src/graphics/shader/link.hpp create mode 100644 src/graphics/vertex.cpp create mode 100644 src/graphics/vertex.hpp create mode 100644 src/graphics/window.cpp create mode 100644 src/graphics/window.hpp create mode 100644 src/main.cpp create mode 100644 src/util/file/files.cmake create mode 100644 src/util/file/load.cpp create mode 100644 src/util/file/load.hpp create mode 100644 src/util/files.cmake create mode 100644 src/util/math/files.cmake create mode 100644 src/util/pointer_diff.cpp create mode 100644 src/util/pointer_diff.hpp create mode 100644 src/util/stream/files.cmake create mode 100644 src/util/stream/matrix.hpp create mode 100644 src/util/stream/vector.hpp create mode 100644 src/world/chunk.cpp create mode 100644 src/world/chunk.hpp create mode 100644 src/world/files.cmake create mode 100644 src/world/map.cpp create mode 100644 src/world/map.hpp create mode 100644 src/world/player.cpp create mode 100644 src/world/player.hpp create mode 100644 src/world/tile/empty.cpp create mode 100644 src/world/tile/empty.hpp create mode 100644 src/world/tile/files.cmake create mode 100644 src/world/tile/tile_base.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c45a1a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +/build/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1b27682 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.25) + +project(NuclearPlantSim VERSION 1.0) + +set(CMAKE_CXX_STANDARD 20) + +if(NOT WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/include/freetype2") +endif() + +if(NOT WIN32) + if(NOT DEFINED SIGFPE_ENABLED) + set(SIGFPE_ENABLED 1) + endif() + set(libs stdc++ m GLEW glfw GL freetype assimp jsoncpp openal vorbisfile alut atomic) +else() + set(libs stdc++ m brotlidec assimp-5 glew32 opengl32 glfw3 freetype jsoncpp zlibstatic soft_oal vorbisfile vorbis ogg alut atomic) +endif() + +if(SIGFPE_ENABLED) + add_compile_definitions(SIGFPE_ENABLED=1) +endif() + +if(DEBUG_ENABLED) + message("-- Enabled: Runtime debug checks") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + add_compile_definitions(NO_DEBUG) +endif() + +message("-- Using cmake flags: ${CMAKE_CXX_FLAGS}") +message("-- Using libs: ${libs}") + +include(src/files.cmake) +add_executable(NuclearPlantSim ${SOURCES}) +target_link_libraries(NuclearPlantSim PUBLIC ${libs}) + diff --git a/assets/shader/math.glsl b/assets/shader/math.glsl new file mode 100644 index 0000000..4575cb5 --- /dev/null +++ b/assets/shader/math.glsl @@ -0,0 +1,5 @@ + +float Map(float x, float i_min, float i_max, float o_min, float o_max) { + return (x - i_min) * (o_max - o_min) / (i_max - i_min) + o_min; +} + diff --git a/assets/shader/model.frag b/assets/shader/model.frag new file mode 100644 index 0000000..dbd7148 --- /dev/null +++ b/assets/shader/model.frag @@ -0,0 +1,16 @@ + +#include "version.glsl" + +out vec4 f_colour; + +in VS_OUT { + vec4 pos; + vec4 colour; +} vin; + +uniform mat4 u_colour = mat4(1); + +void main() { + f_colour = u_colour * vin.colour; +} + diff --git a/assets/shader/model.vert b/assets/shader/model.vert new file mode 100644 index 0000000..fafab62 --- /dev/null +++ b/assets/shader/model.vert @@ -0,0 +1,22 @@ + +#include "version.glsl" + +layout (location = 0) in vec3 v_pos; +layout (location = 1) in vec4 v_colour; + +out VS_OUT { + vec4 pos; + vec4 colour; +} vout; + +uniform mat4 u_model = mat4(1); +uniform mat4 u_view = mat4(1); +uniform mat4 u_projection = mat4(1); + +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; +} + diff --git a/assets/shader/version.glsl b/assets/shader/version.glsl new file mode 100644 index 0000000..3ed0dc3 --- /dev/null +++ b/assets/shader/version.glsl @@ -0,0 +1,3 @@ + +#version 430 core + diff --git a/src/files.cmake b/src/files.cmake new file mode 100644 index 0000000..a7a7681 --- /dev/null +++ b/src/files.cmake @@ -0,0 +1,7 @@ + +file(GLOB SOURCES ${SOURCES} src/*.cpp) + +include(src/graphics/files.cmake) +include(src/util/files.cmake) +include(src/world/files.cmake) + diff --git a/src/graphics/context.cpp b/src/graphics/context.cpp new file mode 100644 index 0000000..b69362a --- /dev/null +++ b/src/graphics/context.cpp @@ -0,0 +1,30 @@ + +#include "context.hpp" +#include "gl/uniform.hpp" +#include +#include + +using Graphics::Context; + +Context::Context(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; +} + +void Context::set_model_matrix(glm::mat4 mat) { + 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); +} +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) { + GL::Uniform::set_mat4(m_u_colour, false, mat); +} + diff --git a/src/graphics/context.hpp b/src/graphics/context.hpp new file mode 100644 index 0000000..297c6ac --- /dev/null +++ b/src/graphics/context.hpp @@ -0,0 +1,22 @@ + +#pragma once + +#include +#include +namespace Graphics { + struct Context { + unsigned int m_program; + unsigned int m_u_model; + unsigned int m_u_view; + unsigned int m_u_projection; + unsigned int m_u_colour; + + Context(unsigned int program); + + void set_model_matrix(glm::mat4 mat); + void set_view_matrix(glm::mat4 mat); + void set_projection_matrix(glm::mat4 mat); + void set_colour_matrix(glm::mat4 mat); + }; +}; + diff --git a/src/graphics/files.cmake b/src/graphics/files.cmake new file mode 100644 index 0000000..3eee195 --- /dev/null +++ b/src/graphics/files.cmake @@ -0,0 +1,6 @@ + +file(GLOB SOURCES ${SOURCES} src/graphics/*.cpp) + +include(src/graphics/shader/files.cmake) +include(src/graphics/gl/files.cmake) + diff --git a/src/graphics/gl/array_buffer.cpp b/src/graphics/gl/array_buffer.cpp new file mode 100644 index 0000000..185937e --- /dev/null +++ b/src/graphics/gl/array_buffer.cpp @@ -0,0 +1,21 @@ + +#include "array_buffer.hpp" +#include "buffer_base.hpp" +#include +#include + +using Graphics::GL::ArrayBuffer; + +ArrayBuffer::ArrayBuffer() { + glGenBuffers(1, &m_handle); +} + +ArrayBuffer::ArrayBuffer(ArrayBuffer&& o) : BufferBase(std::move(o)) { +} + +ArrayBuffer::~ArrayBuffer() { + if(m_handle) { + glDeleteBuffers(1, &m_handle); + } +} + diff --git a/src/graphics/gl/array_buffer.hpp b/src/graphics/gl/array_buffer.hpp new file mode 100644 index 0000000..3200a63 --- /dev/null +++ b/src/graphics/gl/array_buffer.hpp @@ -0,0 +1,12 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct ArrayBuffer : BufferBase { + ArrayBuffer(); + ArrayBuffer(ArrayBuffer&& o); + ~ArrayBuffer(); + }; +}; + diff --git a/src/graphics/gl/buffer_base.cpp b/src/graphics/gl/buffer_base.cpp new file mode 100644 index 0000000..9c3fc3c --- /dev/null +++ b/src/graphics/gl/buffer_base.cpp @@ -0,0 +1,14 @@ + +#include "buffer_base.hpp" + +using Graphics::GL::BufferBase; + +BufferBase::BufferBase(BufferBase&& o) { + m_handle = o.m_handle; + o.m_handle = 0; +} + +BufferBase::operator unsigned int() const { + return m_handle; +} + diff --git a/src/graphics/gl/buffer_base.hpp b/src/graphics/gl/buffer_base.hpp new file mode 100644 index 0000000..2640fd7 --- /dev/null +++ b/src/graphics/gl/buffer_base.hpp @@ -0,0 +1,16 @@ + +#pragma once + +namespace Graphics::GL { + struct BufferBase { + unsigned int m_handle; + + BufferBase() = default; + BufferBase(const BufferBase& o) = delete; + operator unsigned int() const; + + protected: + BufferBase(BufferBase&& o); + }; +}; + diff --git a/src/graphics/gl/files.cmake b/src/graphics/gl/files.cmake new file mode 100644 index 0000000..0bfaef1 --- /dev/null +++ b/src/graphics/gl/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/graphics/gl/*.cpp) + diff --git a/src/graphics/gl/frame_buffer.cpp b/src/graphics/gl/frame_buffer.cpp new file mode 100644 index 0000000..47d2008 --- /dev/null +++ b/src/graphics/gl/frame_buffer.cpp @@ -0,0 +1,20 @@ + +#include "frame_buffer.hpp" +#include +#include + +using Graphics::GL::FrameBuffer; + +FrameBuffer::FrameBuffer() { + glGenFramebuffers(1, &m_handle); +} + +FrameBuffer::FrameBuffer(FrameBuffer&& o) : BufferBase(std::move(o)) { +} + +FrameBuffer::~FrameBuffer() { + if(m_handle) { + glDeleteFramebuffers(1, &m_handle); + } +} + diff --git a/src/graphics/gl/frame_buffer.hpp b/src/graphics/gl/frame_buffer.hpp new file mode 100644 index 0000000..af34287 --- /dev/null +++ b/src/graphics/gl/frame_buffer.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct FrameBuffer : BufferBase { + FrameBuffer(); + FrameBuffer(FrameBuffer&& o); + ~FrameBuffer(); + }; +}; diff --git a/src/graphics/gl/model.cpp b/src/graphics/gl/model.cpp new file mode 100644 index 0000000..4a23506 --- /dev/null +++ b/src/graphics/gl/model.cpp @@ -0,0 +1,34 @@ + +#include +#include +#include "model.hpp" +#include "../../util/stream/vector.hpp" + +using Graphics::GL::Model; + +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 { + glBindVertexArray(m_vao); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo); +} + +void Model::render(int mode) const { + glDrawElements(mode, m_size, GL_UNSIGNED_INT, 0); +} + diff --git a/src/graphics/gl/model.hpp b/src/graphics/gl/model.hpp new file mode 100644 index 0000000..4d16ee5 --- /dev/null +++ b/src/graphics/gl/model.hpp @@ -0,0 +1,20 @@ + +#pragma once + +#include "array_buffer.hpp" +#include "vertex_array.hpp" +#include "../mesh.hpp" + +namespace Graphics::GL { + struct Model { + VertexArray m_vao; + ArrayBuffer m_vbo; + ArrayBuffer m_ebo; + unsigned int m_size; + + void bind() const; + void set(const Mesh& mesh, int usage); + void render(int mode) const; + }; +}; + diff --git a/src/graphics/gl/program.cpp b/src/graphics/gl/program.cpp new file mode 100644 index 0000000..5c9ae88 --- /dev/null +++ b/src/graphics/gl/program.cpp @@ -0,0 +1,20 @@ + +#include +#include +#include "program.hpp" + +using Graphics::GL::Program; + +Program::Program() { + m_handle = glCreateProgram(); +} + +Program::Program(Program&& o) : BufferBase(std::move(o)) { +} + +Program::~Program() { + if(m_handle) { + glDeleteProgram(m_handle); + } +} + diff --git a/src/graphics/gl/program.hpp b/src/graphics/gl/program.hpp new file mode 100644 index 0000000..81f8612 --- /dev/null +++ b/src/graphics/gl/program.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct Program : BufferBase { + Program(); + Program(Program&& o); + ~Program(); + }; +}; diff --git a/src/graphics/gl/render_buffer.cpp b/src/graphics/gl/render_buffer.cpp new file mode 100644 index 0000000..dd90065 --- /dev/null +++ b/src/graphics/gl/render_buffer.cpp @@ -0,0 +1,20 @@ + +#include "render_buffer.hpp" +#include +#include + +using Graphics::GL::RenderBuffer; + +RenderBuffer::RenderBuffer() { + glGenRenderbuffers(1, &m_handle); +} + +RenderBuffer::RenderBuffer(RenderBuffer&& o) : BufferBase(std::move(o)) { +} + +RenderBuffer::~RenderBuffer() { + if(m_handle) { + glDeleteRenderbuffers(1, &m_handle); + } +} + diff --git a/src/graphics/gl/render_buffer.hpp b/src/graphics/gl/render_buffer.hpp new file mode 100644 index 0000000..81d59cc --- /dev/null +++ b/src/graphics/gl/render_buffer.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct RenderBuffer : BufferBase { + RenderBuffer(); + RenderBuffer(RenderBuffer&& o); + ~RenderBuffer(); + }; +}; diff --git a/src/graphics/gl/shader.cpp b/src/graphics/gl/shader.cpp new file mode 100644 index 0000000..971e60a --- /dev/null +++ b/src/graphics/gl/shader.cpp @@ -0,0 +1,20 @@ + +#include +#include +#include "shader.hpp" + +using Graphics::GL::Shader; + +Shader::Shader(int type) { + m_handle = glCreateShader(type); +} + +Shader::Shader(Shader&& o) : BufferBase(std::move(o)) { +} + +Shader::~Shader() { + if(m_handle) { + glDeleteShader(m_handle); + } +} + diff --git a/src/graphics/gl/shader.hpp b/src/graphics/gl/shader.hpp new file mode 100644 index 0000000..7c6ff9f --- /dev/null +++ b/src/graphics/gl/shader.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct Shader : BufferBase { + Shader(int type); + Shader(Shader&& o); + ~Shader(); + }; +}; diff --git a/src/graphics/gl/texture.cpp b/src/graphics/gl/texture.cpp new file mode 100644 index 0000000..b8480b5 --- /dev/null +++ b/src/graphics/gl/texture.cpp @@ -0,0 +1,20 @@ + +#include "texture.hpp" +#include +#include + +using Graphics::GL::Texture; + +Texture::Texture() { + glGenTextures(1, &m_handle); +} + +Texture::Texture(Texture&& o) : BufferBase(std::move(o)) { +} + +Texture::~Texture() { + if(m_handle) { + glDeleteTextures(1, &m_handle); + } +} + diff --git a/src/graphics/gl/texture.hpp b/src/graphics/gl/texture.hpp new file mode 100644 index 0000000..885cd7d --- /dev/null +++ b/src/graphics/gl/texture.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct Texture : BufferBase { + Texture(); + Texture(Texture&& o); + ~Texture(); + }; +}; diff --git a/src/graphics/gl/uniform.cpp b/src/graphics/gl/uniform.cpp new file mode 100644 index 0000000..2ec13ed --- /dev/null +++ b/src/graphics/gl/uniform.cpp @@ -0,0 +1,30 @@ + +#include "uniform.hpp" +#include + +using namespace Graphics::GL; + +void Uniform::set_mat4(unsigned int loc, bool transpose, glm::mat4 v) { + glUniformMatrix4fv(loc, 1, transpose, &v[0][0]); +} + +void Uniform::set_mat3(unsigned int loc, bool transpose, glm::mat3 v) { + glUniformMatrix3fv(loc, 1, transpose, &v[0][0]); +} + +void Uniform::set_mat2(unsigned int loc, bool transpose, glm::mat2 v) { + glUniformMatrix2fv(loc, 1, transpose, &v[0][0]); +} + +void Uniform::set_vec4(unsigned int loc, glm::vec4 v) { + glUniform4fv(loc, 1, &v[0]); +} + +void Uniform::set_vec3(unsigned int loc, glm::vec3 v) { + glUniform3fv(loc, 1, &v[0]); +} + +void Uniform::set_vec2(unsigned int loc, glm::vec2 v) { + glUniform2fv(loc, 1, &v[0]); +} + diff --git a/src/graphics/gl/uniform.hpp b/src/graphics/gl/uniform.hpp new file mode 100644 index 0000000..376dd94 --- /dev/null +++ b/src/graphics/gl/uniform.hpp @@ -0,0 +1,14 @@ + +#pragma once + +#include + +namespace Graphics::GL::Uniform { + void set_mat4(unsigned int loc, bool transpose, glm::mat4 v); + void set_mat3(unsigned int loc, bool transpose, glm::mat3 v); + void set_mat2(unsigned int loc, bool transpose, glm::mat2 v); + void set_vec4(unsigned int loc, glm::vec4 v); + void set_vec3(unsigned int loc, glm::vec3 v); + void set_vec2(unsigned int loc, glm::vec2 v); +}; + diff --git a/src/graphics/gl/vertex_array.cpp b/src/graphics/gl/vertex_array.cpp new file mode 100644 index 0000000..fc226c4 --- /dev/null +++ b/src/graphics/gl/vertex_array.cpp @@ -0,0 +1,20 @@ + +#include "vertex_array.hpp" +#include +#include + +using Graphics::GL::VertexArray; + +VertexArray::VertexArray() { + glGenVertexArrays(1, &m_handle); +} + +VertexArray::VertexArray(VertexArray&& o) : BufferBase(std::move(o)) { +} + +VertexArray::~VertexArray() { + if(m_handle) { + glDeleteVertexArrays(1, &m_handle); + } +} + diff --git a/src/graphics/gl/vertex_array.hpp b/src/graphics/gl/vertex_array.hpp new file mode 100644 index 0000000..0c52031 --- /dev/null +++ b/src/graphics/gl/vertex_array.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "buffer_base.hpp" +namespace Graphics::GL { + struct VertexArray : BufferBase { + VertexArray(); + VertexArray(VertexArray&& o); + ~VertexArray(); + }; +}; diff --git a/src/graphics/init.cpp b/src/graphics/init.cpp new file mode 100644 index 0000000..eaf4dba --- /dev/null +++ b/src/graphics/init.cpp @@ -0,0 +1,19 @@ + +#include +#include +#include "init.hpp" + +static bool is_initialized = false; + +void Graphics::init() { + if(is_initialized) { + return; + } + assert(glfwInit()); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); + is_initialized = true; +} + diff --git a/src/graphics/init.hpp b/src/graphics/init.hpp new file mode 100644 index 0000000..0a39254 --- /dev/null +++ b/src/graphics/init.hpp @@ -0,0 +1,7 @@ + +#pragma once + +namespace Graphics { + void init(); +} + diff --git a/src/graphics/mesh.hpp b/src/graphics/mesh.hpp new file mode 100644 index 0000000..cb723bf --- /dev/null +++ b/src/graphics/mesh.hpp @@ -0,0 +1,25 @@ + +#pragma once + +#include "vertex.hpp" +#include "primitive.hpp" +#include + +namespace Graphics { + struct Mesh { + std::vector m_vertices; + std::vector m_indices; + + template + void add_primitive(const Primitive& p) { + unsigned int index_at = m_vertices.size(); + for(int i = 0; i < VERTICES; i++) { + m_vertices.push_back(p.m_vertices[i]); + } + for(int i = 0; i < INDICES; i++) { + m_indices.push_back(p.m_indices[i] + index_at); + } + } + }; +}; + diff --git a/src/graphics/primitive.hpp b/src/graphics/primitive.hpp new file mode 100644 index 0000000..38bdb3c --- /dev/null +++ b/src/graphics/primitive.hpp @@ -0,0 +1,38 @@ + +#pragma once + +#include "vertex.hpp" +#include + +namespace Graphics { + template + struct Primitive { + Vertex m_vertices[VERTICES]; + unsigned int m_indices[INDICES]; + + constexpr Primitive with_colour(glm::vec4 colour) const { + Primitive p = *this; + for(Vertex& v : p.m_vertices) { + v.m_colour = colour; + } + return p; + } + + constexpr Primitive with_matrix(glm::mat4 mat) const { + Primitive p = *this; + for(Vertex& v : p.m_vertices) { + v.m_pos = mat * v.m_pos; + } + return p; + } + + constexpr Primitive with_translation(glm::vec3 vec) const { + Primitive p = *this; + for(Vertex& v : p.m_vertices) { + v.m_pos += glm::vec4(vec, 0); + } + return p; + } + }; +}; + diff --git a/src/graphics/shader/compile.cpp b/src/graphics/shader/compile.cpp new file mode 100644 index 0000000..f66b5fd --- /dev/null +++ b/src/graphics/shader/compile.cpp @@ -0,0 +1,146 @@ + +#include "compile.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static constexpr std::string KEYWORD = "#include"; + +enum include_mode_t { + WHITESPACE, + READING, + ENDING, +}; + +static bool parse(std::vector& source, const std::filesystem::path& path) { + std::ifstream file(path); + std::vector line; + + int n_line = 1; + int n_col = 0; + int keyword_at = 0; + include_mode_t mode = include_mode_t::WHITESPACE; + + if(!file.is_open()) { + return false; + } + + for(auto it = std::istreambuf_iterator(file); it != std::istreambuf_iterator(); it++) { + char c = *it; + + if(c == '\0') { + break; + } + if(c == '\n') { + n_line++; + n_col = 0; + } else { + n_col++; + } + + if(keyword_at < KEYWORD.size()) { + if(keyword_at == n_col - 1 && KEYWORD[keyword_at] == c) { + keyword_at++; + continue; + } + else if(keyword_at > 0) { + source.insert(source.end(), &KEYWORD[0], &KEYWORD[keyword_at]); + keyword_at = 0; + } + source.push_back(c); + continue; + } + + switch(mode) { + case include_mode_t::WHITESPACE: { + if(c != ' ' && c != '\t' && c != '\r' && c != '"') { + throw std::runtime_error(std::format("At {}:{}: Syntax error", n_line, n_col)); + } + if(c == '"') { + mode = include_mode_t::READING; + } + break; + } + case include_mode_t::READING: { + if(c != '"') { + line.push_back(c); + break; + } + mode = include_mode_t::ENDING; + std::filesystem::path path_next = path.parent_path().append(line.begin(), line.end()); + std::string comment = std::format("//'{}' {}\n", path_next.string(), '{'); + source.insert(source.end(), comment.begin(), comment.end()); + if(!parse(source, path_next)) { + throw std::runtime_error(std::format("At {}:{} in '{}': File '{}' not found", n_line, n_col, path.string(), path_next.string())); + } + comment = "//}\n"; + source.insert(source.end(), comment.begin(), comment.end()); + line.clear(); + break; + } + case include_mode_t::ENDING: { + if(c == '\r') { + break; + } + if(c != '\n') { + throw std::runtime_error(std::format("At {}:{} in '{}': Syntax error", n_line, n_col, path.string())); + } + mode = include_mode_t::WHITESPACE; + keyword_at = 0; + break; + }} + } + + if(keyword_at > 0) { + source.insert(source.end(), &KEYWORD[0], &KEYWORD[keyword_at]); + } + + return true; +} + +Graphics::GL::Shader Graphics::Shader::compile(int type, 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())); + } + + const char* data = source.data(); + int data_len = source.size(); + glShaderSource(shader, 1, &data, &data_len); + glCompileShader(shader); + + int success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if(!success) { + char info_log[1024]; + glGetShaderInfoLog(shader, sizeof(info_log), nullptr, info_log); + + std::ostringstream source_processed; + int n_line = 1; + + source_processed << n_line << '\t'; + + for(char c : source) { + if(c == '\n') { + source_processed << '\n' << ++n_line << '\t'; + } else { + source_processed << c; + } + } + + 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 new file mode 100644 index 0000000..3ca386d --- /dev/null +++ b/src/graphics/shader/compile.hpp @@ -0,0 +1,10 @@ + +#pragma once + +#include "../gl/shader.hpp" +#include + +namespace Graphics::Shader { + GL::Shader compile(int type, const std::filesystem::path& path); +}; + diff --git a/src/graphics/shader/files.cmake b/src/graphics/shader/files.cmake new file mode 100644 index 0000000..72ab5bf --- /dev/null +++ b/src/graphics/shader/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/graphics/shader/*.cpp) + diff --git a/src/graphics/shader/link.cpp b/src/graphics/shader/link.cpp new file mode 100644 index 0000000..17bb610 --- /dev/null +++ b/src/graphics/shader/link.cpp @@ -0,0 +1,26 @@ + +#include "link.hpp" +#include +#include +#include + +Graphics::GL::Program Graphics::Shader::link(const std::vector& shaders) { + GL::Program program; + int success; + + for(unsigned int shader : shaders) { + glAttachShader(program, shader); + } + + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if(!success) { + char buff[1024]; + 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 new file mode 100644 index 0000000..a4f6a37 --- /dev/null +++ b/src/graphics/shader/link.hpp @@ -0,0 +1,10 @@ + +#pragma once + +#include "../gl/program.hpp" +#include + +namespace Graphics::Shader { + GL::Program link(const std::vector& shaders); +} + diff --git a/src/graphics/vertex.cpp b/src/graphics/vertex.cpp new file mode 100644 index 0000000..61a6bcf --- /dev/null +++ b/src/graphics/vertex.cpp @@ -0,0 +1,18 @@ + +#include +#include "vertex.hpp" +#include "../util/pointer_diff.hpp" + +using Graphics::Vertex; + +void Vertex::set_vertex_attribs() { + Vertex v; + + glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(v), (void*)Util::pointer_diff(&v, &v.m_pos)); + glVertexAttribPointer(1, 4, GL_FLOAT, false, sizeof(v), (void*)Util::pointer_diff(&v, &v.m_colour)); + + for(int i = 0; i < 2; i++) { + glEnableVertexAttribArray(i); + } +} + diff --git a/src/graphics/vertex.hpp b/src/graphics/vertex.hpp new file mode 100644 index 0000000..d4f1668 --- /dev/null +++ b/src/graphics/vertex.hpp @@ -0,0 +1,14 @@ + +#pragma once + +#include + +namespace Graphics { + struct Vertex { + glm::vec4 m_pos; + glm::vec4 m_colour; + + static void set_vertex_attribs(); + }; +}; + diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp new file mode 100644 index 0000000..b8b9b3e --- /dev/null +++ b/src/graphics/window.cpp @@ -0,0 +1,61 @@ + +#include +#include +#include +#include +#include +#include "window.hpp" +#include "init.hpp" + +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); + } + else if(severity != GL_DEBUG_SEVERITY_NOTIFICATION) { + std::cout << "GL CALLBACK: " << message << "\n"; + } +} + +Graphics::Window::Window() { + init(); + + m_handle = glfwCreateWindow(800, 600, "Window", nullptr, nullptr); + glfwMakeContextCurrent(m_handle); + glfwSwapInterval(1); + + assert(glewInit() == GLEW_OK); + glDebugMessageCallback(cb_debug_message, nullptr); + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_BLEND); +} + +Graphics::Window::Window(Window&& o) { + m_handle = o.m_handle; + o.m_handle = nullptr; +} + +Graphics::Window::~Window() { + if(m_handle) { + glfwDestroyWindow(m_handle); + } +} + +void Graphics::Window::poll_events() { + glfwPollEvents(); +} + +void Graphics::Window::swap_buffers() { + glfwSwapBuffers(m_handle); +} + +bool Graphics::Window::should_close() { + return glfwWindowShouldClose(m_handle); +} + +void Graphics::Window::make_current() { + glfwMakeContextCurrent(m_handle); +} + diff --git a/src/graphics/window.hpp b/src/graphics/window.hpp new file mode 100644 index 0000000..c8b9acf --- /dev/null +++ b/src/graphics/window.hpp @@ -0,0 +1,19 @@ + +struct GLFWwindow; + +namespace Graphics { + struct Window { + GLFWwindow* m_handle; + + Window(); + Window(const Window& o) = delete; + Window(Window&& o); + ~Window(); + + void make_current(); + bool should_close(); + void swap_buffers(); + void poll_events(); + }; +}; + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d34b05d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,62 @@ + +#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" + +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; + + 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); + + 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(); + } +} + diff --git a/src/util/file/files.cmake b/src/util/file/files.cmake new file mode 100644 index 0000000..efab0ea --- /dev/null +++ b/src/util/file/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/util/file/*.cpp) + diff --git a/src/util/file/load.cpp b/src/util/file/load.cpp new file mode 100644 index 0000000..29141fe --- /dev/null +++ b/src/util/file/load.cpp @@ -0,0 +1,17 @@ + +#include "load.hpp" +#include +#include +#include +#include + +void Util::File::load(std::vector& out, const std::filesystem::path& path) { + std::ifstream file(path); + + if(!file.is_open()) { + throw std::runtime_error(std::runtime_error(std::format("file '{}' not found", path.string()))); + } + + out.insert(out.end(), std::istreambuf_iterator(file), std::istreambuf_iterator()); +} + diff --git a/src/util/file/load.hpp b/src/util/file/load.hpp new file mode 100644 index 0000000..12765ae --- /dev/null +++ b/src/util/file/load.hpp @@ -0,0 +1,10 @@ + +#pragma once + +#include +#include + +namespace Util::File { + void load(std::vector& out, const std::filesystem::path& path); +}; + diff --git a/src/util/files.cmake b/src/util/files.cmake new file mode 100644 index 0000000..7166601 --- /dev/null +++ b/src/util/files.cmake @@ -0,0 +1,7 @@ + +file(GLOB SOURCES ${SOURCES} src/util/*.cpp) + +include(src/util/file/files.cmake) +include(src/util/math/files.cmake) +include(src/util/stream/files.cmake) + diff --git a/src/util/math/files.cmake b/src/util/math/files.cmake new file mode 100644 index 0000000..699bc94 --- /dev/null +++ b/src/util/math/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/util/math/*.cpp) + diff --git a/src/util/pointer_diff.cpp b/src/util/pointer_diff.cpp new file mode 100644 index 0000000..73e6bbb --- /dev/null +++ b/src/util/pointer_diff.cpp @@ -0,0 +1,9 @@ + +#include "pointer_diff.hpp" +#include +#include + +uint64_t Util::pointer_diff(void* a, void* b) { + return std::abs((int64_t)a - (int64_t)b); +} + diff --git a/src/util/pointer_diff.hpp b/src/util/pointer_diff.hpp new file mode 100644 index 0000000..26f5d55 --- /dev/null +++ b/src/util/pointer_diff.hpp @@ -0,0 +1,7 @@ + +#include + +namespace Util { + uint64_t pointer_diff(void* a, void* b); +}; + diff --git a/src/util/stream/files.cmake b/src/util/stream/files.cmake new file mode 100644 index 0000000..a80af01 --- /dev/null +++ b/src/util/stream/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/util/stream/*.cpp) + diff --git a/src/util/stream/matrix.hpp b/src/util/stream/matrix.hpp new file mode 100644 index 0000000..ea556c7 --- /dev/null +++ b/src/util/stream/matrix.hpp @@ -0,0 +1,27 @@ + +#pragma once + +#include "vector.hpp" +#include +#include + +namespace Util::Stream { + template + struct Matrix { + glm::mat m_mat; + + constexpr Matrix(glm::mat mat): m_mat(mat) { + } + + friend std::ostream& operator << (std::ostream& o, const Matrix& v) { + o << "{"; + int i; + for(i = 0; i < C - 1; i++) { + o << Vector(v.m_mat[i]) << ", "; + } + o << Vector(v.m_mat[i]) << "}"; + return o; + } + }; +}; + diff --git a/src/util/stream/vector.hpp b/src/util/stream/vector.hpp new file mode 100644 index 0000000..fd5da3e --- /dev/null +++ b/src/util/stream/vector.hpp @@ -0,0 +1,26 @@ + +#pragma once + +#include +#include + +namespace Util::Stream { + template + struct Vector { + glm::vec m_vec; + + constexpr Vector(glm::vec vec) : m_vec(vec) { + } + + friend std::ostream& operator << (std::ostream& o, const Vector& v) { + o << "{"; + int i; + for(i = 0; i < L - 1; i++) { + o << v.m_vec[i] << ", "; + } + o << v.m_vec[i] << "}"; + return o; + } + }; +}; + diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp new file mode 100644 index 0000000..ea34ab1 --- /dev/null +++ b/src/world/chunk.cpp @@ -0,0 +1,139 @@ + +#include +#include "chunk.hpp" +#include "tile/tile_base.hpp" +#include +#include +#include +#include +#include +#include +#include + +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; +} + +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 { + p = get_pos_mod(p); + return m_tiles[p.x * N + p.y].get(); +} + +TileBase* Chunk::set(glm::vec<2, int> p, std::unique_ptr v) { + TileBase* r = v.get(); + p = get_pos_mod(p); + m_tiles[p.x * N + p.y] = std::move(v); + m_dirty = true; + return r; +} + +void Chunk::update(Map& map) { + for(auto& tile : m_tiles) { + if(tile) { + tile->update(); + } + } + if(!m_dirty) { + return; + } + Graphics::Mesh mesh; + const Chunk* chunks[4] = { + map.get_chunk(m_pos + glm::vec<2, int>(N, 0)), + map.get_chunk(m_pos + glm::vec<2, int>(0, N)), + map.get_chunk(m_pos + glm::vec<2, int>(-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}, + }; + + for(int x = 0; x < N; x++) { + for(int y = 0; y < N; y++) { + if(!get({x, y})) { + 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); + 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 || !chunk_check->get(n_off)) { + mesh.add_primitive(PRIMITIVE_S[i].with_translation({t_off, 0})); + } + } + } + } + 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 { + m_model.bind(); + m_model.render(GL_TRIANGLES); + for(auto& tile : m_tiles) { + if(tile) { + tile->render(); + } + } +} + diff --git a/src/world/chunk.hpp b/src/world/chunk.hpp new file mode 100644 index 0000000..b57dc3a --- /dev/null +++ b/src/world/chunk.hpp @@ -0,0 +1,33 @@ + +#pragma once + +namespace World { + struct Chunk; +}; + +#include "map.hpp" +#include "../graphics/context.hpp" +#include "tile/tile_base.hpp" +#include "../graphics/gl/model.hpp" +#include +#include + +namespace World { + struct Chunk { + static constexpr int N = 16; + + std::unique_ptr m_tiles[N*N]; + Graphics::GL::Model m_model; + glm::vec<2, int> m_pos; + bool m_dirty = false; + + Chunk(glm::vec<2, int> pos); + + void update(Map& map); + void render(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/files.cmake b/src/world/files.cmake new file mode 100644 index 0000000..ff44645 --- /dev/null +++ b/src/world/files.cmake @@ -0,0 +1,5 @@ + +file(GLOB SOURCES ${SOURCES} src/world/*.cpp) + +include(src/world/tile/files.cmake) + diff --git a/src/world/map.cpp b/src/world/map.cpp new file mode 100644 index 0000000..00fc137 --- /dev/null +++ b/src/world/map.cpp @@ -0,0 +1,78 @@ + +#include "map.hpp" +#include "chunk.hpp" +#include "tile/tile_base.hpp" +#include +#include + +using World::Tile::TileBase; +using World::Chunk; +using World::Map; + +constexpr glm::vec<2, int> get_pos_mod(glm::vec<2, int> pos) { + return (pos % Map::N + Map::N) % Map::N; +} + +constexpr uint64_t get_chunk_id(glm::vec<2, int> pos) { + glm::vec<2, int> pos_mod = get_pos_mod(pos); + glm::vec<2, uint32_t> cpos = (pos - pos_mod) / Map::N; + return ((uint64_t)cpos.x << 32) | cpos.y; +} + +Chunk* Map::get_or_generate_chunk(glm::vec<2, int> pos) { + uint64_t cid = get_chunk_id(pos); + auto it = m_chunks.find(cid); + + if(it == m_chunks.end()) { + it = m_chunks.try_emplace(cid, pos - get_pos_mod(pos)).first; + } + return &it->second; +} + +Chunk* Map::get_chunk(glm::vec<2, int> pos) { + uint64_t cid = get_chunk_id(pos); + auto it = m_chunks.find(cid); + + if(it == m_chunks.end()) { + return nullptr; + } + return &it->second; +} + +const Chunk* Map::get_chunk(glm::vec<2, int> pos) const { + uint64_t cid = get_chunk_id(pos); + auto it = m_chunks.find(cid); + + if(it == m_chunks.end()) { + return nullptr; + } + return &it->second; +} + +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 Chunk* c = get_chunk(pos); + return c ? c->get(pos) : nullptr; +} + +TileBase* Map::set_tile(glm::vec<2, int> pos, std::unique_ptr tile) { + tile->m_pos = pos; + return get_or_generate_chunk(pos)->set(pos, std::move(tile)); +} + +void Map::update() { + for(auto& [cid, chunk] : m_chunks) { + chunk.update(*this); + } +} + +void Map::render(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 new file mode 100644 index 0000000..073eb61 --- /dev/null +++ b/src/world/map.hpp @@ -0,0 +1,33 @@ + +#pragma once + +namespace World { + struct Map; +}; + +#include "chunk.hpp" +#include "tile/tile_base.hpp" +#include "../graphics/context.hpp" +#include +#include +#include +#include + +namespace World { + struct Map { + static constexpr int N = 16; + std::map m_chunks; + + const Chunk* get_chunk(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_or_generate_chunk(glm::vec<2, int> pos); + Tile::TileBase* get_tile(glm::vec<2, int> pos); + Tile::TileBase* set_tile(glm::vec<2, int> pos, std::unique_ptr tile); + + void update(); + void render(Graphics::Context& ctx) const; + }; +}; + diff --git a/src/world/player.cpp b/src/world/player.cpp new file mode 100644 index 0000000..0b39c76 --- /dev/null +++ b/src/world/player.cpp @@ -0,0 +1,20 @@ + +#include "player.hpp" +#include + +using World::Player; + +void Player::update() { + m_vel += m_accel; + m_pos += m_vel; + m_accel -= m_vel * 0.01; +} + +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}); + return mat; +} + diff --git a/src/world/player.hpp b/src/world/player.hpp new file mode 100644 index 0000000..4dc77b9 --- /dev/null +++ b/src/world/player.hpp @@ -0,0 +1,21 @@ + +#pragma once + +#include +#include +#include + +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; + double m_pitch = 0; + double m_yaw = glm::pi() * 0.25; + + void update(); + glm::mat4 get_view_matrix() const; + }; +}; + diff --git a/src/world/tile/empty.cpp b/src/world/tile/empty.cpp new file mode 100644 index 0000000..b87d8d5 --- /dev/null +++ b/src/world/tile/empty.cpp @@ -0,0 +1,11 @@ + +#include "empty.hpp" + +using World::Tile::Empty; + +void Empty::update() { +} + +void Empty::render() const { +} + diff --git a/src/world/tile/empty.hpp b/src/world/tile/empty.hpp new file mode 100644 index 0000000..7f98162 --- /dev/null +++ b/src/world/tile/empty.hpp @@ -0,0 +1,11 @@ + +#pragma once + +#include "tile_base.hpp" +namespace World::Tile { + struct Empty : TileBase { + void update() override; + void render() const override; + }; +}; + diff --git a/src/world/tile/files.cmake b/src/world/tile/files.cmake new file mode 100644 index 0000000..fde4f15 --- /dev/null +++ b/src/world/tile/files.cmake @@ -0,0 +1,3 @@ + +file(GLOB SOURCES ${SOURCES} src/world/tile/*.cpp) + diff --git a/src/world/tile/tile_base.hpp b/src/world/tile/tile_base.hpp new file mode 100644 index 0000000..681637d --- /dev/null +++ b/src/world/tile/tile_base.hpp @@ -0,0 +1,17 @@ + +#pragma once + +#include + +namespace World::Tile { + struct TileBase { + int m_facing = 0; + glm::vec<2, int> m_pos; + + virtual ~TileBase() = default; + + virtual void update() = 0; + virtual void render() const = 0; + }; +}; +