From 7add5e6dcbe352144e122f799faa570e7b167e26 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 13:18:47 +0300 Subject: [PATCH 1/7] Added AABB struct --- src/maths/aabb.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/maths/aabb.h diff --git a/src/maths/aabb.h b/src/maths/aabb.h new file mode 100644 index 00000000..097e772f --- /dev/null +++ b/src/maths/aabb.h @@ -0,0 +1,31 @@ +#ifndef MATHS_AABB_H_ +#define MATHS_AABB_H_ + +#include + +// Axis Aligned Bounding Box +struct AABB { + glm::vec3 a; + glm::vec3 b; + + inline glm::vec3 min() const { + return glm::min(a, b); + } + + inline glm::vec3 size() const { + return glm::vec3( + fabs(b.x - a.x), + fabs(b.y - a.y), + fabs(b.z - a.z) + ); + } + + inline bool inside(const glm::vec3 pos) const { + const glm::vec3 p = min(); + const glm::vec3 s = size(); + return !(pos.x < p.x || pos.y < p.y || + pos.x >= p.x+s.x || pos.y >= p.y+s.y); + } +}; + +#endif // MATHS_AABB_H_ \ No newline at end of file From f3889421d833991b11d26957388b58cb8cea7293 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 13:21:31 +0300 Subject: [PATCH 2/7] AABB.inside fix --- src/maths/aabb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/maths/aabb.h b/src/maths/aabb.h index 097e772f..c0e1a501 100644 --- a/src/maths/aabb.h +++ b/src/maths/aabb.h @@ -23,8 +23,8 @@ struct AABB { inline bool inside(const glm::vec3 pos) const { const glm::vec3 p = min(); const glm::vec3 s = size(); - return !(pos.x < p.x || pos.y < p.y || - pos.x >= p.x+s.x || pos.y >= p.y+s.y); + return !(pos.x < p.x || pos.y < p.y || pos.z < p.z || + pos.x >= p.x+s.x || pos.y >= p.y+s.y || pos.z >= p.z+s.z); } }; From cad1f6a669eb5fe2a2717db2d4fa3f0721bb27d8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 13:29:28 +0300 Subject: [PATCH 3/7] temporary fixed grass hitbox --- src/definitions.cpp | 2 +- src/frontend/world_render.cpp | 10 +++----- src/voxels/Chunks.cpp | 43 +++++++++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/definitions.cpp b/src/definitions.cpp index 6378d523..44540b3d 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -71,7 +71,7 @@ void setup_definitions(ContentBuilder* builder) { block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; - block->hitboxScale = 0.5f; + block->hitboxScale = 0.7f; builder->add(block); block = new Block("base:flower", "flower"); diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index 42c4a804..94e8bded 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -168,13 +168,9 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) linesShader->use(); linesShader->uniformMatrix("u_projview", camera->getProjView()); lineBatch->lineWidth(2.0f); - if (block->model == BlockModel::block){ - lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, - 1.008f,1.008f,1.008f, 0,0,0,0.5f); - } else if (block->model == BlockModel::xsprite){ - lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, - 0.805f,0.705f,0.805f, 0,0,0,0.5f); - } + float size = block->hitboxScale; + lineBatch->box(pos.x+0.5f, pos.y+size*0.5f, pos.z+0.5f, + size, size, size, 0, 0, 0, 0.5f); lineBatch->render(); } skybox->unbind(); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index c8a7d6d0..1b2ef382 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -200,20 +200,45 @@ voxel* Chunks::rayCast(vec3 start, while (t <= maxDist){ voxel* voxel = get(ix, iy, iz); - if (voxel == nullptr || contentIds->getBlockDef(voxel->id)->selectable){ + const Block* def = nullptr; + if (voxel == nullptr || (def = contentIds->getBlockDef(voxel->id))->selectable){ end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; + + // TODO: replace this dumb solution with something better + if (def && def->hitboxScale < 1.0f) { + const float sz = def->hitboxScale; + const int subs = 16; + for (int i = 0; i < subs; i++) { + end.x += dx / float(subs); + end.y += dy / float(subs); + end.z += dz / float(subs); + if (end.x - ix >= 0.5f - sz * 0.5f && end.x - ix <= 0.5f + sz * 0.5f && + end.y - iy >= 0.0f && end.y - iy <= sz && + end.z - iz >= 0.5f - sz * 0.5f && end.z - iz <= 0.5f + sz * 0.5f) { + iend.x = ix; + iend.y = iy; + iend.z = iz; - iend.x = ix; - iend.y = iy; - iend.z = iz; + norm.x = norm.y = norm.z = 0.0f; + if (steppedIndex == 0) norm.x = -stepx; + if (steppedIndex == 1) norm.y = -stepy; + if (steppedIndex == 2) norm.z = -stepz; + return voxel; + } + } + } else { + iend.x = ix; + iend.y = iy; + iend.z = iz; - norm.x = norm.y = norm.z = 0.0f; - if (steppedIndex == 0) norm.x = -stepx; - if (steppedIndex == 1) norm.y = -stepy; - if (steppedIndex == 2) norm.z = -stepz; - return voxel; + norm.x = norm.y = norm.z = 0.0f; + if (steppedIndex == 0) norm.x = -stepx; + if (steppedIndex == 1) norm.y = -stepy; + if (steppedIndex == 2) norm.z = -stepz; + return voxel; + } } if (txMax < tyMax) { if (txMax < tzMax) { From 91a6426efe93213c900b6abcba6f2178117414b9 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 16:36:00 +0300 Subject: [PATCH 4/7] AABB block hitboxes --- src/content/Content.cpp | 20 ++++++++++++++++++++ src/definitions.cpp | 7 ++++++- src/frontend/world_render.cpp | 9 ++++++--- src/graphics/LineBatch.h | 6 ++++++ src/maths/aabb.h | 32 ++++++++++++++++++++++++++++++-- src/voxels/Block.h | 12 +++++++++++- src/voxels/Chunks.cpp | 17 +++++++---------- 7 files changed, 86 insertions(+), 17 deletions(-) diff --git a/src/content/Content.cpp b/src/content/Content.cpp index 0a1f88bc..4b61b9e0 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -1,9 +1,11 @@ #include "Content.h" #include +#include #include "../voxels/Block.h" +using glm::vec3; using std::vector; using std::string; using std::unordered_map; @@ -21,6 +23,24 @@ Content* ContentBuilder::build() { for (const string& name : blockIds) { Block* def = blockDefs[name]; def->id = blockDefsIndices.size(); + def->rt.emissive = *((uint32_t*)def->emission); + + // build hitbox grid 3d for raycasts + const AABB& hitbox = def->hitbox; + for (uint gy = 0; gy < BLOCK_AABB_GRID; gy++) { + for (uint gz = 0; gz < BLOCK_AABB_GRID; gz++) { + for (uint gx = 0; gx < BLOCK_AABB_GRID; gx++) { + float x = gx / float(BLOCK_AABB_GRID); + float y = gy / float(BLOCK_AABB_GRID); + float z = gz / float(BLOCK_AABB_GRID); + bool flag = hitbox.inside({x, y, z}); + if (!flag) + def->rt.solid = false; + def->rt.hitboxGrid[gy][gz][gx] = flag; + } + } + } + blockDefsIndices.push_back(def); } ContentIndices* indices = new ContentIndices(blockDefsIndices); diff --git a/src/definitions.cpp b/src/definitions.cpp index 44540b3d..7deec6dc 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -1,11 +1,15 @@ #include "definitions.h" +#include + #include "content/Content.h" #include "window/Window.h" #include "window/Events.h" #include "window/input.h" #include "voxels/Block.h" +using glm::vec3; + // All in-game definitions (blocks, items, etc..) void setup_definitions(ContentBuilder* builder) { Block* block = new Block("core:air", "air"); @@ -71,7 +75,7 @@ void setup_definitions(ContentBuilder* builder) { block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; - block->hitboxScale = 0.7f; + block->hitbox.scale(vec3(0.7f), vec3(0.5f, 0.0f, 0.5f)); builder->add(block); block = new Block("base:flower", "flower"); @@ -79,6 +83,7 @@ void setup_definitions(ContentBuilder* builder) { block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; + block->hitbox.scale(vec3(0.7f)); builder->add(block); block = new Block("base:brick", "brick"); diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index 94e8bded..7a802677 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -31,6 +31,7 @@ #include "graphics/Skybox.h" using glm::vec3; +using glm::vec4; using std::string; using std::shared_ptr; @@ -168,9 +169,11 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) linesShader->use(); linesShader->uniformMatrix("u_projview", camera->getProjView()); lineBatch->lineWidth(2.0f); - float size = block->hitboxScale; - lineBatch->box(pos.x+0.5f, pos.y+size*0.5f, pos.z+0.5f, - size, size, size, 0, 0, 0, 0.5f); + + const AABB& hitbox = block->hitbox; + const vec3 center = pos + hitbox.center(); + const vec3 size = hitbox.size(); + lineBatch->box(center, size, vec4(0.0f, 0.0f, 0.0f, 0.5f)); lineBatch->render(); } skybox->unbind(); diff --git a/src/graphics/LineBatch.h b/src/graphics/LineBatch.h index 58d7de3a..8e37cf61 100644 --- a/src/graphics/LineBatch.h +++ b/src/graphics/LineBatch.h @@ -2,6 +2,7 @@ #define GRAPHICS_LINEBATCH_H_ #include +#include class Mesh; @@ -19,6 +20,11 @@ public: void box(float x, float y, float z, float w, float h, float d, float r, float g, float b, float a); + inline void box(glm::vec3 xyz, glm::vec3 whd, glm::vec4 rgba) { + return box(xyz.x, xyz.y, xyz.z, whd.x, whd.y, whd.z, + rgba.r, rgba.g, rgba.b, rgba.a); + } + void render(); void lineWidth(float width); }; diff --git a/src/maths/aabb.h b/src/maths/aabb.h index c0e1a501..7f790b59 100644 --- a/src/maths/aabb.h +++ b/src/maths/aabb.h @@ -5,13 +5,20 @@ // Axis Aligned Bounding Box struct AABB { - glm::vec3 a; - glm::vec3 b; + glm::vec3 a {0.0f}; + glm::vec3 b {1.0f}; + /* Get AABB point with minimal x,y,z */ inline glm::vec3 min() const { return glm::min(a, b); } + /* Get AABB point with minimal x,y,z */ + inline glm::vec3 max() const { + return glm::max(a, b); + } + + /* Get AABB dimensions: width, height, depth */ inline glm::vec3 size() const { return glm::vec3( fabs(b.x - a.x), @@ -20,6 +27,27 @@ struct AABB { ); } + inline glm::vec3 center() const { + return (a + b) * 0.5f; + } + + /* Multiply AABB size from center */ + inline void scale(const glm::vec3 mul) { + glm::vec3 center = (a + b) * 0.5f; + a = (a - center) * mul + center; + b = (b - center) * mul + center; + } + + /* Multiply AABB size from given origin */ + inline void scale(const glm::vec3 mul, const glm::vec3 orig) { + glm::vec3 beg = min(); + glm::vec3 end = max(); + glm::vec3 center = glm::mix(beg, end, orig); + a = (a - center) * mul + center; + b = (b - center) * mul + center; + } + + /* Check if given point is inside */ inline bool inside(const glm::vec3 pos) const { const glm::vec3 p = min(); const glm::vec3 s = size(); diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 42505f8c..1b1b1e39 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -3,6 +3,8 @@ #include +#include "../maths/aabb.h" + #define FACE_MX 0 #define FACE_PX 1 #define FACE_MY 2 @@ -10,6 +12,8 @@ #define FACE_MZ 4 #define FACE_PZ 5 +#define BLOCK_AABB_GRID 16 + enum class BlockModel { none, block, xsprite }; @@ -29,7 +33,13 @@ public: bool selectable = true; bool breakable = true; bool rotatable = false; - float hitboxScale = 1; + AABB hitbox; + + struct { + bool solid = true; + bool emissive = false; + bool hitboxGrid[BLOCK_AABB_GRID][BLOCK_AABB_GRID][BLOCK_AABB_GRID]; + } rt; Block(std::string name, std::string texture); }; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 1b2ef382..f88a887d 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -159,6 +159,7 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){ chunk->setModified(true); } +#include voxel* Chunks::rayCast(vec3 start, vec3 dir, float maxDist, @@ -207,20 +208,16 @@ voxel* Chunks::rayCast(vec3 start, end.z = pz + t * dz; // TODO: replace this dumb solution with something better - if (def && def->hitboxScale < 1.0f) { - const float sz = def->hitboxScale; - const int subs = 16; + if (def && !def->rt.solid) { + const AABB& box = def->hitbox; + const int subs = BLOCK_AABB_GRID; + iend = vec3(ix, iy, iz); + end -= iend; for (int i = 0; i < subs; i++) { end.x += dx / float(subs); end.y += dy / float(subs); end.z += dz / float(subs); - if (end.x - ix >= 0.5f - sz * 0.5f && end.x - ix <= 0.5f + sz * 0.5f && - end.y - iy >= 0.0f && end.y - iy <= sz && - end.z - iz >= 0.5f - sz * 0.5f && end.z - iz <= 0.5f + sz * 0.5f) { - iend.x = ix; - iend.y = iy; - iend.z = iz; - + if (box.inside(end)) { norm.x = norm.y = norm.z = 0.0f; if (steppedIndex == 0) norm.x = -stepx; if (steppedIndex == 1) norm.y = -stepy; From 56f055562de14b5802082027afde2e36379b02e1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 16:40:44 +0300 Subject: [PATCH 5/7] removed extra include --- src/voxels/Chunks.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index f88a887d..c53bbb49 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -159,7 +159,6 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){ chunk->setModified(true); } -#include voxel* Chunks::rayCast(vec3 start, vec3 dir, float maxDist, From 1c258828c354fbefebe914c6c8073c88e44e7cf2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 17:57:38 +0300 Subject: [PATCH 6/7] Small engine startup fix --- src/engine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engine.cpp b/src/engine.cpp index db46ccd5..844a0ba5 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -36,7 +36,9 @@ using gui::GUI; Engine::Engine(EngineSettings& settings, EnginePaths* paths, Content* content) : settings(settings), content(content), paths(paths) { - Window::initialize(settings.display); + if (Window::initialize(settings.display)){ + throw initialize_error("could not initialize window"); + } Shader::preprocessor->setLibFolder(paths->getResources()/path("shaders/lib")); assets = new Assets(); From 693ad6d9a75d42677e2bd9c04909fc64d889bd8c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 29 Nov 2023 18:04:14 +0300 Subject: [PATCH 7/7] GLFW_OPENGL_PROFILE set to GLFW_OPENGL_ANY_PROFILE --- src/window/Window.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window/Window.cpp b/src/window/Window.cpp index ad221942..2a68d5a9 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -87,7 +87,8 @@ int Window::initialize(DisplaySettings& settings){ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); + glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); glfwWindowHint(GLFW_SAMPLES, settings.samples);