diff --git a/src/content/Content.cpp b/src/content/Content.cpp index 89147004..cdbf2a1d 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -82,16 +82,11 @@ Content* ContentBuilder::build() { def->rt.solid = def->model == BlockModel::block; if (def->rotatable) { - const AABB& hitbox = def->hitbox; for (uint i = 0; i < BlockRotProfile::MAX_COUNT; i++) { - 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->rt.hitboxes[i].reserve(def->hitboxes.size()); + for (AABB aabb : def->hitboxes) { def->rotations.variants[i].transform(aabb); - def->rt.modelBoxes[i].push_back(aabb); + def->rt.hitboxes[i].push_back(aabb); } } } diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 75629b57..a06ed489 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -145,20 +145,27 @@ void ContentLoader::loadBlock(Block& def, std::string name, fs::path file) { } // block hitbox AABB [x, y, z, width, height, depth] - auto boxarr = root->list("hitbox"); + auto boxarr = root->list("hitboxes"); if (boxarr) { - AABB& aabb = def.hitbox; - 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; + def.hitboxes.resize(boxarr->size()); + for (uint i = 0; i < boxarr->size(); i++) { + auto box = boxarr->list(i); + def.hitboxes[i].a = glm::vec3(box->num(0), box->num(1), box->num(2)); + def.hitboxes[i].b = glm::vec3(box->num(3), box->num(4), box->num(5)); + def.hitboxes[i].b += def.hitboxes[i].a; + } } 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); + boxarr = root->list("hitbox"); + if (boxarr) { + AABB aabb; + 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.hitboxes = { aabb }; + } else if (!def.modelBoxes.empty()) { + def.hitboxes = def.modelBoxes; + } else { + def.hitboxes = { AABB() }; } } diff --git a/src/frontend/BlocksPreview.cpp b/src/frontend/BlocksPreview.cpp index b400527e..4791ebbb 100644 --- a/src/frontend/BlocksPreview.cpp +++ b/src/frontend/BlocksPreview.cpp @@ -39,8 +39,13 @@ ImageData* BlocksPreview::draw( glm::vec4(1.0f), !def->rt.emissive); break; case BlockModel::aabb: - batch->blockCube(def->hitbox.size() * glm::vec3(size * 0.63f), - texfaces, glm::vec4(1.0f), !def->rt.emissive); + { + glm::vec3 hitbox = glm::vec3(); + for (const auto& box : def->hitboxes) + hitbox = glm::max(hitbox, box.size()); + batch->blockCube(hitbox * glm::vec3(size * 0.63f), + texfaces, glm::vec4(1.0f), !def->rt.emissive); + } break; case BlockModel::custom: case BlockModel::xsprite: { @@ -99,7 +104,10 @@ std::unique_ptr BlocksPreview::build( glm::vec3 offset(0.1f, 0.5f, 0.1f); if (def->model == BlockModel::aabb) { - offset.y += (1.0f - def->hitbox.size()).y * 0.5f; + glm::vec3 size = glm::vec3(0, 0, 0); + for (const auto& box : def->hitboxes) + size = glm::max(size, box.size()); + offset.y += (1.0f - size).y * 0.5f; } atlas->getTexture()->bind(); shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 4408c5eb..6e7daa88 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -191,18 +191,9 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible const vec3 point = PlayerController::selectedPointPosition; const vec3 norm = PlayerController::selectedBlockNormal; - std::vector hitboxes; - if (!block->hitboxExplicit) { - hitboxes = block->modelBoxes; - } else { - hitboxes = { block->hitbox }; - } - if (block->rotatable) { - auto states = PlayerController::selectedBlockStates; - for (auto& hitbox: hitboxes) { - block->rotations.variants[states].transform(hitbox); - } - } + std::vector& hitboxes = block->rotatable + ? block->rt.hitboxes[PlayerController::selectedBlockStates] + : block->hitboxes; linesShader->use(); linesShader->uniformMatrix("u_projview", camera->getProjView()); diff --git a/src/graphics/BlocksRenderer.cpp b/src/graphics/BlocksRenderer.cpp index 14bdf0cd..bd9069cf 100644 --- a/src/graphics/BlocksRenderer.cpp +++ b/src/graphics/BlocksRenderer.cpp @@ -220,9 +220,17 @@ void BlocksRenderer::blockAABB(const ivec3& icoord, const UVRegion(&texfaces)[6], const Block* block, ubyte rotation, bool lights) { - AABB hitbox = block->hitbox; - vec3 size = hitbox.size(); + if (block->hitboxes.empty()) { + return; + } + AABB hitbox = block->hitboxes[0]; + for (const auto& box : block->hitboxes) { + hitbox.a = glm::min(hitbox.a, box.a); + hitbox.b = glm::max(hitbox.b, box.b); + } + + vec3 size = hitbox.size(); vec3 X(1, 0, 0); vec3 Y(0, 1, 0); vec3 Z(0, 0, 1); diff --git a/src/voxels/Block.h b/src/voxels/Block.h index c61b4889..1832d17e 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -93,8 +93,7 @@ public: bool rotatable = false; bool grounded = false; bool hidden = false; - AABB hitbox; - bool hitboxExplicit = false; + std::vector hitboxes; BlockRotProfile rotations; std::string pickingItem = name+BLOCK_ITEM_SUFFIX; std::string scriptName = name.substr(name.find(':')+1); @@ -105,8 +104,7 @@ public: blockid_t id; bool solid = true; bool emissive = false; - AABB hitboxes[BlockRotProfile::MAX_COUNT]; - std::vector modelBoxes[BlockRotProfile::MAX_COUNT]; + std::vector hitboxes[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 cbac2c21..e65230b8 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -54,27 +54,19 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){ int iy = floor(y); int iz = floor(z); voxel* v = get(ix, iy, iz); - if (v == nullptr) - return &contentIds->getBlockDef(0)->hitbox; + if (v == nullptr) { + static const AABB empty; + return ∅ + } const Block* def = contentIds->getBlockDef(v->id); if (def->obstacle) { - const AABB& hitbox = def->rotatable - ? def->rt.hitboxes[v->rotation()] - : def->hitbox; - if (def->rt.solid) { - return &hitbox; - } else if (def->hitboxExplicit) { + const auto& boxes = def->rotatable + ? def->rt.hitboxes[v->rotation()] + : def->hitboxes; + for (const auto& hitbox : boxes) { if (hitbox.contains({x - ix, y - iy, z - iz})) return &hitbox; - } else { - 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; - } - } + } } return nullptr; } @@ -247,28 +239,27 @@ voxel* Chunks::rayCast(glm::vec3 start, iend.z = iz; if (!def->rt.solid) { - 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; - } + const std::vector& hitboxes = def->rotatable + ? def->rt.hitboxes[voxel->rotation()] + : def->hitboxes; - scalar_t distance; + scalar_t distance = maxDist; Ray ray(start, dir); + bool hit = false; + for (const auto& box : hitboxes) { - if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None) { + scalar_t boxDistance; + glm::ivec3 boxNorm; + if (ray.intersectAABB(iend, box, maxDist, boxNorm, boxDistance) > RayRelation::None && boxDistance < distance) { + hit = true; + distance = boxDistance; + norm = boxNorm; end = start + (dir * glm::vec3(distance)); - return voxel; } } + + if (hit) return voxel; } else { iend.x = ix; iend.y = iy; @@ -357,18 +348,9 @@ 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) { - 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; - } + const std::vector& hitboxes = def->rotatable + ? def->rt.hitboxes[voxel->rotation()] + : def->modelBoxes; scalar_t distance; glm::ivec3 norm;