Speedup attachement handling by replacing vector search by direct array access and...
authorsapier <Sapier at GMX dot net>
Sun, 8 Jun 2014 10:49:06 +0000 (12:49 +0200)
committersapier <Sapier at GMX dot net>
Sun, 22 Jun 2014 22:13:41 +0000 (00:13 +0200)
src/content_cao.cpp
src/content_cao.h
src/environment.cpp
src/environment.h

index b7923ff80d4c02bc03cf980da0232b413eb0b573..bd90e96a540dc7e303f7dd4a162c181cd722c442 100644 (file)
@@ -723,52 +723,29 @@ void GenericCAO::setAttachments()
 ClientActiveObject* GenericCAO::getParent()
 {
        ClientActiveObject *obj = NULL;
-       for(std::vector<core::vector2d<int> >::const_iterator cii = m_env->attachment_list.begin(); cii != m_env->attachment_list.end(); cii++)
-       {
-               if(cii->X == getId()) // This ID is our child
-               {
-                       if(cii->Y > 0) // A parent ID exists for our child
-                       {
-                               if(cii->X != cii->Y) // The parent and child ID are not the same
-                               {
-                                       obj = m_env->getActiveObject(cii->Y);
-                               }
-                       }
-                       break;
-               }
+
+       u16 attached_id = m_env->m_attachements[getId()];
+
+       if ((attached_id != 0) &&
+                       (attached_id != getId())) {
+               obj = m_env->getActiveObject(attached_id);
        }
-       if(obj)
-               return obj;
-       return NULL;
+       return obj;
 }
 
 void GenericCAO::removeFromScene(bool permanent)
 {
        if(permanent) // Should be true when removing the object permanently and false when refreshing (eg: updating visuals)
        {
-               // Detach this object's children
-               for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
-                               ii != m_env->attachment_list.end(); ii++)
-               {
-                       if(ii->Y == getId()) // Is a child of our object
-                       {
-                               ii->Y = 0;
-                               // Get the object of the child
-                               ClientActiveObject *obj = m_env->getActiveObject(ii->X);
-                               if(obj)
-                                       obj->setAttachments();
-                       }
-               }
-               // Delete this object from the attachments list
-               for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
-                               ii != m_env->attachment_list.end(); ii++)
+               for(std::vector<u16>::iterator ci = m_children.begin();
+                                               ci != m_children.end(); ci++)
                {
-                       if(ii->X == getId()) // Is our object
-                       {
-                               m_env->attachment_list.erase(ii);
-                               break;
+                       if (m_env->m_attachements[*ci] == getId()) {
+                               m_env->m_attachements[*ci] = 0;
                        }
                }
+
+               m_env->m_attachements[getId()] = 0;
        }
 
        if(m_meshnode)
@@ -1098,45 +1075,43 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 
                // Attachments, part 1: All attached objects must be unparented first,
                // or Irrlicht causes a segmentation fault
-               for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
-                               ii != m_env->attachment_list.end(); ii++)
+               for(std::vector<u16>::iterator ci = m_children.begin();
+                               ci != m_children.end();)
                {
-                       if(ii->Y == getId()) // This is a child of our parent
+                       if (m_env->m_attachements[*ci] != getId()) {
+                               ci = m_children.erase(ci);
+                               continue;
+                       }
+                       ClientActiveObject *obj = m_env->getActiveObject(*ci);
+                       if(obj)
                        {
-                               // Get the object of the child
-                               ClientActiveObject *obj = m_env->getActiveObject(ii->X);
-                               if(obj)
-                               {
-                                       scene::IMeshSceneNode *m_child_meshnode
-                                                       = obj->getMeshSceneNode();
-                                       scene::IAnimatedMeshSceneNode *m_child_animated_meshnode
-                                                       = obj->getAnimatedMeshSceneNode();
-                                       scene::IBillboardSceneNode *m_child_spritenode
-                                                       = obj->getSpriteSceneNode();
-                                       if(m_child_meshnode)
-                                               m_child_meshnode->setParent(m_smgr->getRootSceneNode());
-                                       if(m_child_animated_meshnode)
-                                               m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
-                                       if(m_child_spritenode)
-                                               m_child_spritenode->setParent(m_smgr->getRootSceneNode());
-                               }
+                               scene::IMeshSceneNode *m_child_meshnode
+                                               = obj->getMeshSceneNode();
+                               scene::IAnimatedMeshSceneNode *m_child_animated_meshnode
+                                               = obj->getAnimatedMeshSceneNode();
+                               scene::IBillboardSceneNode *m_child_spritenode
+                                               = obj->getSpriteSceneNode();
+                               if(m_child_meshnode)
+                                       m_child_meshnode->setParent(m_smgr->getRootSceneNode());
+                               if(m_child_animated_meshnode)
+                                       m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
+                               if(m_child_spritenode)
+                                       m_child_spritenode->setParent(m_smgr->getRootSceneNode());
                        }
+                       ++ci;
                }
 
                removeFromScene(false);
                addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
 
                // Attachments, part 2: Now that the parent has been refreshed, put its attachments back
