mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-17 01:10:10 +00:00
Remove unused actors and navmeshes on update
When there is only one actor (player) on a scene and it moving to other cell first it will be removed from navigator then added. Remove cause navmesh removing for its half extents. After it is added navmesh for same half extents is created and added. While this all happens there are still jobs for old navmesh are processing. Old navmesh still exists because it is stored by shared pointer. So jobs take tiles from cache and place them into old navmesh. After that other jobs take same tiles from cache (half extents and coordinates are equal) and place them into other navmesh. dtNavMesh changes tile data on add and remove. Adding tile to two dtNavMesh corrupts tile in both nameshes.
This commit is contained in:
parent
1078708da0
commit
0479ebf5ae
@ -80,14 +80,6 @@ namespace
|
||||
EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), NavigatorException);
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_removed_agent_should_return_empty)
|
||||
{
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->removeAgent(mAgentHalfExtents);
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>());
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent)
|
||||
{
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
|
@ -21,10 +21,10 @@ namespace DetourNavigator
|
||||
void NavigatorImpl::removeAgent(const osg::Vec3f& agentHalfExtents)
|
||||
{
|
||||
const auto it = mAgents.find(agentHalfExtents);
|
||||
if (it == mAgents.end() || --it->second)
|
||||
if (it == mAgents.end())
|
||||
return;
|
||||
mAgents.erase(it);
|
||||
mNavMeshManager.reset(agentHalfExtents);
|
||||
if (it->second > 0)
|
||||
--it->second;
|
||||
}
|
||||
|
||||
bool NavigatorImpl::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform)
|
||||
@ -113,6 +113,7 @@ namespace DetourNavigator
|
||||
|
||||
void NavigatorImpl::update(const osg::Vec3f& playerPosition)
|
||||
{
|
||||
removeUnusedNavMeshes();
|
||||
for (const auto& v : mAgents)
|
||||
mNavMeshManager.update(playerPosition, v.first);
|
||||
}
|
||||
@ -156,4 +157,15 @@ namespace DetourNavigator
|
||||
inserted.first->second = updateId;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigatorImpl::removeUnusedNavMeshes()
|
||||
{
|
||||
for (auto it = mAgents.begin(); it != mAgents.end();)
|
||||
{
|
||||
if (it->second == 0 && mNavMeshManager.reset(it->first))
|
||||
it = mAgents.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ namespace DetourNavigator
|
||||
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
|
||||
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
|
||||
void updateId(const ObjectId id, const ObjectId waterId, std::unordered_map<ObjectId, ObjectId>& ids);
|
||||
void removeUnusedNavMeshes();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,20 @@ namespace
|
||||
{
|
||||
return current == add ? current : ChangeType::mixed;
|
||||
}
|
||||
|
||||
/// Safely reset shared_ptr with definite underlying object destrutor call.
|
||||
/// Assuming there is another thread holding copy of this shared_ptr or weak_ptr to this shared_ptr.
|
||||
template <class T>
|
||||
bool resetIfUnique(std::shared_ptr<T>& ptr)
|
||||
{
|
||||
const std::weak_ptr<T> weak = std::move(ptr);
|
||||
if (auto shared = weak.lock())
|
||||
{
|
||||
ptr = std::move(shared);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DetourNavigator
|
||||
@ -83,9 +97,15 @@ namespace DetourNavigator
|
||||
log("cache add for agent=", agentHalfExtents);
|
||||
}
|
||||
|
||||
void NavMeshManager::reset(const osg::Vec3f& agentHalfExtents)
|
||||
bool NavMeshManager::reset(const osg::Vec3f& agentHalfExtents)
|
||||
{
|
||||
const auto it = mCache.find(agentHalfExtents);
|
||||
if (it == mCache.end())
|
||||
return true;
|
||||
if (!resetIfUnique(it->second))
|
||||
return false;
|
||||
mCache.erase(agentHalfExtents);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NavMeshManager::addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end)
|
||||
|
@ -36,7 +36,7 @@ namespace DetourNavigator
|
||||
|
||||
bool removeWater(const osg::Vec2i& cellPosition);
|
||||
|
||||
void reset(const osg::Vec3f& agentHalfExtents);
|
||||
bool reset(const osg::Vec3f& agentHalfExtents);
|
||||
|
||||
void addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user