Ticket #1707: RangeManagerOpt.patch

File RangeManagerOpt.patch, 13.2 KB (added by wraitii, 9 years ago)
  • Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/components/CCmpRangeManager.cpp

     
    2626#include "simulation2/components/ICmpVision.h"
    2727#include "simulation2/helpers/Render.h"
    2828#include "simulation2/helpers/Spatial.h"
     29#include "simulation2/helpers/EntityMap.h"
    2930
    3031#include "graphics/Overlay.h"
    3132#include "graphics/Terrain.h"
     
    149150 */
    150151struct EntityDistanceOrdering
    151152{
    152     EntityDistanceOrdering(const std::map<entity_id_t, EntityData>& entities, const CFixedVector2D& source) :
     153    EntityDistanceOrdering(const EntityMap<EntityData>& entities, const CFixedVector2D& source) :
    153154        m_EntityData(entities), m_Source(source)
    154155    {
    155156    }
     
    163164        return (vecA.CompareLength(vecB) < 0);
    164165    }
    165166
    166     const std::map<entity_id_t, EntityData>& m_EntityData;
     167    const EntityMap<EntityData>& m_EntityData;
    167168    CFixedVector2D m_Source;
    168169
    169170private:
     
    210211    // Range query state:
    211212    tag_t m_QueryNext; // next allocated id
    212213    std::map<tag_t, Query> m_Queries;
    213     std::map<entity_id_t, EntityData> m_EntityData;
     214    EntityMap<EntityData> m_EntityData;
    214215    SpatialSubdivision<entity_id_t> m_Subdivision; // spatial index of m_EntityData
    215216
    216217    // LOS state:
     
    288289
    289290        serialize.NumberU32_Unbounded("query next", m_QueryNext);
    290291        SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries);
    291         SerializeMap<SerializeU32_Unbounded, SerializeEntityData>()(serialize, "entity data", m_EntityData);
     292        SerializeEntityMap<SerializeEntityData>()(serialize, "entity data", m_EntityData);
    292293
    293294        SerializeMap<SerializeI32_Unbounded, SerializeBool>()(serialize, "los reveal all", m_LosRevealAll);
    294295        serialize.Bool("los circular", m_LosCircular);
     
    359360            const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg);
    360361            entity_id_t ent = msgData.entity;
    361362
    362             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     363            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    363364
    364365            // Ignore if we're not already tracking this entity
    365366            if (it == m_EntityData.end())
     
    406407            const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    407408            entity_id_t ent = msgData.entity;
    408409
    409             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     410            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    410411
    411412            // Ignore if we're not already tracking this entity
    412413            if (it == m_EntityData.end())
     
    429430            const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg);
    430431            entity_id_t ent = msgData.entity;
    431432
    432             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     433            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    433434
    434435            // Ignore if we're not already tracking this entity
    435436            if (it == m_EntityData.end())
     
    451452            const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg);
    452453            entity_id_t ent = msgData.entity;
    453454
    454             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     455            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    455456
    456457            // Ignore if we're not already tracking this entity
    457458            if (it == m_EntityData.end())
     
    576577        m_LosStateRevealed.clear();
    577578        m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide);
    578579
    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)
    580581        {
    581582            if (it->second.inWorld)
    582583                LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z));
     
    602603        // (TODO: find the optimal number instead of blindly guessing)
    603604        m_Subdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE));
    604605
    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)
    606607        {
    607608            if (it->second.inWorld)
    608609                m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z));
     
    723724
    724725        u32 ownerMask = CalcOwnerMask(player);
    725726
    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)
    727728        {
    728729            // Check owner and add to list if it matches
    729730            if (CalcOwnerMask(it->second.owner) & ownerMask)
     
    834835        // Special case: range -1.0 means check all entities ignoring distance
    835836        if (q.maxRange == entity_pos_t::FromInt(-1))
    836837        {
    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)
    838839            {
    839840                if (!TestEntityQuery(q, it->first, it->second))
    840841                    continue;
     
    845846        else
    846847        {
    847848            // 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);
    849850
    850851            for (size_t i = 0; i < ents.size(); ++i)
    851852            {
    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]);
    853854                ENSURE(it != m_EntityData.end());
    854855
    855856                if (!TestEntityQuery(q, it->first, it->second))
     
    975976
    976977    virtual void SetEntityFlag(entity_id_t ent, std::string identifier, bool value)
    977978    {
    978         std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     979        EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    979980
    980981        // We don't have this entity
    981982        if (it == m_EntityData.end())
  • Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/helpers/Spatial.h

     
    215215
    216216        return GetInRange(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range));
    217217    }
     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    }
    218258
    219259private:
    220260    // 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 */
     12template<typename T> class EntityMap
     13{
     14public:
     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
     29private:
     30    std::vector<value_type> m_Data;
     31
     32public:
     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

     
    2424 */
    2525
    2626#include "simulation2/components/ICmpPathfinder.h"
     27#include "simulation2/helpers/EntityMap.h"
    2728
    2829template<typename ELEM>
    2930struct SerializeVector
     
    8788    }
    8889};
    8990
     91template<typename VS>
     92struct 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
    90123// We have to order the map before serializing to make things consistent
    91124template<typename KS, typename VS>
    92125struct SerializeUnorderedMap