diff --git a/src/client/activeobjectmgr.cpp b/src/client/activeobjectmgr.cpp index af2d6fe63..19e75439f 100644 --- a/src/client/activeobjectmgr.cpp +++ b/src/client/activeobjectmgr.cpp @@ -110,17 +110,8 @@ void ActiveObjectMgr::getActiveObjects(const v3f &origin, f32 max_d, std::vector ActiveObjectMgr::getActiveSelectableObjects(const core::line3d &shootline) { std::vector dest; - // Imagine a not-axis-aligned cuboid oriented into the direction of the shootline, - // with the width of the object's selection box radius * 2 and with length of the - // shootline (+selection box radius forwards and backwards). We check whether - // the selection box center is inside this cuboid. - f32 max_d = shootline.getLength(); v3f dir = shootline.getVector().normalize(); - // arbitrary linearly independent vector and orthogonal dirs - v3f li2dir = dir + (std::fabs(dir.X) < 0.5f ? v3f(1,0,0) : v3f(0,1,0)); - v3f dir_ortho1 = dir.crossProduct(li2dir).normalize(); - v3f dir_ortho2 = dir.crossProduct(dir_ortho1); for (auto &ao_it : m_active_objects) { ClientActiveObject *obj = ao_it.second; @@ -129,23 +120,22 @@ std::vector ActiveObjectMgr::getActiveSelectableObje if (!obj->getSelectionBox(&selection_box)) continue; - // possible optimization: get rid of the sqrt here - f32 selection_box_radius = selection_box.getRadius(); + v3f obj_center = obj->getPosition() + selection_box.getCenter(); + f32 obj_radius_sq = selection_box.getExtent().getLengthSQ() / 4; - v3f pos_diff = obj->getPosition() + selection_box.getCenter() - shootline.start; + v3f c = obj_center - shootline.start; + f32 a = dir.dotProduct(c); // project c onto dir + f32 b_sq = c.getLengthSQ() - a * a; // distance from shootline to obj_center, squared - f32 d = dir.dotProduct(pos_diff); + if (b_sq > obj_radius_sq) + continue; // backward- and far-plane - if (d + selection_box_radius < 0.0f || d - selection_box_radius > max_d) + f32 obj_radius = std::sqrt(obj_radius_sq); + if (a < -obj_radius || a > max_d + obj_radius) continue; - // side-planes - if (std::fabs(dir_ortho1.dotProduct(pos_diff)) > selection_box_radius - || std::fabs(dir_ortho2.dotProduct(pos_diff)) > selection_box_radius) - continue; - - dest.emplace_back(obj, d); + dest.emplace_back(obj, a); } return dest; }