From 9c3c286aab3e4b60105ea71308a41859ed87fb0f Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 24 Apr 2024 22:08:12 +0200 Subject: [PATCH] Optimize code patterns around raycasting --- src/environment.cpp | 26 +++++++++--------- src/serverenvironment.cpp | 55 +++++++++++++++++++++------------------ src/util/pointedthing.cpp | 30 --------------------- src/util/pointedthing.h | 50 ++++++++++++++++++++++++----------- 4 files changed, 77 insertions(+), 84 deletions(-) diff --git a/src/environment.cpp b/src/environment.cpp index 011534e00..887bc36f7 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -129,9 +129,8 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) if (state->m_objects_pointable) { std::vector found; getSelectedActiveObjects(state->m_shootline, found, state->m_pointabilities); - for (const PointedThing &pointed : found) { - state->m_found.push(pointed); - } + for (auto &pointed : found) + state->m_found.push(std::move(pointed)); } // Set search range core::aabbox3d maximal_exceed = nodedef->getSelectionBoxIntUnion(); @@ -150,14 +149,10 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) } Map &map = getMap(); - // If a node is found, this is the center of the - // first nodebox the shootline meets. - v3f found_boxcenter(0, 0, 0); - // The untested nodes are in this range. - core::aabbox3d new_nodes; + std::vector boxes; while (state->m_iterator.m_current_index <= lastIndex) { // Test the nodes around the current node in search_range. - new_nodes = state->m_search_range; + core::aabbox3d new_nodes = state->m_search_range; new_nodes.MinEdge += state->m_iterator.m_current_node_pos; new_nodes.MaxEdge += state->m_iterator.m_current_node_pos; @@ -205,7 +200,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) PointedThing result; - std::vector boxes; + boxes.clear(); n.getSelectionBoxes(nodedef, &boxes, n.getNeighbors(np, &map)); @@ -215,6 +210,9 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) float min_distance_sq = 10000000; // ID of the current box (loop counter) u16 id = 0; + // If a node is found, this is the center of the + // first nodebox the shootline meets. + v3f found_boxcenter(0, 0, 0); // Do calculations relative to the node center // to translate the ray rather than the boxes @@ -253,7 +251,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) result.node_undersurface = np; result.distanceSq = min_distance_sq; // Set undersurface and abovesurface nodes - f32 d = 0.002 * BS; + const f32 d = 0.002 * BS; v3f fake_intersection = result.intersection_point; found_boxcenter += npf; // translate back to world coords // Move intersection towards its source block. @@ -276,8 +274,9 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) fake_intersection, BS); result.node_abovesurface = result.node_real_undersurface + floatToInt(result.intersection_normal, 1.0f); + // Push found PointedThing - state->m_found.push(result); + state->m_found.push(std::move(result)); // If this is nearer than the old nearest object, // the search can be shorter s16 newIndex = state->m_iterator.getIndex( @@ -297,9 +296,8 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p) } else { *result_p = state->m_found.top(); state->m_found.pop(); - if (result_p->pointability == PointabilityType::POINTABLE_BLOCKING) { + if (result_p->pointability == PointabilityType::POINTABLE_BLOCKING) result_p->type = POINTEDTHING_NOTHING; - } } } diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 423f51b40..87bb39d4c 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1817,17 +1817,14 @@ void ServerEnvironment::getSelectedActiveObjects( std::vector &objects, const std::optional &pointabilities) { - std::vector objs; - getObjectsInsideRadius(objs, shootline_on_map.getMiddle(), - 0.5 * shootline_on_map.getLength() + 5 * BS, nullptr); const v3f line_vector = shootline_on_map.getVector(); - for (auto obj : objs) { + auto process = [&] (ServerActiveObject *obj) -> bool { if (obj->isGone()) - continue; + return false; aabb3f selection_box; if (!obj->getSelectionBox(&selection_box)) - continue; + return false; v3f pos = obj->getBasePosition(); v3f rel_pos = shootline_on_map.start - pos; @@ -1847,29 +1844,37 @@ void ServerEnvironment::getSelectedActiveObjects( ¤t_intersection, ¤t_normal); current_raw_normal = current_normal; } - if (collision) { - PointabilityType pointable; - if (pointabilities) { - if (LuaEntitySAO* lsao = dynamic_cast(obj)) { - pointable = pointabilities->matchObject(lsao->getName(), - usao->getArmorGroups()).value_or(props->pointable); - } else if (PlayerSAO* psao = dynamic_cast(obj)) { - pointable = pointabilities->matchPlayer(psao->getArmorGroups()).value_or( - props->pointable); - } else { - pointable = props->pointable; - } + if (!collision) + return false; + + PointabilityType pointable; + if (pointabilities) { + if (LuaEntitySAO* lsao = dynamic_cast(obj)) { + pointable = pointabilities->matchObject(lsao->getName(), + usao->getArmorGroups()).value_or(props->pointable); + } else if (PlayerSAO* psao = dynamic_cast(obj)) { + pointable = pointabilities->matchPlayer(psao->getArmorGroups()).value_or( + props->pointable); } else { pointable = props->pointable; } - if (pointable != PointabilityType::POINTABLE_NOT) { - current_intersection += pos; - objects.emplace_back( - (s16) obj->getId(), current_intersection, current_normal, current_raw_normal, - (current_intersection - shootline_on_map.start).getLengthSQ(), pointable); - } + } else { + pointable = props->pointable; } - } + if (pointable != PointabilityType::POINTABLE_NOT) { + current_intersection += pos; + f32 d_sq = (current_intersection - shootline_on_map.start).getLengthSQ(); + objects.emplace_back( + (s16) obj->getId(), current_intersection, current_normal, + current_raw_normal, d_sq, pointable); + } + return false; + }; + + // Use "logic in callback" pattern to avoid useless vector filling + std::vector tmp; + getObjectsInsideRadius(tmp, shootline_on_map.getMiddle(), + 0.5 * shootline_on_map.getLength() + 5 * BS, process); } /* diff --git a/src/util/pointedthing.cpp b/src/util/pointedthing.cpp index f87021dc6..467e466d5 100644 --- a/src/util/pointedthing.cpp +++ b/src/util/pointedthing.cpp @@ -23,31 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include -PointedThing::PointedThing(const v3s16 &under, const v3s16 &above, - const v3s16 &real_under, const v3f &point, const v3f &normal, - u16 box_id, f32 distSq, PointabilityType pointab): - type(POINTEDTHING_NODE), - node_undersurface(under), - node_abovesurface(above), - node_real_undersurface(real_under), - intersection_point(point), - intersection_normal(normal), - box_id(box_id), - distanceSq(distSq), - pointability(pointab) -{} - -PointedThing::PointedThing(u16 id, const v3f &point, const v3f &normal, - const v3f &raw_normal, f32 distSq, PointabilityType pointab) : - type(POINTEDTHING_OBJECT), - object_id(id), - intersection_point(point), - intersection_normal(normal), - raw_intersection_normal(raw_normal), - distanceSq(distSq), - pointability(pointab) -{} - std::string PointedThing::dump() const { std::ostringstream os(std::ios::binary); @@ -131,8 +106,3 @@ bool PointedThing::operator==(const PointedThing &pt2) const } return true; } - -bool PointedThing::operator!=(const PointedThing &pt2) const -{ - return !(*this == pt2); -} diff --git a/src/util/pointedthing.h b/src/util/pointedthing.h index c44bcc2a8..5c8bc7ca1 100644 --- a/src/util/pointedthing.h +++ b/src/util/pointedthing.h @@ -37,6 +37,8 @@ struct PointedThing { //! The type of the pointed object. PointedThingType type = POINTEDTHING_NOTHING; + //! How the object or node can be pointed at. + PointabilityType pointability = PointabilityType::POINTABLE_NOT; /*! * Only valid if type is POINTEDTHING_NODE. * The coordinates of the node which owns the @@ -63,6 +65,11 @@ struct PointedThing * The ID of the object the ray hit. */ u16 object_id = 0; + /*! + * Only valid if type isn't POINTEDTHING_NONE. + * Indicates which selection box is selected, if there are more of them. + */ + u16 box_id = 0; /*! * Only valid if type isn't POINTEDTHING_NONE. * First intersection point of the ray and the nodebox in irrlicht @@ -81,36 +88,49 @@ struct PointedThing * Raw normal vector of the intersection before applying rotation. */ v3f raw_intersection_normal; - /*! - * Only valid if type isn't POINTEDTHING_NONE. - * Indicates which selection box is selected, if there are more of them. - */ - u16 box_id = 0; /*! * Square of the distance between the pointing * ray's start point and the intersection point in irrlicht coordinates. */ f32 distanceSq = 0; - /*! - * How the object or node has been pointed at. - */ - PointabilityType pointability = PointabilityType::POINTABLE_NOT; //! Constructor for POINTEDTHING_NOTHING PointedThing() = default; //! Constructor for POINTEDTHING_NODE - PointedThing(const v3s16 &under, const v3s16 &above, - const v3s16 &real_under, const v3f &point, const v3f &normal, - u16 box_id, f32 distSq, PointabilityType pointability); + inline PointedThing(const v3s16 under, const v3s16 above, + const v3s16 real_under, const v3f point, const v3f normal, + u16 box_id, f32 distSq, PointabilityType pointab) : + type(POINTEDTHING_NODE), + pointability(pointab), + node_undersurface(under), + node_abovesurface(above), + node_real_undersurface(real_under), + box_id(box_id), + intersection_point(point), + intersection_normal(normal), + distanceSq(distSq) + {} //! Constructor for POINTEDTHING_OBJECT - PointedThing(u16 id, const v3f &point, const v3f &normal, const v3f &raw_normal, f32 distSq, - PointabilityType pointability); + inline PointedThing(u16 id, const v3f point, const v3f normal, + const v3f raw_normal, f32 distSq, PointabilityType pointab) : + type(POINTEDTHING_OBJECT), + pointability(pointab), + object_id(id), + intersection_point(point), + intersection_normal(normal), + raw_intersection_normal(raw_normal), + distanceSq(distSq) + {} + std::string dump() const; void serialize(std::ostream &os) const; void deSerialize(std::istream &is); + /*! * This function ignores the intersection point and normal. */ bool operator==(const PointedThing &pt2) const; - bool operator!=(const PointedThing &pt2) const; + bool operator!=(const PointedThing &pt2) const { + return !(*this == pt2); + } };