1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-02 16:38:41 +00:00

Optimize code patterns around raycasting

This commit is contained in:
sfan5 2024-04-24 22:08:12 +02:00
parent e10adf83d5
commit 9c3c286aab
4 changed files with 77 additions and 84 deletions

View file

@ -129,9 +129,8 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
if (state->m_objects_pointable) { if (state->m_objects_pointable) {
std::vector<PointedThing> found; std::vector<PointedThing> found;
getSelectedActiveObjects(state->m_shootline, found, state->m_pointabilities); getSelectedActiveObjects(state->m_shootline, found, state->m_pointabilities);
for (const PointedThing &pointed : found) { for (auto &pointed : found)
state->m_found.push(pointed); state->m_found.push(std::move(pointed));
}
} }
// Set search range // Set search range
core::aabbox3d<s16> maximal_exceed = nodedef->getSelectionBoxIntUnion(); core::aabbox3d<s16> maximal_exceed = nodedef->getSelectionBoxIntUnion();
@ -150,14 +149,10 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
} }
Map &map = getMap(); Map &map = getMap();
// If a node is found, this is the center of the std::vector<aabb3f> boxes;
// first nodebox the shootline meets.
v3f found_boxcenter(0, 0, 0);
// The untested nodes are in this range.
core::aabbox3d<s16> new_nodes;
while (state->m_iterator.m_current_index <= lastIndex) { while (state->m_iterator.m_current_index <= lastIndex) {
// Test the nodes around the current node in search_range. // Test the nodes around the current node in search_range.
new_nodes = state->m_search_range; core::aabbox3d<s16> new_nodes = state->m_search_range;
new_nodes.MinEdge += state->m_iterator.m_current_node_pos; new_nodes.MinEdge += state->m_iterator.m_current_node_pos;
new_nodes.MaxEdge += 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; PointedThing result;
std::vector<aabb3f> boxes; boxes.clear();
n.getSelectionBoxes(nodedef, &boxes, n.getSelectionBoxes(nodedef, &boxes,
n.getNeighbors(np, &map)); n.getNeighbors(np, &map));
@ -215,6 +210,9 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
float min_distance_sq = 10000000; float min_distance_sq = 10000000;
// ID of the current box (loop counter) // ID of the current box (loop counter)
u16 id = 0; 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 // Do calculations relative to the node center
// to translate the ray rather than the boxes // 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.node_undersurface = np;
result.distanceSq = min_distance_sq; result.distanceSq = min_distance_sq;
// Set undersurface and abovesurface nodes // Set undersurface and abovesurface nodes
f32 d = 0.002 * BS; const f32 d = 0.002 * BS;
v3f fake_intersection = result.intersection_point; v3f fake_intersection = result.intersection_point;
found_boxcenter += npf; // translate back to world coords found_boxcenter += npf; // translate back to world coords
// Move intersection towards its source block. // Move intersection towards its source block.
@ -276,8 +274,9 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
fake_intersection, BS); fake_intersection, BS);
result.node_abovesurface = result.node_real_undersurface result.node_abovesurface = result.node_real_undersurface
+ floatToInt(result.intersection_normal, 1.0f); + floatToInt(result.intersection_normal, 1.0f);
// Push found PointedThing // Push found PointedThing
state->m_found.push(result); state->m_found.push(std::move(result));
// If this is nearer than the old nearest object, // If this is nearer than the old nearest object,
// the search can be shorter // the search can be shorter
s16 newIndex = state->m_iterator.getIndex( s16 newIndex = state->m_iterator.getIndex(
@ -297,9 +296,8 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result_p)
} else { } else {
*result_p = state->m_found.top(); *result_p = state->m_found.top();
state->m_found.pop(); state->m_found.pop();
if (result_p->pointability == PointabilityType::POINTABLE_BLOCKING) { if (result_p->pointability == PointabilityType::POINTABLE_BLOCKING)
result_p->type = POINTEDTHING_NOTHING; result_p->type = POINTEDTHING_NOTHING;
}
} }
} }

View file