-               for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
-                               ii != m_env->attachment_list.end(); ii++)
+               for(std::vector<u16>::iterator ci = m_children.begin();
+                                               ci != m_children.end(); ci++)
                {
-                       if(ii->Y == getId()) // This is a child of our parent
-                       {
                                // Get the object of the child
-                               ClientActiveObject *obj = m_env->getActiveObject(ii->X);
+                               ClientActiveObject *obj = m_env->getActiveObject(*ci);
                                if(obj)
                                        obj->setAttachments();
-                       }
                }
        }
 
@@ -1803,16 +1778,8 @@ void GenericCAO::processMessage(const std::string &data)
                updateBonePosition();
        }
        else if(cmd == GENERIC_CMD_SET_ATTACHMENT) {
-               // If an entry already exists for this object, delete it first to avoid duplicates
-               for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
-               {
-                       if(ii->X == getId()) // This is the ID of our object
-                       {
-                               m_env->attachment_list.erase(ii);
-                               break;
-                       }
-               }
-               m_env->attachment_list.push_back(core::vector2d<int>(getId(), readS16(is)));
+               m_env->m_attachements[getId()] = readS16(is);
+               m_children.push_back(m_env->m_attachements[getId()]);
                m_attachment_bone = deSerializeString(is);
                m_attachment_position = readV3F1000(is);
                m_attachment_rotation = readV3F1000(is);
index 1e55babf2fd0c6fbfdf4adb563208c8a41e46544..bf27ed79ad8c3eac09cf50a9559c6ce46d623b54 100644 (file)
@@ -102,6 +102,8 @@ private:
        u8 m_last_light;
        bool m_is_visible;
 
+       std::vector<u16> m_children;
+
 public:
        GenericCAO(IGameDef *gamedef, ClientEnvironment *env);
 
index fa7ce2ae57f5e27d505342239d34479bd0e84429..8103998c3c847d219caecc9bb40763b5ee44fe88 100644 (file)
@@ -1379,7 +1379,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
 {
        assert(obj);
 
-       v3f objectpos = obj->getBasePosition(); 
+       v3f objectpos = obj->getBasePosition();
 
        // The block in which the object resides in
        v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@@ -1591,7 +1591,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                        object->m_static_block = blockpos;
 
                        if(set_changed)
-                               block->raiseModified(MOD_STATE_WRITE_NEEDED, 
+                               block->raiseModified(MOD_STATE_WRITE_NEEDED,
                                                "addActiveObjectRaw");
                } else {
                        v3s16 p = floatToInt(objectpos, BS);
@@ -1828,7 +1828,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
        If force_delete is set, active object is deleted nevertheless. It
        shall only be set so in the destructor of the environment.
 
-       If block wasn't generated (not in memory or on disk), 
+       If block wasn't generated (not in memory or on disk),
 */
 void ServerEnvironment::deactivateFarObjects(bool force_delete)
 {
@@ -1849,7 +1849,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        continue;
 
                u16 id = i->first;
-               v3f objectpos = obj->getBasePosition(); 
+               v3f objectpos = obj->getBasePosition();
 
                // The block in which the object resides in
                v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@@ -2078,6 +2078,8 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
        m_gamedef(gamedef),
        m_irr(irr)
 {
+       char zero = 0;
+       memset(m_attachements, zero, sizeof(m_attachements));
 }
 
 ClientEnvironment::~ClientEnvironment()
index 5062b9c370e79bd66fb0e6985b34fe692fd36b67..cecc9133a43a73164511e1140f5ecca0a9c2f9b6 100644 (file)
@@ -492,7 +492,7 @@ public:
        // Get event from queue. CEE_NONE is returned if queue is empty.
        ClientEnvEvent getClientEvent();
 
-       std::vector<core::vector2d<int> > attachment_list; // X is child ID, Y is parent ID
+       u16 m_attachements[USHRT_MAX];
 
        std::list<std::string> getPlayerNames()
        { return m_player_names; }