From 9ea8b58d20274d8e994748b15f8231d88e3b3e99 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:47:26 -0600 Subject: [PATCH 01/10] Add dirty flag and integrate --- libopenage/pathfinding/CMakeLists.txt | 1 + libopenage/pathfinding/cost_field.cpp | 22 +++++++-- libopenage/pathfinding/cost_field.h | 28 +++++++++-- libopenage/pathfinding/demo/demo_0.cpp | 20 ++++---- libopenage/pathfinding/demo/demo_1.cpp | 16 ++++++- libopenage/pathfinding/field_cache.cpp | 32 +++++++++++++ libopenage/pathfinding/field_cache.h | 66 ++++++++++++++++++++++++++ libopenage/pathfinding/integrator.cpp | 64 +++++++++++++++++-------- libopenage/pathfinding/integrator.h | 34 ++++--------- libopenage/pathfinding/path.h | 5 ++ libopenage/pathfinding/pathfinder.cpp | 3 +- libopenage/pathfinding/sector.cpp | 4 ++ libopenage/pathfinding/sector.h | 8 ++++ libopenage/pathfinding/tests.cpp | 4 +- 14 files changed, 242 insertions(+), 65 deletions(-) create mode 100644 libopenage/pathfinding/field_cache.cpp create mode 100644 libopenage/pathfinding/field_cache.h diff --git a/libopenage/pathfinding/CMakeLists.txt b/libopenage/pathfinding/CMakeLists.txt index 7f85264d01..33c2844ace 100644 --- a/libopenage/pathfinding/CMakeLists.txt +++ b/libopenage/pathfinding/CMakeLists.txt @@ -1,6 +1,7 @@ add_sources(libopenage cost_field.cpp definitions.cpp + field_cache.cpp flow_field.cpp grid.cpp integration_field.cpp diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index 3299084548..4ad1318874 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -13,7 +13,8 @@ namespace openage::path { CostField::CostField(size_t size) : size{size}, - cells(this->size * this->size, COST_MIN) { + cells(this->size * this->size, COST_MIN), + changed{time::time_t::min_value()} { log::log(DBG << "Created cost field with size " << this->size << "x" << this->size); } @@ -33,29 +34,42 @@ cost_t CostField::get_cost(size_t idx) const { return this->cells.at(idx); } -void CostField::set_cost(const coord::tile_delta &pos, cost_t cost) { +void CostField::set_cost(const coord::tile_delta &pos, cost_t cost, time::time_t &changed) { this->cells[pos.ne + pos.se * this->size] = cost; + this->changed = changed; } -void CostField::set_cost(size_t x, size_t y, cost_t cost) { +void CostField::set_cost(size_t x, size_t y, cost_t cost, time::time_t &changed) { this->cells[x + y * this->size] = cost; + this->changed = changed; } void CostField::set_cost(size_t idx, cost_t cost) { this->cells[idx] = cost; + this->changed = time::TIME_ZERO; +} + +void CostField::set_cost(size_t idx, cost_t cost,time::time_t &changed) { + this->cells[idx] = cost; + this->changed = changed; } const std::vector &CostField::get_costs() const { return this->cells; } -void CostField::set_costs(std::vector &&cells) { +void CostField::set_costs(std::vector &&cells, time::time_t &changed) { ENSURE(cells.size() == this->cells.size(), "cells vector has wrong size: " << cells.size() << "; expected: " << this->cells.size()); this->cells = std::move(cells); + this->changed = changed; +} + +bool CostField::is_dirty(time::time_t &time) { + return time <= this->changed; } } // namespace openage::path diff --git a/libopenage/pathfinding/cost_field.h b/libopenage/pathfinding/cost_field.h index a1fc87b046..99dd16306c 100644 --- a/libopenage/pathfinding/cost_field.h +++ b/libopenage/pathfinding/cost_field.h @@ -6,6 +6,7 @@ #include #include "pathfinding/types.h" +#include "time/time.h" namespace openage { @@ -64,8 +65,9 @@ class CostField { * * @param pos Coordinates of the cell (relative to field origin). * @param cost Cost to set. + * @param changed Time cost is set. */ - void set_cost(const coord::tile_delta &pos, cost_t cost); + void set_cost(const coord::tile_delta &pos, cost_t cost, time::time_t &changed); /** * Set the cost at a specified position. @@ -73,8 +75,9 @@ class CostField { * @param x X-coordinate of the cell. * @param y Y-coordinate of the cell. * @param cost Cost to set. + * @param changed Time cost is set. */ - void set_cost(size_t x, size_t y, cost_t cost); + void set_cost(size_t x, size_t y, cost_t cost, time::time_t &changed); /** * Set the cost at a specified position. @@ -84,6 +87,15 @@ class CostField { */ void set_cost(size_t idx, cost_t cost); + /** + * Set the cost at a specified position. + * + * @param idx Index of the cell. + * @param cost Cost to set. + * @param changed Time cost is set. + */ + void set_cost(size_t idx, cost_t cost, time::time_t &changed); + /** * Get the cost field values. * @@ -95,8 +107,16 @@ class CostField { * Set the cost field values. * * @param cells Cost field values. + * @param changed Time cost is set. */ - void set_costs(std::vector &&cells); + void set_costs(std::vector &&cells, time::time_t &changed); + + /** + * Check if the cost field is dirty at the specified time. + * + * @param time Specified time to check. + */ + bool is_dirty(time::time_t &time); private: /** @@ -104,6 +124,8 @@ class CostField { */ size_t size; + time::time_t changed; + /** * Cost field values. */ diff --git a/libopenage/pathfinding/demo/demo_0.cpp b/libopenage/pathfinding/demo/demo_0.cpp index 483261ebaf..fbe022e8ef 100644 --- a/libopenage/pathfinding/demo/demo_0.cpp +++ b/libopenage/pathfinding/demo/demo_0.cpp @@ -33,15 +33,17 @@ void path_demo_0(const util::Path &path) { // Cost field with some obstacles auto cost_field = std::make_shared(field_length); - cost_field->set_cost(coord::tile_delta{0, 0}, COST_IMPASSABLE); - cost_field->set_cost(coord::tile_delta{1, 0}, 254); - cost_field->set_cost(coord::tile_delta{4, 3}, 128); - cost_field->set_cost(coord::tile_delta{5, 3}, 128); - cost_field->set_cost(coord::tile_delta{6, 3}, 128); - cost_field->set_cost(coord::tile_delta{4, 4}, 128); - cost_field->set_cost(coord::tile_delta{5, 4}, 128); - cost_field->set_cost(coord::tile_delta{6, 4}, 128); - cost_field->set_cost(coord::tile_delta{1, 7}, COST_IMPASSABLE); + + time::time_t time = time::TIME_ZERO; + cost_field->set_cost(coord::tile_delta{0, 0}, COST_IMPASSABLE, time); + cost_field->set_cost(coord::tile_delta{1, 0}, 254, time); + cost_field->set_cost(coord::tile_delta{4, 3}, 128, time); + cost_field->set_cost(coord::tile_delta{5, 3}, 128, time); + cost_field->set_cost(coord::tile_delta{6, 3}, 128, time); + cost_field->set_cost(coord::tile_delta{4, 4}, 128, time); + cost_field->set_cost(coord::tile_delta{5, 4}, 128, time); + cost_field->set_cost(coord::tile_delta{6, 4}, 128, time); + cost_field->set_cost(coord::tile_delta{1, 7}, COST_IMPASSABLE, time); log::log(INFO << "Created cost field"); // Create an integration field from the cost field diff --git a/libopenage/pathfinding/demo/demo_1.cpp b/libopenage/pathfinding/demo/demo_1.cpp index 1edeba52a1..ecb0e4cb63 100644 --- a/libopenage/pathfinding/demo/demo_1.cpp +++ b/libopenage/pathfinding/demo/demo_1.cpp @@ -11,6 +11,8 @@ #include "pathfinding/portal.h" #include "pathfinding/sector.h" #include "util/timer.h" +#include "time/time_loop.h" +#include "time/clock.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" #include "renderer/opengl/window.h" @@ -25,13 +27,17 @@ namespace openage::path::tests { void path_demo_1(const util::Path &path) { + auto time_loop = std::make_shared(); + time_loop->run(); + auto clock = time_loop->get_clock(); auto grid = std::make_shared(0, util::Vector2s{4, 3}, 10); + time::time_t time = clock->get_time(); // Initialize the cost field for each sector. for (auto §or : grid->get_sectors()) { auto cost_field = sector->get_cost_field(); std::vector sector_cost = sectors_cost.at(sector->get_id()); - cost_field->set_costs(std::move(sector_cost)); + cost_field->set_costs(std::move(sector_cost), time); } // Initialize portals between sectors. @@ -87,16 +93,20 @@ void path_demo_1(const util::Path &path) { coord::tile start{2, 26}; coord::tile target{36, 2}; + time::time_t request_time = clock->get_time(); + PathRequest path_request{ grid->get_id(), start, target, + request_time }; + + log::log(INFO << "Pathfinding request at " << request_time); grid->init_portal_nodes(); timer.start(); Path path_result = pathfinder->get_path(path_request); timer.stop(); - log::log(INFO << "Pathfinding took " << timer.getval() / 1000 << " us"); // Create a renderer to display the grid and path @@ -127,6 +137,7 @@ void path_demo_1(const util::Path &path) { grid->get_id(), start, target, + clock->get_time() }; timer.reset(); @@ -147,6 +158,7 @@ void path_demo_1(const util::Path &path) { grid->get_id(), start, target, + clock->get_time() }; timer.reset(); diff --git a/libopenage/pathfinding/field_cache.cpp b/libopenage/pathfinding/field_cache.cpp new file mode 100644 index 0000000000..9d144e1cc4 --- /dev/null +++ b/libopenage/pathfinding/field_cache.cpp @@ -0,0 +1,32 @@ +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#include "field_cache.h" + +namespace openage::path { + +void FieldCache::add(std::pair cache_key, + std::shared_ptr &integration_field, + std::shared_ptr &flow_field) { + this->cache[cache_key] = std::make_pair(integration_field, flow_field); +} + +void FieldCache::evict(std::pair cache_key) { + this->cache.erase(cache_key); +} + +bool FieldCache::is_cached(std::pair cache_key) { + auto cached = this->cache.find(cache_key); + return cached != this->cache.end(); +} + +std::shared_ptr FieldCache::get_integration_field(std::pair cache_key) { + auto cached = this->cache.find(cache_key); + return cached->second.first; +} + +std::shared_ptr FieldCache::get_flow_field(std::pair cache_key) { + auto cached = this->cache.find(cache_key); + return cached->second.second; +} + +} // namespace openage::path \ No newline at end of file diff --git a/libopenage/pathfinding/field_cache.h b/libopenage/pathfinding/field_cache.h new file mode 100644 index 0000000000..7b98c4d957 --- /dev/null +++ b/libopenage/pathfinding/field_cache.h @@ -0,0 +1,66 @@ +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#pragma once + +#include +#include + +#include "pathfinding/types.h" +#include "util/hash.h" + +namespace openage { +namespace coord { +struct tile_delta; +} // namespace coord + +namespace path { +class IntegrationField; +class FlowField; + +class FieldCache +{ +public: + FieldCache() = default; + ~FieldCache() = default; + + void add(std::pair cache_key, + std::shared_ptr &integration_field, + std::shared_ptr &flow_field); + + void evict(std::pair cache_key); + + bool is_cached(std::pair cache_key); + + std::shared_ptr get_integration_field(std::pair cache_key); + + std::shared_ptr get_flow_field(std::pair cache_key); + + using get_return_t = std::pair, std::shared_ptr>; + +private: + /** + * Hash function for the field cache. + */ + struct pair_hash { + template + std::size_t operator()(const std::pair &pair) const { + return util::hash_combine(std::hash{}(pair.first), std::hash{}(pair.second)); + } + }; + + /** + * Cache for already computed fields. + * + * Key is the portal ID and the sector ID from which the field was entered. Fields that are cached are + * cleared of dynamic flags, i.e. wavefront or LOS flags. These have to be recalculated + * when the field is reused. + */ + + std::unordered_map, + get_return_t, + pair_hash> + cache; +}; + +} // namespace path +} // namespace openage \ No newline at end of file diff --git a/libopenage/pathfinding/integrator.cpp b/libopenage/pathfinding/integrator.cpp index 265c5285cc..d91ac9ecb7 100644 --- a/libopenage/pathfinding/integrator.cpp +++ b/libopenage/pathfinding/integrator.cpp @@ -8,6 +8,7 @@ #include "pathfinding/flow_field.h" #include "pathfinding/integration_field.h" #include "pathfinding/portal.h" +#include "pathfinding/field_cache.h" namespace openage::path { @@ -36,24 +37,32 @@ std::shared_ptr Integrator::integrate(const std::shared_ptr &portal, const coord::tile_delta &target, - bool with_los) { + bool with_los, + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); - auto cached = this->field_cache.find(cache_key); - if (cached != this->field_cache.end()) { + if (evict_cache) { + this->field_cache->evict(cache_key); + } + if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached integration field for portal " << portal->get_id() << " from sector " << other_sector_id); + + + //retrieve cached integration field + auto cached_integration_field = this->field_cache->get_integration_field(cache_key); + if (with_los) { log::log(SPAM << "Performing LOS pass on cached field"); // Make a copy of the cached field to avoid modifying the cached field - auto integration_field = std::make_shared(*cached->second.first); + auto integration_field = std::make_shared(*cached_integration_field); // Only integrate LOS; leave the rest of the field as is integration_field->integrate_los(cost_field, other, other_sector_id, portal, target); return integration_field; } - return cached->second.first; + return cached_integration_field; } log::log(DBG << "Integrating cost field for portal " << portal->get_id() @@ -97,17 +106,24 @@ std::shared_ptr Integrator::build(const std::shared_ptr &other, sector_id_t other_sector_id, const std::shared_ptr &portal, - bool with_los) { + bool with_los, + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); - auto cached = this->field_cache.find(cache_key); - if (cached != this->field_cache.end()) { + if (evict_cache) { + this->field_cache->evict(cache_key); + } + if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached flow field for portal " << portal->get_id() << " from sector " << other_sector_id); + + //retrieve cached flow field + auto cached_flow_field = this->field_cache->get_flow_field(cache_key); + if (with_los) { log::log(SPAM << "Transferring LOS flags to cached flow field"); // Make a copy of the cached flow field - auto flow_field = std::make_shared(*cached->second.second); + auto flow_field = std::make_shared(*cached_flow_field); // Transfer the LOS flags to the flow field flow_field->transfer_dynamic_flags(integration_field); @@ -115,7 +131,7 @@ std::shared_ptr Integrator::build(const std::shared_ptrsecond.second; + return cached_flow_field; } log::log(DBG << "Building flow field for portal " << portal->get_id() @@ -140,17 +156,27 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ sector_id_t other_sector_id, const std::shared_ptr &portal, const coord::tile_delta &target, - bool with_los) { + bool with_los, + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); - auto cached = this->field_cache.find(cache_key); - if (cached != this->field_cache.end()) { + if (evict_cache) { + this->field_cache->evict(cache_key); + } + if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached integration and flow fields for portal " << portal->get_id() << " from sector " << other_sector_id); + + + //retrieve cached fields + auto cached_integration_field = this->field_cache->get_integration_field(cache_key); + auto cached_flow_field = this->field_cache->get_flow_field(cache_key); + + if (with_los) { log::log(SPAM << "Performing LOS pass on cached field"); // Make a copy of the cached integration field - auto integration_field = std::make_shared(*cached->second.first); + auto integration_field = std::make_shared(*cached_integration_field); // Only integrate LOS; leave the rest of the field as is integration_field->integrate_los(cost_field, other, other_sector_id, portal, target); @@ -158,7 +184,7 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ log::log(SPAM << "Transferring LOS flags to cached flow field"); // Make a copy of the cached flow field - auto flow_field = std::make_shared(*cached->second.second); + auto flow_field = std::make_shared(*cached_flow_field); // Transfer the LOS flags to the flow field flow_field->transfer_dynamic_flags(integration_field); @@ -166,11 +192,11 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ return std::make_pair(integration_field, flow_field); } - return cached->second; + return std::make_pair(cached_integration_field, cached_flow_field); } - auto integration_field = this->integrate(cost_field, other, other_sector_id, portal, target, with_los); - auto flow_field = this->build(integration_field, other, other_sector_id, portal); + auto integration_field = this->integrate(cost_field, other, other_sector_id, portal, target, with_los, evict_cache); + auto flow_field = this->build(integration_field, other, other_sector_id, portal, evict_cache); log::log(DBG << "Caching integration and flow fields for portal ID: " << portal->get_id() << ", sector ID: " << other_sector_id); @@ -182,7 +208,7 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ std::shared_ptr cached_flow_field = std::make_shared(*flow_field); cached_flow_field->reset_dynamic_flags(); - this->field_cache[cache_key] = std::make_pair(cached_integration_field, cached_flow_field); + this->field_cache->add(cache_key, cached_integration_field, cached_flow_field); return std::make_pair(integration_field, flow_field); } diff --git a/libopenage/pathfinding/integrator.h b/libopenage/pathfinding/integrator.h index c27d3c1eb1..690c525ad7 100644 --- a/libopenage/pathfinding/integrator.h +++ b/libopenage/pathfinding/integrator.h @@ -2,9 +2,7 @@ #pragma once -#include #include -#include #include "pathfinding/types.h" #include "util/hash.h" @@ -20,6 +18,7 @@ class CostField; class FlowField; class IntegrationField; class Portal; +class FieldCache; /** * Integrator for the flow field pathfinding algorithm. @@ -65,7 +64,8 @@ class Integrator { sector_id_t other_sector_id, const std::shared_ptr &portal, const coord::tile_delta &target, - bool with_los = true); + bool with_los = true, + bool evict_cache = false); /** * Build the flow field from an integration field. @@ -91,7 +91,8 @@ class Integrator { const std::shared_ptr &other, sector_id_t other_sector_id, const std::shared_ptr &portal, - bool with_los = true); + bool with_los = true, + bool evict_cache = false); using get_return_t = std::pair, std::shared_ptr>; @@ -123,30 +124,11 @@ class Integrator { sector_id_t other_sector_id, const std::shared_ptr &portal, const coord::tile_delta &target, - bool with_los = true); + bool with_los = true, + bool evict_cache = false); private: - /** - * Hash function for the field cache. - */ - struct pair_hash { - template - std::size_t operator()(const std::pair &pair) const { - return util::hash_combine(std::hash{}(pair.first), std::hash{}(pair.second)); - } - }; - - /** - * Cache for already computed fields. - * - * Key is the portal ID and the sector ID from which the field was entered. Fields that are cached are - * cleared of dynamic flags, i.e. wavefront or LOS flags. These have to be recalculated - * when the field is reused. - */ - std::unordered_map, - get_return_t, - pair_hash> - field_cache; + std::shared_ptr field_cache; }; } // namespace path diff --git a/libopenage/pathfinding/path.h b/libopenage/pathfinding/path.h index d1c61ac325..cfeb7bc503 100644 --- a/libopenage/pathfinding/path.h +++ b/libopenage/pathfinding/path.h @@ -6,6 +6,7 @@ #include "coord/tile.h" #include "pathfinding/types.h" +#include "time/time.h" namespace openage::path { @@ -20,6 +21,8 @@ struct PathRequest { coord::tile start; /// Target position of the path. coord::tile target; + /// Time request was made. + time::time_t time; }; /** @@ -34,6 +37,8 @@ struct Path { /// First waypoint is the start position of the path request. /// Last waypoint is the target position of the path request. std::vector waypoints; + /// Time path was created. + time::time_t time; }; } // namespace openage::path diff --git a/libopenage/pathfinding/pathfinder.cpp b/libopenage/pathfinding/pathfinder.cpp index e46919e62b..0740da3b82 100644 --- a/libopenage/pathfinding/pathfinder.cpp +++ b/libopenage/pathfinding/pathfinder.cpp @@ -155,7 +155,8 @@ const Path Pathfinder::get_path(const PathRequest &request) { prev_sector_id, portal, target_delta, - with_los); + with_los, + next_sector->is_dirty(request.time)); flow_fields.push_back(std::make_pair(next_sector_id, sector_fields.second)); prev_integration_field = sector_fields.first; diff --git a/libopenage/pathfinding/sector.cpp b/libopenage/pathfinding/sector.cpp index f50dc209bf..08843fe016 100644 --- a/libopenage/pathfinding/sector.cpp +++ b/libopenage/pathfinding/sector.cpp @@ -249,4 +249,8 @@ void Sector::connect_exits() { } } +bool Sector::is_dirty(time::time_t time) { + return this->cost_field->is_dirty(time); +} + } // namespace openage::path diff --git a/libopenage/pathfinding/sector.h b/libopenage/pathfinding/sector.h index a4ba94fa52..cc2950f25e 100644 --- a/libopenage/pathfinding/sector.h +++ b/libopenage/pathfinding/sector.h @@ -9,6 +9,7 @@ #include "coord/chunk.h" #include "pathfinding/portal.h" #include "pathfinding/types.h" +#include "time/time.h" namespace openage::path { @@ -103,6 +104,13 @@ class Sector { */ void connect_exits(); + /** + * Check if the cost field is dirty at the specified time. + * + * @param time Specified time to check. + */ + bool is_dirty(time::time_t time); + private: /** * ID of the sector. diff --git a/libopenage/pathfinding/tests.cpp b/libopenage/pathfinding/tests.cpp index 5f92496ff8..6ec26b392d 100644 --- a/libopenage/pathfinding/tests.cpp +++ b/libopenage/pathfinding/tests.cpp @@ -10,6 +10,7 @@ #include "pathfinding/integration_field.h" #include "pathfinding/integrator.h" #include "pathfinding/types.h" +#include "time/time.h" namespace openage { @@ -23,7 +24,8 @@ void flow_field() { // | 1 | 1 | 1 | // | 1 | X | 1 | // | 1 | 1 | 1 | - cost_field->set_costs({1, 1, 1, 1, 255, 1, 1, 1, 1}); + time::time_t time = time::TIME_ZERO; + cost_field->set_costs({1, 1, 1, 1, 255, 1, 1, 1, 1}, time); // Test the different field types { From a12b347421fae83cfc1e73a682929cc72ec6117b Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:50:20 -0600 Subject: [PATCH 02/10] Update libopenage/pathfinding/cost_field.cpp Co-authored-by: Christoph Heine <6852422+heinezen@users.noreply.github.com> --- libopenage/pathfinding/cost_field.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index 4ad1318874..d4ae7f8464 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -14,7 +14,7 @@ namespace openage::path { CostField::CostField(size_t size) : size{size}, cells(this->size * this->size, COST_MIN), - changed{time::time_t::min_value()} { + changed{time::TIME_MIN} { log::log(DBG << "Created cost field with size " << this->size << "x" << this->size); } From 73647d460ecb5b467c5d081ea4ea44c5f317fe3d Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 20:26:51 -0600 Subject: [PATCH 03/10] Add const to time_t and improve docstrings --- libopenage/pathfinding/cost_field.cpp | 10 +++++----- libopenage/pathfinding/cost_field.h | 25 ++++++++++++++----------- libopenage/pathfinding/demo/demo_0.cpp | 2 +- libopenage/pathfinding/demo/demo_1.cpp | 6 +++--- libopenage/pathfinding/field_cache.cpp | 2 +- libopenage/pathfinding/field_cache.h | 2 +- libopenage/pathfinding/path.h | 4 ++-- libopenage/pathfinding/sector.cpp | 2 +- libopenage/pathfinding/sector.h | 2 +- libopenage/pathfinding/tests.cpp | 2 +- 10 files changed, 30 insertions(+), 27 deletions(-) diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index d4ae7f8464..c211d169c1 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -34,12 +34,12 @@ cost_t CostField::get_cost(size_t idx) const { return this->cells.at(idx); } -void CostField::set_cost(const coord::tile_delta &pos, cost_t cost, time::time_t &changed) { +void CostField::set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &changed) { this->cells[pos.ne + pos.se * this->size] = cost; this->changed = changed; } -void CostField::set_cost(size_t x, size_t y, cost_t cost, time::time_t &changed) { +void CostField::set_cost(size_t x, size_t y, cost_t cost, const time::time_t &changed) { this->cells[x + y * this->size] = cost; this->changed = changed; } @@ -49,7 +49,7 @@ void CostField::set_cost(size_t idx, cost_t cost) { this->changed = time::TIME_ZERO; } -void CostField::set_cost(size_t idx, cost_t cost,time::time_t &changed) { +void CostField::set_cost(size_t idx, cost_t cost, const time::time_t &changed) { this->cells[idx] = cost; this->changed = changed; } @@ -58,7 +58,7 @@ const std::vector &CostField::get_costs() const { return this->cells; } -void CostField::set_costs(std::vector &&cells, time::time_t &changed) { +void CostField::set_costs(std::vector &&cells, const time::time_t &changed) { ENSURE(cells.size() == this->cells.size(), "cells vector has wrong size: " << cells.size() << "; expected: " @@ -68,7 +68,7 @@ void CostField::set_costs(std::vector &&cells, time::time_t &changed) { this->changed = changed; } -bool CostField::is_dirty(time::time_t &time) { +bool CostField::is_dirty(const time::time_t &time) { return time <= this->changed; } diff --git a/libopenage/pathfinding/cost_field.h b/libopenage/pathfinding/cost_field.h index 99dd16306c..e62496acf1 100644 --- a/libopenage/pathfinding/cost_field.h +++ b/libopenage/pathfinding/cost_field.h @@ -65,9 +65,9 @@ class CostField { * * @param pos Coordinates of the cell (relative to field origin). * @param cost Cost to set. - * @param changed Time cost is set. + * @param changed Time at which the cost value is changed. */ - void set_cost(const coord::tile_delta &pos, cost_t cost, time::time_t &changed); + void set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &changed); /** * Set the cost at a specified position. @@ -75,9 +75,9 @@ class CostField { * @param x X-coordinate of the cell. * @param y Y-coordinate of the cell. * @param cost Cost to set. - * @param changed Time cost is set. + * @param changed Time at which the cost value is changed. */ - void set_cost(size_t x, size_t y, cost_t cost, time::time_t &changed); + void set_cost(size_t x, size_t y, cost_t cost, const time::time_t &changed); /** * Set the cost at a specified position. @@ -92,9 +92,9 @@ class CostField { * * @param idx Index of the cell. * @param cost Cost to set. - * @param changed Time cost is set. + * @param changed Time at which the cost value is changed. */ - void set_cost(size_t idx, cost_t cost, time::time_t &changed); + void set_cost(size_t idx, cost_t cost, const time::time_t &changed); /** * Get the cost field values. @@ -107,16 +107,16 @@ class CostField { * Set the cost field values. * * @param cells Cost field values. - * @param changed Time cost is set. + * @param changed Time at which the cost value is changed. */ - void set_costs(std::vector &&cells, time::time_t &changed); + void set_costs(std::vector &&cells, const time::time_t &changed); /** * Check if the cost field is dirty at the specified time. * - * @param time Specified time to check. + * @param time Cost field is dirty if the cost field is accessed before the latest change to the cost field. */ - bool is_dirty(time::time_t &time); + bool is_dirty(const time::time_t &time); private: /** @@ -124,7 +124,10 @@ class CostField { */ size_t size; - time::time_t changed; + /** + * Time the cost field was last changed. + */ + const time::time_t changed; /** * Cost field values. diff --git a/libopenage/pathfinding/demo/demo_0.cpp b/libopenage/pathfinding/demo/demo_0.cpp index fbe022e8ef..2dfb825fa0 100644 --- a/libopenage/pathfinding/demo/demo_0.cpp +++ b/libopenage/pathfinding/demo/demo_0.cpp @@ -34,7 +34,7 @@ void path_demo_0(const util::Path &path) { // Cost field with some obstacles auto cost_field = std::make_shared(field_length); - time::time_t time = time::TIME_ZERO; + const time::time_t time = time::TIME_ZERO; cost_field->set_cost(coord::tile_delta{0, 0}, COST_IMPASSABLE, time); cost_field->set_cost(coord::tile_delta{1, 0}, 254, time); cost_field->set_cost(coord::tile_delta{4, 3}, 128, time); diff --git a/libopenage/pathfinding/demo/demo_1.cpp b/libopenage/pathfinding/demo/demo_1.cpp index ecb0e4cb63..a31b9b786b 100644 --- a/libopenage/pathfinding/demo/demo_1.cpp +++ b/libopenage/pathfinding/demo/demo_1.cpp @@ -32,7 +32,7 @@ void path_demo_1(const util::Path &path) { auto clock = time_loop->get_clock(); auto grid = std::make_shared(0, util::Vector2s{4, 3}, 10); - time::time_t time = clock->get_time(); + const time::time_t time = clock->get_time(); // Initialize the cost field for each sector. for (auto §or : grid->get_sectors()) { auto cost_field = sector->get_cost_field(); @@ -93,7 +93,7 @@ void path_demo_1(const util::Path &path) { coord::tile start{2, 26}; coord::tile target{36, 2}; - time::time_t request_time = clock->get_time(); + const time::time_t request_time = clock->get_time(); PathRequest path_request{ grid->get_id(), @@ -102,11 +102,11 @@ void path_demo_1(const util::Path &path) { request_time }; - log::log(INFO << "Pathfinding request at " << request_time); grid->init_portal_nodes(); timer.start(); Path path_result = pathfinder->get_path(path_request); timer.stop(); + log::log(INFO << "Pathfinding request at " << request_time); log::log(INFO << "Pathfinding took " << timer.getval() / 1000 << " us"); // Create a renderer to display the grid and path diff --git a/libopenage/pathfinding/field_cache.cpp b/libopenage/pathfinding/field_cache.cpp index 9d144e1cc4..a798e9fbd7 100644 --- a/libopenage/pathfinding/field_cache.cpp +++ b/libopenage/pathfinding/field_cache.cpp @@ -29,4 +29,4 @@ std::shared_ptr FieldCache::get_flow_field(std::pairsecond.second; } -} // namespace openage::path \ No newline at end of file +} // namespace openage::path diff --git a/libopenage/pathfinding/field_cache.h b/libopenage/pathfinding/field_cache.h index 7b98c4d957..a1f43a563e 100644 --- a/libopenage/pathfinding/field_cache.h +++ b/libopenage/pathfinding/field_cache.h @@ -63,4 +63,4 @@ class FieldCache }; } // namespace path -} // namespace openage \ No newline at end of file +} // namespace openage diff --git a/libopenage/pathfinding/path.h b/libopenage/pathfinding/path.h index cfeb7bc503..ca6391bf67 100644 --- a/libopenage/pathfinding/path.h +++ b/libopenage/pathfinding/path.h @@ -22,7 +22,7 @@ struct PathRequest { /// Target position of the path. coord::tile target; /// Time request was made. - time::time_t time; + const time::time_t time; }; /** @@ -38,7 +38,7 @@ struct Path { /// Last waypoint is the target position of the path request. std::vector waypoints; /// Time path was created. - time::time_t time; + const time::time_t time; }; } // namespace openage::path diff --git a/libopenage/pathfinding/sector.cpp b/libopenage/pathfinding/sector.cpp index 08843fe016..4556fd42c3 100644 --- a/libopenage/pathfinding/sector.cpp +++ b/libopenage/pathfinding/sector.cpp @@ -249,7 +249,7 @@ void Sector::connect_exits() { } } -bool Sector::is_dirty(time::time_t time) { +bool Sector::is_dirty(const time::time_t time) { return this->cost_field->is_dirty(time); } diff --git a/libopenage/pathfinding/sector.h b/libopenage/pathfinding/sector.h index cc2950f25e..e0f751b70d 100644 --- a/libopenage/pathfinding/sector.h +++ b/libopenage/pathfinding/sector.h @@ -109,7 +109,7 @@ class Sector { * * @param time Specified time to check. */ - bool is_dirty(time::time_t time); + bool is_dirty(const time::time_t time); private: /** diff --git a/libopenage/pathfinding/tests.cpp b/libopenage/pathfinding/tests.cpp index 6ec26b392d..2ac0960c34 100644 --- a/libopenage/pathfinding/tests.cpp +++ b/libopenage/pathfinding/tests.cpp @@ -24,7 +24,7 @@ void flow_field() { // | 1 | 1 | 1 | // | 1 | X | 1 | // | 1 | 1 | 1 | - time::time_t time = time::TIME_ZERO; + const time::time_t time = time::TIME_ZERO; cost_field->set_costs({1, 1, 1, 1, 255, 1, 1, 1, 1}, time); // Test the different field types From 5a17e4e65e235bcef005a44b31ca1369e640414b Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 20:28:14 -0600 Subject: [PATCH 04/10] change sector is_dirty to a reference --- libopenage/pathfinding/sector.cpp | 2 +- libopenage/pathfinding/sector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libopenage/pathfinding/sector.cpp b/libopenage/pathfinding/sector.cpp index 4556fd42c3..2da73690c0 100644 --- a/libopenage/pathfinding/sector.cpp +++ b/libopenage/pathfinding/sector.cpp @@ -249,7 +249,7 @@ void Sector::connect_exits() { } } -bool Sector::is_dirty(const time::time_t time) { +bool Sector::is_dirty(const time::time_t &time) { return this->cost_field->is_dirty(time); } diff --git a/libopenage/pathfinding/sector.h b/libopenage/pathfinding/sector.h index e0f751b70d..a8aad24c01 100644 --- a/libopenage/pathfinding/sector.h +++ b/libopenage/pathfinding/sector.h @@ -109,7 +109,7 @@ class Sector { * * @param time Specified time to check. */ - bool is_dirty(const time::time_t time); + bool is_dirty(const time::time_t &time); private: /** From 22e594f80c131e6758dc3d26714da1d5e2336ed6 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:56:07 -0600 Subject: [PATCH 05/10] Change fieldCache to unique_ptr and add docs --- libopenage/pathfinding/field_cache.h | 1 - libopenage/pathfinding/integrator.h | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libopenage/pathfinding/field_cache.h b/libopenage/pathfinding/field_cache.h index a1f43a563e..87dbdf60f9 100644 --- a/libopenage/pathfinding/field_cache.h +++ b/libopenage/pathfinding/field_cache.h @@ -55,7 +55,6 @@ class FieldCache * cleared of dynamic flags, i.e. wavefront or LOS flags. These have to be recalculated * when the field is reused. */ - std::unordered_map, get_return_t, pair_hash> diff --git a/libopenage/pathfinding/integrator.h b/libopenage/pathfinding/integrator.h index 690c525ad7..7d09c00a73 100644 --- a/libopenage/pathfinding/integrator.h +++ b/libopenage/pathfinding/integrator.h @@ -128,7 +128,11 @@ class Integrator { bool evict_cache = false); private: - std::shared_ptr field_cache; + + /** + * Cache for already computed fields. + */ + std::unique_ptr field_cache; }; } // namespace path From ce77c9fe02b653c03d2b6bfd448e4306cfd78635 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:57:25 -0600 Subject: [PATCH 06/10] Grammar Co-authored-by: Christoph Heine <6852422+heinezen@users.noreply.github.com> --- libopenage/pathfinding/path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libopenage/pathfinding/path.h b/libopenage/pathfinding/path.h index ca6391bf67..8be7f802f7 100644 --- a/libopenage/pathfinding/path.h +++ b/libopenage/pathfinding/path.h @@ -37,7 +37,7 @@ struct Path { /// First waypoint is the start position of the path request. /// Last waypoint is the target position of the path request. std::vector waypoints; - /// Time path was created. + /// Time the path was created. const time::time_t time; }; From d33d4f750cd18190f2e51da0364aea8ae85e873d Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:57:41 -0600 Subject: [PATCH 07/10] Grammar Co-authored-by: Christoph Heine <6852422+heinezen@users.noreply.github.com> --- libopenage/pathfinding/path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libopenage/pathfinding/path.h b/libopenage/pathfinding/path.h index 8be7f802f7..2d1f1cd593 100644 --- a/libopenage/pathfinding/path.h +++ b/libopenage/pathfinding/path.h @@ -21,7 +21,7 @@ struct PathRequest { coord::tile start; /// Target position of the path. coord::tile target; - /// Time request was made. + /// Time the request was made. const time::time_t time; }; From 3adb80210e7c5ca52d6deefe8a0c8c2ab20708d5 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:03:37 -0600 Subject: [PATCH 08/10] Use contains() Co-authored-by: Christoph Heine <6852422+heinezen@users.noreply.github.com> --- libopenage/pathfinding/field_cache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libopenage/pathfinding/field_cache.cpp b/libopenage/pathfinding/field_cache.cpp index a798e9fbd7..81b21c8264 100644 --- a/libopenage/pathfinding/field_cache.cpp +++ b/libopenage/pathfinding/field_cache.cpp @@ -15,8 +15,7 @@ void FieldCache::evict(std::pair cache_k } bool FieldCache::is_cached(std::pair cache_key) { - auto cached = this->cache.find(cache_key); - return cached != this->cache.end(); + return this->cache.contains(cache_key); } std::shared_ptr FieldCache::get_integration_field(std::pair cache_key) { From fd72608ddceb27d52214192ca2999f711acea337 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:04:36 -0600 Subject: [PATCH 09/10] several changes --- libopenage/gamestate/map.cpp | 2 +- libopenage/pathfinding/cost_field.cpp | 31 ++++++++--------- libopenage/pathfinding/cost_field.h | 21 +++++------- libopenage/pathfinding/field_cache.cpp | 27 ++++++++------- libopenage/pathfinding/field_cache.h | 46 +++++++++++++++++--------- libopenage/pathfinding/integrator.cpp | 22 ++++++------ libopenage/pathfinding/types.h | 15 +++++++++ 7 files changed, 92 insertions(+), 72 deletions(-) diff --git a/libopenage/gamestate/map.cpp b/libopenage/gamestate/map.cpp index 8300ce273d..88578fabdb 100644 --- a/libopenage/gamestate/map.cpp +++ b/libopenage/gamestate/map.cpp @@ -49,7 +49,7 @@ Map::Map(const std::shared_ptr &state, auto sector = grid->get_sector(chunk_idx); auto cost_field = sector->get_cost_field(); - cost_field->set_cost(tile_idx, path_cost.second); + cost_field->set_cost(tile_idx, path_cost.second, time::TIME_ZERO); } } } diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index c211d169c1..d737f550c0 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -14,7 +14,7 @@ namespace openage::path { CostField::CostField(size_t size) : size{size}, cells(this->size * this->size, COST_MIN), - changed{time::TIME_MIN} { + valid_until{time::TIME_MIN} { log::log(DBG << "Created cost field with size " << this->size << "x" << this->size); } @@ -34,42 +34,39 @@ cost_t CostField::get_cost(size_t idx) const { return this->cells.at(idx); } -void CostField::set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &changed) { - this->cells[pos.ne + pos.se * this->size] = cost; - this->changed = changed; +void CostField::set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &valid_until) { + this->set_cost(pos.ne + pos.se * this->size, cost, valid_until); } -void CostField::set_cost(size_t x, size_t y, cost_t cost, const time::time_t &changed) { - this->cells[x + y * this->size] = cost; - this->changed = changed; +void CostField::set_cost(size_t x, size_t y, cost_t cost, const time::time_t &valid_until) { + this->set_cost(x + y * this->size, cost, valid_until); } -void CostField::set_cost(size_t idx, cost_t cost) { +inline void CostField::set_cost(size_t idx, cost_t cost, const time::time_t &valid_until) { this->cells[idx] = cost; - this->changed = time::TIME_ZERO; -} - -void CostField::set_cost(size_t idx, cost_t cost, const time::time_t &changed) { - this->cells[idx] = cost; - this->changed = changed; + this->valid_until = valid_until; } const std::vector &CostField::get_costs() const { return this->cells; } -void CostField::set_costs(std::vector &&cells, const time::time_t &changed) { +void CostField::set_costs(std::vector &&cells, const time::time_t &valid_until) { ENSURE(cells.size() == this->cells.size(), "cells vector has wrong size: " << cells.size() << "; expected: " << this->cells.size()); this->cells = std::move(cells); - this->changed = changed; + this->valid_until = valid_until; } bool CostField::is_dirty(const time::time_t &time) { - return time <= this->changed; + return time >= this->valid_until; +} + +void CostField::clean() { + this->valid_until = time::TIME_MAX; } } // namespace openage::path diff --git a/libopenage/pathfinding/cost_field.h b/libopenage/pathfinding/cost_field.h index e62496acf1..f70adf9251 100644 --- a/libopenage/pathfinding/cost_field.h +++ b/libopenage/pathfinding/cost_field.h @@ -79,14 +79,6 @@ class CostField { */ void set_cost(size_t x, size_t y, cost_t cost, const time::time_t &changed); - /** - * Set the cost at a specified position. - * - * @param idx Index of the cell. - * @param cost Cost to set. - */ - void set_cost(size_t idx, cost_t cost); - /** * Set the cost at a specified position. * @@ -94,7 +86,7 @@ class CostField { * @param cost Cost to set. * @param changed Time at which the cost value is changed. */ - void set_cost(size_t idx, cost_t cost, const time::time_t &changed); + inline void set_cost(size_t idx, cost_t cost, const time::time_t &changed); /** * Get the cost field values. @@ -113,11 +105,16 @@ class CostField { /** * Check if the cost field is dirty at the specified time. - * - * @param time Cost field is dirty if the cost field is accessed before the latest change to the cost field. + * + * @param time Cost field is dirty if the cost field is accessed after the time given in valid_until. */ bool is_dirty(const time::time_t &time); + /** + * Cleans the dirty flag by setting it to time_MAX. + */ + void clean(); + private: /** * Side length of the field. @@ -127,7 +124,7 @@ class CostField { /** * Time the cost field was last changed. */ - const time::time_t changed; + time::time_t &valid_until; /** * Cost field values. diff --git a/libopenage/pathfinding/field_cache.cpp b/libopenage/pathfinding/field_cache.cpp index 81b21c8264..95276b0818 100644 --- a/libopenage/pathfinding/field_cache.cpp +++ b/libopenage/pathfinding/field_cache.cpp @@ -4,28 +4,27 @@ namespace openage::path { -void FieldCache::add(std::pair cache_key, - std::shared_ptr &integration_field, - std::shared_ptr &flow_field) { - this->cache[cache_key] = std::make_pair(integration_field, flow_field); +void FieldCache::add(cache_key_t cache_key, + field_cache_t cache_entry) { + this->cache[cache_key] = cache_entry; } -void FieldCache::evict(std::pair cache_key) { - this->cache.erase(cache_key); +void FieldCache::evict(cache_key_t cache_key) { + this->cache.erase(cache_key); } -bool FieldCache::is_cached(std::pair cache_key) { - return this->cache.contains(cache_key); +bool FieldCache::is_cached(cache_key_t cache_key) { + return this->cache.contains(cache_key); } -std::shared_ptr FieldCache::get_integration_field(std::pair cache_key) { - auto cached = this->cache.find(cache_key); - return cached->second.first; +std::shared_ptr FieldCache::get_integration_field(cache_key_t cache_key) { + auto cached = this->cache.find(cache_key); + return cached->second.first; } -std::shared_ptr FieldCache::get_flow_field(std::pair cache_key) { - auto cached = this->cache.find(cache_key); - return cached->second.second; +std::shared_ptr FieldCache::get_flow_field(cache_key_t cache_key) { + auto cached = this->cache.find(cache_key); + return cached->second.second; } } // namespace openage::path diff --git a/libopenage/pathfinding/field_cache.h b/libopenage/pathfinding/field_cache.h index 87dbdf60f9..23374e5123 100644 --- a/libopenage/pathfinding/field_cache.h +++ b/libopenage/pathfinding/field_cache.h @@ -17,25 +17,39 @@ namespace path { class IntegrationField; class FlowField; -class FieldCache -{ +/** + * Cache to store already calculated flow and integration fields for the pathfinding algorithm. + */ +class FieldCache { public: - FieldCache() = default; - ~FieldCache() = default; + FieldCache() = default; + ~FieldCache() = default; - void add(std::pair cache_key, - std::shared_ptr &integration_field, - std::shared_ptr &flow_field); + /** + * Adds a new field cache entry to the cache with a given portal and sector cache key. + */ + void add(cache_key_t cache_key, + field_cache_t cache_entry); - void evict(std::pair cache_key); + /** + * Evicts a given field cache entry from the cache at the given cache key. + */ + void evict(cache_key_t cache_key); - bool is_cached(std::pair cache_key); + /** + * Checks if there is a cached entry at a specific cache key. + */ + bool is_cached(cache_key_t cache_key); - std::shared_ptr get_integration_field(std::pair cache_key); - - std::shared_ptr get_flow_field(std::pair cache_key); - - using get_return_t = std::pair, std::shared_ptr>; + /** + * Gets the integration field from a given cache entry. + */ + std::shared_ptr get_integration_field(cache_key_t cache_key); + + /** + * Gets the flow field from a given cache entry. + */ + std::shared_ptr get_flow_field(cache_key_t cache_key); private: /** @@ -55,8 +69,8 @@ class FieldCache * cleared of dynamic flags, i.e. wavefront or LOS flags. These have to be recalculated * when the field is reused. */ - std::unordered_map, - get_return_t, + std::unordered_map cache; }; diff --git a/libopenage/pathfinding/integrator.cpp b/libopenage/pathfinding/integrator.cpp index d91ac9ecb7..e164f3a094 100644 --- a/libopenage/pathfinding/integrator.cpp +++ b/libopenage/pathfinding/integrator.cpp @@ -5,10 +5,10 @@ #include "log/log.h" #include "pathfinding/cost_field.h" +#include "pathfinding/field_cache.h" #include "pathfinding/flow_field.h" #include "pathfinding/integration_field.h" #include "pathfinding/portal.h" -#include "pathfinding/field_cache.h" namespace openage::path { @@ -38,17 +38,16 @@ std::shared_ptr Integrator::integrate(const std::shared_ptr &portal, const coord::tile_delta &target, bool with_los, - bool evict_cache) { + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); if (evict_cache) { this->field_cache->evict(cache_key); } - if (this->field_cache->is_cached(cache_key)) { + else if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached integration field for portal " << portal->get_id() << " from sector " << other_sector_id); - - //retrieve cached integration field + // retrieve cached integration field auto cached_integration_field = this->field_cache->get_integration_field(cache_key); if (with_los) { @@ -107,16 +106,16 @@ std::shared_ptr Integrator::build(const std::shared_ptr &portal, bool with_los, - bool evict_cache) { + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); if (evict_cache) { this->field_cache->evict(cache_key); } - if (this->field_cache->is_cached(cache_key)) { + else if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached flow field for portal " << portal->get_id() << " from sector " << other_sector_id); - //retrieve cached flow field + // retrieve cached flow field auto cached_flow_field = this->field_cache->get_flow_field(cache_key); if (with_los) { @@ -157,17 +156,16 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ const std::shared_ptr &portal, const coord::tile_delta &target, bool with_los, - bool evict_cache) { + bool evict_cache) { auto cache_key = std::make_pair(portal->get_id(), other_sector_id); if (evict_cache) { this->field_cache->evict(cache_key); } - if (this->field_cache->is_cached(cache_key)) { + else if (this->field_cache->is_cached(cache_key)) { log::log(DBG << "Using cached integration and flow fields for portal " << portal->get_id() << " from sector " << other_sector_id); - - //retrieve cached fields + // retrieve cached fields auto cached_integration_field = this->field_cache->get_integration_field(cache_key); auto cached_flow_field = this->field_cache->get_flow_field(cache_key); diff --git a/libopenage/pathfinding/types.h b/libopenage/pathfinding/types.h index 1b48a49654..3229010a91 100644 --- a/libopenage/pathfinding/types.h +++ b/libopenage/pathfinding/types.h @@ -4,6 +4,8 @@ #include #include +#include +#include namespace openage::path { @@ -109,4 +111,17 @@ using sector_id_t = size_t; */ using portal_id_t = size_t; +class FlowField; +class IntegrationField; + +/** + * Cache key for accessing the field cache using a portal id and a sector id. + */ +using cache_key_t = std::pair; + +/** + * Returnable field cache entry pair containing an integration field and a flow field. + */ +using field_cache_t = std::pair, std::shared_ptr>; + } // namespace openage::path From b9f6bd1b826c9e293b68ef2d0c1dd48a00a17732 Mon Sep 17 00:00:00 2001 From: dmwever <56411717+dmwever@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:34:01 -0600 Subject: [PATCH 10/10] next round of changes --- libopenage/pathfinding/cost_field.cpp | 5 ----- libopenage/pathfinding/cost_field.h | 12 ++++++++---- libopenage/pathfinding/integrator.cpp | 4 +++- libopenage/pathfinding/integrator.h | 2 +- libopenage/pathfinding/path.h | 2 -- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index d737f550c0..3ba37a6242 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -42,11 +42,6 @@ void CostField::set_cost(size_t x, size_t y, cost_t cost, const time::time_t &va this->set_cost(x + y * this->size, cost, valid_until); } -inline void CostField::set_cost(size_t idx, cost_t cost, const time::time_t &valid_until) { - this->cells[idx] = cost; - this->valid_until = valid_until; -} - const std::vector &CostField::get_costs() const { return this->cells; } diff --git a/libopenage/pathfinding/cost_field.h b/libopenage/pathfinding/cost_field.h index f70adf9251..f214e30f96 100644 --- a/libopenage/pathfinding/cost_field.h +++ b/libopenage/pathfinding/cost_field.h @@ -67,7 +67,7 @@ class CostField { * @param cost Cost to set. * @param changed Time at which the cost value is changed. */ - void set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &changed); + void set_cost(const coord::tile_delta &pos, cost_t cost, const time::time_t &valid_until); /** * Set the cost at a specified position. @@ -77,7 +77,7 @@ class CostField { * @param cost Cost to set. * @param changed Time at which the cost value is changed. */ - void set_cost(size_t x, size_t y, cost_t cost, const time::time_t &changed); + void set_cost(size_t x, size_t y, cost_t cost, const time::time_t &valid_until); /** * Set the cost at a specified position. @@ -86,7 +86,11 @@ class CostField { * @param cost Cost to set. * @param changed Time at which the cost value is changed. */ - inline void set_cost(size_t idx, cost_t cost, const time::time_t &changed); + + inline void set_cost(size_t idx, cost_t cost, const time::time_t &until) { + cells[idx] = cost; + valid_until = until; + } /** * Get the cost field values. @@ -124,7 +128,7 @@ class CostField { /** * Time the cost field was last changed. */ - time::time_t &valid_until; + time::time_t valid_until; /** * Cost field values. diff --git a/libopenage/pathfinding/integrator.cpp b/libopenage/pathfinding/integrator.cpp index e164f3a094..a71845cffb 100644 --- a/libopenage/pathfinding/integrator.cpp +++ b/libopenage/pathfinding/integrator.cpp @@ -206,7 +206,9 @@ Integrator::get_return_t Integrator::get(const std::shared_ptr &cost_ std::shared_ptr cached_flow_field = std::make_shared(*flow_field); cached_flow_field->reset_dynamic_flags(); - this->field_cache->add(cache_key, cached_integration_field, cached_flow_field); + field_cache_t field_cache = field_cache_t(cached_integration_field, cached_flow_field); + + this->field_cache->add(cache_key, field_cache); return std::make_pair(integration_field, flow_field); } diff --git a/libopenage/pathfinding/integrator.h b/libopenage/pathfinding/integrator.h index 7d09c00a73..daa0e226fd 100644 --- a/libopenage/pathfinding/integrator.h +++ b/libopenage/pathfinding/integrator.h @@ -5,6 +5,7 @@ #include #include "pathfinding/types.h" +#include "pathfinding/field_cache.h" #include "util/hash.h" @@ -18,7 +19,6 @@ class CostField; class FlowField; class IntegrationField; class Portal; -class FieldCache; /** * Integrator for the flow field pathfinding algorithm. diff --git a/libopenage/pathfinding/path.h b/libopenage/pathfinding/path.h index 2d1f1cd593..df1b34a599 100644 --- a/libopenage/pathfinding/path.h +++ b/libopenage/pathfinding/path.h @@ -37,8 +37,6 @@ struct Path { /// First waypoint is the start position of the path request. /// Last waypoint is the target position of the path request. std::vector waypoints; - /// Time the path was created. - const time::time_t time; }; } // namespace openage::path