diff --git a/source/simulation2/components/CCmpObstructionManager.cpp b/source/simulation2/components/CCmpObstructionManager.cpp index 6494284442..4fa06a8e2f 100644 --- a/source/simulation2/components/CCmpObstructionManager.cpp +++ b/source/simulation2/components/CCmpObstructionManager.cpp @@ -547,9 +547,9 @@ bool CCmpObstructionManager::TestLine(const IObstructionTestFilter& filter, enti CFixedVector2D posMin (std::min(x0, x1) - r, std::min(z0, z1) - r); CFixedVector2D posMax (std::max(x0, x1) + r, std::max(z0, z1) + r); - SpatialQueryArray unitShapes; + std::vector unitShapes; m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax); - for (int i = 0; i < unitShapes.size(); ++i) + for (size_t i = 0; i < unitShapes.size(); ++i) { std::map::iterator it = m_UnitShapes.find(unitShapes[i]); ENSURE(it != m_UnitShapes.end()); @@ -563,9 +563,9 @@ bool CCmpObstructionManager::TestLine(const IObstructionTestFilter& filter, enti return true; } - SpatialQueryArray staticShapes; + std::vector staticShapes; m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax); - for (int i = 0; i < staticShapes.size(); ++i) + for (size_t i = 0; i < staticShapes.size(); ++i) { std::map::iterator it = m_StaticShapes.find(staticShapes[i]); ENSURE(it != m_StaticShapes.end()); @@ -885,9 +885,9 @@ void CCmpObstructionManager::GetObstructionsInRange(const IObstructionTestFilter ENSURE(x0 <= x1 && z0 <= z1); - SpatialQueryArray unitShapes; + std::vector unitShapes; m_UnitSubdivision.GetInRange(unitShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); - for (int i = 0; i < unitShapes.size(); ++i) + for (size_t i = 0; i < unitShapes.size(); ++i) { std::map::iterator it = m_UnitShapes.find(unitShapes[i]); ENSURE(it != m_UnitShapes.end()); @@ -907,9 +907,9 @@ void CCmpObstructionManager::GetObstructionsInRange(const IObstructionTestFilter squares.push_back(s); } - SpatialQueryArray staticShapes; + std::vector staticShapes; m_StaticSubdivision.GetInRange(staticShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); - for (int i = 0; i < staticShapes.size(); ++i) + for (size_t i = 0; i < staticShapes.size(); ++i) { std::map::iterator it = m_StaticShapes.find(staticShapes[i]); ENSURE(it != m_StaticShapes.end()); diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index f61deab5f3..af64223c51 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -981,10 +981,10 @@ public: CFixedVector3D pos3d = cmpSourcePosition->GetPosition()+ CFixedVector3D(entity_pos_t::Zero(), q.elevationBonus, entity_pos_t::Zero()) ; // Get a quick list of entities that are potentially in range, with a cutoff of 2*maxRange - SpatialQueryArray ents; + std::vector ents; m_Subdivision.GetNear(ents, pos, q.maxRange*2); - for (int i = 0; i < ents.size(); ++i) + for (size_t i = 0; i < ents.size(); ++i) { EntityMap::const_iterator it = m_EntityData.find(ents[i]); ENSURE(it != m_EntityData.end()); @@ -1018,10 +1018,10 @@ public: else { // Get a quick list of entities that are potentially in range - SpatialQueryArray ents; + std::vector ents; m_Subdivision.GetNear(ents, pos, q.maxRange); - for (int i = 0; i < ents.size(); ++i) + for (size_t i = 0; i < ents.size(); ++i) { EntityMap::const_iterator it = m_EntityData.find(ents[i]); ENSURE(it != m_EntityData.end()); diff --git a/source/simulation2/helpers/Selection.cpp b/source/simulation2/helpers/Selection.cpp index fc83f6fb45..d0e3d04742 100644 --- a/source/simulation2/helpers/Selection.cpp +++ b/source/simulation2/helpers/Selection.cpp @@ -49,12 +49,12 @@ std::vector EntitySelection::PickEntitiesAtPoint(CSimulation2& simu CFixedVector2D pos(fixed::FromFloat(pos3d.X), fixed::FromFloat(pos3d.Z)); // Get a rough group of entities using our approximated origin. - SpatialQueryArray ents; + std::vector ents; cmpRangeManager->GetSubdivision()->GetNear(ents, pos, entity_pos_t::FromInt(range)); // Filter for relevent entities and calculate precise distances. std::vector > hits; // (dist^2, entity) pairs - for (int i = 0; i < ents.size(); ++i) + for (size_t i = 0; i < ents.size(); ++i) { CmpPtr cmpSelectable(simulation, ents[i]); if (!cmpSelectable) diff --git a/source/simulation2/helpers/Spatial.h b/source/simulation2/helpers/Spatial.h index cd3b8d8a40..d7f507f71e 100644 --- a/source/simulation2/helpers/Spatial.h +++ b/source/simulation2/helpers/Spatial.h @@ -20,36 +20,10 @@ #include "simulation2/system/Component.h" #include "simulation2/serialization/SerializeTemplates.h" -#include "ps/CLogger.h" - -/** - * A simple fixed-size array that works similar to an std::vector - * but is obviously limited in its max items - */ -struct SpatialQueryArray -{ - enum { MAX_COUNT = 2048 }; - int count; - uint32_t items[MAX_COUNT]; - - inline SpatialQueryArray() : count(0) {} - inline const uint32_t& operator[](int index) const { return items[index]; } - inline uint32_t& operator[](int index) { return items[index]; } - inline int size() const { return count; } - inline void clear() { count = 0; } - void make_unique() // removes any duplicate entries - { - if (count) - { - std::sort(items, items + count); // we need a sorted list for std::unique to work - count = int(std::unique(items, items + count) - items); - } - } -}; /** * A very basic subdivision scheme for finding items in ranges. - * Items are stored in lists in fixed-size divisions. + * Items are stored in lists in dynamic-sized divisions. * Items have a size (min/max values of their axis-aligned bounding box) * and are stored in all divisions overlapping that area. * @@ -80,23 +54,9 @@ class SpatialSubdivision items.pop_back(); } - void copy_items(SpatialQueryArray& out) + void copy_items_at_end(std::vector& out) { - if (items.empty()) - return; // nothing to copy - - int dsti = out.count; // the index in [out] where to start copying - int count = (int)items.size(); - if ((dsti + count) > SpatialQueryArray::MAX_COUNT) - { - LOGWARNING(L"SpatialSubdivision Query too large. Results truncated."); - count = SpatialQueryArray::MAX_COUNT - dsti; // don't copy overflowing items - } - uint32_t* dst = &out.items[dsti]; - uint32_t* src = &items[0]; - for (int i = 0; i < count; ++i) // copy all items - dst[i] = src[i]; - out.count += count; + out.insert(out.end(), items.begin(), items.end()); } }; @@ -288,7 +248,7 @@ public: * Returns a sorted list of unique items that includes all items * within the given axis-aligned square range. */ - void GetInRange(SpatialQueryArray& out, CFixedVector2D posMin, CFixedVector2D posMax) + void GetInRange(std::vector& out, CFixedVector2D posMin, CFixedVector2D posMax) { out.clear(); ENSURE(posMin.X <= posMax.X && posMin.Y <= posMax.Y); @@ -301,18 +261,19 @@ public: { for (u32 i = i0; i <= i1; ++i) { - m_Divisions[i + j*m_DivisionsW].copy_items(out); + m_Divisions[i + j*m_DivisionsW].copy_items_at_end(out); } } // some buildings span several tiles, so we need to make it unique - out.make_unique(); + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); } /** * Returns a sorted list of unique items that includes all items * within the given circular distance of the given point. */ - void GetNear(SpatialQueryArray& out, CFixedVector2D pos, entity_pos_t range) + void GetNear(std::vector& out, CFixedVector2D pos, entity_pos_t range) { // TODO: be cleverer and return a circular pattern of divisions, // not this square over-approximation