mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 17:29:55 +00:00
Lock TileCachedRecastMeshManager once per changing a cell
To save time on locking mutex and prevent AsyncNavMeshUpdater to use RecastMesh for a tile in the middle of objects loading.
This commit is contained in:
parent
d15e1dca84
commit
22ee592dd3
18 changed files with 570 additions and 429 deletions
|
@ -276,11 +276,13 @@ namespace NavMeshTool
|
||||||
{
|
{
|
||||||
it = navMeshInputs.emplace(cell.mCellId.mWorldspace,
|
it = navMeshInputs.emplace(cell.mCellId.mWorldspace,
|
||||||
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast)).first;
|
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast)).first;
|
||||||
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace);
|
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace, nullptr);
|
||||||
}
|
}
|
||||||
return *it->second;
|
return *it->second;
|
||||||
} ();
|
} ();
|
||||||
|
|
||||||
|
const TileCachedRecastMeshManager::UpdateGuard guard(navMeshInput.mTileCachedRecastMeshManager);
|
||||||
|
|
||||||
if (exterior)
|
if (exterior)
|
||||||
{
|
{
|
||||||
const auto it = std::lower_bound(esmData.mLands.begin(), esmData.mLands.end(), cellPosition, LessByXY {});
|
const auto it = std::lower_bound(esmData.mLands.begin(), esmData.mLands.end(), cellPosition, LessByXY {});
|
||||||
|
@ -292,14 +294,14 @@ namespace NavMeshTool
|
||||||
mergeOrAssign(getAabb(cellPosition, minHeight, maxHeight),
|
mergeOrAssign(getAabb(cellPosition, minHeight, maxHeight),
|
||||||
navMeshInput.mAabb, navMeshInput.mAabbInitialized);
|
navMeshInput.mAabb, navMeshInput.mAabbInitialized);
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, heightfieldShape);
|
navMeshInput.mTileCachedRecastMeshManager.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, heightfieldShape, &guard);
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, ESM::Land::REAL_SIZE, -1);
|
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, ESM::Land::REAL_SIZE, -1, &guard);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((cell.mData.mFlags & ESM::Cell::HasWater) != 0)
|
if ((cell.mData.mFlags & ESM::Cell::HasWater) != 0)
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, std::numeric_limits<int>::max(), cell.mWater);
|
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, std::numeric_limits<int>::max(), cell.mWater, &guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
forEachObject(cell, esmData, vfs, bulletShapeManager, readers,
|
forEachObject(cell, esmData, vfs, bulletShapeManager, readers,
|
||||||
|
@ -318,13 +320,13 @@ namespace NavMeshTool
|
||||||
const CollisionShape shape(object.getShapeInstance(), *object.getCollisionObject().getCollisionShape(), object.getObjectTransform());
|
const CollisionShape shape(object.getShapeInstance(), *object.getCollisionObject().getCollisionShape(), object.getObjectTransform());
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, shape, transform,
|
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, shape, transform,
|
||||||
DetourNavigator::AreaType_ground);
|
DetourNavigator::AreaType_ground, &guard);
|
||||||
|
|
||||||
if (const btCollisionShape* avoid = object.getShapeInstance()->mAvoidCollisionShape.get())
|
if (const btCollisionShape* avoid = object.getShapeInstance()->mAvoidCollisionShape.get())
|
||||||
{
|
{
|
||||||
const CollisionShape avoidShape(object.getShapeInstance(), *avoid, object.getObjectTransform());
|
const CollisionShape avoidShape(object.getShapeInstance(), *avoid, object.getObjectTransform());
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, avoidShape, transform,
|
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, avoidShape, transform,
|
||||||
DetourNavigator::AreaType_null);
|
DetourNavigator::AreaType_null, &guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.mObjects.emplace_back(std::move(object));
|
data.mObjects.emplace_back(std::move(object));
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <components/detournavigator/agentbounds.hpp>
|
#include <components/detournavigator/agentbounds.hpp>
|
||||||
#include <components/misc/convert.hpp>
|
#include <components/misc/convert.hpp>
|
||||||
#include <components/detournavigator/heightfieldshape.hpp>
|
#include <components/detournavigator/heightfieldshape.hpp>
|
||||||
|
#include <components/detournavigator/navigatorimpl.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -135,7 +136,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const MWPhysics::PhysicsSystem& physics,
|
void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const MWPhysics::PhysicsSystem& physics,
|
||||||
DetourNavigator::Navigator& navigator)
|
DetourNavigator::Navigator& navigator, const DetourNavigator::UpdateGuard* navigatorUpdateGuard = nullptr)
|
||||||
{
|
{
|
||||||
if (const auto object = physics.getObject(ptr))
|
if (const auto object = physics.getObject(ptr))
|
||||||
{
|
{
|
||||||
|
@ -173,7 +174,8 @@ namespace
|
||||||
navigator.addObject(
|
navigator.addObject(
|
||||||
DetourNavigator::ObjectId(object),
|
DetourNavigator::ObjectId(object),
|
||||||
DetourNavigator::DoorShapes(object->getShapeInstance(), objectTransform, connectionStart, connectionEnd),
|
DetourNavigator::DoorShapes(object->getShapeInstance(), objectTransform, connectionStart, connectionEnd),
|
||||||
transform
|
transform,
|
||||||
|
navigatorUpdateGuard
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
else if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
||||||
|
@ -181,7 +183,8 @@ namespace
|
||||||
navigator.addObject(
|
navigator.addObject(
|
||||||
DetourNavigator::ObjectId(object),
|
DetourNavigator::ObjectId(object),
|
||||||
DetourNavigator::ObjectShapes(object->getShapeInstance(), objectTransform),
|
DetourNavigator::ObjectShapes(object->getShapeInstance(), objectTransform),
|
||||||
object->getTransform()
|
object->getTransform(),
|
||||||
|
navigatorUpdateGuard
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +323,7 @@ namespace MWWorld
|
||||||
preloadCells(duration);
|
preloadCells(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::unloadCell(CellStore* cell)
|
void Scene::unloadCell(CellStore* cell, const DetourNavigator::UpdateGuard* navigatorUpdateGuard)
|
||||||
{
|
{
|
||||||
if (mActiveCells.find(cell) == mActiveCells.end())
|
if (mActiveCells.find(cell) == mActiveCells.end())
|
||||||
return;
|
return;
|
||||||
|
@ -335,7 +338,7 @@ namespace MWWorld
|
||||||
if (const auto object = mPhysics->getObject(ptr))
|
if (const auto object = mPhysics->getObject(ptr))
|
||||||
{
|
{
|
||||||
if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
||||||
mNavigator.removeObject(DetourNavigator::ObjectId(object));
|
mNavigator.removeObject(DetourNavigator::ObjectId(object), navigatorUpdateGuard);
|
||||||
mPhysics->remove(ptr);
|
mPhysics->remove(ptr);
|
||||||
ptr.mRef->mData.mPhysicsPostponed = false;
|
ptr.mRef->mData.mPhysicsPostponed = false;
|
||||||
}
|
}
|
||||||
|
@ -354,13 +357,13 @@ namespace MWWorld
|
||||||
if (cell->getCell()->isExterior())
|
if (cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
if (mPhysics->getHeightField(cellX, cellY) != nullptr)
|
if (mPhysics->getHeightField(cellX, cellY) != nullptr)
|
||||||
mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY));
|
mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY), navigatorUpdateGuard);
|
||||||
|
|
||||||
mPhysics->removeHeightField(cellX, cellY);
|
mPhysics->removeHeightField(cellX, cellY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->getCell()->hasWater())
|
if (cell->getCell()->hasWater())
|
||||||
mNavigator.removeWater(osg::Vec2i(cellX, cellY));
|
mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard);
|
||||||
|
|
||||||
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
||||||
mNavigator.removePathgrid(*pathgrid);
|
mNavigator.removePathgrid(*pathgrid);
|
||||||
|
@ -379,7 +382,8 @@ namespace MWWorld
|
||||||
mRendering.notifyWorldSpaceChanged();
|
mRendering.notifyWorldSpaceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::loadCell(CellStore *cell, Loading::Listener* loadingListener, bool respawn, const osg::Vec3f& position)
|
void Scene::loadCell(CellStore *cell, Loading::Listener* loadingListener, bool respawn, const osg::Vec3f& position,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard)
|
||||||
{
|
{
|
||||||
using DetourNavigator::HeightfieldShape;
|
using DetourNavigator::HeightfieldShape;
|
||||||
|
|
||||||
|
@ -428,7 +432,7 @@ namespace MWWorld
|
||||||
return heights;
|
return heights;
|
||||||
}
|
}
|
||||||
} ();
|
} ();
|
||||||
mNavigator.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, shape);
|
mNavigator.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, shape, navigatorUpdateGuard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +446,7 @@ namespace MWWorld
|
||||||
if (respawn)
|
if (respawn)
|
||||||
cell->respawn();
|
cell->respawn();
|
||||||
|
|
||||||
insertCell(*cell, loadingListener);
|
insertCell(*cell, loadingListener, navigatorUpdateGuard);
|
||||||
|
|
||||||
mRendering.addCell(cell);
|
mRendering.addCell(cell);
|
||||||
|
|
||||||
|
@ -458,18 +462,18 @@ namespace MWWorld
|
||||||
if (cell->getCell()->isExterior())
|
if (cell->getCell()->isExterior())
|
||||||
{
|
{
|
||||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
mNavigator.addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel);
|
mNavigator.addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel,
|
||||||
|
navigatorUpdateGuard);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mNavigator.addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(), waterLevel);
|
mNavigator.addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(), waterLevel,
|
||||||
|
navigatorUpdateGuard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mPhysics->disableWater();
|
mPhysics->disableWater();
|
||||||
|
|
||||||
mNavigator.update(position);
|
|
||||||
|
|
||||||
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
||||||
mRendering.configureAmbient(cell->getCell());
|
mRendering.configureAmbient(cell->getCell());
|
||||||
|
|
||||||
|
@ -478,11 +482,13 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::clear()
|
void Scene::clear()
|
||||||
{
|
{
|
||||||
|
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
for (auto iter = mActiveCells.begin(); iter!=mActiveCells.end(); )
|
for (auto iter = mActiveCells.begin(); iter!=mActiveCells.end(); )
|
||||||
{
|
{
|
||||||
auto* cell = *iter++;
|
auto* cell = *iter++;
|
||||||
unloadCell (cell);
|
unloadCell(cell, navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
|
navigatorUpdateGuard.reset();
|
||||||
assert(mActiveCells.empty());
|
assert(mActiveCells.empty());
|
||||||
mCurrentCell = nullptr;
|
mCurrentCell = nullptr;
|
||||||
|
|
||||||
|
@ -525,6 +531,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
||||||
{
|
{
|
||||||
|
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
|
|
||||||
for (auto iter = mActiveCells.begin(); iter != mActiveCells.end(); )
|
for (auto iter = mActiveCells.begin(); iter != mActiveCells.end(); )
|
||||||
{
|
{
|
||||||
auto* cell = *iter++;
|
auto* cell = *iter++;
|
||||||
|
@ -533,14 +541,15 @@ namespace MWWorld
|
||||||
const auto dx = std::abs(playerCellX - cell->getCell()->getGridX());
|
const auto dx = std::abs(playerCellX - cell->getCell()->getGridX());
|
||||||
const auto dy = std::abs(playerCellY - cell->getCell()->getGridY());
|
const auto dy = std::abs(playerCellY - cell->getCell()->getGridY());
|
||||||
if (dx > mHalfGridSize || dy > mHalfGridSize)
|
if (dx > mHalfGridSize || dy > mHalfGridSize)
|
||||||
unloadCell(cell);
|
unloadCell(cell, navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
unloadCell (cell);
|
unloadCell(cell, navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
mNavigator.setWorldspace(mWorld.getExterior(playerCellX, playerCellY)->getCell()->mCellId.mWorldspace);
|
mNavigator.setWorldspace(mWorld.getExterior(playerCellX, playerCellY)->getCell()->mCellId.mWorldspace,
|
||||||
mNavigator.updateBounds(pos);
|
navigatorUpdateGuard.get());
|
||||||
|
mNavigator.updateBounds(pos, navigatorUpdateGuard.get());
|
||||||
|
|
||||||
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY);
|
||||||
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
||||||
|
@ -601,10 +610,14 @@ namespace MWWorld
|
||||||
if (!isCellInCollection(x, y, mActiveCells))
|
if (!isCellInCollection(x, y, mActiveCells))
|
||||||
{
|
{
|
||||||
CellStore *cell = mWorld.getExterior(x, y);
|
CellStore *cell = mWorld.getExterior(x, y);
|
||||||
loadCell(cell, loadingListener, changeEvent, pos);
|
loadCell(cell, loadingListener, changeEvent, pos, navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNavigator.update(pos, navigatorUpdateGuard.get());
|
||||||
|
|
||||||
|
navigatorUpdateGuard.reset();
|
||||||
|
|
||||||
CellStore* current = mWorld.getExterior(playerCellX, playerCellY);
|
CellStore* current = mWorld.getExterior(playerCellX, playerCellY);
|
||||||
MWBase::Environment::get().getWindowManager()->changeCell(current);
|
MWBase::Environment::get().getWindowManager()->changeCell(current);
|
||||||
|
|
||||||
|
@ -653,15 +666,21 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Store<ESM::Cell>::iterator it = cells.extBegin();
|
MWWorld::Store<ESM::Cell>::iterator it = cells.extBegin();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
for (; it != cells.extEnd(); ++it)
|
for (; it != cells.extEnd(); ++it)
|
||||||
{
|
{
|
||||||
loadingListener->setLabel("Testing exterior cells ("+std::to_string(i)+"/"+std::to_string(cells.getExtSize())+")...");
|
loadingListener->setLabel("Testing exterior cells ("+std::to_string(i)+"/"+std::to_string(cells.getExtSize())+")...");
|
||||||
|
|
||||||
CellStore *cell = mWorld.getExterior(it->mData.mX, it->mData.mY);
|
CellStore *cell = mWorld.getExterior(it->mData.mX, it->mData.mY);
|
||||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace, navigatorUpdateGuard.get());
|
||||||
const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits;
|
const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits;
|
||||||
mNavigator.updateBounds(position);
|
mNavigator.updateBounds(position, navigatorUpdateGuard.get());
|
||||||
loadCell(cell, nullptr, false, position);
|
loadCell(cell, nullptr, false, position, navigatorUpdateGuard.get());
|
||||||
|
|
||||||
|
mNavigator.update(position, navigatorUpdateGuard.get());
|
||||||
|
navigatorUpdateGuard.reset();
|
||||||
|
mNavigator.wait(DetourNavigator::WaitConditionType::requiredTilesPresent, nullptr);
|
||||||
|
navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
|
|
||||||
auto iter = mActiveCells.begin();
|
auto iter = mActiveCells.begin();
|
||||||
while (iter != mActiveCells.end())
|
while (iter != mActiveCells.end())
|
||||||
|
@ -669,7 +688,7 @@ namespace MWWorld
|
||||||
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
||||||
it->mData.mY == (*iter)->getCell()->getGridY())
|
it->mData.mY == (*iter)->getCell()->getGridY())
|
||||||
{
|
{
|
||||||
unloadCell(*iter);
|
unloadCell(*iter, navigatorUpdateGuard.get());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,16 +720,22 @@ namespace MWWorld
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
MWWorld::Store<ESM::Cell>::iterator it = cells.intBegin();
|
MWWorld::Store<ESM::Cell>::iterator it = cells.intBegin();
|
||||||
|
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
for (; it != cells.intEnd(); ++it)
|
for (; it != cells.intEnd(); ++it)
|
||||||
{
|
{
|
||||||
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
||||||
|
|
||||||
CellStore *cell = mWorld.getInterior(it->mName);
|
CellStore *cell = mWorld.getInterior(it->mName);
|
||||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace, navigatorUpdateGuard.get());
|
||||||
ESM::Position position;
|
ESM::Position position;
|
||||||
mWorld.findInteriorPosition(it->mName, position);
|
mWorld.findInteriorPosition(it->mName, position);
|
||||||
mNavigator.updateBounds(position.asVec3());
|
mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get());
|
||||||
loadCell(cell, nullptr, false, position.asVec3());
|
loadCell(cell, nullptr, false, position.asVec3(), navigatorUpdateGuard.get());
|
||||||
|
|
||||||
|
mNavigator.update(position.asVec3(), navigatorUpdateGuard.get());
|
||||||
|
navigatorUpdateGuard.reset();
|
||||||
|
mNavigator.wait(DetourNavigator::WaitConditionType::requiredTilesPresent, nullptr);
|
||||||
|
navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
|
|
||||||
auto iter = mActiveCells.begin();
|
auto iter = mActiveCells.begin();
|
||||||
while (iter != mActiveCells.end())
|
while (iter != mActiveCells.end())
|
||||||
|
@ -719,7 +744,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (it->mName == (*iter)->getCell()->mName)
|
if (it->mName == (*iter)->getCell()->mName)
|
||||||
{
|
{
|
||||||
unloadCell(*iter);
|
unloadCell(*iter, navigatorUpdateGuard.get());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,22 +863,26 @@ namespace MWWorld
|
||||||
|
|
||||||
Log(Debug::Info) << "Changing to interior";
|
Log(Debug::Info) << "Changing to interior";
|
||||||
|
|
||||||
|
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
|
||||||
|
|
||||||
// unload
|
// unload
|
||||||
for (auto iter = mActiveCells.begin(); iter!=mActiveCells.end(); )
|
for (auto iter = mActiveCells.begin(); iter!=mActiveCells.end(); )
|
||||||
{
|
{
|
||||||
auto* cellToUnload = *iter++;
|
auto* cellToUnload = *iter++;
|
||||||
unloadCell(cellToUnload);
|
unloadCell(cellToUnload, navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
assert(mActiveCells.empty());
|
assert(mActiveCells.empty());
|
||||||
|
|
||||||
loadingListener->setProgressRange(cell->count());
|
loadingListener->setProgressRange(cell->count());
|
||||||
|
|
||||||
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace);
|
mNavigator.setWorldspace(cell->getCell()->mCellId.mWorldspace, navigatorUpdateGuard.get());
|
||||||
mNavigator.updateBounds(position.asVec3());
|
mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get());
|
||||||
|
|
||||||
// Load cell.
|
// Load cell.
|
||||||
mPagedRefs.clear();
|
mPagedRefs.clear();
|
||||||
loadCell(cell, loadingListener, changeEvent, position.asVec3());
|
loadCell(cell, loadingListener, changeEvent, position.asVec3(), navigatorUpdateGuard.get());
|
||||||
|
|
||||||
|
navigatorUpdateGuard.reset();
|
||||||
|
|
||||||
changePlayerCell(cell, position, adjustPlayerPos);
|
changePlayerCell(cell, position, adjustPlayerPos);
|
||||||
|
|
||||||
|
@ -904,12 +933,13 @@ namespace MWWorld
|
||||||
mCellChanged = false;
|
mCellChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener)
|
void Scene::insertCell(CellStore &cell, Loading::Listener* loadingListener,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard)
|
||||||
{
|
{
|
||||||
InsertVisitor insertVisitor(cell, loadingListener);
|
InsertVisitor insertVisitor(cell, loadingListener);
|
||||||
cell.forEach (insertVisitor);
|
cell.forEach (insertVisitor);
|
||||||
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, mWorld, mPagedRefs, *mPhysics, mRendering); });
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, mWorld, mPagedRefs, *mPhysics, mRendering); });
|
||||||
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, mWorld, *mPhysics, mNavigator); });
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, mWorld, *mPhysics, mNavigator, navigatorUpdateGuard); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::addObjectToScene (const Ptr& ptr)
|
void Scene::addObjectToScene (const Ptr& ptr)
|
||||||
|
@ -938,7 +968,7 @@ namespace MWWorld
|
||||||
if (const auto object = mPhysics->getObject(ptr))
|
if (const auto object = mPhysics->getObject(ptr))
|
||||||
{
|
{
|
||||||
if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None)
|
||||||
mNavigator.removeObject(DetourNavigator::ObjectId(object));
|
mNavigator.removeObject(DetourNavigator::ObjectId(object), nullptr);
|
||||||
}
|
}
|
||||||
else if (mPhysics->getActor(ptr))
|
else if (mPhysics->getActor(ptr))
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace Loading
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct Navigator;
|
struct Navigator;
|
||||||
|
class UpdateGuard;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -110,7 +111,9 @@ namespace MWWorld
|
||||||
|
|
||||||
std::optional<ChangeCellGridRequest> mChangeCellGridRequest;
|
std::optional<ChangeCellGridRequest> mChangeCellGridRequest;
|
||||||
|
|
||||||
void insertCell(CellStore &cell, Loading::Listener* loadingListener);
|
void insertCell(CellStore &cell, Loading::Listener* loadingListener,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard);
|
||||||
|
|
||||||
osg::Vec2i mCurrentGridCenter;
|
osg::Vec2i mCurrentGridCenter;
|
||||||
|
|
||||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||||
|
@ -128,8 +131,9 @@ namespace MWWorld
|
||||||
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const;
|
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const;
|
||||||
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;
|
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;
|
||||||
|
|
||||||
void unloadCell(CellStore* cell);
|
void unloadCell(CellStore* cell, const DetourNavigator::UpdateGuard* navigatorUpdateGuard);
|
||||||
void loadCell(CellStore *cell, Loading::Listener* loadingListener, bool respawn, const osg::Vec3f& position);
|
void loadCell(CellStore *cell, Loading::Listener* loadingListener, bool respawn, const osg::Vec3f& position,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <components/detournavigator/settings.hpp>
|
#include <components/detournavigator/settings.hpp>
|
||||||
#include <components/detournavigator/agentbounds.hpp>
|
#include <components/detournavigator/agentbounds.hpp>
|
||||||
#include <components/detournavigator/stats.hpp>
|
#include <components/detournavigator/stats.hpp>
|
||||||
|
#include <components/detournavigator/navigatorimpl.hpp>
|
||||||
|
|
||||||
#include <components/loadinglistener/loadinglistener.hpp>
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
|
|
||||||
|
@ -1541,28 +1542,32 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::updateNavigator()
|
void World::updateNavigator()
|
||||||
{
|
{
|
||||||
|
auto navigatorUpdateGuard = mNavigator->makeUpdateGuard();
|
||||||
|
|
||||||
mPhysics->forEachAnimatedObject([&] (const auto& pair)
|
mPhysics->forEachAnimatedObject([&] (const auto& pair)
|
||||||
{
|
{
|
||||||
const auto [object, changed] = pair;
|
const auto [object, changed] = pair;
|
||||||
if (changed)
|
if (changed)
|
||||||
updateNavigatorObject(*object);
|
updateNavigatorObject(*object, navigatorUpdateGuard.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const auto& door : mDoorStates)
|
for (const auto& door : mDoorStates)
|
||||||
if (const auto object = mPhysics->getObject(door.first))
|
if (const auto object = mPhysics->getObject(door.first))
|
||||||
updateNavigatorObject(*object);
|
updateNavigatorObject(*object, navigatorUpdateGuard.get());
|
||||||
|
|
||||||
mNavigator->update(getPlayerPtr().getRefData().getPosition().asVec3());
|
mNavigator->update(getPlayerPtr().getRefData().getPosition().asVec3(), navigatorUpdateGuard.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::updateNavigatorObject(const MWPhysics::Object& object)
|
void World::updateNavigatorObject(const MWPhysics::Object& object,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard)
|
||||||
{
|
{
|
||||||
if (object.getShapeInstance()->mVisualCollisionType != Resource::VisualCollisionType::None)
|
if (object.getShapeInstance()->mVisualCollisionType != Resource::VisualCollisionType::None)
|
||||||
return;
|
return;
|
||||||
const MWWorld::Ptr ptr = object.getPtr();
|
const MWWorld::Ptr ptr = object.getPtr();
|
||||||
const DetourNavigator::ObjectShapes shapes(object.getShapeInstance(),
|
const DetourNavigator::ObjectShapes shapes(object.getShapeInstance(),
|
||||||
DetourNavigator::ObjectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()});
|
DetourNavigator::ObjectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()});
|
||||||
mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform());
|
mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform(),
|
||||||
|
navigatorUpdateGuard);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWPhysics::RayCastingInterface* World::getRayCasting() const
|
const MWPhysics::RayCastingInterface* World::getRayCasting() const
|
||||||
|
@ -1854,8 +1859,8 @@ namespace MWWorld
|
||||||
|
|
||||||
if (mWorldScene->hasCellLoaded())
|
if (mWorldScene->hasCellLoaded())
|
||||||
{
|
{
|
||||||
mNavigator->wait(*MWBase::Environment::get().getWindowManager()->getLoadingScreen(),
|
mNavigator->wait(DetourNavigator::WaitConditionType::requiredTilesPresent,
|
||||||
DetourNavigator::WaitConditionType::requiredTilesPresent);
|
MWBase::Environment::get().getWindowManager()->getLoadingScreen());
|
||||||
mWorldScene->resetCellLoaded();
|
mWorldScene->resetCellLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void updateNavigator();
|
void updateNavigator();
|
||||||
|
|
||||||
void updateNavigatorObject(const MWPhysics::Object& object);
|
void updateNavigatorObject(const MWPhysics::Object& object,
|
||||||
|
const DetourNavigator::UpdateGuard* navigatorUpdateGuard = nullptr);
|
||||||
|
|
||||||
void ensureNeededRecords();
|
void ensureNeededRecords();
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace
|
||||||
void addHeightFieldPlane(TileCachedRecastMeshManager& recastMeshManager, const osg::Vec2i cellPosition = osg::Vec2i(0, 0))
|
void addHeightFieldPlane(TileCachedRecastMeshManager& recastMeshManager, const osg::Vec2i cellPosition = osg::Vec2i(0, 0))
|
||||||
{
|
{
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
recastMeshManager.addHeightfield(cellPosition, cellSize, HeightfieldPlane {0});
|
recastMeshManager.addHeightfield(cellPosition, cellSize, HeightfieldPlane {0}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addObject(const btBoxShape& shape, TileCachedRecastMeshManager& recastMeshManager)
|
void addObject(const btBoxShape& shape, TileCachedRecastMeshManager& recastMeshManager)
|
||||||
|
@ -42,7 +42,7 @@ namespace
|
||||||
osg::ref_ptr<Resource::BulletShapeInstance>(new Resource::BulletShapeInstance(bulletShape)),
|
osg::ref_ptr<Resource::BulletShapeInstance>(new Resource::BulletShapeInstance(bulletShape)),
|
||||||
shape, objectTransform
|
shape, objectTransform
|
||||||
);
|
);
|
||||||
recastMeshManager.addObject(id, collisionShape, btTransform::getIdentity(), AreaType_ground);
|
recastMeshManager.addObject(id, collisionShape, btTransform::getIdentity(), AreaType_ground, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DetourNavigatorAsyncNavMeshUpdaterTest : Test
|
struct DetourNavigatorAsyncNavMeshUpdaterTest : Test
|
||||||
|
@ -60,43 +60,43 @@ namespace
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, for_all_jobs_done_when_empty_wait_should_terminate)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, for_all_jobs_done_when_empty_wait_should_terminate)
|
||||||
{
|
{
|
||||||
AsyncNavMeshUpdater updater {mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr};
|
AsyncNavMeshUpdater updater {mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr};
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, for_required_tiles_present_when_empty_wait_should_terminate)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, for_required_tiles_present_when_empty_wait_should_terminate)
|
||||||
{
|
{
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||||
updater.wait(mListener, WaitConditionType::requiredTilesPresent);
|
updater.wait(WaitConditionType::requiredTilesPresent, &mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_generate_navmesh_tile)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_generate_navmesh_tile)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
EXPECT_NE(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
EXPECT_NE(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, repeated_post_should_lead_to_cache_hit)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, repeated_post_should_lead_to_cache_hit)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
||||||
ASSERT_EQ(stats.mCache.mHitCount, 0);
|
ASSERT_EQ(stats.mCache.mHitCount, 0);
|
||||||
}
|
}
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
||||||
|
@ -106,20 +106,20 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_for_update_change_type_should_not_update_cache)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_for_update_change_type_should_not_update_cache)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::update}};
|
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::update}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
||||||
ASSERT_EQ(stats.mCache.mHitCount, 0);
|
ASSERT_EQ(stats.mCache.mHitCount, 0);
|
||||||
}
|
}
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
||||||
|
@ -129,7 +129,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_write_generated_tile_to_db)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_write_generated_tile_to_db)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
addObject(mBox, mRecastMeshManager);
|
addObject(mBox, mRecastMeshManager);
|
||||||
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
||||||
|
@ -139,7 +139,7 @@ namespace
|
||||||
const TilePosition tilePosition {0, 0};
|
const TilePosition tilePosition {0, 0};
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
updater.stop();
|
updater.stop();
|
||||||
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
||||||
ASSERT_NE(recastMesh, nullptr);
|
ASSERT_NE(recastMesh, nullptr);
|
||||||
|
@ -155,7 +155,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_when_writing_to_db_disabled_should_not_write_tiles)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_when_writing_to_db_disabled_should_not_write_tiles)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
addObject(mBox, mRecastMeshManager);
|
addObject(mBox, mRecastMeshManager);
|
||||||
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
||||||
|
@ -166,7 +166,7 @@ namespace
|
||||||
const TilePosition tilePosition {0, 0};
|
const TilePosition tilePosition {0, 0};
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
updater.stop();
|
updater.stop();
|
||||||
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
||||||
ASSERT_NE(recastMesh, nullptr);
|
ASSERT_NE(recastMesh, nullptr);
|
||||||
|
@ -180,7 +180,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_when_writing_to_db_disabled_should_not_write_shapes)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_when_writing_to_db_disabled_should_not_write_shapes)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
addObject(mBox, mRecastMeshManager);
|
addObject(mBox, mRecastMeshManager);
|
||||||
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
||||||
|
@ -191,7 +191,7 @@ namespace
|
||||||
const TilePosition tilePosition {0, 0};
|
const TilePosition tilePosition {0, 0};
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{tilePosition, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
updater.stop();
|
updater.stop();
|
||||||
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
const auto recastMesh = mRecastMeshManager.getMesh(mWorldspace, tilePosition);
|
||||||
ASSERT_NE(recastMesh, nullptr);
|
ASSERT_NE(recastMesh, nullptr);
|
||||||
|
@ -202,7 +202,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_read_from_db_on_cache_miss)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, post_should_read_from_db_on_cache_miss)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
mSettings.mMaxNavMeshTilesCacheSize = 0;
|
mSettings.mMaxNavMeshTilesCacheSize = 0;
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager,
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager,
|
||||||
|
@ -210,7 +210,7 @@ namespace
|
||||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||||
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTiles {{TilePosition {0, 0}, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
ASSERT_EQ(stats.mCache.mGetCount, 1);
|
||||||
|
@ -220,7 +220,7 @@ namespace
|
||||||
ASSERT_EQ(stats.mDbGetTileHits, 0);
|
ASSERT_EQ(stats.mDbGetTileHits, 0);
|
||||||
}
|
}
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
{
|
{
|
||||||
const auto stats = updater.getStats();
|
const auto stats = updater.getStats();
|
||||||
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
EXPECT_EQ(stats.mCache.mGetCount, 2);
|
||||||
|
@ -233,24 +233,24 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, on_changing_player_tile_post_should_remove_tiles_out_of_range)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, on_changing_player_tile_post_should_remove_tiles_out_of_range)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
addHeightFieldPlane(mRecastMeshManager);
|
addHeightFieldPlane(mRecastMeshManager);
|
||||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||||
const std::map<TilePosition, ChangeType> changedTilesAdd {{TilePosition {0, 0}, ChangeType::add}};
|
const std::map<TilePosition, ChangeType> changedTilesAdd {{TilePosition {0, 0}, ChangeType::add}};
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTilesAdd);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTilesAdd);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
ASSERT_NE(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
ASSERT_NE(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
||||||
const std::map<TilePosition, ChangeType> changedTilesRemove {{TilePosition {0, 0}, ChangeType::remove}};
|
const std::map<TilePosition, ChangeType> changedTilesRemove {{TilePosition {0, 0}, ChangeType::remove}};
|
||||||
const TilePosition playerTile(100, 100);
|
const TilePosition playerTile(100, 100);
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, playerTile, mWorldspace, changedTilesRemove);
|
updater.post(mAgentBounds, navMeshCacheItem, playerTile, mWorldspace, changedTilesRemove);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
EXPECT_EQ(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
EXPECT_EQ(navMeshCacheItem->lockConst()->getImpl().getTileRefAt(0, 0, 0), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, should_stop_writing_to_db_when_size_limit_is_reached)
|
TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, should_stop_writing_to_db_when_size_limit_is_reached)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.setWorldspace(mWorldspace);
|
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||||
for (int x = -1; x <= 1; ++x)
|
for (int x = -1; x <= 1; ++x)
|
||||||
for (int y = -1; y <= 1; ++y)
|
for (int y = -1; y <= 1; ++y)
|
||||||
addHeightFieldPlane(mRecastMeshManager, osg::Vec2i(x, y));
|
addHeightFieldPlane(mRecastMeshManager, osg::Vec2i(x, y));
|
||||||
|
@ -264,7 +264,7 @@ namespace
|
||||||
for (int y = -5; y <= 5; ++y)
|
for (int y = -5; y <= 5; ++y)
|
||||||
changedTiles.emplace(TilePosition {x, y}, ChangeType::add);
|
changedTiles.emplace(TilePosition {x, y}, ChangeType::add);
|
||||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||||
updater.wait(mListener, WaitConditionType::allJobsDone);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
updater.stop();
|
updater.stop();
|
||||||
const std::set<TilePosition> present {
|
const std::set<TilePosition> present {
|
||||||
TilePosition(-2, 0),
|
TilePosition(-2, 0),
|
||||||
|
|
|
@ -155,9 +155,11 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
auto updateGuard = mNavigator->makeUpdateGuard();
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, updateGuard.get());
|
||||||
mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent);
|
mNavigator->update(mPlayerPosition, updateGuard.get());
|
||||||
|
updateGuard.reset();
|
||||||
|
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -207,9 +209,9 @@ namespace
|
||||||
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -239,9 +241,12 @@ namespace
|
||||||
Vec3fEq(460, 56.66666412353515625, 1.99998295307159423828125)
|
Vec3fEq(460, 56.66666412353515625, 1.99998295307159423828125)
|
||||||
)) << mPath;
|
)) << mPath;
|
||||||
|
|
||||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform);
|
{
|
||||||
mNavigator->update(mPlayerPosition);
|
auto updateGuard = mNavigator->makeUpdateGuard();
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, updateGuard.get());
|
||||||
|
mNavigator->update(mPlayerPosition, updateGuard.get());
|
||||||
|
}
|
||||||
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mPath.clear();
|
mPath.clear();
|
||||||
mOut = std::back_inserter(mPath);
|
mOut = std::back_inserter(mPath);
|
||||||
|
@ -291,10 +296,10 @@ namespace
|
||||||
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
compound.shape().addChildShape(btTransform(btMatrix3x3::getIdentity(), btVector3(0, 0, 0)), new btBoxShape(btVector3(20, 20, 100)));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -327,9 +332,9 @@ namespace
|
||||||
|
|
||||||
compound.shape().updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0)));
|
compound.shape().updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0)));
|
||||||
|
|
||||||
mNavigator->updateObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform);
|
mNavigator->updateObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mPath.clear();
|
mPath.clear();
|
||||||
mOut = std::back_inserter(mPath);
|
mOut = std::back_inserter(mPath);
|
||||||
|
@ -385,10 +390,10 @@ namespace
|
||||||
heightfield2.shape().setLocalScaling(btVector3(128, 128, 1));
|
heightfield2.shape().setLocalScaling(btVector3(128, 128, 1));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -442,15 +447,15 @@ namespace
|
||||||
const int cellSize2 = mHeightfieldTileSize * (surface2.mSize - 1);
|
const int cellSize2 = mHeightfieldTileSize * (surface2.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize1, surface1);
|
mNavigator->addHeightfield(mCellPosition, cellSize1, surface1, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
|
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
|
||||||
|
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize2, surface2);
|
mNavigator->addHeightfield(mCellPosition, cellSize2, surface2, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
|
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
|
||||||
}
|
}
|
||||||
|
@ -484,9 +489,9 @@ namespace
|
||||||
osg::ref_ptr<const Resource::BulletShapeInstance> instance(new Resource::BulletShapeInstance(bulletShape));
|
osg::ref_ptr<const Resource::BulletShapeInstance> instance(new Resource::BulletShapeInstance(bulletShape));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addObject(ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance, mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance, mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -531,10 +536,10 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addWater(mCellPosition, cellSize, 300);
|
mNavigator->addWater(mCellPosition, cellSize, 300, nullptr);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mStart.x() = 256;
|
mStart.x() = 256;
|
||||||
mStart.z() = 300;
|
mStart.z() = 300;
|
||||||
|
@ -579,10 +584,10 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addWater(mCellPosition, cellSize, -25);
|
mNavigator->addWater(mCellPosition, cellSize, -25, nullptr);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mStart.x() = 256;
|
mStart.x() = 256;
|
||||||
mEnd.x() = 256;
|
mEnd.x() = 256;
|
||||||
|
@ -625,10 +630,10 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->addWater(mCellPosition, std::numeric_limits<int>::max(), -25);
|
mNavigator->addWater(mCellPosition, std::numeric_limits<int>::max(), -25, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mStart.x() = 256;
|
mStart.x() = 256;
|
||||||
mEnd.x() = 256;
|
mEnd.x() = 256;
|
||||||
|
@ -671,10 +676,10 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addWater(mCellPosition, cellSize, -25);
|
mNavigator->addWater(mCellPosition, cellSize, -25, nullptr);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mStart.x() = 256;
|
mStart.x() = 256;
|
||||||
mEnd.x() = 256;
|
mEnd.x() = 256;
|
||||||
|
@ -715,17 +720,17 @@ namespace
|
||||||
heightfield.shape().setLocalScaling(btVector3(128, 128, 1));
|
heightfield.shape().setLocalScaling(btVector3(128, 128, 1));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mNavigator->removeObject(ObjectId(&heightfield.shape()));
|
mNavigator->removeObject(ObjectId(&heightfield.shape()), nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -769,17 +774,17 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mNavigator->removeHeightfield(mCellPosition);
|
mNavigator->removeHeightfield(mCellPosition, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -824,9 +829,9 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
Misc::Rng::init(42);
|
Misc::Rng::init(42);
|
||||||
|
|
||||||
|
@ -862,12 +867,12 @@ namespace
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
|
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < boxes.size(); ++i)
|
for (std::size_t i = 0; i < boxes.size(); ++i)
|
||||||
{
|
{
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10, shift.y() + i * 10, i * 10));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10, shift.y() + i * 10, i * 10));
|
||||||
mNavigator->addObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform);
|
mNavigator->addObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||||
|
@ -875,11 +880,11 @@ namespace
|
||||||
for (std::size_t i = 0; i < boxes.size(); ++i)
|
for (std::size_t i = 0; i < boxes.size(); ++i)
|
||||||
{
|
{
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10 + 1, shift.y() + i * 10 + 1, i * 10 + 1));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10 + 1, shift.y() + i * 10 + 1, i * 10 + 1));
|
||||||
mNavigator->updateObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform);
|
mNavigator->updateObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -921,27 +926,27 @@ namespace
|
||||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||||
{
|
{
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32, i * 32, i * 32));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32, i * 32, i * 32));
|
||||||
mNavigator->addObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform);
|
mNavigator->addObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform, nullptr);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const auto start = std::chrono::steady_clock::now();
|
const auto start = std::chrono::steady_clock::now();
|
||||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||||
{
|
{
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 1, i * 32 + 1, i * 32 + 1));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 1, i * 32 + 1, i * 32 + 1));
|
||||||
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform);
|
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform, nullptr);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < shapes.size(); ++i)
|
for (std::size_t i = 0; i < shapes.size(); ++i)
|
||||||
{
|
{
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 2, i * 32 + 2, i * 32 + 2));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 2, i * 32 + 2, i * 32 + 2));
|
||||||
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform);
|
mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform, nullptr);
|
||||||
}
|
}
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const auto duration = std::chrono::steady_clock::now() - start;
|
const auto duration = std::chrono::steady_clock::now() - start;
|
||||||
|
|
||||||
|
@ -962,9 +967,9 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
const int cellSize = mHeightfieldTileSize * (surface.mSize - 1);
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const osg::Vec3f start(57, 460, 1);
|
const osg::Vec3f start(57, 460, 1);
|
||||||
const osg::Vec3f end(460, 57, 1);
|
const osg::Vec3f end(460, 57, 1);
|
||||||
|
@ -991,14 +996,14 @@ namespace
|
||||||
CollisionShapeInstance borderBox(std::make_unique<btBoxShape>(btVector3(50, 50, 50)));
|
CollisionShapeInstance borderBox(std::make_unique<btBoxShape>(btVector3(50, 50, 50)));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->addObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform),
|
mNavigator->addObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform),
|
||||||
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition));
|
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition), nullptr);
|
||||||
// add this box to make navmesh bound box independent from oscillatingBoxShape rotations
|
// add this box to make navmesh bound box independent from oscillatingBoxShape rotations
|
||||||
mNavigator->addObject(ObjectId(&borderBox.shape()), ObjectShapes(borderBox.instance(), mObjectTransform),
|
mNavigator->addObject(ObjectId(&borderBox.shape()), ObjectShapes(borderBox.instance(), mObjectTransform),
|
||||||
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200)));
|
btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200)), nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const Version expectedVersion {1, 4};
|
const Version expectedVersion {1, 4};
|
||||||
|
|
||||||
|
@ -1010,9 +1015,9 @@ namespace
|
||||||
{
|
{
|
||||||
const btTransform transform(btQuaternion(btVector3(0, 0, 1), n * 2 * osg::PI / 10),
|
const btTransform transform(btQuaternion(btVector3(0, 0, 1), n * 2 * osg::PI / 10),
|
||||||
oscillatingBoxShapePosition);
|
oscillatingBoxShapePosition);
|
||||||
mNavigator->updateObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform), transform);
|
mNavigator->updateObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform), transform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(navMeshes.size(), 1);
|
ASSERT_EQ(navMeshes.size(), 1);
|
||||||
|
@ -1025,9 +1030,9 @@ namespace
|
||||||
const int cellSize = mHeightfieldTileSize * 4;
|
const int cellSize = mHeightfieldTileSize * 4;
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, plane);
|
mNavigator->addHeightfield(mCellPosition, cellSize, plane, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent);
|
mNavigator->wait(WaitConditionType::requiredTilesPresent, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::Success);
|
Status::Success);
|
||||||
|
@ -1075,10 +1080,10 @@ namespace
|
||||||
new btBoxShape(btVector3(200, 200, 1000)));
|
new btBoxShape(btVector3(200, 200, 1000)));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
EXPECT_EQ(findPath(*mNavigator, mAgentBounds, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut),
|
||||||
Status::PartialPath);
|
Status::PartialPath);
|
||||||
|
@ -1114,10 +1119,10 @@ namespace
|
||||||
new btBoxShape(btVector3(100, 100, 1000)));
|
new btBoxShape(btVector3(100, 100, 1000)));
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addHeightfield(mCellPosition, cellSize, surface);
|
mNavigator->addHeightfield(mCellPosition, cellSize, surface, nullptr);
|
||||||
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform);
|
mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const float endTolerance = 1000.0f;
|
const float endTolerance = 1000.0f;
|
||||||
|
|
||||||
|
@ -1154,15 +1159,15 @@ namespace
|
||||||
const float level2 = 2;
|
const float level2 = 2;
|
||||||
|
|
||||||
mNavigator->addAgent(mAgentBounds);
|
mNavigator->addAgent(mAgentBounds);
|
||||||
mNavigator->addWater(mCellPosition, cellSize1, level1);
|
mNavigator->addWater(mCellPosition, cellSize1, level1, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
|
const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion();
|
||||||
|
|
||||||
mNavigator->addWater(mCellPosition, cellSize2, level2);
|
mNavigator->addWater(mCellPosition, cellSize2, level2, nullptr);
|
||||||
mNavigator->update(mPlayerPosition);
|
mNavigator->update(mPlayerPosition, nullptr);
|
||||||
mNavigator->wait(mListener, WaitConditionType::allJobsDone);
|
mNavigator->wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
|
|
||||||
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
|
EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
EXPECT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
EXPECT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_for_existing_object_should_return_false)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_for_existing_object_should_return_false)
|
||||||
|
@ -56,17 +56,17 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_should_add_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_should_add_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
for (int x = -1; x < 1; ++x)
|
for (int x = -1; x < 1; ++x)
|
||||||
for (int y = -1; y < 1; ++y)
|
for (int y = -1; y < 1; ++y)
|
||||||
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
||||||
|
@ -80,9 +80,9 @@ namespace
|
||||||
TileBounds bounds;
|
TileBounds bounds;
|
||||||
bounds.mMin = osg::Vec2f(182, 182);
|
bounds.mMin = osg::Vec2f(182, 182);
|
||||||
bounds.mMax = osg::Vec2f(1000, 1000);
|
bounds.mMax = osg::Vec2f(1000, 1000);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), ElementsAre(std::pair(TilePosition(0, 0), ChangeType::add)));
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), ElementsAre(std::pair(TilePosition(0, 0), ChangeType::add)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, update_object_for_changed_object_should_add_changed_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, update_object_for_changed_object_should_add_changed_tiles)
|
||||||
|
@ -94,11 +94,11 @@ namespace
|
||||||
TileBounds bounds;
|
TileBounds bounds;
|
||||||
bounds.mMin = osg::Vec2f(-1000, -1000);
|
bounds.mMin = osg::Vec2f(-1000, -1000);
|
||||||
bounds.mMax = osg::Vec2f(1000, 1000);
|
bounds.mMax = osg::Vec2f(1000, 1000);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr);
|
||||||
manager.takeChangedTiles();
|
manager.takeChangedTiles(nullptr);
|
||||||
EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground));
|
EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), ElementsAre(
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), ElementsAre(
|
||||||
std::pair(TilePosition(-1, -1), ChangeType::add),
|
std::pair(TilePosition(-1, -1), ChangeType::add),
|
||||||
std::pair(TilePosition(-1, 0), ChangeType::add),
|
std::pair(TilePosition(-1, 0), ChangeType::add),
|
||||||
std::pair(TilePosition(0, -1), ChangeType::update),
|
std::pair(TilePosition(0, -1), ChangeType::update),
|
||||||
|
@ -113,10 +113,10 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
manager.takeChangedTiles();
|
manager.takeChangedTiles(nullptr);
|
||||||
EXPECT_FALSE(manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground));
|
EXPECT_FALSE(manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), IsEmpty());
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_object_should_return_add_changed_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_object_should_return_add_changed_tiles)
|
||||||
|
@ -127,20 +127,20 @@ namespace
|
||||||
TileBounds bounds;
|
TileBounds bounds;
|
||||||
bounds.mMin = osg::Vec2f(182, 182);
|
bounds.mMin = osg::Vec2f(182, 182);
|
||||||
bounds.mMax = osg::Vec2f(1000, 1000);
|
bounds.mMax = osg::Vec2f(1000, 1000);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
manager.takeChangedTiles();
|
manager.takeChangedTiles(nullptr);
|
||||||
manager.removeObject(ObjectId(&boxShape));
|
manager.removeObject(ObjectId(&boxShape), nullptr);
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), ElementsAre(std::pair(TilePosition(0, 0), ChangeType::remove)));
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), ElementsAre(std::pair(TilePosition(0, 0), ChangeType::remove)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_after_add_object_should_return_recast_mesh_for_each_used_tile)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_after_add_object_should_return_recast_mesh_for_each_used_tile)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
|
@ -150,10 +150,10 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_after_add_object_should_return_nullptr_for_unused_tile)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_after_add_object_should_return_nullptr_for_unused_tile)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,20 +163,20 @@ namespace
|
||||||
TileBounds bounds;
|
TileBounds bounds;
|
||||||
bounds.mMin = osg::Vec2f(-1000, -1000);
|
bounds.mMin = osg::Vec2f(-1000, -1000);
|
||||||
bounds.mMax = osg::Vec2f(1000, 1000);
|
bounds.mMax = osg::Vec2f(1000, 1000);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
|
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
|
|
||||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr);
|
||||||
|
|
||||||
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
|
@ -186,17 +186,17 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_nullptr_for_unused_tile)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_nullptr_for_unused_tile)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
|
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
|
|
||||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
|
|
||||||
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr);
|
||||||
}
|
}
|
||||||
|
@ -204,11 +204,11 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_removed_object_should_return_nullptr_for_all_previously_used_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_removed_object_should_return_nullptr_for_all_previously_used_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
manager.removeObject(ObjectId(&boxShape));
|
manager.removeObject(ObjectId(&boxShape), nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_EQ(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
|
@ -218,17 +218,17 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_not_changed_object_after_update_should_return_recast_mesh_for_same_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_not_changed_object_after_update_should_return_recast_mesh_for_same_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
|
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr);
|
||||||
|
|
||||||
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr);
|
||||||
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr);
|
||||||
|
@ -241,7 +241,7 @@ namespace
|
||||||
const auto initialRevision = manager.getRevision();
|
const auto initialRevision = manager.getRevision();
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getRevision(), initialRevision + 1);
|
EXPECT_EQ(manager.getRevision(), initialRevision + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,9 +250,9 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
const auto beforeAddRevision = manager.getRevision();
|
const auto beforeAddRevision = manager.getRevision();
|
||||||
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
EXPECT_EQ(manager.getRevision(), beforeAddRevision);
|
EXPECT_EQ(manager.getRevision(), beforeAddRevision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,21 +262,21 @@ namespace
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr);
|
||||||
const auto beforeUpdateRevision = manager.getRevision();
|
const auto beforeUpdateRevision = manager.getRevision();
|
||||||
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision + 1);
|
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_revision_after_update_not_changed_object_should_return_same_value)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_revision_after_update_not_changed_object_should_return_same_value)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
const auto beforeUpdateRevision = manager.getRevision();
|
const auto beforeUpdateRevision = manager.getRevision();
|
||||||
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision);
|
EXPECT_EQ(manager.getRevision(), beforeUpdateRevision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,9 +285,9 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
const auto beforeRemoveRevision = manager.getRevision();
|
const auto beforeRemoveRevision = manager.getRevision();
|
||||||
manager.removeObject(ObjectId(&boxShape));
|
manager.removeObject(ObjectId(&boxShape), nullptr);
|
||||||
EXPECT_EQ(manager.getRevision(), beforeRemoveRevision + 1);
|
EXPECT_EQ(manager.getRevision(), beforeRemoveRevision + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ namespace
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const auto beforeRemoveRevision = manager.getRevision();
|
const auto beforeRemoveRevision = manager.getRevision();
|
||||||
manager.removeObject(ObjectId(&manager));
|
manager.removeObject(ObjectId(&manager), nullptr);
|
||||||
EXPECT_EQ(manager.getRevision(), beforeRemoveRevision);
|
EXPECT_EQ(manager.getRevision(), beforeRemoveRevision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,8 +304,8 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
const auto changedTiles = manager.takeChangedTiles();
|
const auto changedTiles = manager.takeChangedTiles(nullptr);
|
||||||
EXPECT_EQ(changedTiles.begin()->first, TilePosition(-1, -1));
|
EXPECT_EQ(changedTiles.begin()->first, TilePosition(-1, -1));
|
||||||
EXPECT_EQ(changedTiles.rbegin()->first, TilePosition(11, 11));
|
EXPECT_EQ(changedTiles.rbegin()->first, TilePosition(11, 11));
|
||||||
for (const auto& [k, v] : changedTiles)
|
for (const auto& [k, v] : changedTiles)
|
||||||
|
@ -315,10 +315,10 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_not_max_int_should_add_new_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_not_max_int_should_add_new_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
for (int x = -1; x < 12; ++x)
|
for (int x = -1; x < 12; ++x)
|
||||||
for (int y = -1; y < 12; ++y)
|
for (int y = -1; y < 12; ++y)
|
||||||
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
||||||
|
@ -327,13 +327,13 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_max_int_should_not_add_new_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_max_int_should_not_add_new_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = std::numeric_limits<int>::max();
|
const int cellSize = std::numeric_limits<int>::max();
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
for (int x = -6; x < 6; ++x)
|
for (int x = -6; x < 6; ++x)
|
||||||
for (int y = -6; y < 6; ++y)
|
for (int y = -6; y < 6; ++y)
|
||||||
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0);
|
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0);
|
||||||
|
@ -342,8 +342,8 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_absent_cell_should_not_add_changed_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_absent_cell_should_not_add_changed_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.removeWater(osg::Vec2i(0, 0));
|
manager.removeWater(osg::Vec2i(0, 0), nullptr);
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), ElementsAre());
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), ElementsAre());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_add_changed_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_add_changed_tiles)
|
||||||
|
@ -351,10 +351,10 @@ namespace
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
manager.takeChangedTiles();
|
manager.takeChangedTiles(nullptr);
|
||||||
manager.removeWater(cellPosition);
|
manager.removeWater(cellPosition, nullptr);
|
||||||
const auto changedTiles = manager.takeChangedTiles();
|
const auto changedTiles = manager.takeChangedTiles(nullptr);
|
||||||
EXPECT_EQ(changedTiles.begin()->first, TilePosition(-1, -1));
|
EXPECT_EQ(changedTiles.begin()->first, TilePosition(-1, -1));
|
||||||
EXPECT_EQ(changedTiles.rbegin()->first, TilePosition(11, 11));
|
EXPECT_EQ(changedTiles.rbegin()->first, TilePosition(11, 11));
|
||||||
for (const auto& [k, v] : changedTiles)
|
for (const auto& [k, v] : changedTiles)
|
||||||
|
@ -364,11 +364,11 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_remove_empty_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_remove_empty_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
manager.removeWater(cellPosition);
|
manager.removeWater(cellPosition, nullptr);
|
||||||
for (int x = -6; x < 6; ++x)
|
for (int x = -6; x < 6; ++x)
|
||||||
for (int y = -6; y < 6; ++y)
|
for (int y = -6; y < 6; ++y)
|
||||||
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
||||||
|
@ -377,14 +377,14 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_leave_not_empty_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_leave_not_empty_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
manager.removeWater(cellPosition);
|
manager.removeWater(cellPosition, nullptr);
|
||||||
for (int x = -6; x < 6; ++x)
|
for (int x = -6; x < 6; ++x)
|
||||||
for (int y = -6; y < 6; ++y)
|
for (int y = -6; y < 6; ++y)
|
||||||
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0);
|
ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0);
|
||||||
|
@ -393,14 +393,14 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_object_should_not_remove_tile_with_water)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_object_should_not_remove_tile_with_water)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const osg::Vec2i cellPosition(0, 0);
|
const osg::Vec2i cellPosition(0, 0);
|
||||||
const int cellSize = 8192;
|
const int cellSize = 8192;
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
const CollisionShape shape(mInstance, boxShape, mObjectTransform);
|
||||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
manager.addWater(cellPosition, cellSize, 0.0f);
|
manager.addWater(cellPosition, cellSize, 0.0f, nullptr);
|
||||||
manager.removeObject(ObjectId(&boxShape));
|
manager.removeObject(ObjectId(&boxShape), nullptr);
|
||||||
for (int x = -1; x < 12; ++x)
|
for (int x = -1; x < 12; ++x)
|
||||||
for (int y = -1; y < 12; ++y)
|
for (int y = -1; y < 12; ++y)
|
||||||
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr);
|
||||||
|
@ -409,11 +409,11 @@ namespace
|
||||||
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_new_worldspace_should_remove_tiles)
|
TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_new_worldspace_should_remove_tiles)
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager manager(mSettings);
|
TileCachedRecastMeshManager manager(mSettings);
|
||||||
manager.setWorldspace("worldspace");
|
manager.setWorldspace("worldspace", nullptr);
|
||||||
const btBoxShape boxShape(btVector3(20, 20, 100));
|
const btBoxShape boxShape(btVector3(20, 20, 100));
|
||||||
const CollisionShape shape(nullptr, boxShape, mObjectTransform);
|
const CollisionShape shape(nullptr, boxShape, mObjectTransform);
|
||||||
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground));
|
ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr));
|
||||||
manager.setWorldspace("other");
|
manager.setWorldspace("other", nullptr);
|
||||||
for (int x = -1; x < 1; ++x)
|
for (int x = -1; x < 1; ++x)
|
||||||
for (int y = -1; y < 1; ++y)
|
for (int y = -1; y < 1; ++y)
|
||||||
ASSERT_EQ(manager.getMesh("other", TilePosition(x, y)), nullptr);
|
ASSERT_EQ(manager.getMesh("other", TilePosition(x, y)), nullptr);
|
||||||
|
@ -427,13 +427,13 @@ namespace
|
||||||
TileBounds bounds;
|
TileBounds bounds;
|
||||||
bounds.mMin = osg::Vec2f(182, 0);
|
bounds.mMin = osg::Vec2f(182, 0);
|
||||||
bounds.mMax = osg::Vec2f(1000, 1000);
|
bounds.mMax = osg::Vec2f(1000, 1000);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground);
|
manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr);
|
||||||
bounds.mMin = osg::Vec2f(-1000, -1000);
|
bounds.mMin = osg::Vec2f(-1000, -1000);
|
||||||
bounds.mMax = osg::Vec2f(0, -182);
|
bounds.mMax = osg::Vec2f(0, -182);
|
||||||
manager.takeChangedTiles();
|
manager.takeChangedTiles(nullptr);
|
||||||
manager.setBounds(bounds);
|
manager.setBounds(bounds, nullptr);
|
||||||
EXPECT_THAT(manager.takeChangedTiles(), ElementsAre(
|
EXPECT_THAT(manager.takeChangedTiles(nullptr), ElementsAre(
|
||||||
std::pair(TilePosition(-1, -1), ChangeType::add),
|
std::pair(TilePosition(-1, -1), ChangeType::add),
|
||||||
std::pair(TilePosition(0, 0), ChangeType::remove)
|
std::pair(TilePosition(0, 0), ChangeType::remove)
|
||||||
));
|
));
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace DetourNavigator
|
||||||
mDbWorker->updateJobs(playerTile, maxTiles);
|
mDbWorker->updateJobs(playerTile, maxTiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
void AsyncNavMeshUpdater::wait(WaitConditionType waitConditionType, Loading::Listener* listener)
|
||||||
{
|
{
|
||||||
switch (waitConditionType)
|
switch (waitConditionType)
|
||||||
{
|
{
|
||||||
|
@ -254,7 +254,7 @@ namespace DetourNavigator
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener)
|
void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener* listener)
|
||||||
{
|
{
|
||||||
const int maxDistanceToPlayer = mSettings.get().mWaitUntilMinDistanceToPlayer;
|
const int maxDistanceToPlayer = mSettings.get().mWaitUntilMinDistanceToPlayer;
|
||||||
if (maxDistanceToPlayer <= 0)
|
if (maxDistanceToPlayer <= 0)
|
||||||
|
@ -276,23 +276,28 @@ namespace DetourNavigator
|
||||||
if (!isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles)
|
if (!isAbsentTileTooClose(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles, mProcessingTiles)
|
||||||
|| mJobs.empty())
|
|| mJobs.empty())
|
||||||
return;
|
return;
|
||||||
Loading::ScopedLoad load(&listener);
|
const Loading::ScopedLoad load(listener);
|
||||||
listener.setLabel("#{Navigation:BuildingNavigationMesh}");
|
if (listener != nullptr)
|
||||||
listener.setProgressRange(maxProgress);
|
{
|
||||||
|
listener->setLabel("#{Navigation:BuildingNavigationMesh}");
|
||||||
|
listener->setProgressRange(maxProgress);
|
||||||
|
}
|
||||||
while (!mDone.wait_for(lock, std::chrono::milliseconds(20), isDone))
|
while (!mDone.wait_for(lock, std::chrono::milliseconds(20), isDone))
|
||||||
{
|
{
|
||||||
|
if (listener == nullptr)
|
||||||
|
continue;
|
||||||
if (maxProgress < jobsLeft)
|
if (maxProgress < jobsLeft)
|
||||||
{
|
{
|
||||||
maxProgress = jobsLeft;
|
maxProgress = jobsLeft;
|
||||||
listener.setProgressRange(maxProgress);
|
listener->setProgressRange(maxProgress);
|
||||||
listener.setProgress(jobsDone);
|
listener->setProgress(jobsDone);
|
||||||
}
|
}
|
||||||
else if (jobsLeft < prevJobsLeft)
|
else if (jobsLeft < prevJobsLeft)
|
||||||
{
|
{
|
||||||
const std::size_t newJobsDone = prevJobsLeft - jobsLeft;
|
const std::size_t newJobsDone = prevJobsLeft - jobsLeft;
|
||||||
jobsDone += newJobsDone;
|
jobsDone += newJobsDone;
|
||||||
prevJobsLeft = jobsLeft;
|
prevJobsLeft = jobsLeft;
|
||||||
listener.increaseProgress(newJobsDone);
|
listener->increaseProgress(newJobsDone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace DetourNavigator
|
||||||
const TilePosition& playerTile, std::string_view worldspace,
|
const TilePosition& playerTile, std::string_view worldspace,
|
||||||
const std::map<TilePosition, ChangeType>& changedTiles);
|
const std::map<TilePosition, ChangeType>& changedTiles);
|
||||||
|
|
||||||
void wait(Loading::Listener& listener, WaitConditionType waitConditionType);
|
void wait(WaitConditionType waitConditionType, Loading::Listener* listener);
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void cleanupLastUpdates();
|
void cleanupLastUpdates();
|
||||||
|
|
||||||
inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener);
|
inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener* listener);
|
||||||
|
|
||||||
inline void waitUntilAllJobsDone();
|
inline void waitUntilAllJobsDone();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace DetourNavigator
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UpdateGuard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Top level interface of detournavigator component. Navigator allows to build a scene with navmesh and find
|
* @brief Top level interface of detournavigator component. Navigator allows to build a scene with navmesh and find
|
||||||
* a path for an agent there. Scene contains agents, geometry objects and water. Agent are distinguished only by
|
* a path for an agent there. Scene contains agents, geometry objects and water. Agent are distinguished only by
|
||||||
|
@ -66,6 +68,8 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
virtual ~Navigator() = default;
|
virtual ~Navigator() = default;
|
||||||
|
|
||||||
|
virtual std::unique_ptr<const UpdateGuard> makeUpdateGuard() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief addAgent should be called for each agent even if all of them has same half extents.
|
* @brief addAgent should be called for each agent even if all of them has same half extents.
|
||||||
* @param agentBounds allows to setup bounding cylinder for each agent, for each different half extents
|
* @param agentBounds allows to setup bounding cylinder for each agent, for each different half extents
|
||||||
|
@ -83,13 +87,13 @@ namespace DetourNavigator
|
||||||
* @brief setWorldspace should be called before adding object from new worldspace
|
* @brief setWorldspace should be called before adding object from new worldspace
|
||||||
* @param worldspace
|
* @param worldspace
|
||||||
*/
|
*/
|
||||||
virtual void setWorldspace(std::string_view worldspace) = 0;
|
virtual void setWorldspace(std::string_view worldspace, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief updateBounds should be called before adding object from loading cell
|
* @brief updateBounds should be called before adding object from loading cell
|
||||||
* @param playerPosition corresponds to the bounds center
|
* @param playerPosition corresponds to the bounds center
|
||||||
*/
|
*/
|
||||||
virtual void updateBounds(const osg::Vec3f& playerPosition) = 0;
|
virtual void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes
|
* @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes
|
||||||
|
@ -97,7 +101,8 @@ namespace DetourNavigator
|
||||||
* @param shape members must live until object is updated by another shape removed from Navigator
|
* @param shape members must live until object is updated by another shape removed from Navigator
|
||||||
* @param transform allows to setup objects geometry according to its world state
|
* @param transform allows to setup objects geometry according to its world state
|
||||||
*/
|
*/
|
||||||
virtual void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
|
virtual void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief addObject is used to add doors.
|
* @brief addObject is used to add doors.
|
||||||
|
@ -105,7 +110,8 @@ namespace DetourNavigator
|
||||||
* @param shape members must live until object is updated by another shape or removed from Navigator.
|
* @param shape members must live until object is updated by another shape or removed from Navigator.
|
||||||
* @param transform allows to setup objects geometry according to its world state.
|
* @param transform allows to setup objects geometry according to its world state.
|
||||||
*/
|
*/
|
||||||
virtual void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
|
virtual void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief updateObject replace object geometry by given data.
|
* @brief updateObject replace object geometry by given data.
|
||||||
|
@ -113,7 +119,8 @@ namespace DetourNavigator
|
||||||
* @param shape members must live until object is updated by another shape removed from Navigator.
|
* @param shape members must live until object is updated by another shape removed from Navigator.
|
||||||
* @param transform allows to setup objects geometry according to its world state.
|
* @param transform allows to setup objects geometry according to its world state.
|
||||||
*/
|
*/
|
||||||
virtual void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0;
|
virtual void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief updateObject replace object geometry by given data.
|
* @brief updateObject replace object geometry by given data.
|
||||||
|
@ -121,13 +128,14 @@ namespace DetourNavigator
|
||||||
* @param shape members must live until object is updated by another shape removed from Navigator.
|
* @param shape members must live until object is updated by another shape removed from Navigator.
|
||||||
* @param transform allows to setup objects geometry according to its world state.
|
* @param transform allows to setup objects geometry according to its world state.
|
||||||
*/
|
*/
|
||||||
virtual void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0;
|
virtual void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief removeObject to make it no more available at the scene.
|
* @brief removeObject to make it no more available at the scene.
|
||||||
* @param id is used to find object.
|
* @param id is used to find object.
|
||||||
*/
|
*/
|
||||||
virtual void removeObject(const ObjectId id) = 0;
|
virtual void removeObject(const ObjectId id, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief addWater is used to set water level at given world cell.
|
* @brief addWater is used to set water level at given world cell.
|
||||||
|
@ -135,17 +143,19 @@ namespace DetourNavigator
|
||||||
* @param cellSize set cell borders. std::numeric_limits<int>::max() disables cell borders.
|
* @param cellSize set cell borders. std::numeric_limits<int>::max() disables cell borders.
|
||||||
* @param shift set global shift of cell center.
|
* @param shift set global shift of cell center.
|
||||||
*/
|
*/
|
||||||
virtual void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0;
|
virtual void addWater(const osg::Vec2i& cellPosition, int cellSize, float level,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief removeWater to make it no more available at the scene.
|
* @brief removeWater to make it no more available at the scene.
|
||||||
* @param cellPosition allows to find cell.
|
* @param cellPosition allows to find cell.
|
||||||
*/
|
*/
|
||||||
virtual void removeWater(const osg::Vec2i& cellPosition) = 0;
|
virtual void removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
virtual void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) = 0;
|
virtual void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape,
|
||||||
|
const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
virtual void removeHeightfield(const osg::Vec2i& cellPosition) = 0;
|
virtual void removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
virtual void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) = 0;
|
virtual void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) = 0;
|
||||||
|
|
||||||
|
@ -155,13 +165,14 @@ namespace DetourNavigator
|
||||||
* @brief update starts background navmesh update using current scene state.
|
* @brief update starts background navmesh update using current scene state.
|
||||||
* @param playerPosition setup initial point to order build tiles of navmesh.
|
* @param playerPosition setup initial point to order build tiles of navmesh.
|
||||||
*/
|
*/
|
||||||
virtual void update(const osg::Vec3f& playerPosition) = 0;
|
virtual void update(const osg::Vec3f& playerPosition, const UpdateGuard* guard) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief wait locks thread until tiles are updated from last update call based on passed condition type.
|
* @brief wait locks thread until tiles are updated from last update call based on passed condition type.
|
||||||
* @param waitConditionType defines when waiting will stop
|
* @param waitConditionType defines when waiting will stop
|
||||||
|
* @param listener optional listener for a progress bar
|
||||||
*/
|
*/
|
||||||
virtual void wait(Loading::Listener& listener, WaitConditionType waitConditionType) = 0;
|
virtual void wait(WaitConditionType waitConditionType, Loading::Listener* listener) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getNavMesh returns navmesh for specific agent half extents
|
* @brief getNavMesh returns navmesh for specific agent half extents
|
||||||
|
|
|
@ -32,41 +32,44 @@ namespace DetourNavigator
|
||||||
--it->second;
|
--it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::setWorldspace(std::string_view worldspace)
|
void NavigatorImpl::setWorldspace(std::string_view worldspace, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.setWorldspace(worldspace);
|
mNavMeshManager.setWorldspace(worldspace, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateBounds(const osg::Vec3f& playerPosition)
|
void NavigatorImpl::updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.updateBounds(playerPosition);
|
mNavMeshManager.updateBounds(playerPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
|
void NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
addObjectImpl(id, shapes, transform);
|
addObjectImpl(id, shapes, transform, guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NavigatorImpl::addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
|
bool NavigatorImpl::addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform);
|
const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform);
|
||||||
bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground);
|
bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground, getImpl(guard));
|
||||||
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
|
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
|
||||||
{
|
{
|
||||||
const ObjectId avoidId(avoidShape);
|
const ObjectId avoidId(avoidShape);
|
||||||
const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform);
|
const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform);
|
||||||
if (mNavMeshManager.addObject(avoidId, avoidCollisionShape, transform, AreaType_null))
|
if (mNavMeshManager.addObject(avoidId, avoidCollisionShape, transform, AreaType_null, getImpl(guard)))
|
||||||
{
|
{
|
||||||
updateAvoidShapeId(id, avoidId);
|
updateAvoidShapeId(id, avoidId, guard);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
|
void NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
if (addObjectImpl(id, static_cast<const ObjectShapes&>(shapes), transform))
|
if (addObjectImpl(id, static_cast<const ObjectShapes&>(shapes), transform, guard))
|
||||||
{
|
{
|
||||||
const osg::Vec3f start = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionStart);
|
const osg::Vec3f start = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionStart);
|
||||||
const osg::Vec3f end = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionEnd);
|
const osg::Vec3f end = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionEnd);
|
||||||
|
@ -75,52 +78,55 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform)
|
void NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.updateObject(id, transform, AreaType_ground);
|
mNavMeshManager.updateObject(id, transform, AreaType_ground, getImpl(guard));
|
||||||
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
|
if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get())
|
||||||
{
|
{
|
||||||
const ObjectId avoidId(avoidShape);
|
const ObjectId avoidId(avoidShape);
|
||||||
if (mNavMeshManager.updateObject(avoidId, transform, AreaType_null))
|
if (mNavMeshManager.updateObject(avoidId, transform, AreaType_null, getImpl(guard)))
|
||||||
updateAvoidShapeId(id, avoidId);
|
updateAvoidShapeId(id, avoidId, guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform)
|
void NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
return updateObject(id, static_cast<const ObjectShapes&>(shapes), transform);
|
return updateObject(id, static_cast<const ObjectShapes&>(shapes), transform, guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::removeObject(const ObjectId id)
|
void NavigatorImpl::removeObject(const ObjectId id, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.removeObject(id);
|
mNavMeshManager.removeObject(id, getImpl(guard));
|
||||||
const auto avoid = mAvoidIds.find(id);
|
const auto avoid = mAvoidIds.find(id);
|
||||||
if (avoid != mAvoidIds.end())
|
if (avoid != mAvoidIds.end())
|
||||||
mNavMeshManager.removeObject(avoid->second);
|
mNavMeshManager.removeObject(avoid->second, getImpl(guard));
|
||||||
const auto water = mWaterIds.find(id);
|
const auto water = mWaterIds.find(id);
|
||||||
if (water != mWaterIds.end())
|
if (water != mWaterIds.end())
|
||||||
mNavMeshManager.removeObject(water->second);
|
mNavMeshManager.removeObject(water->second, getImpl(guard));
|
||||||
mNavMeshManager.removeOffMeshConnections(id);
|
mNavMeshManager.removeOffMeshConnections(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
|
void NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.addWater(cellPosition, cellSize, level);
|
mNavMeshManager.addWater(cellPosition, cellSize, level, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::removeWater(const osg::Vec2i& cellPosition)
|
void NavigatorImpl::removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.removeWater(cellPosition);
|
mNavMeshManager.removeWater(cellPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
|
void NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape,
|
||||||
|
const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.addHeightfield(cellPosition, cellSize, shape);
|
mNavMeshManager.addHeightfield(cellPosition, cellSize, shape, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition)
|
void NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mNavMeshManager.removeHeightfield(cellPosition);
|
mNavMeshManager.removeHeightfield(cellPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid)
|
void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid)
|
||||||
|
@ -144,15 +150,15 @@ namespace DetourNavigator
|
||||||
mNavMeshManager.removeOffMeshConnections(ObjectId(&pathgrid));
|
mNavMeshManager.removeOffMeshConnections(ObjectId(&pathgrid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::update(const osg::Vec3f& playerPosition)
|
void NavigatorImpl::update(const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
removeUnusedNavMeshes();
|
removeUnusedNavMeshes();
|
||||||
mNavMeshManager.update(playerPosition);
|
mNavMeshManager.update(playerPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
void NavigatorImpl::wait(WaitConditionType waitConditionType, Loading::Listener* listener)
|
||||||
{
|
{
|
||||||
mNavMeshManager.wait(listener, waitConditionType);
|
mNavMeshManager.wait(waitConditionType, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const AgentBounds& agentBounds) const
|
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const AgentBounds& agentBounds) const
|
||||||
|
@ -180,22 +186,18 @@ namespace DetourNavigator
|
||||||
return mNavMeshManager.getRecastMeshTiles();
|
return mNavMeshManager.getRecastMeshTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId)
|
void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
updateId(id, avoidId, mWaterIds);
|
updateId(id, avoidId, mWaterIds, guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateWaterShapeId(const ObjectId id, const ObjectId waterId)
|
void NavigatorImpl::updateId(const ObjectId id, const ObjectId updateId,
|
||||||
{
|
std::unordered_map<ObjectId, ObjectId>& ids, const UpdateGuard* guard)
|
||||||
updateId(id, waterId, mWaterIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigatorImpl::updateId(const ObjectId id, const ObjectId updateId, std::unordered_map<ObjectId, ObjectId>& ids)
|
|
||||||
{
|
{
|
||||||
auto inserted = ids.insert(std::make_pair(id, updateId));
|
auto inserted = ids.insert(std::make_pair(id, updateId));
|
||||||
if (!inserted.second)
|
if (!inserted.second)
|
||||||
{
|
{
|
||||||
mNavMeshManager.removeObject(inserted.first->second);
|
mNavMeshManager.removeObject(inserted.first->second, getImpl(guard));
|
||||||
inserted.first->second = updateId;
|
inserted.first->second = updateId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,39 +18,49 @@ namespace DetourNavigator
|
||||||
*/
|
*/
|
||||||
explicit NavigatorImpl(const Settings& settings, std::unique_ptr<NavMeshDb>&& db);
|
explicit NavigatorImpl(const Settings& settings, std::unique_ptr<NavMeshDb>&& db);
|
||||||
|
|
||||||
|
std::unique_ptr<const DetourNavigator::UpdateGuard> makeUpdateGuard() override
|
||||||
|
{
|
||||||
|
return std::make_unique<const UpdateGuard>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void addAgent(const AgentBounds& agentBounds) override;
|
void addAgent(const AgentBounds& agentBounds) override;
|
||||||
|
|
||||||
void removeAgent(const AgentBounds& agentBounds) override;
|
void removeAgent(const AgentBounds& agentBounds) override;
|
||||||
|
|
||||||
void setWorldspace(std::string_view worldspace) override;
|
void setWorldspace(std::string_view worldspace, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void updateBounds(const osg::Vec3f& playerPosition) override;
|
void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
|
void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
|
void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override;
|
void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override;
|
void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform,
|
||||||
|
const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void removeObject(const ObjectId id) override;
|
void removeObject(const ObjectId id, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override;
|
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void removeWater(const osg::Vec2i& cellPosition) override;
|
void removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) override;
|
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape,
|
||||||
|
const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void removeHeightfield(const osg::Vec2i& cellPosition) override;
|
void removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) override;
|
void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) override;
|
||||||
|
|
||||||
void removePathgrid(const ESM::Pathgrid& pathgrid) override;
|
void removePathgrid(const ESM::Pathgrid& pathgrid) override;
|
||||||
|
|
||||||
void update(const osg::Vec3f& playerPosition) override;
|
void update(const osg::Vec3f& playerPosition, const UpdateGuard* guard) override;
|
||||||
|
|
||||||
void wait(Loading::Listener& listener, WaitConditionType waitConditionType) override;
|
void wait(WaitConditionType waitConditionType, Loading::Listener* listener) override;
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const override;
|
SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const override;
|
||||||
|
|
||||||
|
@ -72,11 +82,31 @@ namespace DetourNavigator
|
||||||
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
||||||
std::unordered_map<ObjectId, ObjectId> mWaterIds;
|
std::unordered_map<ObjectId, ObjectId> mWaterIds;
|
||||||
|
|
||||||
inline bool addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform);
|
inline bool addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform,
|
||||||
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
|
const UpdateGuard* guard);
|
||||||
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
|
|
||||||
void updateId(const ObjectId id, const ObjectId waterId, std::unordered_map<ObjectId, ObjectId>& ids);
|
inline void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId, const UpdateGuard* guard);
|
||||||
void removeUnusedNavMeshes();
|
|
||||||
|
inline void updateId(const ObjectId id, const ObjectId waterId, std::unordered_map<ObjectId, ObjectId>& ids,
|
||||||
|
const UpdateGuard* guard);
|
||||||
|
|
||||||
|
inline void removeUnusedNavMeshes();
|
||||||
|
|
||||||
|
friend class UpdateGuard;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpdateGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit UpdateGuard(NavigatorImpl& navigator) : mImpl(navigator.mNavMeshManager) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NavMeshManager::UpdateGuard mImpl;
|
||||||
|
|
||||||
|
friend inline const NavMeshManager::UpdateGuard* getImpl(const UpdateGuard* guard)
|
||||||
|
{
|
||||||
|
return guard == nullptr ? nullptr : &guard->mImpl;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,40 +17,47 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
NavigatorStub() = default;
|
NavigatorStub() = default;
|
||||||
|
|
||||||
|
std::unique_ptr<const UpdateGuard> makeUpdateGuard() override { return nullptr; }
|
||||||
|
|
||||||
void addAgent(const AgentBounds& /*agentBounds*/) override {}
|
void addAgent(const AgentBounds& /*agentBounds*/) override {}
|
||||||
|
|
||||||
void removeAgent(const AgentBounds& /*agentBounds*/) override {}
|
void removeAgent(const AgentBounds& /*agentBounds*/) override {}
|
||||||
|
|
||||||
void setWorldspace(std::string_view /*worldspace*/) override {}
|
void setWorldspace(std::string_view /*worldspace*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {}
|
void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/,
|
||||||
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {}
|
void addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/,
|
||||||
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {}
|
void updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/,
|
||||||
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {}
|
void updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/,
|
||||||
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void removeObject(const ObjectId /*id*/) override {}
|
void removeObject(const ObjectId /*id*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override {}
|
void addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/,
|
||||||
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void removeWater(const osg::Vec2i& /*cellPosition*/) override {}
|
void removeWater(const osg::Vec2i& /*cellPosition*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/)
|
void addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/,
|
||||||
override {}
|
const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void removeHeightfield(const osg::Vec2i& /*cellPosition*/) override {}
|
void removeHeightfield(const osg::Vec2i& /*cellPosition*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) override {}
|
void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) override {}
|
||||||
|
|
||||||
void removePathgrid(const ESM::Pathgrid& /*pathgrid*/) override {}
|
void removePathgrid(const ESM::Pathgrid& /*pathgrid*/) override {}
|
||||||
|
|
||||||
void update(const osg::Vec3f& /*playerPosition*/) override {}
|
void update(const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void updateBounds(const osg::Vec3f& /*playerPosition*/) override {}
|
void updateBounds(const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override {}
|
||||||
|
|
||||||
void wait(Loading::Listener& /*listener*/, WaitConditionType /*waitConditionType*/) override {}
|
void wait(WaitConditionType /*waitConditionType*/, Loading::Listener* /*listener*/) override {}
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const AgentBounds& /*agentBounds*/) const override
|
SharedNavMeshCacheItem getNavMesh(const AgentBounds& /*agentBounds*/) const override
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,57 +57,57 @@ namespace DetourNavigator
|
||||||
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db))
|
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void NavMeshManager::setWorldspace(std::string_view worldspace)
|
void NavMeshManager::setWorldspace(std::string_view worldspace, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
if (worldspace == mWorldspace)
|
if (worldspace == mWorldspace)
|
||||||
return;
|
return;
|
||||||
mRecastMeshManager.setWorldspace(worldspace);
|
mRecastMeshManager.setWorldspace(worldspace, getImpl(guard));
|
||||||
for (auto& [agent, cache] : mCache)
|
for (auto& [agent, cache] : mCache)
|
||||||
cache = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter);
|
cache = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter);
|
||||||
mWorldspace = worldspace;
|
mWorldspace = worldspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::updateBounds(const osg::Vec3f& playerPosition)
|
void NavMeshManager::updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const TileBounds bounds = makeBounds(mSettings.mRecast, osg::Vec2f(playerPosition.x(), playerPosition.y()),
|
const TileBounds bounds = makeBounds(mSettings.mRecast, osg::Vec2f(playerPosition.x(), playerPosition.y()),
|
||||||
mSettings.mMaxTilesNumber);
|
mSettings.mMaxTilesNumber);
|
||||||
mRecastMeshManager.setBounds(bounds);
|
mRecastMeshManager.setBounds(bounds, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NavMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
bool NavMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType)
|
const AreaType areaType, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
return mRecastMeshManager.addObject(id, shape, transform, areaType);
|
return mRecastMeshManager.addObject(id, shape, transform, areaType, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NavMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType)
|
bool NavMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
return mRecastMeshManager.updateObject(id, transform, areaType);
|
return mRecastMeshManager.updateObject(id, transform, areaType, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::removeObject(const ObjectId id)
|
void NavMeshManager::removeObject(const ObjectId id, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.removeObject(id);
|
mRecastMeshManager.removeObject(id, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
|
void NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.addWater(cellPosition, cellSize, level);
|
mRecastMeshManager.addWater(cellPosition, cellSize, level, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::removeWater(const osg::Vec2i& cellPosition)
|
void NavMeshManager::removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.removeWater(cellPosition);
|
mRecastMeshManager.removeWater(cellPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape)
|
void NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.addHeightfield(cellPosition, cellSize, shape);
|
mRecastMeshManager.addHeightfield(cellPosition, cellSize, shape, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
|
void NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
mRecastMeshManager.removeHeightfield(cellPosition);
|
mRecastMeshManager.removeHeightfield(cellPosition, getImpl(guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::addAgent(const AgentBounds& agentBounds)
|
void NavMeshManager::addAgent(const AgentBounds& agentBounds)
|
||||||
|
@ -153,7 +153,7 @@ namespace DetourNavigator
|
||||||
mRecastMeshManager.addChangedTile(tile, ChangeType::update);
|
mRecastMeshManager.addChangedTile(tile, ChangeType::update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::update(const osg::Vec3f& playerPosition)
|
void NavMeshManager::update(const osg::Vec3f& playerPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const auto playerTile = getTilePosition(mSettings.mRecast,
|
const auto playerTile = getTilePosition(mSettings.mRecast,
|
||||||
toNavMeshCoordinates(mSettings.mRecast, playerPosition));
|
toNavMeshCoordinates(mSettings.mRecast, playerPosition));
|
||||||
|
@ -162,7 +162,7 @@ namespace DetourNavigator
|
||||||
return;
|
return;
|
||||||
mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision();
|
mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision();
|
||||||
mPlayerTile = playerTile;
|
mPlayerTile = playerTile;
|
||||||
const auto changedTiles = mRecastMeshManager.takeChangedTiles();
|
const auto changedTiles = mRecastMeshManager.takeChangedTiles(getImpl(guard));
|
||||||
const TilesPositionsRange range = mRecastMeshManager.getRange();
|
const TilesPositionsRange range = mRecastMeshManager.getRange();
|
||||||
for (const auto& [agentBounds, cached] : mCache)
|
for (const auto& [agentBounds, cached] : mCache)
|
||||||
update(agentBounds, playerTile, range, cached, changedTiles);
|
update(agentBounds, playerTile, range, cached, changedTiles);
|
||||||
|
@ -194,9 +194,9 @@ namespace DetourNavigator
|
||||||
" playerTile=" << playerTile << " recastMeshManagerRevision=" << mLastRecastMeshManagerRevision;
|
" playerTile=" << playerTile << " recastMeshManagerRevision=" << mLastRecastMeshManagerRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::wait(Loading::Listener& listener, WaitConditionType waitConditionType)
|
void NavMeshManager::wait(WaitConditionType waitConditionType, Loading::Listener* listener)
|
||||||
{
|
{
|
||||||
mAsyncNavMeshUpdater.wait(listener, waitConditionType);
|
mAsyncNavMeshUpdater.wait(waitConditionType, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNavMeshCacheItem NavMeshManager::getNavMesh(const AgentBounds& agentBounds) const
|
SharedNavMeshCacheItem NavMeshManager::getNavMesh(const AgentBounds& agentBounds) const
|
||||||
|
|
|
@ -20,28 +20,44 @@ namespace DetourNavigator
|
||||||
class NavMeshManager
|
class NavMeshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class UpdateGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit UpdateGuard(NavMeshManager& manager) : mImpl(manager.mRecastMeshManager) {}
|
||||||
|
|
||||||
|
friend const TileCachedRecastMeshManager::UpdateGuard* getImpl(const UpdateGuard* guard)
|
||||||
|
{
|
||||||
|
return guard == nullptr ? nullptr : &guard->mImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const TileCachedRecastMeshManager::UpdateGuard mImpl;
|
||||||
|
};
|
||||||
|
|
||||||
explicit NavMeshManager(const Settings& settings, std::unique_ptr<NavMeshDb>&& db);
|
explicit NavMeshManager(const Settings& settings, std::unique_ptr<NavMeshDb>&& db);
|
||||||
|
|
||||||
void setWorldspace(std::string_view worldspace);
|
void setWorldspace(std::string_view worldspace, const UpdateGuard* guard);
|
||||||
|
|
||||||
void updateBounds(const osg::Vec3f& playerPosition);
|
void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType);
|
const AreaType areaType, const UpdateGuard* guard);
|
||||||
|
|
||||||
bool updateObject(ObjectId id, const btTransform& transform, AreaType areaType);
|
bool updateObject(ObjectId id, const btTransform& transform, AreaType areaType,
|
||||||
|
const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeObject(const ObjectId id);
|
void removeObject(const ObjectId id, const UpdateGuard* guard);
|
||||||
|
|
||||||
void addAgent(const AgentBounds& agentBounds);
|
void addAgent(const AgentBounds& agentBounds);
|
||||||
|
|
||||||
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
|
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level, const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeWater(const osg::Vec2i& cellPosition);
|
void removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape);
|
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape,
|
||||||
|
const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeHeightfield(const osg::Vec2i& cellPosition);
|
void removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
bool reset(const AgentBounds& agentBounds);
|
bool reset(const AgentBounds& agentBounds);
|
||||||
|
|
||||||
|
@ -49,9 +65,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void removeOffMeshConnections(const ObjectId id);
|
void removeOffMeshConnections(const ObjectId id);
|
||||||
|
|
||||||
void update(const osg::Vec3f& playerPosition);
|
void update(const osg::Vec3f& playerPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
void wait(Loading::Listener& listener, WaitConditionType waitConditionType);
|
void wait(WaitConditionType waitConditionType, Loading::Listener* listener);
|
||||||
|
|
||||||
SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const;
|
SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,18 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
return TilePosition(v.get<0>(), v.get<1>());
|
return TilePosition(v.get<0>(), v.get<1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Mutex>
|
||||||
|
class MaybeLockGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MaybeLockGuard(Mutex& mutex, const TileCachedRecastMeshManager::UpdateGuard* guard)
|
||||||
|
: mImpl(guard == nullptr ? std::optional<std::unique_lock<Mutex>>(mutex) : std::nullopt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::optional<std::unique_lock<Mutex>> mImpl;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings)
|
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings)
|
||||||
|
@ -51,7 +63,7 @@ namespace DetourNavigator
|
||||||
, mRange(makeTilesPositionsRange(mBounds.mMin, mBounds.mMax, mSettings))
|
, mRange(makeTilesPositionsRange(mBounds.mMin, mBounds.mMax, mSettings))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::setBounds(const TileBounds& bounds)
|
void TileCachedRecastMeshManager::setBounds(const TileBounds& bounds, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
if (mBounds == bounds)
|
if (mBounds == bounds)
|
||||||
return;
|
return;
|
||||||
|
@ -87,7 +99,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
++mRevision;
|
++mRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +116,9 @@ namespace DetourNavigator
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace)
|
void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
if (mWorldspace == worldspace)
|
if (mWorldspace == worldspace)
|
||||||
return;
|
return;
|
||||||
mWorldspace = worldspace;
|
mWorldspace = worldspace;
|
||||||
|
@ -120,11 +132,11 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileCachedRecastMeshManager::addObject(ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
bool TileCachedRecastMeshManager::addObject(ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType)
|
const AreaType areaType, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const TilesPositionsRange range = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
|
const TilesPositionsRange range = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
const auto it = mObjects.find(id);
|
const auto it = mObjects.find(id);
|
||||||
if (it != mObjects.end())
|
if (it != mObjects.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -147,12 +159,12 @@ namespace DetourNavigator
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileCachedRecastMeshManager::updateObject(ObjectId id, const btTransform& transform, const AreaType areaType)
|
bool TileCachedRecastMeshManager::updateObject(ObjectId id, const btTransform& transform, const AreaType areaType, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
TilesPositionsRange newRange;
|
TilesPositionsRange newRange;
|
||||||
TilesPositionsRange oldRange;
|
TilesPositionsRange oldRange;
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
const auto it = mObjects.find(id);
|
const auto it = mObjects.find(id);
|
||||||
if (it == mObjects.end())
|
if (it == mObjects.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -196,11 +208,11 @@ namespace DetourNavigator
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::removeObject(ObjectId id)
|
void TileCachedRecastMeshManager::removeObject(ObjectId id, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
TilesPositionsRange range;
|
TilesPositionsRange range;
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
const auto it = mObjects.find(id);
|
const auto it = mObjects.find(id);
|
||||||
if (it == mObjects.end())
|
if (it == mObjects.end())
|
||||||
return;
|
return;
|
||||||
|
@ -213,14 +225,14 @@ namespace DetourNavigator
|
||||||
[&] (const TilePosition& v) { addChangedTile(v, ChangeType::remove); });
|
[&] (const TilePosition& v) { addChangedTile(v, ChangeType::remove); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const float level)
|
void TileCachedRecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const float level, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level));
|
const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level));
|
||||||
const std::optional<TilesPositionsRange> range = cellSize == std::numeric_limits<int>::max()
|
const std::optional<TilesPositionsRange> range = cellSize == std::numeric_limits<int>::max()
|
||||||
? std::optional<TilesPositionsRange>()
|
? std::optional<TilesPositionsRange>()
|
||||||
: makeTilesPositionsRange(cellSize, shift, mSettings);
|
: makeTilesPositionsRange(cellSize, shift, mSettings);
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
auto it = mWater.find(cellPosition);
|
auto it = mWater.find(cellPosition);
|
||||||
if (it != mWater.end())
|
if (it != mWater.end())
|
||||||
return;
|
return;
|
||||||
|
@ -239,11 +251,11 @@ namespace DetourNavigator
|
||||||
addChangedTiles(range, ChangeType::add);
|
addChangedTiles(range, ChangeType::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
|
void TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
std::optional<TilesPositionsRange> range;
|
std::optional<TilesPositionsRange> range;
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
const auto it = mWater.find(cellPosition);
|
const auto it = mWater.find(cellPosition);
|
||||||
if (it == mWater.end())
|
if (it == mWater.end())
|
||||||
return;
|
return;
|
||||||
|
@ -259,14 +271,14 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::addHeightfield(const osg::Vec2i& cellPosition, const int cellSize,
|
void TileCachedRecastMeshManager::addHeightfield(const osg::Vec2i& cellPosition, const int cellSize,
|
||||||
const HeightfieldShape& shape)
|
const HeightfieldShape& shape, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
const btVector3 shift = getHeightfieldShift(shape, cellPosition, cellSize);
|
const btVector3 shift = getHeightfieldShift(shape, cellPosition, cellSize);
|
||||||
const std::optional<TilesPositionsRange> range = cellSize == std::numeric_limits<int>::max()
|
const std::optional<TilesPositionsRange> range = cellSize == std::numeric_limits<int>::max()
|
||||||
? std::optional<TilesPositionsRange>()
|
? std::optional<TilesPositionsRange>()
|
||||||
: makeTilesPositionsRange(cellSize, shift, mSettings);
|
: makeTilesPositionsRange(cellSize, shift, mSettings);
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
auto it = mHeightfields.find(cellPosition);
|
auto it = mHeightfields.find(cellPosition);
|
||||||
if (it != mHeightfields.end())
|
if (it != mHeightfields.end())
|
||||||
return;
|
return;
|
||||||
|
@ -286,11 +298,11 @@ namespace DetourNavigator
|
||||||
addChangedTiles(range, ChangeType::add);
|
addChangedTiles(range, ChangeType::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileCachedRecastMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
|
void TileCachedRecastMeshManager::removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
std::optional<TilesPositionsRange> range;
|
std::optional<TilesPositionsRange> range;
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
const auto it = mHeightfields.find(cellPosition);
|
const auto it = mHeightfields.find(cellPosition);
|
||||||
if (it == mHeightfields.end())
|
if (it == mHeightfields.end())
|
||||||
return;
|
return;
|
||||||
|
@ -378,10 +390,10 @@ namespace DetourNavigator
|
||||||
tile->second = addChangeType(tile->second, changeType);
|
tile->second = addChangeType(tile->second, changeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<osg::Vec2i, ChangeType> TileCachedRecastMeshManager::takeChangedTiles()
|
std::map<osg::Vec2i, ChangeType> TileCachedRecastMeshManager::takeChangedTiles(const UpdateGuard* guard)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const MaybeLockGuard lock(mMutex, guard);
|
||||||
for (const auto& [tilePosition, changeType] : mChangedTiles)
|
for (const auto& [tilePosition, changeType] : mChangedTiles)
|
||||||
if (const auto it = mCache.find(tilePosition); it != mCache.end())
|
if (const auto it = mCache.find(tilePosition); it != mCache.end())
|
||||||
++it->second.mVersion.mRevision;
|
++it->second.mVersion.mRevision;
|
||||||
|
|
|
@ -31,27 +31,38 @@ namespace DetourNavigator
|
||||||
class TileCachedRecastMeshManager
|
class TileCachedRecastMeshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class UpdateGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit UpdateGuard(TileCachedRecastMeshManager& manager) : mImpl(manager.mMutex) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::lock_guard<std::mutex> mImpl;
|
||||||
|
};
|
||||||
|
|
||||||
explicit TileCachedRecastMeshManager(const RecastSettings& settings);
|
explicit TileCachedRecastMeshManager(const RecastSettings& settings);
|
||||||
|
|
||||||
void setBounds(const TileBounds& bounds);
|
void setBounds(const TileBounds& bounds, const UpdateGuard* guard);
|
||||||
|
|
||||||
TilesPositionsRange getRange() const;
|
TilesPositionsRange getRange() const;
|
||||||
|
|
||||||
void setWorldspace(std::string_view worldspace);
|
void setWorldspace(std::string_view worldspace, const UpdateGuard* guard);
|
||||||
|
|
||||||
bool addObject(ObjectId id, const CollisionShape& shape, const btTransform& transform, AreaType areaType);
|
bool addObject(ObjectId id, const CollisionShape& shape, const btTransform& transform, AreaType areaType,
|
||||||
|
const UpdateGuard* guard);
|
||||||
|
|
||||||
bool updateObject(ObjectId id, const btTransform& transform, AreaType areaType);
|
bool updateObject(ObjectId id, const btTransform& transform, AreaType areaType, const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeObject(ObjectId id);
|
void removeObject(ObjectId id, const UpdateGuard* guard);
|
||||||
|
|
||||||
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level);
|
void addWater(const osg::Vec2i& cellPosition, int cellSize, float level, const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeWater(const osg::Vec2i& cellPosition);
|
void removeWater(const osg::Vec2i& cellPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape);
|
void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape,
|
||||||
|
const UpdateGuard* guard);
|
||||||
|
|
||||||
void removeHeightfield(const osg::Vec2i& cellPosition);
|
void removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard);
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> getMesh(std::string_view worldspace, const TilePosition& tilePosition);
|
std::shared_ptr<RecastMesh> getMesh(std::string_view worldspace, const TilePosition& tilePosition);
|
||||||
|
|
||||||
|
@ -65,7 +76,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void addChangedTile(const TilePosition& tilePosition, ChangeType changeType);
|
void addChangedTile(const TilePosition& tilePosition, ChangeType changeType);
|
||||||
|
|
||||||
std::map<osg::Vec2i, ChangeType> takeChangedTiles();
|
std::map<osg::Vec2i, ChangeType> takeChangedTiles(const UpdateGuard* guard);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Report
|
struct Report
|
||||||
|
|
Loading…
Reference in a new issue