Skip to content

Commit 35ec385

Browse files
sapiersapier
sapier
authored and
sapier
committed
Speedup attachement handling by replacing vector search by direct array access and secondary child lookup vector
1 parent 56bf867 commit 35ec385

File tree

4 files changed

+48
-77
lines changed

4 files changed

+48
-77
lines changed

src/content_cao.cpp

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -723,52 +723,29 @@ void GenericCAO::setAttachments()
723723
ClientActiveObject* GenericCAO::getParent()
724724
{
725725
ClientActiveObject *obj = NULL;
726-
for(std::vector<core::vector2d<int> >::const_iterator cii = m_env->attachment_list.begin(); cii != m_env->attachment_list.end(); cii++)
727-
{
728-
if(cii->X == getId()) // This ID is our child
729-
{
730-
if(cii->Y > 0) // A parent ID exists for our child
731-
{
732-
if(cii->X != cii->Y) // The parent and child ID are not the same
733-
{
734-
obj = m_env->getActiveObject(cii->Y);
735-
}
736-
}
737-
break;
738-
}
726+
727+
u16 attached_id = m_env->m_attachements[getId()];
728+
729+
if ((attached_id != 0) &&
730+
(attached_id != getId())) {
731+
obj = m_env->getActiveObject(attached_id);
739732
}
740-
if(obj)
741-
return obj;
742-
return NULL;
733+
return obj;
743734
}
744735

745736
void GenericCAO::removeFromScene(bool permanent)
746737
{
747738
if(permanent) // Should be true when removing the object permanently and false when refreshing (eg: updating visuals)
748739
{
749-
// Detach this object's children
750-
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
751-
ii != m_env->attachment_list.end(); ii++)
752-
{
753-
if(ii->Y == getId()) // Is a child of our object
754-
{
755-
ii->Y = 0;
756-
// Get the object of the child
757-
ClientActiveObject *obj = m_env->getActiveObject(ii->X);
758-
if(obj)
759-
obj->setAttachments();
760-
}
761-
}
762-
// Delete this object from the attachments list
763-
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
764-
ii != m_env->attachment_list.end(); ii++)
740+
for(std::vector<u16>::iterator ci = m_children.begin();
741+
ci != m_children.end(); ci++)
765742
{
766-
if(ii->X == getId()) // Is our object
767-
{
768-
m_env->attachment_list.erase(ii);
769-
break;
743+
if (m_env->m_attachements[*ci] == getId()) {
744+
m_env->m_attachements[*ci] = 0;
770745
}
771746
}
747+
748+
m_env->m_attachements[getId()] = 0;
772749
}
773750

774751
if(m_meshnode)
@@ -1098,45 +1075,43 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
10981075

10991076
// Attachments, part 1: All attached objects must be unparented first,
11001077
// or Irrlicht causes a segmentation fault
1101-
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
1102-
ii != m_env->attachment_list.end(); ii++)
1078+
for(std::vector<u16>::iterator ci = m_children.begin();
1079+
ci != m_children.end();)
11031080
{
1104-
if(ii->Y == getId()) // This is a child of our parent
1081+
if (m_env->m_attachements[*ci] != getId()) {
1082+
ci = m_children.erase(ci);
1083+
continue;
1084+
}
1085+
ClientActiveObject *obj = m_env->getActiveObject(*ci);
1086+
if(obj)
11051087
{
1106-
// Get the object of the child
1107-
ClientActiveObject *obj = m_env->getActiveObject(ii->X);
1108-
if(obj)
1109-
{
1110-
scene::IMeshSceneNode *m_child_meshnode
1111-
= obj->getMeshSceneNode();
1112-
scene::IAnimatedMeshSceneNode *m_child_animated_meshnode
1113-
= obj->getAnimatedMeshSceneNode();
1114-
scene::IBillboardSceneNode *m_child_spritenode
1115-
= obj->getSpriteSceneNode();
1116-
if(m_child_meshnode)
1117-
m_child_meshnode->setParent(m_smgr->getRootSceneNode());
1118-
if(m_child_animated_meshnode)
1119-
m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
1120-
if(m_child_spritenode)
1121-
m_child_spritenode->setParent(m_smgr->getRootSceneNode());
1122-
}
1088+
scene::IMeshSceneNode *m_child_meshnode
1089+
= obj->getMeshSceneNode();
1090+
scene::IAnimatedMeshSceneNode *m_child_animated_meshnode
1091+
= obj->getAnimatedMeshSceneNode();
1092+
scene::IBillboardSceneNode *m_child_spritenode
1093+
= obj->getSpriteSceneNode();
1094+
if(m_child_meshnode)
1095+
m_child_meshnode->setParent(m_smgr->getRootSceneNode());
1096+
if(m_child_animated_meshnode)
1097+
m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
1098+
if(m_child_spritenode)
1099+
m_child_spritenode->setParent(m_smgr->getRootSceneNode());
11231100
}
1101+
++ci;
11241102
}
11251103

11261104
removeFromScene(false);
11271105
addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
11281106

11291107
// Attachments, part 2: Now that the parent has been refreshed, put its attachments back
1130-
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
1131-
ii != m_env->attachment_list.end(); ii++)
1108+
for(std::vector<u16>::iterator ci = m_children.begin();
1109+
ci != m_children.end(); ci++)
11321110
{
1133-
if(ii->Y == getId()) // This is a child of our parent
1134-
{
11351111
// Get the object of the child
1136-
ClientActiveObject *obj = m_env->getActiveObject(ii->X);
1112+
ClientActiveObject *obj = m_env->getActiveObject(*ci);
11371113
if(obj)
11381114
obj->setAttachments();
1139-
}
11401115
}
11411116
}
11421117

@@ -1803,16 +1778,8 @@ void GenericCAO::processMessage(const std::string &data)
18031778
updateBonePosition();
18041779
}
18051780
else if(cmd == GENERIC_CMD_SET_ATTACHMENT) {
1806-
// If an entry already exists for this object, delete it first to avoid duplicates
1807-
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
1808-
{
1809-
if(ii->X == getId()) // This is the ID of our object
1810-
{
1811-
m_env->attachment_list.erase(ii);
1812-
break;
1813-
}
1814-
}
1815-
m_env->attachment_list.push_back(core::vector2d<int>(getId(), readS16(is)));
1781+
m_env->m_attachements[getId()] = readS16(is);
1782+
m_children.push_back(m_env->m_attachements[getId()]);
18161783
m_attachment_bone = deSerializeString(is);
18171784
m_attachment_position = readV3F1000(is);
18181785
m_attachment_rotation = readV3F1000(is);

src/content_cao.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class GenericCAO : public ClientActiveObject
102102
u8 m_last_light;
103103
bool m_is_visible;
104104

105+
std::vector<u16> m_children;
106+
105107
public:
106108
GenericCAO(IGameDef *gamedef, ClientEnvironment *env);
107109

src/environment.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,7 +1379,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
13791379
{
13801380
assert(obj);
13811381

1382-
v3f objectpos = obj->getBasePosition();
1382+
v3f objectpos = obj->getBasePosition();
13831383

13841384
// The block in which the object resides in
13851385
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@@ -1591,7 +1591,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
15911591
object->m_static_block = blockpos;
15921592

15931593
if(set_changed)
1594-
block->raiseModified(MOD_STATE_WRITE_NEEDED,
1594+
block->raiseModified(MOD_STATE_WRITE_NEEDED,
15951595
"addActiveObjectRaw");
15961596
} else {
15971597
v3s16 p = floatToInt(objectpos, BS);
@@ -1828,7 +1828,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
18281828
If force_delete is set, active object is deleted nevertheless. It
18291829
shall only be set so in the destructor of the environment.
18301830
1831-
If block wasn't generated (not in memory or on disk),
1831+
If block wasn't generated (not in memory or on disk),
18321832
*/
18331833
void ServerEnvironment::deactivateFarObjects(bool force_delete)
18341834
{
@@ -1849,7 +1849,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
18491849
continue;
18501850

18511851
u16 id = i->first;
1852-
v3f objectpos = obj->getBasePosition();
1852+
v3f objectpos = obj->getBasePosition();
18531853

18541854
// The block in which the object resides in
18551855
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@@ -2078,6 +2078,8 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
20782078
m_gamedef(gamedef),
20792079
m_irr(irr)
20802080
{
2081+
char zero = 0;
2082+
memset(m_attachements, zero, sizeof(m_attachements));
20812083
}
20822084

20832085
ClientEnvironment::~ClientEnvironment()

src/environment.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ class ClientEnvironment : public Environment
492492
// Get event from queue. CEE_NONE is returned if queue is empty.
493493
ClientEnvEvent getClientEvent();
494494

495-
std::vector<core::vector2d<int> > attachment_list; // X is child ID, Y is parent ID
495+
u16 m_attachements[USHRT_MAX];
496496

497497
std::list<std::string> getPlayerNames()
498498
{ return m_player_names; }

0 commit comments

Comments
 (0)