@ -1817,17 +1817,14 @@ void ServerEnvironment::getSelectedActiveObjects(
std::vector<PointedThing> &objects, std::vector<PointedThing> &objects,
const std::optional<Pointabilities> &pointabilities) const std::optional<Pointabilities> &pointabilities)
{ {
std::vector<ServerActiveObject *> objs;
getObjectsInsideRadius(objs, shootline_on_map.getMiddle(),
0.5 * shootline_on_map.getLength() + 5 * BS, nullptr);
const v3f line_vector = shootline_on_map.getVector(); const v3f line_vector = shootline_on_map.getVector();
for (auto obj : objs) { auto process = [&] (ServerActiveObject *obj) -> bool {
if (obj->isGone()) if (obj->isGone())
continue; return false;
aabb3f selection_box; aabb3f selection_box;
if (!obj->getSelectionBox(&selection_box)) if (!obj->getSelectionBox(&selection_box))
continue; return false;
v3f pos = obj->getBasePosition(); v3f pos = obj->getBasePosition();
v3f rel_pos = shootline_on_map.start - pos; v3f rel_pos = shootline_on_map.start - pos;
@ -1847,29 +1844,37 @@ void ServerEnvironment::getSelectedActiveObjects(
&current_intersection, &current_normal); &current_intersection, &current_normal);
current_raw_normal = current_normal; current_raw_normal = current_normal;
} }
if (collision) { if (!collision)
PointabilityType pointable; return false;
if (pointabilities) {
if (LuaEntitySAO* lsao = dynamic_cast<LuaEntitySAO*>(obj)) { PointabilityType pointable;
pointable = pointabilities->matchObject(lsao->getName(), if (pointabilities) {
usao->getArmorGroups()).value_or(props->pointable); if (LuaEntitySAO* lsao = dynamic_cast<LuaEntitySAO*>(obj)) {
} else if (PlayerSAO* psao = dynamic_cast<PlayerSAO*>(obj)) { pointable = pointabilities->matchObject(lsao->getName(),
pointable = pointabilities->matchPlayer(psao->getArmorGroups()).value_or( usao->getArmorGroups()).value_or(props->pointable);
props->pointable); } else if (PlayerSAO* psao = dynamic_cast<PlayerSAO*>(obj)) {
} else { pointable = pointabilities->matchPlayer(psao->getArmorGroups()).value_or(
pointable = props->pointable; props->pointable);
}
} else { } else {
pointable = props->pointable; pointable = props->pointable;
} }
if (pointable != PointabilityType::POINTABLE_NOT) { } else {
current_intersection += pos; pointable = props->pointable;
objects.emplace_back(
(s16) obj->getId(), current_intersection, current_normal, current_raw_normal,
(current_intersection - shootline_on_map.start).getLengthSQ(), 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<ServerActiveObject*> tmp;
getObjectsInsideRadius(tmp, shootline_on_map.getMiddle(),
0.5 * shootline_on_map.getLength() + 5 * BS, process);
} }
/* /*

View file

@ -23,31 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "exceptions.h" #include "exceptions.h"
#include <sstream> #include <sstream>
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::string PointedThing::dump() const
{ {
std::ostringstream os(std::ios::binary); std::ostringstream os(std::ios::binary);
@ -131,8 +106,3 @@ bool PointedThing::operator==(const PointedThing &pt2) const
} }
return true; return true;
} }
bool PointedThing::operator!=(const PointedThing &pt2) const
{
return !(*this == pt2);
}

View file

@ -37,6 +37,8 @@ struct PointedThing
{ {
//! The type of the pointed object. //! The type of the pointed object.
PointedThingType type = POINTEDTHING_NOTHING; 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. * Only valid if type is POINTEDTHING_NODE.
* The coordinates of the node which owns the * The coordinates of the node which owns the
@ -63,6 +65,11 @@ struct PointedThing
* The ID of the object the ray hit. * The ID of the object the ray hit.
*/ */
u16 object_id = 0; 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. * Only valid if type isn't POINTEDTHING_NONE.
* First intersection point of the ray and the nodebox in irrlicht * 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. * Raw normal vector of the intersection before applying rotation.
*/ */
v3f raw_intersection_normal; 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 * Square of the distance between the pointing
* ray's start point and the intersection point in irrlicht coordinates. * ray's start point and the intersection point in irrlicht coordinates.
*/ */
f32 distanceSq = 0; f32 distanceSq = 0;
/*!
* How the object or node has been pointed at.
*/
PointabilityType pointability = PointabilityType::POINTABLE_NOT;
//! Constructor for POINTEDTHING_NOTHING //! Constructor for POINTEDTHING_NOTHING
PointedThing() = default; PointedThing() = default;
//! Constructor for POINTEDTHING_NODE //! Constructor for POINTEDTHING_NODE
PointedThing(const v3s16 &under, const v3s16 &above, inline PointedThing(const v3s16 under, const v3s16 above,
const v3s16 &real_under, const v3f &point, const v3f &normal, const v3s16 real_under, const v3f point, const v3f normal,
u16 box_id, f32 distSq, PointabilityType pointability); 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 //! Constructor for POINTEDTHING_OBJECT
PointedThing(u16 id, const v3f &point, const v3f &normal, const v3f &raw_normal, f32 distSq, inline PointedThing(u16 id, const v3f point, const v3f normal,
PointabilityType pointability); 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; std::string dump() const;
void serialize(std::ostream &os) const; void serialize(std::ostream &os) const;
void deSerialize(std::istream &is); void deSerialize(std::istream &is);
/*! /*!
* This function ignores the intersection point and normal. * 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; bool operator!=(const PointedThing &pt2) const {
return !(*this == pt2);
}
}; };