Ticket #1707: RangeManagerOpt.2.patch

File RangeManagerOpt.2.patch, 13.0 KB (added by wraitii, 9 years ago)
  • 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
  • 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        {
    607             if (it->second.inWorld)
     608            if (it->second.inWorld) // also checks validity as default is false.
    608609                m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z));
    609610        }
    610611    }
     
    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
    729             if (CalcOwnerMask(it->second.owner) & ownerMask)
     730            if (it->first != INVALID_ENTITY && CalcOwnerMask(it->second.owner) & ownerMask)
    730731                entities.push_back(it->first);
    731732        }
    732733
     
    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            {
     840                if (it->first == INVALID_ENTITY)
     841                    continue;
    839842                if (!TestEntityQuery(q, it->first, it->second))
    840843                    continue;
    841844
     
    845848        else
    846849        {
    847850            // Get a quick list of entities that are potentially in range
    848             std::vector<entity_id_t> ents = m_Subdivision.GetNear(pos, q.maxRange);
     851            std::vector<entity_id_t> ents = m_Subdivision.GetNearUnsorted(pos, q.maxRange);
    849852
    850853            for (size_t i = 0; i < ents.size(); ++i)
    851854            {
    852                 std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.find(ents[i]);
     855                EntityMap<EntityData>::const_iterator it = m_EntityData.find(ents[i]);
    853856                ENSURE(it != m_EntityData.end());
    854857
    855858                if (!TestEntityQuery(q, it->first, it->second))
     
    975978
    976979    virtual void SetEntityFlag(entity_id_t ent, std::string identifier, bool value)
    977980    {
    978         std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     981        EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    979982
    980983        // We don't have this entity
    981984        if (it == m_EntityData.end())
  • 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
  • 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
     27private:
     28    std::vector<value_type> m_Data;
     29    size_t m_Size;
     30
     31public:
     32    inline EntityMap() : m_Data(), m_Size(0)
     33    {
     34    }
     35
     36    inline EntityMap(const EntityMap& m) : m_Data(m.m_Data), m_Size(m.m_Size)
     37    {
     38    }
     39
     40    // Iterators
     41
     42    inline iterator begin()
     43    {
     44        iterator it(m_Data.begin());
     45        if (size() != 0 && it->first == INVALID_ENTITY)
     46            while (it != end() && (it++)->first == INVALID_ENTITY);
     47        return it;
     48    }
     49    inline iterator end()
     50    {
     51        if (size() == 0) return begin();
     52        return m_Data.end();
     53    }
     54    inline const_iterator begin() const
     55    {
     56        const_iterator it(m_Data.begin());
     57        if (size() != 0 && it->first == INVALID_ENTITY)
     58            while (it != end() && (it++)->first == INVALID_ENTITY);
     59        return it;
     60    }
     61    inline const_iterator end() const
     62    {
     63        if (size() == 0) return begin();
     64        return m_Data.end();
     65    }
     66
     67    // Capacity
     68    inline bool empty() const                   { return m_Size == 0;   }
     69    inline size_type size() const               { return m_Size;        }
     70
     71    // Modification
     72    std::pair<iterator, bool> insert(const value_type& val)
     73    {
     74        difference_type index = val.first;
     75        bool new_index = false; // was a new element created?
     76        if (index >= (int)m_Data.size())
     77        {
     78            m_Data.resize(index + 1);
     79            new_index = true;
     80            ++m_Size;
     81        }
     82        m_Data[index] = val;
     83        return std::make_pair(iterator(&m_Data[index]), new_index); // false: element existed
     84    }
     85   
     86    void erase(iterator it)
     87    {
     88        // only reliable way right now? or we could try ~T() and memset null?
     89        it->first = INVALID_ENTITY; // mark it as 'invalid entity_id'
     90        it->second.~T(); // call dtor
     91        new (&it->second) T(); // call placement new
     92        --m_Size;
     93    }
     94   
     95    size_type erase(const key_type& key)
     96    {
     97        iterator it = find(key);
     98        if (it != end())
     99            erase(it);
     100        return 1;
     101    }
     102   
     103    inline void swap(EntityMap &map)
     104    {
     105        m_Data.swap(map.m_Data);
     106    }
     107
     108    inline void clear()
     109    {
     110        m_Size = 0;
     111        m_Data.clear();
     112    }
     113
     114    // Operations
     115    inline iterator find(const key_type& key)
     116    {
     117        if (key < m_Data.size())
     118        {
     119            const value_type& val = m_Data[key];
     120            if (val.first != INVALID_ENTITY) // is this a valid element?
     121                return iterator(&m_Data[key]);
     122        }
     123        return end(); // not found
     124    }
     125
     126    inline const_iterator find(const key_type& key) const
     127    {
     128        if (key < m_Data.size())
     129        {
     130            const value_type& val = m_Data[key];
     131            if (val.first != INVALID_ENTITY) // is this a valid element?
     132                return const_iterator(&m_Data[key]);
     133        }
     134        return end(); // not found
     135    }
     136   
     137    inline size_type count(const key_type& key) const
     138    {
     139        return find(key) == end() ? 0 : 1;
     140    }
     141};
     142#endif