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 *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++)
for(std::vector<u16>::iterator ci = m_children.begin();
ci != m_children.end(); ci++)
{
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++)
{
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
{
// 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());
}
if (m_env->m_attachements[*ci] != getId()) {
ci = m_children.erase(ci);
continue;
}
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);
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);

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

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

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