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

@ -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,45 +1075,43 @@ 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);
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());
}
} }
ClientActiveObject *obj = m_env->getActiveObject(*ci);
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());
}
++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();
}
} }
} }
@ -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);

@ -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);

@ -1379,7 +1379,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
{ {
assert(obj); assert(obj);
v3f objectpos = obj->getBasePosition(); v3f objectpos = obj->getBasePosition();
// The block in which the object resides in // The block in which the object resides in
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@ -1591,7 +1591,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
object->m_static_block = blockpos; object->m_static_block = blockpos;
if(set_changed) if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"addActiveObjectRaw"); "addActiveObjectRaw");
} else { } else {
v3s16 p = floatToInt(objectpos, BS); 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 If force_delete is set, active object is deleted nevertheless. It
shall only be set so in the destructor of the environment. 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) void ServerEnvironment::deactivateFarObjects(bool force_delete)
{ {
@ -1849,7 +1849,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
continue; continue;
u16 id = i->first; u16 id = i->first;
v3f objectpos = obj->getBasePosition(); v3f objectpos = obj->getBasePosition();
// The block in which the object resides in // The block in which the object resides in
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
@ -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()

@ -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; }