From f3003dcfc3be37437d029ec1983ae71593dbe285 Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Fri, 15 Nov 2024 18:16:12 +0000 Subject: [PATCH] less map look ups --- libopenage/pathfinding/grid.cpp | 16 +++---- libopenage/pathfinding/grid.h | 1 - libopenage/pathfinding/pathfinder.cpp | 62 ++++++++++++++++++++------- libopenage/pathfinding/pathfinder.h | 48 ++++++++++++++++----- 4 files changed, 92 insertions(+), 35 deletions(-) diff --git a/libopenage/pathfinding/grid.cpp b/libopenage/pathfinding/grid.cpp index 502e86f521..bf87e6ae36 100644 --- a/libopenage/pathfinding/grid.cpp +++ b/libopenage/pathfinding/grid.cpp @@ -109,20 +109,20 @@ void Grid::init_portal_nodes() { for(auto& portal : sector->get_portals()) { - if(this->portal_nodes.find(portal->get_id()) == this->portal_nodes.end()) - { - this->portal_nodes[portal->get_id()] = std::make_shared(portal); + if(!this->portal_nodes.contains(portal->get_id())) + { + auto portal_node = std::make_shared(portal); + portal_node->node_sector_0 = sector->get_id(); + portal_node->node_sector_1 = portal_node->portal->get_exit_sector(sector->get_id()); + this->portal_nodes[portal->get_id()] = portal_node; } } } //init portal_node exits - for(auto& sector : this->sectors) + for(auto& [id, node] : this->portal_nodes) { - for(auto& portal : sector->get_portals()) - { - this->portal_nodes[portal->get_id()]->init_exits(this->portal_nodes, sector->get_id()); - } + node->init_exits(this->portal_nodes); } } diff --git a/libopenage/pathfinding/grid.h b/libopenage/pathfinding/grid.h index 4513bb7b99..edcc3d0de1 100644 --- a/libopenage/pathfinding/grid.h +++ b/libopenage/pathfinding/grid.h @@ -10,7 +10,6 @@ #include "pathfinding/pathfinder.h" #include "pathfinding/types.h" #include "util/vector.h" -#include "pathfinding/pathfinder.h" namespace openage::path { diff --git a/libopenage/pathfinding/pathfinder.cpp b/libopenage/pathfinding/pathfinder.cpp index f020e77325..b19f866927 100644 --- a/libopenage/pathfinding/pathfinder.cpp +++ b/libopenage/pathfinding/pathfinder.cpp @@ -11,6 +11,7 @@ #include "pathfinding/integrator.h" #include "pathfinding/portal.h" #include "pathfinding/sector.h" +#include "error/error.h" namespace openage::path { @@ -211,9 +212,7 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req // path node storage, always provides cheapest next node. heap_t node_candidates; - // list of known portals and corresponding node. std::unordered_set visited_portals; - std::unordered_set was_best; // TODO: Compute cost to travel from one portal to another when creating portals // const int distance_cost = 1; @@ -226,7 +225,6 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req } auto& portal_node = portal_map.at(portal->get_id()); - portal_node->prev_portal = nullptr; portal_node->entry_sector = start_sector->get_id(); auto sector_pos = grid->get_sector(portal->get_exit_sector(start_sector->get_id()))->get_position().to_tile(sector_size); @@ -239,6 +237,8 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req portal_node->future_cost = portal_node->current_cost + heuristic_cost; portal_node->heap_node = node_candidates.push(portal_node); + portal_node->prev_portal = nullptr; + portal_node->was_best = false; visited_portals.insert(portal->get_id()); } @@ -250,7 +250,7 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req while (not node_candidates.empty()) { auto current_node = node_candidates.pop(); - was_best.insert(current_node->portal->get_id()); + current_node->was_best = true; // check if the current node is a portal in the target sector that can // be reached from the target cell @@ -270,18 +270,23 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req } // get the exits of the current node - const auto& exits = current_node->exits.at(current_node->entry_sector); + const auto& exits = current_node->get_exits(current_node->entry_sector); // evaluate all neighbors of the current candidate for further progress - for (auto &[exit_id, distance_cost] : exits) { - auto& exit = portal_map.at(exit_id); + for (auto &[exit, distance_cost] : exits) { exit->entry_sector = current_node->portal->get_exit_sector(current_node->entry_sector); - if (was_best.contains(exit->portal->get_id())) { + bool not_visited = !visited_portals.contains(exit->portal->get_id()); + + if(not_visited) + { + exit->was_best = false; + } + else if(exit->was_best) + { continue; } - bool not_visited = !visited_portals.contains(exit->portal->get_id()); auto tentative_cost = current_node->current_cost + distance_cost; if (not_visited or tentative_cost < exit->current_cost) { @@ -471,6 +476,7 @@ PortalNode::PortalNode(const std::shared_ptr &portal) : future_cost{std::numeric_limits::max()}, current_cost{std::numeric_limits::max()}, heuristic_cost{std::numeric_limits::max()}, + was_best{false}, prev_portal{nullptr}, heap_node{nullptr} {} @@ -482,6 +488,7 @@ PortalNode::PortalNode(const std::shared_ptr &portal, future_cost{std::numeric_limits::max()}, current_cost{std::numeric_limits::max()}, heuristic_cost{std::numeric_limits::max()}, + was_best{false}, prev_portal{prev_portal}, heap_node{nullptr} {} @@ -495,6 +502,7 @@ PortalNode::PortalNode(const std::shared_ptr &portal, future_cost{past_cost + heuristic_cost}, current_cost{past_cost}, heuristic_cost{heuristic_cost}, + was_best{false}, prev_portal{prev_portal}, heap_node{nullptr} { } @@ -520,15 +528,39 @@ std::vector PortalNode::generate_backtrace() { return waypoints; } -void PortalNode::init_exits(sector_id_t entry_sector) { - auto &exits = this->portal->get_exits(entry_sector); - sector_id_t exit_sector = this->portal->get_exit_sector(entry_sector); +void PortalNode::init_exits(const nodemap_t& node_map) { + auto exits = this->portal->get_exits(this->node_sector_0); + for (auto &exit : exits) { + int distance_cost = Pathfinder::distance_cost( + this->portal->get_exit_center(this->node_sector_0), + exit->get_entry_center(this->node_sector_1)); + + auto exit_node = node_map.at(exit->get_id()); + this->exits_1[exit_node] = distance_cost; + } + + exits = this->portal->get_exits(this->node_sector_1); for (auto &exit : exits) { int distance_cost = Pathfinder::distance_cost( - this->portal->get_exit_center(entry_sector), - exit->get_entry_center(exit_sector)); + this->portal->get_exit_center(this->node_sector_1), + exit->get_entry_center(this->node_sector_0)); + + auto exit_node = node_map.at(exit->get_id()); + this->exits_0[exit_node] = distance_cost; + } +} + +const PortalNode::exits_t& PortalNode::get_exits(sector_id_t entry_sector) +{ + ENSURE(entry_sector == this->node_sector_0 || entry_sector == this->node_sector_1, "Invalid entry sector"); - this->exits[entry_sector][exit->get_id()] = distance_cost; + if(this->node_sector_0 == entry_sector) + { + return exits_1; + } + else + { + return exits_0; } } diff --git a/libopenage/pathfinding/pathfinder.h b/libopenage/pathfinding/pathfinder.h index 79b9eeecc8..f8f908e5d0 100644 --- a/libopenage/pathfinding/pathfinder.h +++ b/libopenage/pathfinding/pathfinder.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include "coord/tile.h" #include "datastructure/pairing_heap.h" @@ -150,7 +150,6 @@ using nodemap_t = std::unordered_map; class PortalNode : public std::enable_shared_from_this { public: PortalNode(const std::shared_ptr &portal); - PortalNode(const std::shared_ptr &portal, sector_id_t entry_sector, const node_t &prev_portal); @@ -184,7 +183,25 @@ class PortalNode : public std::enable_shared_from_this { /** * init PortalNode::exits. */ - void init_exits(sector_id_t entry_sector); + void init_exits(const nodemap_t& node_map); + + + + + /** + * maps node_t of a neigbhour portal to the distance cost to travel between the portals + */ + using exits_t = std::map; + + + /** + * Get the exit portals reachable via the portal when entering from a specified sector. + * + * @param entry_sector Sector from which the portal is entered. + * + * @return Exit portals nodes reachable from the portal. + */ + const exits_t& get_exits(sector_id_t entry_sector); /** * The portal this node is associated to. @@ -232,16 +249,25 @@ class PortalNode : public std::enable_shared_from_this { heap_t::element_t heap_node; /** - * maps portal_id_t of a neigbhour portal to the distance cost to travel between the portals - */ - using neighbours_t = std::unordered_map; + * First sector connected by the portal. + */ + sector_id_t node_sector_0; + + /** + * Second sector connected by the portal. + */ + sector_id_t node_sector_1; + /** + * Exits in sector 0 reachable from the portal. + */ + exits_t exits_0; + + /** + * Exits in sector 1 reachable from the portal. + */ + exits_t exits_1; - /* - * maps a sector_id that the portal can be entered from - * to a set of portal_ids that connect to the sector the portal will be exited from and the cost to travel to them. - */ - std::unordered_map exits; };