From 5f551d6888fb64cfac15a80b1a0554467b3208ca Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Sat, 24 Feb 2024 00:21:17 +0300 Subject: [PATCH 1/3] 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; From 5c3eafb33167fbca1a145f7b75c92d8c56333724 Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Sat, 24 Feb 2024 00:55:56 +0300 Subject: [PATCH 2/3] Kinda works, but not raycast --- src/content/Content.cpp | 6 ++++++ src/voxels/Block.h | 3 ++- src/voxels/Chunks.cpp | 38 +++++++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/content/Content.cpp b/src/content/Content.cpp index d208af2b..89147004 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -87,6 +87,12 @@ Content* ContentBuilder::build() { AABB aabb = hitbox; def->rotations.variants[i].transform(aabb); def->rt.hitboxes[i] = aabb; + + def->rt.modelBoxes[i].reserve(def->modelBoxes.size()); + for (AABB aabb : def->modelBoxes) { + def->rotations.variants[i].transform(aabb); + def->rt.modelBoxes[i].push_back(aabb); + } } } diff --git a/src/voxels/Block.h b/src/voxels/Block.h index da2f4d13..c61b4889 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -105,7 +105,8 @@ public: blockid_t id; bool solid = true; bool emissive = false; - AABB hitboxes[BlockRotProfile::MAX_COUNT]; + AABB hitboxes[BlockRotProfile::MAX_COUNT]; + std::vector modelBoxes[BlockRotProfile::MAX_COUNT]; block_funcs_set funcsset {}; itemid_t pickingItem = 0; } rt; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index fa0b46b1..df7e651d 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -67,7 +67,10 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){ if (hitbox.contains({x - ix, y - iy, z - iz})) return &hitbox; } else { - for (const auto& hitbox : def->modelBoxes) { + const auto& boxes = def->rotatable + ? def->rt.modelBoxes[v->rotation()] + : def->modelBoxes; + for (const auto& hitbox : boxes) { if (hitbox.contains({x - ix, y - iy, z - iz})) return &hitbox; } @@ -342,16 +345,29 @@ glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDis const Block* def = contentIds->getBlockDef(voxel->id); if (def->obstacle) { if (!def->rt.solid) { - const AABB& box = def->rotatable - ? def->rt.hitboxes[voxel->rotation()] - : def->hitbox; - scalar_t distance; - glm::ivec3 norm; - Ray ray(start, dir); - // norm is dummy now, can be inefficient - if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) { - return start + (dir * glm::vec3(distance)); - } + std::vector hitboxes; + if (def->hitboxExplicit) { + hitboxes = { + def->rotatable + ? def->rt.hitboxes[voxel->rotation()] + : def->hitbox + }; + } else { + hitboxes = def->rotatable + ? def->rt.modelBoxes[voxel->rotation()] + : def->modelBoxes; + } + + scalar_t distance; + glm::ivec3 norm; + Ray ray(start, dir); + + for (const auto& box : hitboxes) { + // norm is dummy now, can be inefficient + if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) { + return start + (dir * glm::vec3(distance)); + } + } } else { return glm::vec3(px + t * dx, py + t * dy, pz + t * dz); From 70d309dfd9ea92369429f2985b67e24dd35eeadb Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Sat, 24 Feb 2024 12:06:35 +0300 Subject: [PATCH 3/3] Done --- src/voxels/Chunks.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index df7e651d..cbac2c21 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -247,16 +247,28 @@ voxel* Chunks::rayCast(glm::vec3 start, iend.z = iz; if (!def->rt.solid) { - const AABB& box = def->rotatable - ? def->rt.hitboxes[voxel->rotation()] - : def->hitbox; - scalar_t distance; - Ray ray(start, dir); - if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None){ - end = start + (dir * glm::vec3(distance)); - return voxel; - } + std::vector hitboxes; + if (def->hitboxExplicit) { + hitboxes = { + def->rotatable + ? def->rt.hitboxes[voxel->rotation()] + : def->hitbox + }; + } else { + hitboxes = def->rotatable + ? def->rt.modelBoxes[voxel->rotation()] + : def->modelBoxes; + } + scalar_t distance; + Ray ray(start, dir); + + for (const auto& box : hitboxes) { + if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None) { + end = start + (dir * glm::vec3(distance)); + return voxel; + } + } } else { iend.x = ix; iend.y = iy;