Ticket #1707: rangeManagerOptimizations.patch

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

     
    129129struct SerializeEntityData
    130130{
    131131    template<typename S>
    132     void operator()(S& serialize, const char* UNUSED(name), EntityData& value)
     132    void operator()(S& serialize, const char* UNUSED(name), EntityData* value)
    133133    {
    134         serialize.NumberFixed_Unbounded("x", value.x);
    135         serialize.NumberFixed_Unbounded("z", value.z);
    136         serialize.NumberFixed_Unbounded("vision", value.visionRange);
    137         serialize.NumberU8("retain in fog", value.retainInFog, 0, 1);
    138         serialize.NumberI8_Unbounded("owner", value.owner);
    139         serialize.NumberU8("in world", value.inWorld, 0, 1);
    140         serialize.NumberU8_Unbounded("flags", value.flags);
     134        serialize.NumberFixed_Unbounded("x", value->x);
     135        serialize.NumberFixed_Unbounded("z", value->z);
     136        serialize.NumberFixed_Unbounded("vision", value->visionRange);
     137        serialize.NumberU8("retain in fog", value->retainInFog, 0, 1);
     138        serialize.NumberI8_Unbounded("owner", value->owner);
     139        serialize.NumberU8("in world", value->inWorld, 0, 1);
     140        serialize.NumberU8_Unbounded("flags", value->flags);
    141141    }
    142142};
    143143
     
    149149 */
    150150struct EntityDistanceOrdering
    151151{
    152     EntityDistanceOrdering(const std::map<entity_id_t, EntityData>& entities, const CFixedVector2D& source) :
     152    EntityDistanceOrdering(const std::vector<EntityData*>& entities, const CFixedVector2D& source) :
    153153        m_EntityData(entities), m_Source(source)
    154154    {
    155155    }
    156156
    157157    bool operator()(entity_id_t a, entity_id_t b)
    158158    {
    159         const EntityData& da = m_EntityData.find(a)->second;
    160         const EntityData& db = m_EntityData.find(b)->second;
    161         CFixedVector2D vecA = CFixedVector2D(da.x, da.z) - m_Source;
    162         CFixedVector2D vecB = CFixedVector2D(db.x, db.z) - m_Source;
     159        const EntityData* da = m_EntityData[a];
     160        const EntityData* db = m_EntityData[b];
     161        if (da == NULL)
     162            return false;
     163        if (db == NULL)
     164            return false;
     165        CFixedVector2D vecA = CFixedVector2D(da->x, da->z) - m_Source;
     166        CFixedVector2D vecB = CFixedVector2D(db->x, db->z) - m_Source;
    163167        return (vecA.CompareLength(vecB) < 0);
    164168    }
    165169
    166     const std::map<entity_id_t, EntityData>& m_EntityData;
     170    const std::vector<EntityData*>& m_EntityData;
    167171    CFixedVector2D m_Source;
    168172
    169173private:
     
    210214    // Range query state:
    211215    tag_t m_QueryNext; // next allocated id
    212216    std::map<tag_t, Query> m_Queries;
    213     std::map<entity_id_t, EntityData> m_EntityData;
     217    //std::map<entity_id_t, EntityData> m_EntityData;
     218    std::vector<EntityData*> m_EntityData;
    214219    SpatialSubdivision<entity_id_t> m_Subdivision; // spatial index of m_EntityData
    215220
    216221    // LOS state:
     
    284289
    285290        serialize.NumberU32_Unbounded("query next", m_QueryNext);
    286291        SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries);
    287         SerializeMap<SerializeU32_Unbounded, SerializeEntityData>()(serialize, "entity data", m_EntityData);
     292        //SerializeVector<SerializeEntityData>()(serialize, "entity data array", m_EntityData);
    288293
    289294        SerializeMap<SerializeI32_Unbounded, SerializeBool>()(serialize, "los reveal all", m_LosRevealAll);
    290295        serialize.Bool("los circular", m_LosCircular);
     
    335340            // The newly-created entity will have owner -1 and position out-of-world
    336341            // (any initialisation of those values will happen later), so we can just
    337342            // use the default-constructed EntityData here
    338             EntityData entdata;
    339 
     343            EntityData* entdata = new EntityData;
     344           
    340345            // Store the LOS data, if any
    341346            CmpPtr<ICmpVision> cmpVision(GetSimContext(), ent);
    342347            if (cmpVision)
    343348            {
    344                 entdata.visionRange = cmpVision->GetRange();
    345                 entdata.retainInFog = (cmpVision->GetRetainInFog() ? 1 : 0);
     349                entdata->visionRange = cmpVision->GetRange();
     350                entdata->retainInFog = (cmpVision->GetRetainInFog() ? 1 : 0);
    346351            }
    347352
    348353            // Remember this entity
    349             m_EntityData.insert(std::make_pair(ent, entdata));
     354            if (ent >= m_EntityData.size()) {
     355                m_EntityData.resize(ent+1);
     356            }
     357            m_EntityData[ent] = entdata;
    350358
    351359            break;
    352360        }
     
    355363            const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg);
    356364            entity_id_t ent = msgData.entity;
    357365
    358             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
    359 
    360366            // Ignore if we're not already tracking this entity
    361             if (it == m_EntityData.end())
     367            if (ent >= m_EntityData.size())
    362368                break;
    363369
     370            EntityData* entData = m_EntityData[ent];
     371
    364372            if (msgData.inWorld)
    365373            {
    366                 if (it->second.inWorld)
     374                if (entData->inWorld)
    367375                {
    368                     CFixedVector2D from(it->second.x, it->second.z);
     376                    CFixedVector2D from(entData->x, entData->z);
    369377                    CFixedVector2D to(msgData.x, msgData.z);
    370378                    m_Subdivision.Move(ent, from, to);
    371                     LosMove(it->second.owner, it->second.visionRange, from, to);
     379                    LosMove(entData->owner, entData->visionRange, from, to);
    372380                }
    373381                else
    374382                {
    375383                    CFixedVector2D to(msgData.x, msgData.z);
    376384                    m_Subdivision.Add(ent, to);
    377                     LosAdd(it->second.owner, it->second.visionRange, to);
     385                    LosAdd(entData->owner, entData->visionRange, to);
    378386                }
    379387
    380                 it->second.inWorld = 1;
    381                 it->second.x = msgData.x;
    382                 it->second.z = msgData.z;
     388                entData->inWorld = 1;
     389                entData->x = msgData.x;
     390                entData->z = msgData.z;
    383391            }
    384392            else
    385393            {
    386                 if (it->second.inWorld)
     394                if (entData->inWorld)
    387395                {
    388                     CFixedVector2D from(it->second.x, it->second.z);
     396                    CFixedVector2D from(entData->x, entData->z);
    389397                    m_Subdivision.Remove(ent, from);
    390                     LosRemove(it->second.owner, it->second.visionRange, from);
     398                    LosRemove(entData->owner, entData->visionRange, from);
    391399                }
    392400
    393                 it->second.inWorld = 0;
    394                 it->second.x = entity_pos_t::Zero();
    395                 it->second.z = entity_pos_t::Zero();
     401                entData->inWorld = 0;
     402                entData->x = entity_pos_t::Zero();
     403                entData->z = entity_pos_t::Zero();
    396404            }
    397405
    398406            break;
     
    402410            const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    403411            entity_id_t ent = msgData.entity;
    404412
    405             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
    406 
    407413            // Ignore if we're not already tracking this entity
    408             if (it == m_EntityData.end())
     414            if (ent >= m_EntityData.size())
    409415                break;
    410416
    411             if (it->second.inWorld)
     417            EntityData* entData = m_EntityData[ent];
     418           
     419            if (entData->inWorld)
    412420            {
    413                 CFixedVector2D pos(it->second.x, it->second.z);
    414                 LosRemove(it->second.owner, it->second.visionRange, pos);
    415                 LosAdd(msgData.to, it->second.visionRange, pos);
     421                CFixedVector2D pos(entData->x, entData->z);
     422                LosRemove(entData->owner, entData->visionRange, pos);
     423                LosAdd(msgData.to, entData->visionRange, pos);
    416424            }
    417425
    418426            ENSURE(-128 <= msgData.to && msgData.to <= 127);
    419             it->second.owner = (i8)msgData.to;
    420 
     427            entData->owner = (i8)msgData.to;
     428           
    421429            break;
    422430        }
    423431        case MT_Destroy:
     
    425433            const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg);
    426434            entity_id_t ent = msgData.entity;
    427435
    428             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
    429 
    430436            // Ignore if we're not already tracking this entity
    431             if (it == m_EntityData.end())
     437            if (ent >= m_EntityData.size())
    432438                break;
    433439
    434             if (it->second.inWorld)
    435                 m_Subdivision.Remove(ent, CFixedVector2D(it->second.x, it->second.z));
     440            EntityData* entData = m_EntityData[ent];
    436441
    437             // This will be called after Ownership's OnDestroy, so ownership will be set
    438             // to -1 already and we don't have to do a LosRemove here
    439             ENSURE(it->second.owner == -1);
     442            if (entData != NULL && entData->inWorld)
     443                m_Subdivision.Remove(ent, CFixedVector2D(entData->x, entData->z));
    440444
    441             m_EntityData.erase(it);
     445            SAFE_DELETE(entData);
     446            m_EntityData[ent] = NULL;
    442447
    443448            break;
    444449        }
     
    447452            const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg);
    448453            entity_id_t ent = msgData.entity;
    449454
    450             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
    451 
    452455            // Ignore if we're not already tracking this entity
    453             if (it == m_EntityData.end())
     456            if (ent >= m_EntityData.size())
    454457                break;
    455 
     458           
     459            EntityData* entData = m_EntityData[ent];
     460           
    456461            CmpPtr<ICmpVision> cmpVision(GetSimContext(), ent);
    457462            if (!cmpVision)
    458463                break;
    459464
    460             entity_pos_t oldRange = it->second.visionRange;
     465            entity_pos_t oldRange = entData->visionRange;
    461466            entity_pos_t newRange = msgData.newRange;
    462467
    463468            // If the range changed and the entity's in-world, we need to manually adjust it
    464469            //  but if it's not in-world, we only need to set the new vision range
    465             CFixedVector2D pos(it->second.x, it->second.z);
    466             if (it->second.inWorld)
    467                 LosRemove(it->second.owner, oldRange, pos);
     470            CFixedVector2D pos(entData->x, entData->z);
     471            if (entData->inWorld)
     472                LosRemove(entData->owner, oldRange, pos);
    468473
    469             it->second.visionRange = newRange;
     474            entData->visionRange = newRange;
    470475
    471             if (it->second.inWorld)
    472                 LosAdd(it->second.owner, newRange, pos);
     476            if (entData->inWorld)
     477                LosAdd(entData->owner, newRange, pos);
    473478
    474479            break;
    475480        }
     
    555560        m_LosStateRevealed.clear();
    556561        m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide);
    557562
    558         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     563        for (size_t i = 0; i < m_EntityData.size(); ++i)
    559564        {
    560             if (it->second.inWorld)
    561                 LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z));
     565            if (m_EntityData[i] != NULL && m_EntityData[i]->inWorld)
     566                LosAdd(m_EntityData[i]->owner, m_EntityData[i]->visionRange, CFixedVector2D(m_EntityData[i]->x, m_EntityData[i]->z));
    562567        }
    563568
    564569        for (ssize_t j = 0; j < m_TerrainVerticesPerSide; ++j)
     
    572577        // (TODO: find the optimal number instead of blindly guessing)
    573578        m_Subdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE));
    574579
    575         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     580        for (size_t i = 0; i < m_EntityData.size(); ++i)
    576581        {
    577             if (it->second.inWorld)
    578                 m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z));
     582            if (m_EntityData[i] != NULL && m_EntityData[i]->inWorld)
     583                m_Subdivision.Add(i, CFixedVector2D(m_EntityData[i]->x, m_EntityData[i]->z));
    579584        }
    580585    }
    581586
     
    643648            return r;
    644649        }
    645650
     651        PROFILE_START("perform");
    646652        PerformQuery(q, r);
     653        PROFILE_END("perform");
    647654
    648655        // Return the list sorted by distance from the entity
    649656        CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
     
    693700
    694701        u32 ownerMask = CalcOwnerMask(player);
    695702
    696         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     703        for (size_t i = 0; i < m_EntityData.size(); ++i)
    697704        {
    698705            // Check owner and add to list if it matches
    699             if (CalcOwnerMask(it->second.owner) & ownerMask)
    700                 entities.push_back(it->first);
     706            if (m_EntityData[i] != NULL && CalcOwnerMask(m_EntityData[i]->owner) & ownerMask)
     707                entities.push_back(i);
    701708        }
    702709
    703710        return entities;
     
    766773    /**
    767774     * Returns whether the given entity matches the given query (ignoring maxRange)
    768775     */
    769     bool TestEntityQuery(const Query& q, entity_id_t id, const EntityData& entity)
     776    bool TestEntityQuery(const Query& q, entity_id_t id, const EntityData* entity)
    770777    {
    771778        // Quick filter to ignore entities with the wrong owner
    772         if (!(CalcOwnerMask(entity.owner) & q.ownersMask))
     779        if (!(CalcOwnerMask(entity->owner) & q.ownersMask))
    773780            return false;
    774781
    775782        // Ignore entities not present in the world
    776         if (!entity.inWorld)
     783        if (!entity->inWorld)
    777784            return false;
    778785
    779786        // Ignore entities that don't match the current flags
    780         if (!(entity.flags & q.flagsMask))
     787        if (!(entity->flags & q.flagsMask))
    781788            return false;
    782789
    783790        // Ignore self
     
    804811        // Special case: range -1.0 means check all entities ignoring distance
    805812        if (q.maxRange == entity_pos_t::FromInt(-1))
    806813        {
    807             for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     814            for (size_t i = 0; i < m_EntityData.size(); ++i)
    808815            {
    809                 if (!TestEntityQuery(q, it->first, it->second))
     816                if (m_EntityData[i] == NULL || !TestEntityQuery(q, i, m_EntityData[i]))
    810817                    continue;
    811818
    812                 r.push_back(it->first);
     819                r.push_back(i);
    813820            }
    814821        }
    815822        else
    816823        {
    817824            // Get a quick list of entities that are potentially in range
    818             std::vector<entity_id_t> ents = m_Subdivision.GetNear(pos, q.maxRange);
     825            std::vector<entity_id_t> ents;
     826            PROFILE_START("GetNear");
     827            //ents = m_Subdivision.GetNear(pos, q.maxRange);
     828            ents = m_Subdivision.GetNearUnsorted(pos, q.maxRange);
     829            PROFILE_END("GetNear");
    819830
    820831            for (size_t i = 0; i < ents.size(); ++i)
    821832            {
    822                 std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.find(ents[i]);
    823                 ENSURE(it != m_EntityData.end());
    824 
    825                 if (!TestEntityQuery(q, it->first, it->second))
     833                const EntityData* entData = m_EntityData[ents[i]];
     834               
     835                if (!TestEntityQuery(q, ents[i], entData))
    826836                    continue;
    827837
    828838                // Restrict based on precise distance
    829                 int distVsMax = (CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(q.maxRange);
     839                int distVsMax = (CFixedVector2D(entData->x, entData->z) - pos).CompareLength(q.maxRange);
    830840                if (distVsMax > 0)
    831841                    continue;
    832842
    833843                if (!q.minRange.IsZero())
    834844                {
    835                     int distVsMin = (CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(q.minRange);
     845                    int distVsMin = (CFixedVector2D(entData->x, entData->z) - pos).CompareLength(q.minRange);
    836846                    if (distVsMin < 0)
    837847                        continue;
    838848                }
    839849
    840                 r.push_back(it->first);
     850                r.push_back(ents[i]);
    841851            }
    842852        }
    843853    }
     
    945955   
    946956    virtual void SetEntityFlag(entity_id_t ent, std::string identifier, bool value)
    947957    {
    948         std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
    949 
    950958        // We don't have this entity
    951         if (it == m_EntityData.end())
     959        if (ent >= m_EntityData.size())
    952960            return;
    953961
     962        EntityData* entData = m_EntityData[ent];
     963       
    954964        u8 flag = GetEntityFlagMask(identifier);
    955965
    956966        // We don't have a flag set
     
    961971        }
    962972
    963973        if (value)
    964             it->second.flags |= flag;
     974            entData->flags |= flag;
    965975        else
    966             it->second.flags &= ~flag;
     976            entData->flags &= ~flag;
    967977    }
    968978
    969979    // ****************************************************************
  • Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/components/CCmpObstructionManager.cpp

     
    544544    CFixedVector2D posMin (std::min(x0, x1) - r, std::min(z0, z1) - r);
    545545    CFixedVector2D posMax (std::max(x0, x1) + r, std::max(z0, z1) + r);
    546546
    547     std::vector<u32> unitShapes = m_UnitSubdivision.GetInRange(posMin, posMax);
     547    std::vector<u32> unitShapes = m_UnitSubdivision.GetInRangeUnsorted(posMin, posMax);
    548548    for (size_t i = 0; i < unitShapes.size(); ++i)
    549549    {
    550550        std::map<u32, UnitShape>::iterator it = m_UnitShapes.find(unitShapes[i]);
     
    559559            return true;
    560560    }
    561561
    562     std::vector<u32> staticShapes = m_StaticSubdivision.GetInRange(posMin, posMax);
     562    std::vector<u32> staticShapes = m_StaticSubdivision.GetInRangeUnsorted(posMin, posMax);
    563563    for (size_t i = 0; i < staticShapes.size(); ++i)
    564564    {
    565565        std::map<u32, StaticShape>::iterator it = m_StaticShapes.find(staticShapes[i]);
     
    880880
    881881    ENSURE(x0 <= x1 && z0 <= z1);
    882882
    883     std::vector<u32> unitShapes = m_UnitSubdivision.GetInRange(CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
     883    std::vector<u32> unitShapes = m_UnitSubdivision.GetInRangeUnsorted(CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
    884884    for (size_t i = 0; i < unitShapes.size(); ++i)
    885885    {
    886886        std::map<u32, UnitShape>::iterator it = m_UnitShapes.find(unitShapes[i]);
     
    901901        squares.push_back(s);
    902902    }
    903903
    904     std::vector<u32> staticShapes = m_StaticSubdivision.GetInRange(CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
     904    std::vector<u32> staticShapes = m_StaticSubdivision.GetInRangeUnsorted(CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
    905905    for (size_t i = 0; i < staticShapes.size(); ++i)
    906906    {
    907907        std::map<u32, StaticShape>::iterator it = m_StaticShapes.find(staticShapes[i]);
  • Users/lancelot/Desktop/0ad-svn/trunk/source/simulation2/helpers/Spatial.h

     
    203203
    204204        return ret;
    205205    }
     206   
     207    /**
     208     * Returns a sorted list of unique items that includes all items
     209     * within the given axis-aligned square range.
     210     */
     211    std::vector<T> GetInRangeUnsorted(CFixedVector2D posMin, CFixedVector2D posMax)
     212    {
     213        std::vector<T> ret;
     214       
     215        ENSURE(posMin.X <= posMax.X && posMin.Y <= posMax.Y);
     216       
     217        u32 i0 = GetI0(posMin.X);
     218        u32 j0 = GetJ0(posMin.Y);
     219        u32 i1 = GetI1(posMax.X);
     220        u32 j1 = GetJ1(posMax.Y);
     221        for (u32 j = j0; j <= j1; ++j)
     222        {
     223            for (u32 i = i0; i <= i1; ++i)
     224            {
     225                std::vector<T>& div = m_Divisions[i + j*m_DivisionsW];
     226                ret.insert(ret.end(), div.begin(), div.end());
     227            }
     228        }
     229       
     230        // Remove duplicates
     231        //std::sort(ret.begin(), ret.end());
     232        //ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
     233       
     234        return ret;
     235    }
    206236
    207237    /**
    208238     * Returns a sorted list of unique items that includes all items
     
    216246        return GetInRange(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range));
    217247    }
    218248
     249    /**
     250     * Returns a sorted list of unique items that includes all items
     251     * within the given circular distance of the given point.
     252     */
     253    std::vector<T> GetNearUnsorted(CFixedVector2D pos, entity_pos_t range)
     254    {
     255        // TODO: be cleverer and return a circular pattern of divisions,
     256        // not this square over-approximation
     257       
     258        return GetInRangeUnsorted(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range));
     259    }
     260   
    219261private:
    220262    // Helper functions for translating coordinates into division indexes
    221263    // (avoiding out-of-bounds accesses, and rounding correctly so that