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);