Ticket #1707: RangeManagerOpt.patch
File RangeManagerOpt.patch, 13.2 KB (added by , 11 years ago) |
---|
-
Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/components/CCmpRangeManager.cpp
26 26 #include "simulation2/components/ICmpVision.h" 27 27 #include "simulation2/helpers/Render.h" 28 28 #include "simulation2/helpers/Spatial.h" 29 #include "simulation2/helpers/EntityMap.h" 29 30 30 31 #include "graphics/Overlay.h" 31 32 #include "graphics/Terrain.h" … … 149 150 */ 150 151 struct EntityDistanceOrdering 151 152 { 152 EntityDistanceOrdering(const std::map<entity_id_t,EntityData>& entities, const CFixedVector2D& source) :153 EntityDistanceOrdering(const EntityMap<EntityData>& entities, const CFixedVector2D& source) : 153 154 m_EntityData(entities), m_Source(source) 154 155 { 155 156 } … … 163 164 return (vecA.CompareLength(vecB) < 0); 164 165 } 165 166 166 const std::map<entity_id_t,EntityData>& m_EntityData;167 const EntityMap<EntityData>& m_EntityData; 167 168 CFixedVector2D m_Source; 168 169 169 170 private: … … 210 211 // Range query state: 211 212 tag_t m_QueryNext; // next allocated id 212 213 std::map<tag_t, Query> m_Queries; 213 std::map<entity_id_t,EntityData> m_EntityData;214 EntityMap<EntityData> m_EntityData; 214 215 SpatialSubdivision<entity_id_t> m_Subdivision; // spatial index of m_EntityData 215 216 216 217 // LOS state: … … 288 289 289 290 serialize.NumberU32_Unbounded("query next", m_QueryNext); 290 291 SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries); 291 Serialize Map<SerializeU32_Unbounded,SerializeEntityData>()(serialize, "entity data", m_EntityData);292 SerializeEntityMap<SerializeEntityData>()(serialize, "entity data", m_EntityData); 292 293 293 294 SerializeMap<SerializeI32_Unbounded, SerializeBool>()(serialize, "los reveal all", m_LosRevealAll); 294 295 serialize.Bool("los circular", m_LosCircular); … … 359 360 const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg); 360 361 entity_id_t ent = msgData.entity; 361 362 362 std::map<entity_id_t,EntityData>::iterator it = m_EntityData.find(ent);363 EntityMap<EntityData>::iterator it = m_EntityData.find(ent); 363 364 364 365 // Ignore if we're not already tracking this entity 365 366 if (it == m_EntityData.end()) … … 406 407 const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); 407 408 entity_id_t ent = msgData.entity; 408 409 409 std::map<entity_id_t,EntityData>::iterator it = m_EntityData.find(ent);410 EntityMap<EntityData>::iterator it = m_EntityData.find(ent); 410 411 411 412 // Ignore if we're not already tracking this entity 412 413 if (it == m_EntityData.end()) … … 429 430 const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg); 430 431 entity_id_t ent = msgData.entity; 431 432 432 std::map<entity_id_t,EntityData>::iterator it = m_EntityData.find(ent);433 EntityMap<EntityData>::iterator it = m_EntityData.find(ent); 433 434 434 435 // Ignore if we're not already tracking this entity 435 436 if (it == m_EntityData.end()) … … 451 452 const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg); 452 453 entity_id_t ent = msgData.entity; 453 454 454 std::map<entity_id_t,EntityData>::iterator it = m_EntityData.find(ent);455 EntityMap<EntityData>::iterator it = m_EntityData.find(ent); 455 456 456 457 // Ignore if we're not already tracking this entity 457 458 if (it == m_EntityData.end()) … … 576 577 m_LosStateRevealed.clear(); 577 578 m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide); 578 579 579 for ( std::map<entity_id_t,EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)580 for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) 580 581 { 581 582 if (it->second.inWorld) 582 583 LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z)); … … 602 603 // (TODO: find the optimal number instead of blindly guessing) 603 604 m_Subdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE)); 604 605 605 for ( std::map<entity_id_t,EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)606 for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) 606 607 { 607 608 if (it->second.inWorld) 608 609 m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z)); … … 723 724 724 725 u32 ownerMask = CalcOwnerMask(player); 725 726 726 for ( std::map<entity_id_t,EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)727 for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) 727 728 { 728 729 // Check owner and add to list if it matches 729 730 if (CalcOwnerMask(it->second.owner) & ownerMask) … … 834 835 // Special case: range -1.0 means check all entities ignoring distance 835 836 if (q.maxRange == entity_pos_t::FromInt(-1)) 836 837 { 837 for ( std::map<entity_id_t,EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)838 for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) 838 839 { 839 840 if (!TestEntityQuery(q, it->first, it->second)) 840 841 continue; … … 845 846 else 846 847 { 847 848 // Get a quick list of entities that are potentially in range 848 std::vector<entity_id_t> ents = m_Subdivision.GetNear (pos, q.maxRange);849 std::vector<entity_id_t> ents = m_Subdivision.GetNearUnsorted(pos, q.maxRange); 849 850 850 851 for (size_t i = 0; i < ents.size(); ++i) 851 852 { 852 std::map<entity_id_t,EntityData>::const_iterator it = m_EntityData.find(ents[i]);853 EntityMap<EntityData>::const_iterator it = m_EntityData.find(ents[i]); 853 854 ENSURE(it != m_EntityData.end()); 854 855 855 856 if (!TestEntityQuery(q, it->first, it->second)) … … 975 976 976 977 virtual void SetEntityFlag(entity_id_t ent, std::string identifier, bool value) 977 978 { 978 std::map<entity_id_t,EntityData>::iterator it = m_EntityData.find(ent);979 EntityMap<EntityData>::iterator it = m_EntityData.find(ent); 979 980 980 981 // We don't have this entity 981 982 if (it == m_EntityData.end()) -
Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/helpers/Spatial.h
215 215 216 216 return GetInRange(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range)); 217 217 } 218 219 /** 220 * Returns a list of items that includes all items 221 * within the given axis-aligned square range. 222 * This version is unsorted, which is faster if that's not required. 223 * However the result might contain some entities twice or more. 224 */ 225 std::vector<T> GetInRangeUnsorted(CFixedVector2D posMin, CFixedVector2D posMax) 226 { 227 std::vector<T> ret; 228 229 ENSURE(posMin.X <= posMax.X && posMin.Y <= posMax.Y); 230 231 u32 i0 = GetI0(posMin.X); 232 u32 j0 = GetJ0(posMin.Y); 233 u32 i1 = GetI1(posMax.X); 234 u32 j1 = GetJ1(posMax.Y); 235 for (u32 j = j0; j <= j1; ++j) 236 { 237 for (u32 i = i0; i <= i1; ++i) 238 { 239 std::vector<T>& div = m_Divisions[i + j*m_DivisionsW]; 240 ret.insert(ret.end(), div.begin(), div.end()); 241 } 242 } 243 return ret; 244 } 245 246 /** 247 * Returns a sorted list of unique items that includes all items 248 * within the given circular distance of the given point. 249 * This returns unsorted results. 250 */ 251 std::vector<T> GetNearUnsorted(CFixedVector2D pos, entity_pos_t range) 252 { 253 // TODO: be cleverer and return a circular pattern of divisions, 254 // not this square over-approximation 255 256 return GetInRangeUnsorted(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range)); 257 } 218 258 219 259 private: 220 260 // Helper functions for translating coordinates into division indexes -
Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/helpers/EntityMap.h
1 #ifndef INCLUDED_ENTITYMAP 2 #define INCLUDED_ENTITYMAP 3 4 /** 5 * A fast replacement for map<entity_id_t, T>. 6 * We make the following assumptions: 7 * - entity id's (keys) are unique and are inserted in increasing order 8 * - an entity id that was removed is never added again 9 * - modifications (add / delete) are far less frequent then look-ups 10 * - preformance for iteration is important 11 */ 12 template<typename T> class EntityMap 13 { 14 public: 15 // Map interface: 16 // Member types 17 typedef entity_id_t key_type; 18 typedef T mapped_type; 19 typedef std::pair<entity_id_t, T> value_type; 20 21 typedef typename std::vector<value_type>::difference_type difference_type; 22 typedef typename std::vector<value_type>::size_type size_type; 23 24 typedef typename std::vector<value_type>::iterator iterator; 25 typedef typename std::vector<value_type>::const_iterator const_iterator; 26 typedef typename std::vector<value_type>::reverse_iterator reverse_iterator; 27 typedef typename std::vector<value_type>::const_reverse_iterator const_reverse_iterator; 28 29 private: 30 std::vector<value_type> m_Data; 31 32 public: 33 inline EntityMap() : m_Data() 34 { 35 } 36 37 inline EntityMap(const EntityMap& m) : m_Data(m.m_Data) 38 { 39 } 40 41 // Iterators 42 inline iterator begin() { return m_Data.begin(); } 43 inline iterator end() { return m_Data.end(); } 44 inline const_iterator begin() const { return m_Data.begin(); } 45 inline const_iterator end() const { return m_Data.end(); } 46 inline reverse_iterator rbegin() { return m_Data.rbegin(); } 47 inline reverse_iterator rend() { return m_Data.rend(); } 48 inline const_reverse_iterator rbegin() const{ return m_Data.rbegin(); } 49 inline const_reverse_iterator rend() const { return m_Data.rend(); } 50 51 // Capacity 52 inline bool empty() const { return m_Data.empty(); } 53 inline size_type size() const { return m_Data.size(); } 54 inline size_type max_size() const { return m_Data.max_size(); } 55 56 // Modification 57 std::pair<iterator, bool> insert(const value_type& val) 58 { 59 difference_type index = val.first; 60 bool new_index = false; // was a new element created? 61 if (index >= (int)m_Data.size()) 62 { 63 m_Data.resize(index + 1); 64 new_index = true; 65 } 66 m_Data[index] = val; 67 return std::make_pair(m_Data.begin() + index, new_index); // false: element existed 68 } 69 70 void erase(iterator it) 71 { 72 // only reliable way right now? or we could try ~T() and memset null? 73 it->first = -1; // mark it as 'invalid entity_id' 74 it->second.~T(); // call dtor 75 new (&it->second) T(); // call placement new 76 } 77 78 size_type erase(const key_type& key) 79 { 80 size_type count = 0; 81 iterator it = find(key); 82 if (it != end()) 83 { 84 erase(it); 85 count = 1; 86 } 87 return count; 88 } 89 90 inline void swap(EntityMap &map) 91 { 92 m_Data.swap(map.m_Data); 93 } 94 95 inline void clear() 96 { 97 m_Data.clear(); 98 } 99 100 // Operations 101 inline iterator find(const key_type& key) 102 { 103 if (key < m_Data.size()) 104 { 105 const value_type& val = m_Data[key]; 106 if (val.first != -1) // is this a valid element? 107 return m_Data.begin() + key; 108 } 109 return m_Data.end(); // not found 110 } 111 112 inline const_iterator find(const key_type& key) const 113 { 114 if (key < m_Data.size()) 115 { 116 const value_type& val = m_Data[key]; 117 if (val.first != -1) // is this a valid element? 118 return m_Data.begin() + key; 119 } 120 return m_Data.end(); // not found 121 } 122 123 inline size_type count(const key_type& key) const 124 { 125 return find(key) == end() ? 0 : 1; 126 } 127 }; 128 #endif -
Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/serialization/SerializeTemplates.h
24 24 */ 25 25 26 26 #include "simulation2/components/ICmpPathfinder.h" 27 #include "simulation2/helpers/EntityMap.h" 27 28 28 29 template<typename ELEM> 29 30 struct SerializeVector … … 87 88 } 88 89 }; 89 90 91 template<typename VS> 92 struct SerializeEntityMap 93 { 94 template<typename V> 95 void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<V>& value) 96 { 97 size_t len = value.size(); 98 serialize.NumberU32_Unbounded("length", (u32)len); 99 for (typename EntityMap<V>::iterator it = value.begin(); it != value.end(); ++it) 100 { 101 serialize.NumberU32_Unbounded("key", it->first); 102 VS()(serialize, "value", it->second); 103 } 104 } 105 106 template<typename V> 107 void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<V>& value) 108 { 109 value.clear(); 110 u32 len; 111 deserialize.NumberU32_Unbounded("length", len); 112 for (size_t i = 0; i < len; ++i) 113 { 114 entity_id_t k; 115 deserialize.NumberU32_Unbounded("key", k); 116 V v; 117 VS()(deserialize, "value", v); 118 value.insert(std::make_pair(k, v)); 119 } 120 } 121 }; 122 90 123 // We have to order the map before serializing to make things consistent 91 124 template<typename KS, typename VS> 92 125 struct SerializeUnorderedMap