From 5f551d6888fb64cfac15a80b1a0554467b3208ca Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Sat, 24 Feb 2024 00:21:17 +0300 Subject: [PATCH] Multiple Hitboxes --- src/content/ContentLoader.cpp | 9 +++++++++ src/frontend/WorldRenderer.cpp | 34 ++++++++++++++++++++++------------ src/voxels/Block.h | 1 + src/voxels/Chunks.cpp | 15 ++++++++++----- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 00a325d8..75629b57 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -151,6 +151,15 @@ void ContentLoader::loadBlock(Block& def, std::string name, fs::path file) { aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5)); aabb.b += aabb.a; + def.hitboxExplicit = true; + } else if (def.modelBoxes.empty()) { + def.hitboxExplicit = true; + } else { + def.hitbox = def.modelBoxes[0]; + for (const auto& box : def.modelBoxes) { + def.hitbox.a = glm::min(def.hitbox.a, box.a); + def.hitbox.b = glm::max(def.hitbox.b, box.b); + } } // block light emission [r, g, b] where r,g,b in range [0..15] diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 2e25d6f4..4408c5eb 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -190,20 +190,30 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible const vec3 pos = PlayerController::selectedBlockPosition; const vec3 point = PlayerController::selectedPointPosition; const vec3 norm = PlayerController::selectedBlockNormal; - AABB hitbox = block->hitbox; + + std::vector hitboxes; + if (!block->hitboxExplicit) { + hitboxes = block->modelBoxes; + } else { + hitboxes = { block->hitbox }; + } if (block->rotatable) { - auto states = PlayerController::selectedBlockStates; - block->rotations.variants[states].transform(hitbox); + auto states = PlayerController::selectedBlockStates; + for (auto& hitbox: hitboxes) { + block->rotations.variants[states].transform(hitbox); + } } - const vec3 center = pos + hitbox.center(); - const vec3 size = hitbox.size(); - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjView()); - lineBatch->lineWidth(2.0f); - lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f)); - if (level->player->debug) - lineBatch->line(point, point+norm*0.5f, vec4(1.0f, 0.0f, 1.0f, 1.0f)); + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + for (auto& hitbox: hitboxes) { + const vec3 center = pos + hitbox.center(); + const vec3 size = hitbox.size(); + lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f)); + if (level->player->debug) + lineBatch->line(point, point+norm*0.5f, vec4(1.0f, 0.0f, 1.0f, 1.0f)); + } lineBatch->render(); } skybox->unbind(); @@ -289,4 +299,4 @@ void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) lineBatch->render(); } -float WorldRenderer::fog = 0.0f; \ No newline at end of file +float WorldRenderer::fog = 0.0f; diff --git a/src/voxels/Block.h b/src/voxels/Block.h index e51fc3b4..da2f4d13 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -94,6 +94,7 @@ public: bool grounded = false; bool hidden = false; AABB hitbox; + bool hitboxExplicit = false; BlockRotProfile rotations; std::string pickingItem = name+BLOCK_ITEM_SUFFIX; std::string scriptName = name.substr(name.find(':')+1); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index f29b59a0..fa0b46b1 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -15,6 +15,7 @@ #include #include +#include Chunks::Chunks(int w, int d, int ox, int oz, @@ -52,7 +53,7 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){ int ix = floor(x); int iy = floor(y); int iz = floor(z); - voxel* v = get(ix,iy,iz); + voxel* v = get(ix, iy, iz); if (v == nullptr) return &contentIds->getBlockDef(0)->hitbox; const Block* def = contentIds->getBlockDef(v->id); @@ -62,10 +63,14 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){ : def->hitbox; if (def->rt.solid) { return &hitbox; - } else { - if (hitbox.contains({x - ix, y - iy, z - iz})) - return &hitbox; - return nullptr; + } else if (def->hitboxExplicit) { + if (hitbox.contains({x - ix, y - iy, z - iz})) + return &hitbox; + } else { + for (const auto& hitbox : def->modelBoxes) { + if (hitbox.contains({x - ix, y - iy, z - iz})) + return &hitbox; + } } } return nullptr;