initial commit
This commit is contained in:
commit
4e3ab6460b
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
/build/
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
#version 430 core
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
#include "context.hpp"
|
||||||
|
#include "gl/uniform.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <glm/ext/matrix_float4x4.hpp>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/ext/matrix_float4x4.hpp>
|
||||||
|
#include <glm/ext/vector_float4.hpp>
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/graphics/*.cpp)
|
||||||
|
|
||||||
|
include(src/graphics/shader/files.cmake)
|
||||||
|
include(src/graphics/gl/files.cmake)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#include "array_buffer.hpp"
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct ArrayBuffer : BufferBase {
|
||||||
|
ArrayBuffer();
|
||||||
|
ArrayBuffer(ArrayBuffer&& o);
|
||||||
|
~ArrayBuffer();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/graphics/gl/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "frame_buffer.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct FrameBuffer : BufferBase {
|
||||||
|
FrameBuffer();
|
||||||
|
FrameBuffer(FrameBuffer&& o);
|
||||||
|
~FrameBuffer();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <iostream>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct Program : BufferBase {
|
||||||
|
Program();
|
||||||
|
Program(Program&& o);
|
||||||
|
~Program();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "render_buffer.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct RenderBuffer : BufferBase {
|
||||||
|
RenderBuffer();
|
||||||
|
RenderBuffer(RenderBuffer&& o);
|
||||||
|
~RenderBuffer();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct Shader : BufferBase {
|
||||||
|
Shader(int type);
|
||||||
|
Shader(Shader&& o);
|
||||||
|
~Shader();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "texture.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct Texture : BufferBase {
|
||||||
|
Texture();
|
||||||
|
Texture(Texture&& o);
|
||||||
|
~Texture();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
#include "uniform.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/matrix.hpp>
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "vertex_array.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buffer_base.hpp"
|
||||||
|
namespace Graphics::GL {
|
||||||
|
struct VertexArray : BufferBase {
|
||||||
|
VertexArray();
|
||||||
|
VertexArray(VertexArray&& o);
|
||||||
|
~VertexArray();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <cassert>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
void init();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vertex.hpp"
|
||||||
|
#include "primitive.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
struct Mesh {
|
||||||
|
std::vector<Vertex> m_vertices;
|
||||||
|
std::vector<unsigned int> m_indices;
|
||||||
|
|
||||||
|
template <int VERTICES, int INDICES>
|
||||||
|
void add_primitive(const Primitive<VERTICES, INDICES>& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vertex.hpp"
|
||||||
|
#include <glm/matrix.hpp>
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
template <int VERTICES, int INDICES>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
|
||||||
|
#include "compile.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
static constexpr std::string KEYWORD = "#include";
|
||||||
|
|
||||||
|
enum include_mode_t {
|
||||||
|
WHITESPACE,
|
||||||
|
READING,
|
||||||
|
ENDING,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool parse(std::vector<char>& source, const std::filesystem::path& path) {
|
||||||
|
std::ifstream file(path);
|
||||||
|
std::vector<char> 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<char>(file); it != std::istreambuf_iterator<char>(); 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<char> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../gl/shader.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace Graphics::Shader {
|
||||||
|
GL::Shader compile(int type, const std::filesystem::path& path);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/graphics/shader/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include "link.hpp"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <format>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
Graphics::GL::Program Graphics::Shader::link(const std::vector<unsigned int>& 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../gl/program.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Graphics::Shader {
|
||||||
|
GL::Program link(const std::vector<unsigned int>& shaders);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
struct Vertex {
|
||||||
|
glm::vec4 m_pos;
|
||||||
|
glm::vec4 m_colour;
|
||||||
|
|
||||||
|
static void set_vertex_attribs();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
#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/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<World::Tile::Empty>());
|
||||||
|
map.set_tile({1, 0}, std::make_unique<World::Tile::Empty>());
|
||||||
|
map.set_tile({2, 1}, std::make_unique<World::Tile::Empty>());
|
||||||
|
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);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/util/file/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#include "load.hpp"
|
||||||
|
#include <format>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void Util::File::load(std::vector<char>& 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<char>(file), std::istreambuf_iterator<char>());
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Util::File {
|
||||||
|
void load(std::vector<char>& out, const std::filesystem::path& path);
|
||||||
|
};
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/util/math/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#include "pointer_diff.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
uint64_t Util::pointer_diff(void* a, void* b) {
|
||||||
|
return std::abs((int64_t)a - (int64_t)b);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
uint64_t pointer_diff(void* a, void* b);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/util/stream/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vector.hpp"
|
||||||
|
#include <glm/matrix.hpp>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace Util::Stream {
|
||||||
|
template <int C, int R, typename T>
|
||||||
|
struct Matrix {
|
||||||
|
glm::mat<C, R, T> m_mat;
|
||||||
|
|
||||||
|
constexpr Matrix(glm::mat<C, R, T> 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/matrix.hpp>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace Util::Stream {
|
||||||
|
template <int L, typename T>
|
||||||
|
struct Vector {
|
||||||
|
glm::vec<L, T> m_vec;
|
||||||
|
|
||||||
|
constexpr Vector(glm::vec<L, T> 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "chunk.hpp"
|
||||||
|
#include "tile/tile_base.hpp"
|
||||||
|
#include <glm/detail/qualifier.hpp>
|
||||||
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
|
#include <glm/ext/quaternion_transform.hpp>
|
||||||
|
#include <glm/ext/scalar_constants.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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<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) {
|
||||||
|
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<TileBase> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 <glm/gtc/integer.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace World {
|
||||||
|
struct Chunk {
|
||||||
|
static constexpr int N = 16;
|
||||||
|
|
||||||
|
std::unique_ptr<Tile::TileBase> 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<Tile::TileBase> v);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/world/*.cpp)
|
||||||
|
|
||||||
|
include(src/world/tile/files.cmake)
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
#include "map.hpp"
|
||||||
|
#include "chunk.hpp"
|
||||||
|
#include "tile/tile_base.hpp"
|
||||||
|
#include <glm/gtc/integer.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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<TileBase> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace World {
|
||||||
|
struct Map;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "chunk.hpp"
|
||||||
|
#include "tile/tile_base.hpp"
|
||||||
|
#include "../graphics/context.hpp"
|
||||||
|
#include <glm/gtc/integer.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace World {
|
||||||
|
struct Map {
|
||||||
|
static constexpr int N = 16;
|
||||||
|
std::map<uint64_t, Chunk> 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::TileBase> tile);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
void render(Graphics::Context& ctx) const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "player.hpp"
|
||||||
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/ext/matrix_float4x4.hpp>
|
||||||
|
#include <glm/ext/scalar_constants.hpp>
|
||||||
|
#include <glm/matrix.hpp>
|
||||||
|
|
||||||
|
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<double>() * 0.25;
|
||||||
|
|
||||||
|
void update();
|
||||||
|
glm::mat4 get_view_matrix() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#include "empty.hpp"
|
||||||
|
|
||||||
|
using World::Tile::Empty;
|
||||||
|
|
||||||
|
void Empty::update() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Empty::render() const {
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tile_base.hpp"
|
||||||
|
namespace World::Tile {
|
||||||
|
struct Empty : TileBase {
|
||||||
|
void update() override;
|
||||||
|
void render() const override;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
file(GLOB SOURCES ${SOURCES} src/world/tile/*.cpp)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/gtc/integer.hpp>
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue