1
0
mirror of https://github.com/moparisthebest/minetest synced 2024-08-13 16:53:49 -04:00

Speedup attachement handling by replacing vector search by direct array access and secondary child lookup vector

This commit is contained in:
sapier 2014-06-08 12:49:06 +02:00
parent 56bf867874
commit 35ec3855f6
4 changed files with 49 additions and 78 deletions

View File

@ -723,52 +723,29 @@ void GenericCAO::setAttachments()
ClientActiveObject* GenericCAO::getParent() ClientActiveObject* GenericCAO::getParent()
{ {
ClientActiveObject *obj = NULL; ClientActiveObject *obj = NULL;
for(std::vector<core::vector2d<int> >::const_iterator cii = m_env->attachment_list.begin(); cii != m_env->attachment_list.end(); cii++)
{ u16 attached_id = m_env->m_attachements[getId()];
if(cii->X == getId()) // This ID is our child
{ if ((attached_id != 0) &&
if(cii->Y > 0) // A parent ID exists for our child (attached_id != getId())) {
{ obj = m_env->getActiveObject(attached_id);
if(cii->X != cii->Y) // The parent and child ID are not the same
{
obj = m_env->getActiveObject(cii->Y);
} }
}
break;
}
}
if(obj)
return obj; return obj;
return NULL;
} }
void GenericCAO::removeFromScene(bool permanent) void GenericCAO::removeFromScene(bool permanent)
{ {
if(permanent) // Should be true when removing the object permanently and false when refreshing (eg: updating visuals) 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<u16>::iterator ci = m_children.begin();
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ci != m_children.end(); ci++)
ii != m_env->attachment_list.end(); ii++)
{ {
if(ii->Y == getId()) // Is a child of our object if (m_env->m_attachements[*ci] == getId()) {
{ m_env->m_attachements[*ci] = 0;
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++)
{
if(ii->X == getId()) // Is our object
{
m_env->attachment_list.erase(ii);
break;
} }
} }
m_env->m_attachements[getId()] = 0;
} }
if(m_meshnode) if(m_meshnode)
@ -1098,13 +1075,14 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
// Attachments, part 1: All attached objects must be unparented first, // Attachments, part 1: All attached objects must be unparented first,
// or Irrlicht causes a segmentation fault // or Irrlicht causes a segmentation fault
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); for(std::vector<u16>::iterator ci = m_children.begin();
ii != m_env->attachment_list.end(); ii++) 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);
// Get the object of the child continue;
ClientActiveObject *obj = m_env->getActiveObject(ii->X); }
ClientActiveObject *obj = m_env->getActiveObject(*ci);
if(obj) if(obj)
{ {
scene::IMeshSceneNode *m_child_meshnode scene::IMeshSceneNode *m_child_meshnode
@ -1120,25 +1098,22 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
if(m_child_spritenode) if(m_child_spritenode)
m_child_spritenode->setParent(m_smgr->getRootSceneNode()); m_child_spritenode->setParent(m_smgr->getRootSceneNode());
} }
} ++ci;
} }
removeFromScene(false); removeFromScene(false);
addToScene(m_smgr, m_gamedef->tsrc(), m_irr); addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
// Attachments, part 2: Now that the parent has been refreshed, put its attachments back // 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(); for(std::vector<u16>::iterator ci = m_children.begin();
ii != m_env->attachment_list.end(); ii++) ci != m_children.end(); ci++)
{
if(ii->Y == getId()) // This is a child of our parent
{ {
// Get the object of the child // Get the object of the child
ClientActiveObject *obj = m_env->getActiveObject(ii->X); ClientActiveObject *obj = m_env->getActiveObject(*ci);
if(obj) if(obj)
obj->setAttachments(); obj->setAttachments();
} }
} }
}
// Make sure m_is_visible is always applied // Make sure m_is_visible is always applied
if(m_meshnode) if(m_meshnode)
@ -1803,16 +1778,8 @@ void GenericCAO::processMessage(const std::string &data)
updateBonePosition(); updateBonePosition();
} }
else if(cmd == GENERIC_CMD_SET_ATTACHMENT) { else if(cmd == GENERIC_CMD_SET_ATTACHMENT) {
// If an entry already exists for this object, delete it first to avoid duplicates m_env->m_attachements[getId()] = readS16(is);
for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++) m_children.push_back(m_env->m_attachements[getId()]);
{
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_attachment_bone = deSerializeString(is); m_attachment_bone = deSerializeString(is);
m_attachment_position = readV3F1000(is); m_attachment_position = readV3F1000(is);
m_attachment_rotation = readV3F1000(is); m_attachment_rotation = readV3F1000(is);

View File

@ -102,6 +102,8 @@ private:
u8 m_last_light; u8 m_last_light;
bool m_is_visible; bool m_is_visible;
std::vector<u16> m_children;
public: public:
GenericCAO(IGameDef *gamedef, ClientEnvironment *env); GenericCAO(IGameDef *gamedef, ClientEnvironment *env);

View File

@ -2078,6 +2078,8 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
m_gamedef(gamedef), m_gamedef(gamedef),
m_irr(irr) m_irr(irr)
{ {
char zero = 0;
memset(m_attachements, zero, sizeof(m_attachements));
} }
ClientEnvironment::~ClientEnvironment() ClientEnvironment::~ClientEnvironment()

View File

@ -492,7 +492,7 @@ public:
// Get event from queue. CEE_NONE is returned if queue is empty. // Get event from queue. CEE_NONE is returned if queue is empty.
ClientEnvEvent getClientEvent(); 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() std::list<std::string> getPlayerNames()
{ return m_player_names; } { return m_player_names; }