diff --git a/.gitignore b/.gitignore
index 9af1833..c2cd13a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
[Bb]uild/*
!*/.gitkeep
+
+cmake-build-debug/*
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..c4c5c0f
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+gloom
\ No newline at end of file
diff --git a/.idea/VoxelEngine.iml b/.idea/VoxelEngine.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/VoxelEngine.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..79b3c94
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..929ec77
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e09ceef..d5d5b6b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,12 @@
cmake_minimum_required (VERSION 3.0)
project (gloom)
+# set c++ 17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+
#
# CMake setup
#
@@ -78,3 +84,15 @@ target_link_libraries (${PROJECT_NAME}
${GLAD_LIBRARIES})
set_target_properties (${PROJECT_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
+## Copy shaders to build directory with a symlink
+add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E create_symlink
+ ${CMAKE_SOURCE_DIR}/gloom/shaders
+ $/shaders)
+
+## Copy assets folder to build folder
+
+add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_SOURCE_DIR}/gloom/assets
+ $/assets)
diff --git a/gloom/assets/dirt.png b/gloom/assets/dirt.png
new file mode 100644
index 0000000..d9ea267
Binary files /dev/null and b/gloom/assets/dirt.png differ
diff --git a/gloom/shaders/simple.frag b/gloom/shaders/simple.frag
index 91f8fff..20664b2 100644
--- a/gloom/shaders/simple.frag
+++ b/gloom/shaders/simple.frag
@@ -1,8 +1,17 @@
-#version 430 core
+#version 460 core
+precision highp float;
-out vec4 color;
+out vec4 FragColor;
+
+in vec3 ourColor;
+in vec2 TexCoord;
+in vec3 pos;
+
+uniform sampler2D ourTexture;
void main()
{
- color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
-}
+ FragColor = texture(ourTexture, TexCoord);
+// FragColor = vec4(1.0f, TexCoord.x, 1.0f, 1.0);
+// FragColor = vec4(137 / 255, 85 / 255, 95 / 255, 1.0f);
+}
\ No newline at end of file
diff --git a/gloom/shaders/simple.shader b/gloom/shaders/simple.shader
new file mode 100644
index 0000000..5ca3a81
--- /dev/null
+++ b/gloom/shaders/simple.shader
@@ -0,0 +1,34 @@
+#version 330 core
+
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec3 aColor;
+layout (location = 2) in vec2 aTexCoord;
+
+out vec3 ourColor;
+out vec2 TexCoord;
+
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
+
+void main()
+{
+ gl_Position = projection * view * model * vec4(aPos, 1.0);
+ ourColor = aColor;
+ TexCoord = aTexCoord;
+}
+
+
+#version 330 core
+out vec4 FragColor;
+
+in vec3 ourColor;
+in vec2 TexCoord;
+
+uniform sampler2D ourTexture;
+
+void main()
+{
+ FragColor = texture(ourTexture, TexCoord);
+// FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0);
+}
\ No newline at end of file
diff --git a/gloom/shaders/simple.vert b/gloom/shaders/simple.vert
index 1178ec6..73dd368 100644
--- a/gloom/shaders/simple.vert
+++ b/gloom/shaders/simple.vert
@@ -1,8 +1,20 @@
-#version 430 core
+#version 460 core
+precision highp float;
-in vec3 position;
+layout (location = 0) in vec3 aPos;
+//layout (location = 1) in vec3 aColor;
+layout (location = 1) in vec2 aTexCoord;
+
+out vec2 TexCoord;
+out vec3 pos;
+
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
void main()
{
- gl_Position = vec4(position, 1.0f);
-}
+ gl_Position = projection * view * model * vec4(aPos, 1.0);
+ TexCoord = aTexCoord;
+ pos = aPos;
+}
\ No newline at end of file
diff --git a/gloom/src/Block.cpp b/gloom/src/Block.cpp
new file mode 100644
index 0000000..7a57f58
--- /dev/null
+++ b/gloom/src/Block.cpp
@@ -0,0 +1,5 @@
+//
+// Created by Bram on 26/08/2024.
+//
+
+#include "Block.h"
diff --git a/gloom/src/Block.h b/gloom/src/Block.h
new file mode 100644
index 0000000..4525031
--- /dev/null
+++ b/gloom/src/Block.h
@@ -0,0 +1,26 @@
+//
+// Created by Bram on 26/08/2024.
+//
+
+#ifndef GLOOM_BLOCK_H
+#define GLOOM_BLOCK_H
+
+//This will hold all the data of a block, but not the mesh since this is held by the chunk
+
+
+#include "BlockType.h"
+
+
+class Block {
+public:
+ Block(BlockType type) : m_type(type) {}
+
+ BlockType getType() const { return m_type; }
+
+
+private:
+ BlockType m_type;
+};
+
+
+#endif //GLOOM_BLOCK_H
diff --git a/gloom/src/BlockType.h b/gloom/src/BlockType.h
new file mode 100644
index 0000000..6d3d9f3
--- /dev/null
+++ b/gloom/src/BlockType.h
@@ -0,0 +1,17 @@
+//
+// Created by Bram on 26/08/2024.
+//
+
+#ifndef GLOOM_BLOCKTYPE_H
+#define GLOOM_BLOCKTYPE_H
+
+enum class BlockType{
+ AIR = 0,
+ DIRT = 1,
+ STONE = 2,
+ GONCALO = 3,
+ SNOW = 4,
+ GRASS = 5
+};
+
+#endif //GLOOM_BLOCKTYPE_H
diff --git a/gloom/src/Chunk.cpp b/gloom/src/Chunk.cpp
new file mode 100644
index 0000000..9f8e629
--- /dev/null
+++ b/gloom/src/Chunk.cpp
@@ -0,0 +1,134 @@
+//
+// Created by Bram on 25/08/2024.
+//
+
+#include "Chunk.h"
+#include "gloom/Mesh.h"
+#include "Cube.h"
+#include "gloom/Singleton.h"
+
+#include
+#include "World.h"
+
+
+void Chunk::loadBlocks() {
+ for (int x = 0; x < CHUNK_SIZE; x++) {
+ for (int y = 0; y < CHUNK_HEIGHT; y++) {
+ for (int z = 0; z < CHUNK_SIZE; z++) {
+ glm::vec3 actualPos = glm::vec3(x, y, z) + glm::vec3(m_chunkPos.x * CHUNK_SIZE, 0, m_chunkPos.y * CHUNK_SIZE);
+ BlockType blockType = generateTerrain(actualPos);
+ if (m_blocks[x][y][z] != nullptr) {
+ delete m_blocks[x][y][z];
+ }
+ m_blocks[x][y][z] = new Block(blockType);
+ }
+ }
+ }
+
+}
+
+void Chunk::loadMesh() {
+ std::vector vertexes{};
+ std::vector indices{};
+
+ for (int x = 0; x < CHUNK_SIZE; x++) {
+ for (int y = 0; y < CHUNK_HEIGHT; y++) {
+ for (int z = 0; z < CHUNK_SIZE; z++) {
+ //Check direction and call LoadFace on that direction
+ Block* block = this->getBlock(x, y, z);
+ if (block->getType() != BlockType::AIR) {
+ BlockType type = block->getType();
+ //Get the block in world space using World::GetInstance().getBlock
+ Block* leftBlock = World::GetInstance().getBlock(x - 1 + m_chunkPos.x * CHUNK_SIZE, y, z + m_chunkPos.y * CHUNK_SIZE);
+ Block* rightBlock = World::GetInstance().getBlock(x + 1 + m_chunkPos.x * CHUNK_SIZE, y, z + m_chunkPos.y * CHUNK_SIZE);
+ Block* bottomBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y - 1, z + m_chunkPos.y * CHUNK_SIZE);
+ Block* topBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y + 1, z + m_chunkPos.y * CHUNK_SIZE);
+ Block* backBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y, z - 1 + m_chunkPos.y * CHUNK_SIZE);
+ Block* frontBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y, z + 1 + m_chunkPos.y * CHUNK_SIZE);
+
+
+
+
+ if (leftBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::LEFT, vertexes, indices, glm::vec3(x, y, z), type);
+ }
+ if (rightBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::RIGHT, vertexes, indices, glm::vec3(x, y, z),type);
+ }
+ if (bottomBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::BOTTOM, vertexes, indices, glm::vec3(x, y, z), type);
+ }
+ if (topBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::TOP, vertexes, indices, glm::vec3(x, y, z), type);
+ }
+ if (backBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::FRONT, vertexes, indices, glm::vec3(x, y, z), type);
+ }
+ if (frontBlock->getType() == BlockType::AIR) {
+ Cube::LoadFace(Face::BACK, vertexes, indices, glm::vec3(x, y, z), type);
+ }
+ }
+ }
+ }
+ }
+
+ m_mesh = Mesh(vertexes, indices);
+ m_mesh.setPosition(glm::vec3(m_chunkPos.x * CHUNK_SIZE, 0, m_chunkPos.y * CHUNK_SIZE));
+ m_mesh.setupMesh();
+}
+
+Chunk::Chunk(const glm::vec2 &pos): m_chunkPos(pos) {
+ for (int x = 0; x < CHUNK_SIZE; x++) {
+ for (int y = 0; y < CHUNK_HEIGHT; y++) {
+ for (int z = 0; z < CHUNK_SIZE; z++) {
+ m_blocks[x][y][z] = new Block(BlockType::AIR);
+ }
+ }
+ }
+}
+
+BlockType Chunk::generateTerrain(glm::vec3 position) {
+ double noise = perlin.octave2D_01((position.x * 0.01), (position.z * 0.01), 4);
+ noise = pow(noise, 3);
+ int height = noise * 70;
+ if (position.y > height) {
+ return BlockType::AIR;
+ }
+ else if (position.y == height) {
+ //snow
+ int variance = ((float)rand() / RAND_MAX) * 7; //between 0-7
+ if (position.y > 20 + variance)
+ return BlockType::SNOW; //snow
+ return BlockType::GRASS; //grass
+ }
+ else {
+ return BlockType::DIRT; //dirt
+ }
+}
+
+Chunk::Chunk() {
+// m_chunkPos = glm::vec2(0, 0);
+
+ for (int x = 0; x < CHUNK_SIZE; x++) {
+ for (int y = 0; y < CHUNK_HEIGHT; y++) {
+ for (int z = 0; z < CHUNK_SIZE; z++) {
+ m_blocks[x][y][z] = new Block(BlockType::AIR);
+ }
+ }
+ }
+
+
+}
+
+Chunk::~Chunk() {
+ for (int x = 0; x < CHUNK_SIZE; ++x) {
+ for (int y = 0; y < CHUNK_HEIGHT; ++y) {
+ for (int z = 0; z < CHUNK_SIZE; ++z) {
+ delete m_blocks[x][y][z]; // Delete each dynamically allocated Block
+ m_blocks[x][y][z] = nullptr; // Set the pointer to nullptr to avoid dangling references
+ }
+ }
+ }
+}
+
+
diff --git a/gloom/src/Chunk.h b/gloom/src/Chunk.h
new file mode 100644
index 0000000..1325a90
--- /dev/null
+++ b/gloom/src/Chunk.h
@@ -0,0 +1,69 @@
+//
+// Created by Bram on 25/08/2024.
+//
+
+#ifndef GLOOM_CHUNK_H
+#define GLOOM_CHUNK_H
+
+#include "gloom/config.hpp"
+#include "gloom/Mesh.h"
+#include "gloom/PerlinNoise.hpp"
+#include "BlockType.h"
+#include "Block.h"
+
+enum class ChunkLoadStatus{
+ GENERATED,
+ GENERATING,
+ NOT_GENERATED,
+ NOT_AVAILABLE,
+};
+
+static const int BLOCK_TYPES_COUNT = 4;
+
+class Chunk {
+public:
+ Chunk();
+ Chunk(const glm::vec2& pos);
+
+ ~Chunk();
+
+ void loadBlocks();
+ void loadMesh();
+
+ void Draw(GLuint shaderProgram) {
+ m_mesh.draw(shaderProgram);
+ }
+
+ Mesh m_mesh;
+
+ BlockType generateTerrain(glm::vec3 position);
+
+ Block* getBlock(int x, int y, int z) {
+ //if out of bounds, return dirt
+ if (x < 0 || x >= CHUNK_SIZE || y < 0 || y >= CHUNK_HEIGHT || z < 0 || z >= CHUNK_SIZE) {
+ return new Block(BlockType::AIR);
+ } else {
+ if(m_blocks[x][y][z] == nullptr) {
+ return new Block(BlockType::AIR);
+ } else {
+ return m_blocks[x][y][z];
+ }
+ }
+ }
+
+ void setBlock(int x, int y, int z, const Block& block) {
+ m_blocks[x][y][z] = new Block(block.getType());
+ }
+
+
+
+private:
+ Block* m_blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE]{ nullptr };
+
+ glm::vec3 m_position;
+ glm::vec2 m_chunkPos;
+
+};
+
+
+#endif //GLOOM_CHUNK_H
diff --git a/gloom/src/Cube.cpp b/gloom/src/Cube.cpp
new file mode 100644
index 0000000..03bf841
--- /dev/null
+++ b/gloom/src/Cube.cpp
@@ -0,0 +1,140 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Cube.h"
+
+glm::vec3 unitVertices[8] = {
+ glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f),
+ glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
+ glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(1.0f, 0.0f, 1.0f),
+ glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f)
+};
+
+
+unsigned int faceVertices[6][4] = {
+ {3, 2, 6, 7},
+ {1, 0, 4, 5},
+ {4, 0, 3, 7},
+ {1, 5, 6, 2},
+ // FRONT (0, 1, 2, 3)
+ {0, 1, 2, 3},
+ // BACK (5, 4, 7, 6)
+ {5, 4, 7, 6}
+};
+
+static const glm::vec2 DIRTCOORDS = Cube::getTexCoords(0);
+static const glm::vec2 STONECOORDS = Cube::getTexCoords(1);
+static const glm::vec2 GONCALOCOORDS = Cube::getTexCoords(2);
+static const glm::vec2 GRASSCOORDS = Cube::getTexCoords(3);
+static const glm::vec2 SNOWCOORDS = Cube::getTexCoords(4);
+
+Cube::Cube(const glm::vec3 &position, BlockType blockType) : position(position), texture("assets/dirt.png"),
+ type(blockType) {
+// setupCube();
+}
+
+void Cube::LoadFace(Face face, std::vector &vertices, std::vector &indices, const glm::vec3 &position, BlockType type) {
+
+ glm::vec3 normal;
+ switch (face) {
+ case Face::TOP:
+ normal = glm::vec3(0.0f, 1.0f, 0.0f);
+ break;
+ case Face::BOTTOM:
+ normal = glm::vec3(0.0f, -1.0f, 0.0f);
+ break;
+ case Face::LEFT:
+ normal = glm::vec3(-1.0f, 0.0f, 0.0f);
+ break;
+ case Face::RIGHT:
+ normal = glm::vec3(1.0f, 0.0f, 0.0f);
+ break;
+ case Face::FRONT:
+ normal = glm::vec3(0.0f, 0.0f, 1.0f);
+ break;
+ case Face::BACK:
+ normal = glm::vec3(0.0f, 0.0f, -1.0f);
+ break;
+ }
+
+ glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f);
+
+ glm::vec2 textureOffset = glm::vec2(0.0f, 0.0f);
+
+ switch(type){
+ case BlockType::STONE:
+ textureOffset = STONECOORDS;
+ break;
+ case BlockType::DIRT:
+ textureOffset = DIRTCOORDS;
+ break;
+ case BlockType::GONCALO:
+ textureOffset = GONCALOCOORDS;
+ break;
+ case BlockType::GRASS:
+ textureOffset = GRASSCOORDS;
+ break;
+ case BlockType::SNOW:
+ textureOffset = SNOWCOORDS;
+ break;
+ }
+
+ glm::vec2 uvCoordinates[4] = {
+ glm::vec2(textureOffset.x, textureOffset.y + CELL_HEIGHT),
+ glm::vec2(textureOffset.x + CELL_WIDTH, textureOffset.y + CELL_HEIGHT),
+ glm::vec2(textureOffset.x + CELL_WIDTH, textureOffset.y),
+ glm::vec2(textureOffset.x, textureOffset.y)
+ };
+
+ unsigned int index = vertices.size();
+
+ for (int i = 0; i < 4; i++) {
+ unsigned int vertexIndex = faceVertices[faceToIndex(face)][i];
+ Mesh::Vertex v;
+ v.position = unitVertices[vertexIndex] + position;
+ v.texCoords = uvCoordinates[i];
+ vertices.push_back(v);
+ }
+
+ indices.push_back(index);
+ indices.push_back(index + 1);
+ indices.push_back(index + 2);
+ indices.push_back(index);
+ indices.push_back(index + 2);
+ indices.push_back(index + 3);
+
+
+}
+
+void Cube::LoadAllFaces(std::vector &vertices, std::vector &indices, const glm::vec3 &position, BlockType type) {
+ Cube::LoadFace(Face::TOP, vertices, indices, position, type);
+ Cube::LoadFace(Face::BOTTOM, vertices, indices, position, type);
+ Cube::LoadFace(Face::LEFT, vertices, indices, position, type);
+ Cube::LoadFace(Face::RIGHT, vertices, indices, position, type);
+ Cube::LoadFace(Face::FRONT, vertices, indices, position, type);
+ Cube::LoadFace(Face::BACK, vertices, indices, position, type);
+}
+
+int Cube::faceToIndex(Face face) {
+ switch (face) {
+ case Face::TOP:
+ return 0;
+ case Face::BOTTOM:
+ return 1;
+ case Face::LEFT:
+ return 2;
+ case Face::RIGHT:
+ return 3;
+ case Face::FRONT:
+ return 4;
+ case Face::BACK:
+ return 5;
+ }
+}
+
+glm::dvec2 Cube::getTexCoords(int pos) {
+ int x = pos % TEXTURE_WIDTH;
+ int y = pos / 16;
+ return glm::vec2(x * CELL_WIDTH, y * CELL_HEIGHT);
+}
diff --git a/gloom/src/Cube.h b/gloom/src/Cube.h
new file mode 100644
index 0000000..d63cd65
--- /dev/null
+++ b/gloom/src/Cube.h
@@ -0,0 +1,62 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#ifndef GLOOM_CUBE_H
+#define GLOOM_CUBE_H
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "glad/glad.h"
+#include "gloom/Texture.h"
+#include "gloom/config.hpp"
+#include "Chunk.h"
+#include "gloom/Mesh.h"
+
+struct CubeVertex {
+ CubeVertex(glm::vec3 pos, glm::vec3 color, glm::vec2 texCoords) : position(pos), color(color),
+ texCoords(texCoords) {};
+
+ glm::vec3 position;
+ glm::vec3 color;
+ glm::vec2 texCoords;
+};
+
+
+enum Face {
+ TOP = 0x01, // 0000 0001
+ BOTTOM = 0x02, // 0000 0010
+ LEFT = 0x04, // 0000 0100
+ RIGHT = 0x08, // 0000 1000
+ FRONT = 0x10, // 0001 0000
+ BACK = 0x20 // 0010 0000
+};
+
+
+class Cube {
+public:
+ explicit Cube(const glm::vec3 &position, BlockType blockType);
+
+
+ static void LoadFace(Face face, std::vector& vertices, std::vector& indices, const glm::vec3& position, BlockType type);
+ static void LoadAllFaces(std::vector& vertices, std::vector& indices, const glm::vec3& position, BlockType type);
+
+ static int faceToIndex(Face face);
+
+ static glm::dvec2 getTexCoords(int pos);
+
+ Mesh* mesh;
+private:
+ glm::vec3 position;
+
+ Texture texture;
+ BlockType type{ BlockType::AIR };
+};
+
+
+#endif //GLOOM_CUBE_H
diff --git a/gloom/src/Game.cpp b/gloom/src/Game.cpp
new file mode 100644
index 0000000..582a18e
--- /dev/null
+++ b/gloom/src/Game.cpp
@@ -0,0 +1,273 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Game.h"
+#include "gloom/config.hpp"
+#include "gloom/Camera.h"
+
+#include
+#include
+#include
+#include
+
+// A callback which allows GLFW to report errors whenever they occur
+static void glfwErrorCallback(int error, const char *description) {
+ fprintf(stderr, "GLFW returned an error:\n\t%s (%i)\n", description, error);
+}
+
+static void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
+ glm::vec2 mousePos((float) xpos, (float) -ypos);
+
+ Camera::getInstance().updateMouse(mousePos);
+
+}
+
+Game::Game() {
+ // Initialise GLFW
+ if (!glfwInit()) {
+ fprintf(stderr, "Could not start GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Set core window options (adjust version numbers if needed)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+ // Enable the GLFW runtime error callback function defined previously.
+ glfwSetErrorCallback(glfwErrorCallback);
+ // We to good for errors
+
+ // Set additional window options
+ glfwWindowHint(GLFW_RESIZABLE, windowResizable);
+// glfwWindowHint(GLFW_SAMPLES, windowSamples); // MSAA
+
+// glDisable(GL_MULTISAMPLE);
+
+ // Create window using GLFW
+ m_window = glfwCreateWindow(windowWidth,
+ windowHeight,
+ windowTitle.c_str(),
+ nullptr,
+ nullptr);
+
+ // Ensure the window is set up correctly
+ if (!m_window) {
+ fprintf(stderr, "Could not open GLFW window\n");
+ //Get the error and print it
+ const char *description;
+ int error = glfwGetError(&description);
+ fprintf(stderr, "Error: %s\n", description);
+
+ glfwTerminate();
+ exit(EXIT_FAILURE);
+ }
+
+ // Let the window be the current OpenGL context and initialise glad
+ glfwMakeContextCurrent(m_window);
+ gladLoadGL();
+
+ // Print various OpenGL information to stdout
+ printf("%s: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
+ printf("GLFW\t %s\n", glfwGetVersionString());
+ printf("OpenGL\t %s\n", glGetString(GL_VERSION));
+ printf("GLSL\t %s\n\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
+
+ // Set up the mouse callback
+ glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwSetCursorPosCallback(m_window, mouse_callback);
+
+ // Set up the shader
+ m_shader.setShader("shaders/simple.vert", "shaders/simple.frag");
+
+ // Set up the block
+// // 16 x 16
+// for (int x = 0; x < CHUNK_SIZE; x+=1) {
+// for(int y = 0; y < CHUNK_HEIGHT / 4; y+=1) {
+// for (int z = 0; z < CHUNK_SIZE; z+=1) {
+// BlockType type = static_cast(rand() % 3);
+// m_cubes.emplace_back(glm::vec3(x, y, z), type);
+// }
+// }
+// }
+
+
+// //10 x 10 chunk
+// for (int i = 0; i < 10; ++i) {
+// for (int j = 0; j < 10; ++j) {
+// m_chunks.push_back(new Chunk(glm::vec2(i, j)));
+// m_chunks[m_chunks.size() - 1]->loadBlocks();
+// m_chunks[m_chunks.size() - 1]->loadMesh();
+// }
+// }
+
+ m_world = &World::GetInstance();
+ m_world->generateChunk(0, 0);
+// m_world->generateChunk(1, 0);
+// m_world->getChunk(0, 0)->loadMesh();
+// m_world->generateChunk(0, 1);
+// m_world->generateChunk(1, 1);
+// m_world->getChunk(1, 0)->loadMesh();
+
+
+
+
+
+}
+
+Game::~Game() {
+ glfwTerminate();
+}
+
+void Game::run() {
+ // Enable depth (Z) buffer (accept "closest" fragment)
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // Configure miscellaneous OpenGL settings
+// glEnable(GL_CULL_FACE);
+
+ // Set default colour after clearing the colour buffer
+ glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
+
+ double lastChunkUpdate = glfwGetTime();
+
+ // Set up your scene here (create Vertex Array Objects, etc.)
+
+ // Rendering Loop
+ while (!glfwWindowShouldClose(this->m_window)) {
+
+ // Calculate delta time
+ double currentTime = glfwGetTime();
+ m_deltaTime = currentTime - m_lastFrameTime;
+ m_lastFrameTime = currentTime;
+
+// // wait until next frame with fps
+// while (glfwGetTime() - m_lastFrameTime < 1.0 / MAX_FPS) {
+// }
+
+
+
+ // Clear colour and depth buffers
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // Draw your scene here
+
+ // Set the shader program
+ m_shader.use();
+ glViewport(0, 0, windowWidth, windowHeight);
+
+ m_shader.setMat4("view", Camera::getInstance().getViewMatrix());
+ m_shader.setMat4("projection", Camera::getInstance().projectionMatrix);
+
+
+// for (auto &chunk: m_chunks) {
+// chunk->Draw(m_shader.ID);
+// }
+//
+ m_world->Draw(m_shader.ID, Camera::getInstance().camPos);
+//
+// // if player is above chunk that is not generated, generate it, add a variance of the renderdistance
+ int playerX = (int) Camera::getInstance().camPos.x / CHUNK_SIZE;
+ int playerZ = (int) Camera::getInstance().camPos.z / CHUNK_SIZE;
+
+ if(glfwGetTime() - lastChunkUpdate > 0.5) {
+ lastChunkUpdate = glfwGetTime();
+ for (int x = playerX - RENDER_DISTANCE; x < playerX + RENDER_DISTANCE; x++) {
+ for (int z = playerZ - RENDER_DISTANCE; z < playerZ + RENDER_DISTANCE; z++) {
+ if (m_world->isChunkGenerated(x,z) == ChunkLoadStatus::NOT_GENERATED) {
+ m_world->generateChunk(x, z);
+ //Now take the 4 chunks next to it and update those
+ //
+ if (m_world->isChunkGenerated(x + 1, z) == ChunkLoadStatus::GENERATED) {
+ m_world->getChunk(x + 1, z)->loadMesh();
+ }
+ if (m_world->isChunkGenerated(x - 1, z) == ChunkLoadStatus::GENERATED) {
+ m_world->getChunk(x - 1, z)->loadMesh();
+ }
+ if (m_world->isChunkGenerated(x, z + 1) == ChunkLoadStatus::GENERATED) {
+ m_world->getChunk(x, z + 1)->loadMesh();
+ }
+ if (m_world->isChunkGenerated(x, z - 1) == ChunkLoadStatus::GENERATED) {
+ m_world->getChunk(x, z - 1)->loadMesh();
+ }
+ }
+ }
+ }
+ }
+//
+
+ // Handle other events
+ glfwPollEvents();
+ this->handleKeyboard();
+
+ // Flip buffers
+ glfwSwapBuffers(this->m_window);
+ }
+
+}
+
+void Game::handleKeyboard() {
+ if (glfwGetKey(m_window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
+ glfwSetWindowShouldClose(m_window, GL_TRUE);
+ }
+
+ glm::vec3 moveDir(0, 0, 0);
+
+ //movement
+ if (glfwGetKey(this->m_window, GLFW_KEY_W) == GLFW_PRESS)
+ moveDir.z -= 1; // Move forward
+ if (glfwGetKey(this->m_window, GLFW_KEY_S) == GLFW_PRESS)
+ moveDir.z += 1; // Move backward
+ if (glfwGetKey(this->m_window, GLFW_KEY_A) == GLFW_PRESS)
+ moveDir.x -= 1; // Move left
+ if (glfwGetKey(this->m_window, GLFW_KEY_D) == GLFW_PRESS)
+ moveDir.x += 1; // Move right
+ if (glfwGetKey(this->m_window, GLFW_KEY_E) == GLFW_PRESS)
+ moveDir.y += 1;
+ if (glfwGetKey(this->m_window, GLFW_KEY_Q) == GLFW_PRESS)
+ moveDir.y -= 1;
+
+ if (length(moveDir) > 0)
+ Camera::getInstance().updatePos(normalize(moveDir), m_deltaTime);
+
+ static bool lastR = false; //Kinda shitty but damm i could not care less
+ if (glfwGetKey(this->m_window, GLFW_KEY_R) == GLFW_PRESS && !lastR) {
+ renderWireframe = !renderWireframe;
+ lastR = true;
+ } else if (glfwGetKey(this->m_window, GLFW_KEY_R) == GLFW_RELEASE) {
+ lastR = false;
+ }
+
+ //unlock mouse
+ static bool keyWasPressed = false;
+ if (glfwGetKey(this->m_window, GLFW_KEY_T) == GLFW_PRESS) {
+ if (!keyWasPressed) {
+ m_isMouseLocked = !m_isMouseLocked; // Toggle the state
+ glfwSetInputMode(this->m_window, GLFW_CURSOR, m_isMouseLocked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
+ keyWasPressed = true;
+ }
+ } else {
+ keyWasPressed = false;
+ }
+
+
+ static bool balls = false;
+ if (glfwGetKey(this->m_window, GLFW_KEY_F) == GLFW_PRESS) {
+ if (!balls) {
+ //Random number between 1234u and 500u
+ SEED = rand() * 10000u;
+ perlin = siv::PerlinNoise(SEED);
+ m_world->generateChunk(1, 0);
+ m_world->generateChunk(0, 1);
+ m_world->generateChunk(0, 0);
+ m_world->generateChunk(1, 1);
+ std::cout << "Seed: " << SEED << std::endl;
+ balls = true;
+ }
+ } else {
+ balls = false;
+ }
+
+}
diff --git a/gloom/src/Game.h b/gloom/src/Game.h
new file mode 100644
index 0000000..ffa1f3e
--- /dev/null
+++ b/gloom/src/Game.h
@@ -0,0 +1,43 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#ifndef GLOOM_GAME_H
+#define GLOOM_GAME_H
+
+
+#include "GLFW/glfw3.h"
+#include "gloom/Shader.h"
+#include "Cube.h"
+#include "World.h"
+
+static void glfwErrorCallback(int error, const char *description);
+
+class Game {
+public:
+ Game();
+ ~Game();
+
+ void run();
+ void handleKeyboard();
+
+
+private:
+ GLFWwindow* m_window;
+
+ bool m_isMouseLocked{ false };
+
+ double m_lastFrameTime{ 0.0 };
+ double m_deltaTime{ 0.0 };
+
+ Shader m_shader;
+
+// Mesh* m_mesh;
+// std::vector m_chunks;
+// std::vector m_cubes;
+
+ World* m_world;
+};
+
+
+#endif //GLOOM_GAME_H
diff --git a/gloom/src/World.cpp b/gloom/src/World.cpp
new file mode 100644
index 0000000..e2fee1f
--- /dev/null
+++ b/gloom/src/World.cpp
@@ -0,0 +1,104 @@
+//
+// Created by Bram on 26/08/2024.
+//
+
+#include "World.h"
+#include
+Chunk * World::getChunk(int x, int z) {
+ return chunks[x][z];
+}
+
+void World::generateChunk(int x, int z) {
+ //Calc offset so there is a 1 block space between each chunk
+// glm::vec2 offset = glm::vec2(x * 2, z * 2);
+ if(chunks[x][z] != nullptr){
+ delete chunks[x][z];
+ }
+
+ chunks[x][z] = new Chunk(glm::vec2(x, z));
+ chunkGenerated[x][z] = ChunkLoadStatus::GENERATING;
+ chunks[x][z]->loadBlocks();
+ chunks[x][z]->loadMesh();
+ chunkGenerated[x][z] = ChunkLoadStatus::GENERATED;
+
+ //Call the sourounding chunks to update their mesh
+ if (x > 0) {
+ if(chunkGenerated[x - 1][z] == ChunkLoadStatus::GENERATED)
+ chunks[x - 1][z]->loadMesh();
+ }
+ if (x < WORLD_WIDTH - 1) {
+ if(chunkGenerated[x + 1][z] == ChunkLoadStatus::GENERATED)
+ chunks[x + 1][z]->loadMesh();
+ }
+ if (z > 0) {
+ if(chunkGenerated[x][z - 1] == ChunkLoadStatus::GENERATED)
+ chunks[x][z - 1]->loadMesh();
+ }
+ if (z < WORLD_HEIGHT - 1) {
+ if(chunkGenerated[x][z + 1] == ChunkLoadStatus::GENERATED)
+ chunks[x][z + 1]->loadMesh();
+ }
+}
+
+Block* World::getBlock(int x, int y, int z) {
+ int chunkX = x / CHUNK_SIZE;
+ int chunkZ = z / CHUNK_SIZE;
+
+ int blockX = x % CHUNK_SIZE;
+ int blockZ = z % CHUNK_SIZE;
+
+ Chunk* chunk = chunks[chunkX][chunkZ];
+ ChunkLoadStatus status = isChunkGenerated(chunkX, chunkZ);
+
+ // check if the chunk is generated
+ switch(isChunkGenerated(chunkX, chunkZ)) {
+ case ChunkLoadStatus::NOT_GENERATED:
+// generateChunk(chunkX, chunkZ);
+ return new Block(BlockType::DIRT);
+ break;
+ case ChunkLoadStatus::NOT_AVAILABLE:
+ return new Block(BlockType::AIR);
+ break;
+ case ChunkLoadStatus::GENERATING:
+ //Prob current chunk is generating
+ break;
+ default:
+ break;
+ }
+
+ return chunks[chunkX][chunkZ]->getBlock(blockX, y, blockZ);
+}
+
+void World::setBlock(int x, int y, int z, const Block &block) {
+ int chunkX = x / CHUNK_SIZE;
+ int chunkZ = z / CHUNK_SIZE;
+
+ int blockX = x % CHUNK_SIZE;
+ int blockZ = z % CHUNK_SIZE;
+
+ chunks[chunkX][chunkZ]->setBlock(blockX, y, blockZ, block);
+}
+
+void World::Draw(GLuint shaderProgram, glm::vec3 playerPos) {
+ for (int x = 0; x < WORLD_WIDTH; x++) {
+ for (int z = 0; z < WORLD_HEIGHT; z++) {
+ //Check if the player is RENDERDISTANCE chunks away from the chunk
+ if (glm::distance(playerPos, glm::vec3(x * CHUNK_SIZE, 0, z * CHUNK_SIZE)) > RENDER_DISTANCE * CHUNK_SIZE) {
+ continue;
+ }
+ if (chunkGenerated[x][z] == ChunkLoadStatus::GENERATED) {
+ chunks[x][z]->Draw(shaderProgram);
+ }
+ }
+ }
+
+}
+
+World::World() {
+ for (int x = 0; x < WORLD_WIDTH; x++) {
+ for (int z = 0; z < WORLD_HEIGHT; z++) {
+ chunks[x][z] = nullptr;
+ chunkGenerated[x][z] = ChunkLoadStatus::NOT_GENERATED;
+ }
+ }
+}
diff --git a/gloom/src/World.h b/gloom/src/World.h
new file mode 100644
index 0000000..0869ea8
--- /dev/null
+++ b/gloom/src/World.h
@@ -0,0 +1,42 @@
+//
+// Created by Bram on 26/08/2024.
+//
+
+#ifndef GLOOM_WORLD_H
+#define GLOOM_WORLD_H
+
+#include
+#include "Chunk.h"
+#include "gloom/Singleton.h"
+
+
+class World: public Singleton {
+public:
+ World();
+ Chunk * getChunk(int x, int z);
+ void generateChunk(int x, int z);
+
+ //Optional ig
+ Block* getBlock(int x, int y, int z);
+ void setBlock(int x, int y, int z, const Block& block);
+
+ void Draw(GLuint shaderProgram, glm::vec3 playerPos);
+
+ ChunkLoadStatus isChunkGenerated(int x, int z) {
+ //if out of bounds, return true
+ if (x < 0 || x >= WORLD_WIDTH || z < 0 || z >= WORLD_HEIGHT) {
+ return ChunkLoadStatus::NOT_AVAILABLE;
+ } else {
+ return chunkGenerated[x][z];
+ }
+ }
+
+private:
+ //2D array
+ Chunk* chunks[WORLD_HEIGHT][WORLD_WIDTH]{ nullptr };
+ ChunkLoadStatus chunkGenerated[WORLD_HEIGHT][WORLD_WIDTH]{ ChunkLoadStatus::NOT_GENERATED };
+
+};
+
+
+#endif //GLOOM_WORLD_H
diff --git a/gloom/src/gloom/Camera.cpp b/gloom/src/gloom/Camera.cpp
new file mode 100644
index 0000000..bc6ddaa
--- /dev/null
+++ b/gloom/src/gloom/Camera.cpp
@@ -0,0 +1,64 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Camera.h"
+
+const float CAM_SENSITIVITY = .002f;
+const float CAM_SPEED = 20;
+
+//projection params
+
+Camera::Camera() {
+ projectionMatrix = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / SCR_HEIGHT, NEAR_PLANE, FAR_PLANE);
+ camPos = glm::vec3(0, 0, 0);
+}
+
+glm::vec3 Camera::getFrontVector() {
+ glm::vec3 front;
+ front.x = cos(cameraAngle.x) * cos(cameraAngle.y);
+ front.y = sin(cameraAngle.y);
+ front.z = sin(cameraAngle.x) * cos(cameraAngle.y);
+
+ return front;
+}
+
+void Camera::updateMouse(glm::vec2 mousePos) {
+ glm::vec2 offset = mousePos - lastMousePos;
+ lastMousePos = mousePos;
+ cameraAngle += offset * CAM_SENSITIVITY;
+ cameraAngle.y = glm::clamp(cameraAngle.y, glm::radians(-89.0f), glm::radians(89.0f));
+}
+
+
+void Camera::updatePos(glm::vec3 moveDirection, double dt) {
+ glm::vec3 up(0.0f, 1.0f, 0.0f);
+
+ glm::vec3 front = glm::normalize(getFrontVector());
+ glm::vec3 right = glm::normalize(glm::cross(front, up));
+ up = glm::normalize(glm::cross(right, front));
+
+ camPos += up * moveDirection.y * CAM_SPEED * (float)dt;
+ camPos += front * moveDirection.z * -CAM_SPEED * (float)dt;
+ camPos += right * moveDirection.x * CAM_SPEED * (float)dt;
+
+ // Camera::print();
+}
+
+glm::mat4 Camera::getViewMatrix() {
+ glm::vec3 front = getFrontVector();
+
+ glm::vec3 cameraTarget = camPos + front;
+
+
+ return glm::lookAt(camPos, cameraTarget, glm::vec3(0.0f, 1.0f, 0.0f));
+}
+
+void Camera::print() {
+ std::cout << "Camera Position: " << camPos.x << ", " << camPos.y << ", " <
+#include
+#include
+#include
+
+class Camera
+{
+private:
+ glm::vec2 cameraAngle; //pitch and yaw
+ glm::vec3 getFrontVector();
+ glm::vec2 lastMousePos = glm::vec2(400.0f, 300.0f);
+
+
+
+ Camera();
+
+public:
+
+ //constants
+ static constexpr int SCR_WIDTH = 1200;
+ static constexpr int SCR_HEIGHT = 900;
+ static constexpr float FOV = 90;
+ static constexpr float NEAR_PLANE = 0.1f;
+ static constexpr float FAR_PLANE = 200.0f;
+
+ static Camera& getInstance();
+
+ glm::vec3 camPos = glm::vec3(0.0f, 0.0f, 0.0f);
+ void updateMouse(glm::vec2 mousePos);
+ void updatePos(glm::vec3 moveDirection, double dt);
+ void print();
+ glm::mat4 getViewMatrix();
+ glm::mat4 projectionMatrix;
+};
+
+
+#endif //GLOOM_CAMERA_H
diff --git a/gloom/src/gloom/Mesh.cpp b/gloom/src/gloom/Mesh.cpp
new file mode 100644
index 0000000..eece878
--- /dev/null
+++ b/gloom/src/gloom/Mesh.cpp
@@ -0,0 +1,89 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Mesh.h"
+#include "glad/glad.h"
+#include "config.hpp"
+#include
+#include
+#include "TextureManager.h"
+
+Mesh::Mesh() {
+ VAO = 0;
+ VBO = 0;
+ EBO = 0;
+ VAOSIZE = 0;
+}
+
+Mesh::~Mesh() {
+ glDeleteVertexArrays(1, &VAO);
+ glDeleteBuffers(1, &VBO);
+ glDeleteBuffers(1, &EBO);
+}
+
+Mesh::Mesh(const std::vector &vertices, const std::vector &indices) {
+ this->vertices = vertices;
+ this->indices = indices;
+ m_texture = TextureManager::GetInstance().getTexture("assets/dirt.png");
+ setupMesh();
+}
+
+void Mesh::draw(GLuint shaderID) {
+
+ glUseProgram(shaderID);
+
+ GLuint modelLoc = glGetUniformLocation(shaderID, "model");
+ glm::mat4 model = glm::mat4(1.0f);
+
+ model = glm::translate(model, m_position);
+ model = glm::rotate(model, glm::radians(m_rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
+ model = glm::rotate(model, glm::radians(m_rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
+ model = glm::rotate(model, glm::radians(m_rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
+ model = glm::scale(model, m_scale);
+
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+
+
+ glBindVertexArray(VAO);
+
+ if(renderWireframe) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ } else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+ m_texture->bind(0);
+
+ //Get error
+ glDrawElements(GL_TRIANGLES, VAOSIZE, GL_UNSIGNED_INT, nullptr);
+
+ glBindVertexArray(0);
+}
+
+void Mesh::setupMesh() {
+
+ glGenVertexArrays(1, &VAO);
+ glGenBuffers(1, &VBO);
+ glGenBuffers(1, &EBO);
+
+ glBindVertexArray(VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
+
+ // vertex positions
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, position));
+ glEnableVertexAttribArray(0);
+
+ // vertex texture coords
+ glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, texCoords));
+ glEnableVertexAttribArray(1);
+
+ glBindVertexArray(0);
+
+ // Free memory
+ VAOSIZE = indices.size(); // Now using the size of the indices
+}
diff --git a/gloom/src/gloom/Mesh.h b/gloom/src/gloom/Mesh.h
new file mode 100644
index 0000000..6abb664
--- /dev/null
+++ b/gloom/src/gloom/Mesh.h
@@ -0,0 +1,46 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#ifndef GLOOM_MESH_H
+#define GLOOM_MESH_H
+
+#include
+#include
+#include "glad/glad.h"
+#include "Texture.h"
+
+class Mesh {
+public:
+ struct Vertex{
+ glm::vec3 position;
+ glm::dvec2 texCoords;
+ };
+
+ Mesh();
+ ~Mesh();
+ Mesh(const std::vector& vertices, const std::vector& indices);
+
+
+ void draw(GLuint shaderID);
+ void setupMesh();
+
+ void setPosition(glm::vec3 position) { m_position = position; }
+ void setRotation(glm::vec3 rotation) { m_rotation = rotation; }
+ void setScale(glm::vec3 scale) { m_scale = scale; }
+private:
+ unsigned int VAO, VBO, EBO, VAOSIZE;
+
+ glm::vec3 m_position{ 0.0f, -5.0f, 0.0f };
+ glm::vec3 m_rotation{ 0.0f, 0.0f, 0.0f };
+ glm::vec3 m_scale{ 1.0f, 1.0f, 1.0f };
+
+
+ std::vector vertices;
+ std::vector indices;
+
+ Texture* m_texture{ nullptr };
+};
+
+
+#endif //GLOOM_MESH_H
diff --git a/gloom/src/gloom/PerlinNoise.hpp b/gloom/src/gloom/PerlinNoise.hpp
new file mode 100644
index 0000000..9dc3106
--- /dev/null
+++ b/gloom/src/gloom/PerlinNoise.hpp
@@ -0,0 +1,659 @@
+//----------------------------------------------------------------------------------------
+//
+// siv::PerlinNoise
+// Perlin noise library for modern C++
+//
+// Copyright (C) 2013-2021 Ryo Suzuki
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files(the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions :
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//----------------------------------------------------------------------------------------
+
+# pragma once
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+
+# if __has_include() && defined(__cpp_concepts)
+# include
+# endif
+
+
+// Library major version
+# define SIVPERLIN_VERSION_MAJOR 3
+
+// Library minor version
+# define SIVPERLIN_VERSION_MINOR 0
+
+// Library revision version
+# define SIVPERLIN_VERSION_REVISION 0
+
+// Library version
+# define SIVPERLIN_VERSION ((SIVPERLIN_VERSION_MAJOR * 100 * 100) + (SIVPERLIN_VERSION_MINOR * 100) + (SIVPERLIN_VERSION_REVISION))
+
+
+// [[nodiscard]] for constructors
+# if (201907L <= __has_cpp_attribute(nodiscard))
+# define SIVPERLIN_NODISCARD_CXX20 [[nodiscard]]
+# else
+# define SIVPERLIN_NODISCARD_CXX20
+# endif
+
+
+// std::uniform_random_bit_generator concept
+# if __cpp_lib_concepts
+# define SIVPERLIN_CONCEPT_URBG template
+# define SIVPERLIN_CONCEPT_URBG_ template
+# else
+# define SIVPERLIN_CONCEPT_URBG template , std::is_unsigned>>>* = nullptr>
+# define SIVPERLIN_CONCEPT_URBG_ template , std::is_unsigned>>>*>
+# endif
+
+
+// arbitrary value for increasing entropy
+# ifndef SIVPERLIN_DEFAULT_Y
+# define SIVPERLIN_DEFAULT_Y (0.12345)
+# endif
+
+// arbitrary value for increasing entropy
+# ifndef SIVPERLIN_DEFAULT_Z
+# define SIVPERLIN_DEFAULT_Z (0.34567)
+# endif
+
+
+namespace siv
+{
+ template
+ class BasicPerlinNoise
+ {
+ public:
+
+ static_assert(std::is_floating_point_v);
+
+ ///////////////////////////////////////
+ //
+ // Typedefs
+ //
+
+ using state_type = std::array;
+
+ using value_type = Float;
+
+ using default_random_engine = std::mt19937;
+
+ using seed_type = typename default_random_engine::result_type;
+
+ ///////////////////////////////////////
+ //
+ // Constructors
+ //
+
+ SIVPERLIN_NODISCARD_CXX20
+ constexpr BasicPerlinNoise() noexcept;
+
+ SIVPERLIN_NODISCARD_CXX20
+ explicit BasicPerlinNoise(seed_type seed);
+
+ SIVPERLIN_CONCEPT_URBG
+ SIVPERLIN_NODISCARD_CXX20
+ explicit BasicPerlinNoise(URBG&& urbg);
+
+ ///////////////////////////////////////
+ //
+ // Reseed
+ //
+
+ void reseed(seed_type seed);
+
+ SIVPERLIN_CONCEPT_URBG
+ void reseed(URBG&& urbg);
+
+ ///////////////////////////////////////
+ //
+ // Serialization
+ //
+
+ [[nodiscard]]
+ constexpr const state_type& serialize() const noexcept;
+
+ constexpr void deserialize(const state_type& state) noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Noise (The result is in the range [-1, 1])
+ //
+
+ [[nodiscard]]
+ value_type noise1D(value_type x) const noexcept;
+
+ [[nodiscard]]
+ value_type noise2D(value_type x, value_type y) const noexcept;
+
+ [[nodiscard]]
+ value_type noise3D(value_type x, value_type y, value_type z) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Noise (The result is remapped to the range [0, 1])
+ //
+
+ [[nodiscard]]
+ value_type noise1D_01(value_type x) const noexcept;
+
+ [[nodiscard]]
+ value_type noise2D_01(value_type x, value_type y) const noexcept;
+
+ [[nodiscard]]
+ value_type noise3D_01(value_type x, value_type y, value_type z) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Octave noise (The result can be out of the range [-1, 1])
+ //
+
+ [[nodiscard]]
+ value_type octave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Octave noise (The result is clamped to the range [-1, 1])
+ //
+
+ [[nodiscard]]
+ value_type octave1D_11(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave2D_11(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave3D_11(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Octave noise (The result is clamped and remapped to the range [0, 1])
+ //
+
+ [[nodiscard]]
+ value_type octave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type octave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Octave noise (The result is normalized to the range [-1, 1])
+ //
+
+ [[nodiscard]]
+ value_type normalizedOctave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type normalizedOctave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type normalizedOctave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ ///////////////////////////////////////
+ //
+ // Octave noise (The result is normalized and remapped to the range [0, 1])
+ //
+
+ [[nodiscard]]
+ value_type normalizedOctave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type normalizedOctave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ [[nodiscard]]
+ value_type normalizedOctave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
+
+ private:
+
+ state_type m_permutation;
+ };
+
+ using PerlinNoise = BasicPerlinNoise;
+
+ namespace perlin_detail
+ {
+ ////////////////////////////////////////////////
+ //
+ // These functions are provided for consistency.
+ // You may get different results from std::shuffle() with different standard library implementations.
+ //
+ SIVPERLIN_CONCEPT_URBG
+ [[nodiscard]]
+ inline std::uint64_t Random(const std::uint64_t max, URBG&& urbg)
+ {
+ return (urbg() % (max + 1));
+ }
+
+ template
+ inline void Shuffle(RandomIt first, RandomIt last, URBG&& urbg)
+ {
+ if (first == last)
+ {
+ return;
+ }
+
+ using difference_type = typename std::iterator_traits::difference_type;
+
+ for (RandomIt it = first + 1; it < last; ++it)
+ {
+ const std::uint64_t n = static_cast(it - first);
+ std::iter_swap(it, first + static_cast(Random(n, std::forward(urbg))));
+ }
+ }
+ //
+ ////////////////////////////////////////////////
+
+ template
+ [[nodiscard]]
+ inline constexpr Float Fade(const Float t) noexcept
+ {
+ return t * t * t * (t * (t * 6 - 15) + 10);
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float Lerp(const Float a, const Float b, const Float t) noexcept
+ {
+ return (a + (b - a) * t);
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float Grad(const std::uint8_t hash, const Float x, const Float y, const Float z) noexcept
+ {
+ const std::uint8_t h = hash & 15;
+ const Float u = h < 8 ? x : y;
+ const Float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float Remap_01(const Float x) noexcept
+ {
+ return (x * Float(0.5) + Float(0.5));
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float Clamp_11(const Float x) noexcept
+ {
+ return std::clamp(x, Float(-1.0), Float(1.0));
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float RemapClamp_01(const Float x) noexcept
+ {
+ if (x <= Float(-1.0))
+ {
+ return Float(0.0);
+ }
+ else if (Float(1.0) <= x)
+ {
+ return Float(1.0);
+ }
+
+ return (x * Float(0.5) + Float(0.5));
+ }
+
+ template
+ [[nodiscard]]
+ inline auto Octave1D(const Noise& noise, Float x, const std::int32_t octaves, const Float persistence) noexcept
+ {
+ using value_type = Float;
+ value_type result = 0;
+ value_type amplitude = 1;
+
+ for (std::int32_t i = 0; i < octaves; ++i)
+ {
+ result += (noise.noise1D(x) * amplitude);
+ x *= 2;
+ amplitude *= persistence;
+ }
+
+ return result;
+ }
+
+ template
+ [[nodiscard]]
+ inline auto Octave2D(const Noise& noise, Float x, Float y, const std::int32_t octaves, const Float persistence) noexcept
+ {
+ using value_type = Float;
+ value_type result = 0;
+ value_type amplitude = 1;
+
+ for (std::int32_t i = 0; i < octaves; ++i)
+ {
+ result += (noise.noise2D(x, y) * amplitude);
+ x *= 2;
+ y *= 2;
+ amplitude *= persistence;
+ }
+
+ return result;
+ }
+
+ template
+ [[nodiscard]]
+ inline auto Octave3D(const Noise& noise, Float x, Float y, Float z, const std::int32_t octaves, const Float persistence) noexcept
+ {
+ using value_type = Float;
+ value_type result = 0;
+ value_type amplitude = 1;
+
+ for (std::int32_t i = 0; i < octaves; ++i)
+ {
+ result += (noise.noise3D(x, y, z) * amplitude);
+ x *= 2;
+ y *= 2;
+ z *= 2;
+ amplitude *= persistence;
+ }
+
+ return result;
+ }
+
+ template
+ [[nodiscard]]
+ inline constexpr Float MaxAmplitude(const std::int32_t octaves, const Float persistence) noexcept
+ {
+ using value_type = Float;
+ value_type result = 0;
+ value_type amplitude = 1;
+
+ for (std::int32_t i = 0; i < octaves; ++i)
+ {
+ result += amplitude;
+ amplitude *= persistence;
+ }
+
+ return result;
+ }
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline constexpr BasicPerlinNoise::BasicPerlinNoise() noexcept
+ : m_permutation{ 151,160,137,91,90,15,
+ 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+ 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+ 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+ 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+ 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+ 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+ 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+ 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+ 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+ 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+ 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+ 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 } {}
+
+ template
+ inline BasicPerlinNoise::BasicPerlinNoise(const seed_type seed)
+ {
+ reseed(seed);
+ }
+
+ template
+ SIVPERLIN_CONCEPT_URBG_
+ inline BasicPerlinNoise::BasicPerlinNoise(URBG&& urbg)
+ {
+ reseed(std::forward(urbg));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline void BasicPerlinNoise::reseed(const seed_type seed)
+ {
+ reseed(default_random_engine{ seed });
+ }
+
+ template
+ SIVPERLIN_CONCEPT_URBG_
+ inline void BasicPerlinNoise::reseed(URBG&& urbg)
+ {
+ std::iota(m_permutation.begin(), m_permutation.end(), uint8_t{ 0 });
+
+ perlin_detail::Shuffle(m_permutation.begin(), m_permutation.end(), std::forward(urbg));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline constexpr const typename BasicPerlinNoise::state_type& BasicPerlinNoise::serialize() const noexcept
+ {
+ return m_permutation;
+ }
+
+ template
+ inline constexpr void BasicPerlinNoise::deserialize(const state_type& state) noexcept
+ {
+ m_permutation = state;
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise1D(const value_type x) const noexcept
+ {
+ return noise3D(x,
+ static_cast(SIVPERLIN_DEFAULT_Y),
+ static_cast(SIVPERLIN_DEFAULT_Z));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise2D(const value_type x, const value_type y) const noexcept
+ {
+ return noise3D(x,
+ y,
+ static_cast(SIVPERLIN_DEFAULT_Z));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise3D(const value_type x, const value_type y, const value_type z) const noexcept
+ {
+ const value_type _x = std::floor(x);
+ const value_type _y = std::floor(y);
+ const value_type _z = std::floor(z);
+
+ const std::int32_t ix = static_cast(_x) & 255;
+ const std::int32_t iy = static_cast(_y) & 255;
+ const std::int32_t iz = static_cast(_z) & 255;
+
+ const value_type fx = (x - _x);
+ const value_type fy = (y - _y);
+ const value_type fz = (z - _z);
+
+ const value_type u = perlin_detail::Fade(fx);
+ const value_type v = perlin_detail::Fade(fy);
+ const value_type w = perlin_detail::Fade(fz);
+
+ const std::uint8_t A = (m_permutation[ix & 255] + iy) & 255;
+ const std::uint8_t B = (m_permutation[(ix + 1) & 255] + iy) & 255;
+
+ const std::uint8_t AA = (m_permutation[A] + iz) & 255;
+ const std::uint8_t AB = (m_permutation[(A + 1) & 255] + iz) & 255;
+
+ const std::uint8_t BA = (m_permutation[B] + iz) & 255;
+ const std::uint8_t BB = (m_permutation[(B + 1) & 255] + iz) & 255;
+
+ const value_type p0 = perlin_detail::Grad(m_permutation[AA], fx, fy, fz);
+ const value_type p1 = perlin_detail::Grad(m_permutation[BA], fx - 1, fy, fz);
+ const value_type p2 = perlin_detail::Grad(m_permutation[AB], fx, fy - 1, fz);
+ const value_type p3 = perlin_detail::Grad(m_permutation[BB], fx - 1, fy - 1, fz);
+ const value_type p4 = perlin_detail::Grad(m_permutation[(AA + 1) & 255], fx, fy, fz - 1);
+ const value_type p5 = perlin_detail::Grad(m_permutation[(BA + 1) & 255], fx - 1, fy, fz - 1);
+ const value_type p6 = perlin_detail::Grad(m_permutation[(AB + 1) & 255], fx, fy - 1, fz - 1);
+ const value_type p7 = perlin_detail::Grad(m_permutation[(BB + 1) & 255], fx - 1, fy - 1, fz - 1);
+
+ const value_type q0 = perlin_detail::Lerp(p0, p1, u);
+ const value_type q1 = perlin_detail::Lerp(p2, p3, u);
+ const value_type q2 = perlin_detail::Lerp(p4, p5, u);
+ const value_type q3 = perlin_detail::Lerp(p6, p7, u);
+
+ const value_type r0 = perlin_detail::Lerp(q0, q1, v);
+ const value_type r1 = perlin_detail::Lerp(q2, q3, v);
+
+ return perlin_detail::Lerp(r0, r1, w);
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise1D_01(const value_type x) const noexcept
+ {
+ return perlin_detail::Remap_01(noise1D(x));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise2D_01(const value_type x, const value_type y) const noexcept
+ {
+ return perlin_detail::Remap_01(noise2D(x, y));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::noise3D_01(const value_type x, const value_type y, const value_type z) const noexcept
+ {
+ return perlin_detail::Remap_01(noise3D(x, y, z));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Octave1D(*this, x, octaves, persistence);
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Octave2D(*this, x, y, octaves, persistence);
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Octave3D(*this, x, y, z, octaves, persistence);
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave1D_11(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Clamp_11(octave1D(x, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave2D_11(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Clamp_11(octave2D(x, y, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave3D_11(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Clamp_11(octave3D(x, y, z, octaves, persistence));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::RemapClamp_01(octave1D(x, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::RemapClamp_01(octave2D(x, y, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::octave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::RemapClamp_01(octave3D(x, y, z, octaves, persistence));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return (octave1D(x, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return (octave2D(x, y, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return (octave3D(x, y, z, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
+ }
+
+ ///////////////////////////////////////
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Remap_01(normalizedOctave1D(x, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Remap_01(normalizedOctave2D(x, y, octaves, persistence));
+ }
+
+ template
+ inline typename BasicPerlinNoise::value_type BasicPerlinNoise::normalizedOctave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
+ {
+ return perlin_detail::Remap_01(normalizedOctave3D(x, y, z, octaves, persistence));
+ }
+}
+
+# undef SIVPERLIN_NODISCARD_CXX20
+# undef SIVPERLIN_CONCEPT_URBG
+# undef SIVPERLIN_CONCEPT_URBG_
diff --git a/gloom/src/gloom/Shader.cpp b/gloom/src/gloom/Shader.cpp
new file mode 100644
index 0000000..4525835
--- /dev/null
+++ b/gloom/src/gloom/Shader.cpp
@@ -0,0 +1,157 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Shader.h"
+
+
+
+Shader::Shader() {
+
+}
+
+void Shader::setShader(const char* vertexPath, const char* fragmentPath) {
+ std::string vertexCode, fragmentCode;
+ std::ifstream vShaderFile, fShaderFile;
+
+ vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ try {
+ //open files
+ vShaderFile.open(vertexPath);
+ fShaderFile.open(fragmentPath);
+ std::stringstream vShaderStream, fShaderStream;
+
+ vShaderStream << vShaderFile.rdbuf();
+ fShaderStream << fShaderFile.rdbuf();
+
+ vShaderFile.close();
+ fShaderFile.close();
+
+ vertexCode = vShaderStream.str();
+ fragmentCode = fShaderStream.str();
+ }
+ catch (std::ifstream::failure e) {
+ std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
+ }
+
+ const char* vShaderCode = vertexCode.c_str();
+ const char* fShaderCode = fragmentCode.c_str();
+
+
+ //next, compile shaders
+ unsigned int vertex, fragment;
+ int success;
+ char infoLog[512];
+ //vertex
+ vertex = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex, 1, &vShaderCode, NULL);
+ glCompileShader(vertex);
+ //vertex errors
+ glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(vertex, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
+ }
+
+ //fragment
+ fragment = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment, 1, &fShaderCode, NULL);
+ glCompileShader(fragment);
+ //fragment compile errors
+ glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(fragment, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
+ }
+
+ //setup shader program
+ ID = glCreateProgram();
+ glAttachShader(ID, vertex);
+ glAttachShader(ID, fragment);
+ glLinkProgram(ID);
+ //shader program linking errors
+ glGetProgramiv(ID, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetProgramInfoLog(ID, 512, NULL, infoLog);
+ std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
+ }
+
+ //cleanup
+ glDeleteShader(vertex);
+ glDeleteShader(fragment);
+}
+
+
+
+//shadow mapping
+void Shader::setupShadowMap() {
+ // Create framebuffer to attach depth texture
+ glGenFramebuffers(1, &depthMapFBO);
+ glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
+ // Create depth texture
+ glGenTextures(1, &depthMap);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, depthMap);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowWidth, shadowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthMap, 0);
+
+ glDrawBuffer(GL_NONE);
+
+
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ std::cout << "Error getting framebuffer" << std::endl;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+}
+void Shader::renderShadowMap(glm::mat4 lightSpaceMatrix) {
+ glViewport(0, 0, shadowWidth, shadowHeight);
+ glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // Render the scene
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+
+
+//enable this shader
+void Shader::use() {
+ glUseProgram(ID);
+}
+
+//uniform set functions
+void Shader::setBool(const std::string& name, bool value) const
+{
+ glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
+}
+void Shader::setInt(const std::string& name, int value) const
+{
+ glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
+}
+void Shader::setFloat(const std::string& name, float value) const
+{
+ glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
+}
+void Shader::setMat4(const std::string& name, glm::mat4 value) const
+{
+ glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
+
+}
+void Shader::setVec3(const std::string& name, glm::vec3 value) const {
+ glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, glm::value_ptr(value));
+}
\ No newline at end of file
diff --git a/gloom/src/gloom/Shader.h b/gloom/src/gloom/Shader.h
new file mode 100644
index 0000000..700bded
--- /dev/null
+++ b/gloom/src/gloom/Shader.h
@@ -0,0 +1,41 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#ifndef GLOOM_SHADER_H
+#define GLOOM_SHADER_H
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+class Shader
+{
+public:
+ unsigned int ID;
+ Shader();
+
+ void use();
+ void setShader(const char* vertexPath, const char* fragmentPath);
+
+ void setBool(const std::string& name, bool value) const;
+ void setInt(const std::string& name, int value) const;
+ void setFloat(const std::string& name, float value) const;
+ void setMat4(const std::string& name, glm::mat4 value) const;
+ void setVec3(const std::string& name, glm::vec3 value) const;
+
+
+ //shadow map
+ unsigned int depthMapFBO, depthMap;
+ int shadowWidth = 4096, shadowHeight = 4096; // Adjust the size as needed
+ void setupShadowMap();
+ void renderShadowMap(glm::mat4 lightSpaceMatrix);
+};
+#endif //GLOOM_SHADER_H
diff --git a/gloom/src/gloom/Singleton.h b/gloom/src/gloom/Singleton.h
new file mode 100644
index 0000000..ec1c0c8
--- /dev/null
+++ b/gloom/src/gloom/Singleton.h
@@ -0,0 +1,35 @@
+//
+// Created by Bram on 25/08/2024.
+//
+
+#ifndef GLOOM_SINGLETON_H
+#define GLOOM_SINGLETON_H
+
+#ifndef SINGLETON_H
+#define SINGLETON_H
+
+template
+class Singleton {
+public:
+ static T &GetInstance() {
+ static T instance{};
+ return instance;
+ }
+
+ virtual ~Singleton() = default;
+
+ Singleton(Singleton &&other) = delete;
+
+ Singleton(const Singleton &other) = delete;
+
+ Singleton &operator=(Singleton &&other) = delete;
+
+ Singleton &operator=(const Singleton &other) = delete;
+
+protected:
+ Singleton() = default;
+};
+
+#endif // SINGLETON_H
+
+#endif //GLOOM_SINGLETON_H
diff --git a/gloom/src/gloom/Texture.cpp b/gloom/src/gloom/Texture.cpp
new file mode 100644
index 0000000..3c4342d
--- /dev/null
+++ b/gloom/src/gloom/Texture.cpp
@@ -0,0 +1,52 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#include "Texture.h"
+#include "glad/glad.h"
+#include
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+
+Texture::Texture(const std::string &filename) {
+ // Load the image
+ int width, height, channels;
+ unsigned char* image = stbi_load(filename.c_str(), &width, &height, &channels, 0);
+
+ // Generate a texture
+ glGenTextures(1, &m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+
+ // Set the texture wrapping/filtering options
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ //mipmap resizing
+
+
+
+ // Load and generate the texture
+ if (image) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ } else {
+ std::cerr << "Failed to load texture" << std::endl;
+ }
+
+ // Free the image
+ stbi_image_free(image);
+
+}
+
+void Texture::bind(unsigned int slot) const {
+ glActiveTexture(GL_TEXTURE0 + slot);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+}
+
+void Texture::unbind() const {
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
diff --git a/gloom/src/gloom/Texture.h b/gloom/src/gloom/Texture.h
new file mode 100644
index 0000000..7fda4e5
--- /dev/null
+++ b/gloom/src/gloom/Texture.h
@@ -0,0 +1,24 @@
+//
+// Created by Bram on 23/08/2024.
+//
+
+#ifndef GLOOM_TEXTURE_H
+#define GLOOM_TEXTURE_H
+
+
+#include
+
+class Texture {
+public:
+ Texture(const std::string& filename);
+
+ void bind(unsigned int slot = 0) const;
+ void unbind() const;
+
+ unsigned int getTexture() const { return m_texture; }
+private:
+ unsigned int m_texture{ 0 };
+};
+
+
+#endif //GLOOM_TEXTURE_H
diff --git a/gloom/src/gloom/TextureManager.cpp b/gloom/src/gloom/TextureManager.cpp
new file mode 100644
index 0000000..5d9c7a5
--- /dev/null
+++ b/gloom/src/gloom/TextureManager.cpp
@@ -0,0 +1,12 @@
+//
+// Created by Bram on 25/08/2024.
+//
+
+#include "TextureManager.h"
+
+Texture * TextureManager::getTexture(const std::string &path) {
+ if (m_textures.find(path) == m_textures.end()) {
+ m_textures[path] = new Texture(path);
+ }
+ return m_textures[path];
+}
diff --git a/gloom/src/gloom/TextureManager.h b/gloom/src/gloom/TextureManager.h
new file mode 100644
index 0000000..308a8f0
--- /dev/null
+++ b/gloom/src/gloom/TextureManager.h
@@ -0,0 +1,27 @@
+//
+// Created by Bram on 25/08/2024.
+//
+
+#ifndef GLOOM_TEXTUREMANAGER_H
+#define GLOOM_TEXTUREMANAGER_H
+
+
+#include
+#include "Singleton.h"
+#include "Texture.h"
+#include
+
+class TextureManager: public Singleton{
+public:
+ TextureManager() = default;
+ ~TextureManager() override = default;
+
+ Texture * getTexture(const std::string& path);
+
+private:
+ std::unordered_map m_textures;
+
+};
+
+
+#endif //GLOOM_TEXTUREMANAGER_H
diff --git a/gloom/src/gloom/camera.hpp b/gloom/src/gloom/camera.hpp
deleted file mode 100644
index bbfe338..0000000
--- a/gloom/src/gloom/camera.hpp
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef CAMERA_HPP
-#define CAMERA_HPP
-#pragma once
-
-// System headers
-#include
-#include
-#include
-#include
-#include
-
-
-namespace Gloom
-{
- class Camera
- {
- public:
- Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 2.0f),
- GLfloat movementSpeed = 5.0f,
- GLfloat mouseSensitivity = 0.005f)
- {
- cPosition = position;
- cMovementSpeed = movementSpeed;
- cMouseSensitivity = mouseSensitivity;
-
- // Set up the initial view matrix
- updateViewMatrix();
- }
-
- // Public member functions
-
- /* Getter for the view matrix */
- glm::mat4 getViewMatrix() { return matView; }
-
-
- /* Handle keyboard inputs from a callback mechanism */
- void handleKeyboardInputs(int key, int action)
- {
- // Keep track of pressed/released buttons
- if (key >= 0 && key < 512)
- {
- if (action == GLFW_PRESS)
- {
- keysInUse[key] = true;
- }
- else if (action == GLFW_RELEASE)
- {
- keysInUse[key] = false;
- }
- }
- }
-
-
- /* Handle mouse button inputs from a callback mechanism */
- void handleMouseButtonInputs(int button, int action)
- {
- // Ensure that the camera only rotates when the left mouse button is
- // pressed
- if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
- {
- isMousePressed = true;
- }
- else
- {
- isMousePressed = false;
- resetMouse = true;
- }
- }
-
-
- /* Handle cursor position from a callback mechanism */
- void handleCursorPosInput(double xpos, double ypos)
- {
- // Do nothing if the left mouse button is not pressed
- if (isMousePressed == false)
- return;
-
- // There should be no movement when the mouse button is released
- if (resetMouse)
- {
- lastXPos = xpos;
- lastYPos = ypos;
- resetMouse = false;
- }
-
- // Keep track of pitch and yaw for the current frame
- fYaw = xpos - lastXPos;
- fPitch = ypos - lastYPos;
-
- // Update last known cursor position
- lastXPos = xpos;
- lastYPos = ypos;
- }
-
-
- /* Update the camera position and view matrix
- `deltaTime` is the time between the current and last frame */
- void updateCamera(GLfloat deltaTime)
- {
- // Extract movement information from the view matrix
- glm::vec3 dirX(matView[0][0], matView[1][0], matView[2][0]);
- glm::vec3 dirY(matView[0][1], matView[1][1], matView[2][1]);
- glm::vec3 dirZ(matView[0][2], matView[1][2], matView[2][2]);
-
- // Alter position in the appropriate direction
- glm::vec3 fMovement(0.0f, 0.0f, 0.0f);
-
- if (keysInUse[GLFW_KEY_W]) // forward
- fMovement -= dirZ;
-
- if (keysInUse[GLFW_KEY_S]) // backward
- fMovement += dirZ;
-
- if (keysInUse[GLFW_KEY_A]) // left
- fMovement -= dirX;
-
- if (keysInUse[GLFW_KEY_D]) // right
- fMovement += dirX;
-
- if (keysInUse[GLFW_KEY_E]) // vertical up
- fMovement += dirY;
-
- if (keysInUse[GLFW_KEY_Q]) // vertical down
- fMovement -= dirY;
-
- // Trick to balance PC speed with movement
- GLfloat velocity = cMovementSpeed * deltaTime;
-
- // Update camera position using the appropriate velocity
- cPosition += fMovement * velocity;
-
- // Update the view matrix based on the new information
- updateViewMatrix();
- }
-
- private:
- // Disable copying and assignment
- Camera(Camera const &) = delete;
- Camera & operator =(Camera const &) = delete;
-
- // Private member function
-
- /* Update the view matrix based on the current information */
- void updateViewMatrix()
- {
- // Adjust cursor movement using the specified sensitivity
- fPitch *= cMouseSensitivity;
- fYaw *= cMouseSensitivity;
-
- // Create quaternions given the current pitch and yaw
- glm::quat qPitch = glm::quat(glm::vec3(fPitch, 0.0f, 0.0f));
- glm::quat qYaw = glm::quat(glm::vec3(0.0f, fYaw, 0.0f));
-
- // Reset pitch and yaw values for the current rotation
- fPitch = 0.0f;
- fYaw = 0.0f;
-
- // Update camera quaternion and normalise
- cQuaternion = qYaw * qPitch * cQuaternion;
- cQuaternion = glm::normalize(cQuaternion);
-
- // Build rotation matrix using the camera quaternion
- glm::mat4 matRotation = glm::mat4_cast(cQuaternion);
-
- // Build translation matrix
- glm::mat4 matTranslate = glm::translate(glm::mat4(1.0f), -cPosition);
-
- // Update view matrix
- matView = matRotation * matTranslate;
- }
-
- // Private member variables
-
- // Camera quaternion and frame pitch and yaw
- glm::quat cQuaternion;
- GLfloat fPitch = 0.0f;
- GLfloat fYaw = 0.0f;
-
- // Camera position
- glm::vec3 cPosition;
-
- // Variables used for bookkeeping
- GLboolean resetMouse = true;
- GLboolean isMousePressed = false;
- GLboolean keysInUse[512];
-
- // Last cursor position
- GLfloat lastXPos = 0.0f;
- GLfloat lastYPos = 0.0f;
-
- // Camera settings
- GLfloat cMovementSpeed;
- GLfloat cMouseSensitivity;
-
- // View matrix
- glm::mat4 matView;
- };
-}
-
-#endif
diff --git a/gloom/src/gloom/config.hpp b/gloom/src/gloom/config.hpp
new file mode 100644
index 0000000..5907b15
--- /dev/null
+++ b/gloom/src/gloom/config.hpp
@@ -0,0 +1,45 @@
+// Preprocessor directives
+#ifndef GLOOM_HPP
+#define GLOOM_HPP
+#pragma once
+
+// System Headers
+#include
+
+// Standard headers
+#include
+#include "PerlinNoise.hpp"
+
+// Constants
+const int windowWidth = 1200;
+const int windowHeight = 900;
+const std::string windowTitle = "OpenGL";
+const GLint windowResizable = GL_FALSE;
+const int windowSamples = 4;
+
+const int MAX_FPS = 60;
+
+static bool renderWireframe = false;
+
+static const int CHUNK_SIZE = 16;
+static const int CHUNK_HEIGHT = 256;
+
+static const int TEXTURE_WIDTH = 16;
+static const int TEXTURE_HEIGHT = 16;
+
+static const int ATLAS_WIDTH = 128;
+static const int ATLAS_HEIGHT = 128;
+
+static const double CELL_WIDTH = 1.0 / ATLAS_WIDTH * TEXTURE_WIDTH;
+static const double CELL_HEIGHT = 1.0 / ATLAS_HEIGHT * TEXTURE_HEIGHT;
+
+static const int RENDER_DISTANCE = 10;
+
+static const int WORLD_WIDTH = 128;
+static const int WORLD_HEIGHT = 128;
+
+static int SEED = 1234u;
+
+static siv::PerlinNoise perlin{ static_cast(SEED) };
+
+#endif
diff --git a/gloom/src/gloom/gloom.hpp b/gloom/src/gloom/gloom.hpp
deleted file mode 100644
index a2eccbf..0000000
--- a/gloom/src/gloom/gloom.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Preprocessor directives
-#ifndef GLOOM_HPP
-#define GLOOM_HPP
-#pragma once
-
-// System Headers
-#include
-
-// Standard headers
-#include
-
-// Constants
-const int windowWidth = 1024;
-const int windowHeight = 768;
-const std::string windowTitle = "OpenGL";
-const GLint windowResizable = GL_FALSE;
-const int windowSamples = 4;
-
-#endif
diff --git a/gloom/src/gloom/old/Cube.cpp b/gloom/src/gloom/old/Cube.cpp
new file mode 100644
index 0000000..36195d0
--- /dev/null
+++ b/gloom/src/gloom/old/Cube.cpp
@@ -0,0 +1,175 @@
+////
+//// Created by Bram on 23/08/2024.
+////
+//
+//#include "Cube.h"
+//
+//glm::vec3 unitVertices[8] = {
+// glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f),
+// glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
+// glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(1.0f, 0.0f, 1.0f),
+// glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f)
+//};
+//
+//unsigned int faceVertices[6][6] = {
+// // TOP (3, 2, 6, 3, 6, 7)
+// {3, 2, 6, 3, 6, 7},
+// // BOTTOM (1, 0, 4, 1, 4, 5)
+// {1, 0, 4, 1, 4, 5},
+// // LEFT (0, 3, 7, 0, 7, 4)
+// {0, 3, 7, 0, 7, 4},
+// // RIGHT (2, 1, 5, 2, 5, 6)
+// {2, 1, 5, 2, 5, 6},
+// // FRONT (0, 1, 2, 0, 2, 3)
+// {0, 1, 2, 0, 2, 3},
+// // BACK (5, 4, 7, 5, 7, 6)
+// {5, 4, 7, 5, 7, 6}
+//};
+//
+//
+//void Cube::Draw(GLuint shaderProgram) {
+// // Use the shader program
+// glUseProgram(shaderProgram);
+//
+// // Transform the cube
+// glm::mat4 model = glm::translate(glm::mat4(1.0f), position);
+// GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
+// glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+//
+// if(renderWireframe) {
+// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+// } else {
+// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+// }
+//
+// // Draw the cube
+// texture.bind(0);
+// glBindVertexArray(VAO);
+// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+// glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
+// glBindVertexArray(0);
+//
+//}
+//
+//void Cube::setupCube() {
+//
+//
+//
+//
+// std::array cubeVertices = {
+// // Front face (z = 1.0f)
+// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
+//
+// // Back face (z = -1.0f)
+// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f)), // Top-left
+//
+// // Left face (x = -1.0f)
+// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
+//
+// // Right face (x = 1.0f)
+// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec2(0.0f, 1.0f)), // Top-left
+//
+// // Bottom face (y = -1.0f)
+// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
+//
+// // Top face (y = 1.0f)
+// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
+// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
+// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
+// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec2(0.0f, 1.0f)) // Top-left
+// };
+//
+// glGenVertexArrays(1, &VAO);
+// glGenBuffers(1, &VBO);
+// glGenBuffers(1, &EBO);
+//
+// glBindVertexArray(VAO);
+// glBindBuffer(GL_ARRAY_BUFFER, VBO);
+// glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices.data(), GL_STATIC_DRAW);
+//
+//
+// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
+// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices.data(), GL_STATIC_DRAW);
+//
+//
+// // Position attribute
+// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, position));
+// glEnableVertexAttribArray(0);
+//
+// // Color attribute
+// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, color));
+// glEnableVertexAttribArray(1);
+//
+// // Texture Coords
+// glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, texCoords));
+// glEnableVertexAttribArray(2);
+//
+// glBindBuffer(GL_ARRAY_BUFFER, 0);
+// glBindVertexArray(0);
+//}
+//
+//Cube::Cube(const glm::vec3 &position, BlockType blockType): position(position), texture("assets/dirt.png"), type(blockType) {
+// setupCube();
+//}
+//
+//void Cube::LoadFace(Face face, std::vector &vertices) {
+//
+// glm::vec3 normal;
+// switch (face) {
+// case Face::TOP:
+// normal = glm::vec3(0.0f, 1.0f, 0.0f);
+// break;
+// case Face::BOTTOM:
+// normal = glm::vec3(0.0f, -1.0f, 0.0f);
+// break;
+// case Face::LEFT:
+// normal = glm::vec3(-1.0f, 0.0f, 0.0f);
+// break;
+// case Face::RIGHT:
+// normal = glm::vec3(1.0f, 0.0f, 0.0f);
+// break;
+// case Face::FRONT:
+// normal = glm::vec3(0.0f, 0.0f, 1.0f);
+// break;
+// case Face::BACK:
+// normal = glm::vec3(0.0f, 0.0f, -1.0f);
+// break;
+// }
+//
+// glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f);
+// glm::vec2 texCoords = glm::vec2(0.0f, 0.0f);
+//
+// for (int i = 0; i < 6; i++) {
+// CubeVertex vertex = {
+// unitVertices[faceVertices[face][i]],
+// color,
+// texCoords
+// };
+// vertices.push_back(vertex);
+// }
+//
+//}
+//
+//void Cube::LoadAllFaces(std::vector &vertices) {
+// LoadFace(Face::TOP, vertices);
+// LoadFace(Face::BOTTOM, vertices);
+// LoadFace(Face::LEFT, vertices);
+// LoadFace(Face::RIGHT, vertices);
+// LoadFace(Face::FRONT, vertices);
+// LoadFace(Face::BACK, vertices);
+//}
diff --git a/gloom/src/gloom/old/Cube.h b/gloom/src/gloom/old/Cube.h
new file mode 100644
index 0000000..66eb62f
--- /dev/null
+++ b/gloom/src/gloom/old/Cube.h
@@ -0,0 +1,89 @@
+////
+//// Created by Bram on 23/08/2024.
+////
+//
+//#ifndef GLOOM_CUBE_H
+//#define GLOOM_CUBE_H
+//
+//
+//#include
+//#include
+//#include
+//#include
+//#include
+//#include
+//#include "glad/glad.h"
+//#include "gloom/Texture.h"
+//#include "gloom/config.hpp"
+//#include "Chunk.h"
+//#include "gloom/Mesh.h"
+//
+//struct CubeVertex {
+// CubeVertex(glm::vec3 pos, glm::vec3 color, glm::vec2 texCoords) : position(pos), color(color),
+// texCoords(texCoords) {};
+//
+// glm::vec3 position;
+// glm::vec3 color;
+// glm::vec2 texCoords;
+//};
+//
+//struct CubeFace {
+//};
+//
+//static std::array cubeIndices = {
+// // Front face
+// 0, 1, 2, // First triangle (0, 1, 2)
+// 0, 2, 3, // Second triangle (0, 2, 3)
+//
+// // Back face
+// 4, 5, 6, // First triangle (4, 5, 6)
+// 4, 6, 7, // Second triangle (4, 6, 7)
+//
+// // Left face
+// 8, 9, 10, // First triangle (8, 9, 10)
+// 8, 10, 11,// Second triangle (8, 10, 11)
+//
+// // Right face
+// 12, 13, 14,// First triangle (12, 13, 14)
+// 12, 14, 15,// Second triangle (12, 14, 15)
+//
+// // Bottom face
+// 16, 17, 18,// First triangle (16, 17, 18)
+// 16, 18, 19,// Second triangle (16, 18, 19)
+//
+// // Top face
+// 20, 21, 22,// First triangle (20, 21, 22)
+// 20, 22, 23 // Second triangle (20, 22, 23)
+//};
+//
+//enum Face {
+// TOP = 0x01, // 0000 0001
+// BOTTOM = 0x02, // 0000 0010
+// LEFT = 0x04, // 0000 0100
+// RIGHT = 0x08, // 0000 1000
+// FRONT = 0x10, // 0001 0000
+// BACK = 0x20 // 0010 0000
+//};
+//
+//
+//class Cube {
+//public:
+// explicit Cube(const glm::vec3 &position, BlockType blockType);
+//
+// void Draw(GLuint shaderProgram);
+//
+// void LoadFace(Face face, std::vector& vertices);
+// void LoadAllFaces(std::vector& vertices);
+//
+// Mesh mesh;
+//private:
+// GLuint VAO{}, VBO{}, EBO{};
+// glm::vec3 position;
+//
+// Texture texture;
+// BlockType type{ BlockType::AIR };
+// void setupCube();
+//};
+//
+//
+//#endif //GLOOM_CUBE_H
diff --git a/gloom/src/gloom/shader.hpp b/gloom/src/gloom/shader.hpp
deleted file mode 100644
index bd722be..0000000
--- a/gloom/src/gloom/shader.hpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef SHADER_HPP
-#define SHADER_HPP
-#pragma once
-
-// System headers
-#include
-
-// Standard headers
-#include
-#include
-#include
-#include
-
-
-namespace Gloom
-{
- class Shader
- {
- public:
- Shader() { mProgram = glCreateProgram(); }
-
- // Public member functions
- void activate() { glUseProgram(mProgram); }
- void deactivate() { glUseProgram(0); }
- GLuint get() { return mProgram; }
- void destroy() { glDeleteProgram(mProgram); }
-
- /* Attach a shader to the current shader program */
- void attach(std::string const &filename)
- {
- // Load GLSL Shader from source
- std::ifstream fd(filename.c_str());
- if (fd.fail())
- {
- fprintf(stderr,
- "Something went wrong when attaching the Shader file at \"%s\".\n"
- "The file may not exist or is currently inaccessible.\n",
- filename.c_str());
- return;
- }
- auto src = std::string(std::istreambuf_iterator(fd),
- (std::istreambuf_iterator()));
-
- // Create shader object
- const char * source = src.c_str();
- auto shader = create(filename);
- glShaderSource(shader, 1, &source, nullptr);
- glCompileShader(shader);
-
- // Display errors
- glGetShaderiv(shader, GL_COMPILE_STATUS, &mStatus);
- if (!mStatus)
- {
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &mLength);
- std::unique_ptr buffer(new char[mLength]);
- glGetShaderInfoLog(shader, mLength, nullptr, buffer.get());
- fprintf(stderr, "%s\n%s", filename.c_str(), buffer.get());
- }
-
- assert(mStatus);
-
- // Attach shader and free allocated memory
- glAttachShader(mProgram, shader);
- glDeleteShader(shader);
- }
-
-
- /* Links all attached shaders together into a shader program */
- void link()
- {
- // Link all attached shaders
- glLinkProgram(mProgram);
-
- // Display errors
- glGetProgramiv(mProgram, GL_LINK_STATUS, &mStatus);
- if (!mStatus)
- {
- glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &mLength);
- std::unique_ptr buffer(new char[mLength]);
- glGetProgramInfoLog(mProgram, mLength, nullptr, buffer.get());
- fprintf(stderr, "%s\n", buffer.get());
- }
-
- assert(mStatus);
- }
-
-
- /* Convenience function that attaches and links a vertex and a
- fragment shader in a shader program */
- void makeBasicShader(std::string const &vertexFilename,
- std::string const &fragmentFilename)
- {
- attach(vertexFilename);
- attach(fragmentFilename);
- link();
- }
-
-
- /* Used for debugging shader programs (expensive to run) */
- bool isValid()
- {
- // Validate linked shader program
- glValidateProgram(mProgram);
-
- // Display errors
- glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &mStatus);
- if (!mStatus)
- {
- glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &mLength);
- std::unique_ptr buffer(new char[mLength]);
- glGetProgramInfoLog(mProgram, mLength, nullptr, buffer.get());
- fprintf(stderr, "%s\n", buffer.get());
- return false;
- }
- return true;
- }
-
-
- /* Helper function for creating shaders */
- GLuint create(std::string const &filename)
- {
- // Extract file extension and create the correct shader type
- auto idx = filename.rfind(".");
- auto ext = filename.substr(idx + 1);
- if (ext == "comp") return glCreateShader(GL_COMPUTE_SHADER);
- else if (ext == "frag") return glCreateShader(GL_FRAGMENT_SHADER);
- else if (ext == "geom") return glCreateShader(GL_GEOMETRY_SHADER);
- else if (ext == "tcs") return glCreateShader(GL_TESS_CONTROL_SHADER);
- else if (ext == "tes") return glCreateShader(GL_TESS_EVALUATION_SHADER);
- else if (ext == "vert") return glCreateShader(GL_VERTEX_SHADER);
- else return false;
- }
-
- private:
- // Disable copying and assignment
- Shader(Shader const &) = delete;
- Shader & operator =(Shader const &) = delete;
-
- // Private member variables
- GLuint mProgram;
- GLint mStatus;
- GLint mLength;
- };
-}
-
-#endif
diff --git a/gloom/src/main.cpp b/gloom/src/main.cpp
index 2ee46a2..2291047 100644
--- a/gloom/src/main.cpp
+++ b/gloom/src/main.cpp
@@ -1,82 +1,19 @@
// Local headers
-#include "gloom/gloom.hpp"
-#include "program.hpp"
-
-// System headers
-#include
-#include
+#include "gloom/config.hpp"
+#include "Game.h"
// Standard headers
#include
-// A callback which allows GLFW to report errors whenever they occur
-static void glfwErrorCallback(int error, const char *description)
-{
- fprintf(stderr, "GLFW returned an error:\n\t%s (%i)\n", description, error);
-}
-GLFWwindow* initialise()
-{
- // Initialise GLFW
- if (!glfwInit())
- {
- fprintf(stderr, "Could not start GLFW\n");
- exit(EXIT_FAILURE);
- }
- // Set core window options (adjust version numbers if needed)
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
- // Enable the GLFW runtime error callback function defined previously.
- glfwSetErrorCallback(glfwErrorCallback);
-
- // Set additional window options
- glfwWindowHint(GLFW_RESIZABLE, windowResizable);
- glfwWindowHint(GLFW_SAMPLES, windowSamples); // MSAA
-
- // Create window using GLFW
- GLFWwindow* window = glfwCreateWindow(windowWidth,
- windowHeight,
- windowTitle.c_str(),
- nullptr,
- nullptr);
-
- // Ensure the window is set up correctly
- if (!window)
- {
- fprintf(stderr, "Could not open GLFW window\n");
- glfwTerminate();
- exit(EXIT_FAILURE);
- }
-
- // Let the window be the current OpenGL context and initialise glad
- glfwMakeContextCurrent(window);
- gladLoadGL();
-
- // Print various OpenGL information to stdout
- printf("%s: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
- printf("GLFW\t %s\n", glfwGetVersionString());
- printf("OpenGL\t %s\n", glGetString(GL_VERSION));
- printf("GLSL\t %s\n\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
-
- return window;
-}
-
-
-int main(int argc, char* argb[])
-{
- // Initialise window using GLFW
- GLFWwindow* window = initialise();
-
- // Run an OpenGL application using this window
- runProgram(window);
-
- // Terminate GLFW (no need to call glfwDestroyWindow)
- glfwTerminate();
+int main(int argc, char *argb[]) {
+ srand(time(nullptr));
+ std::cout << "Seed: " << SEED << std::endl;
+ Game game;
+ game.run();
return EXIT_SUCCESS;
}
diff --git a/gloom/src/program.cpp b/gloom/src/program.cpp
deleted file mode 100644
index e1e6d02..0000000
--- a/gloom/src/program.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Local headers
-#include "program.hpp"
-#include "gloom/gloom.hpp"
-
-
-void runProgram(GLFWwindow* window)
-{
- // Enable depth (Z) buffer (accept "closest" fragment)
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
-
- // Configure miscellaneous OpenGL settings
- glEnable(GL_CULL_FACE);
-
- // Set default colour after clearing the colour buffer
- glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
-
- // Set up your scene here (create Vertex Array Objects, etc.)
-
- // Rendering Loop
- while (!glfwWindowShouldClose(window))
- {
- // Clear colour and depth buffers
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- // Draw your scene here
-
- // Handle other events
- glfwPollEvents();
- handleKeyboardInput(window);
-
- // Flip buffers
- glfwSwapBuffers(window);
- }
-}
-
-
-void handleKeyboardInput(GLFWwindow* window)
-{
- // Use escape key for terminating the GLFW window
- if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
- {
- glfwSetWindowShouldClose(window, GL_TRUE);
- }
-}
diff --git a/gloom/src/program.hpp b/gloom/src/program.hpp
deleted file mode 100644
index e38b73b..0000000
--- a/gloom/src/program.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef PROGRAM_HPP
-#define PROGRAM_HPP
-#pragma once
-
-
-// System headers
-#include
-#include
-#include
-
-
-// Main OpenGL program
-void runProgram(GLFWwindow* window);
-
-
-// Function for handling keypresses
-void handleKeyboardInput(GLFWwindow* window);
-
-
-// Checks for whether an OpenGL error occurred. If one did,
-// it prints out the error type and ID
-inline void printGLError() {
- int errorID = glGetError();
-
- if(errorID != GL_NO_ERROR) {
- std::string errorString;
-
- switch(errorID) {
- case GL_INVALID_ENUM:
- errorString = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_OPERATION:
- errorString = "GL_INVALID_OPERATION";
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- errorString = "GL_INVALID_FRAMEBUFFER_OPERATION";
- break;
- case GL_OUT_OF_MEMORY:
- errorString = "GL_OUT_OF_MEMORY";
- break;
- case GL_STACK_UNDERFLOW:
- errorString = "GL_STACK_UNDERFLOW";
- break;
- case GL_STACK_OVERFLOW:
- errorString = "GL_STACK_OVERFLOW";
- break;
- default:
- errorString = "[Unknown error ID]";
- break;
- }
-
- fprintf(stderr, "An OpenGL error occurred (%i): %s.\n",
- errorID, errorString.c_str());
- }
-}
-
-
-#endif