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;