2018-03-13 22:49:08 +00:00
|
|
|
#include "recastmeshmanager.hpp"
|
2021-07-03 00:59:07 +00:00
|
|
|
#include "recastmeshbuilder.hpp"
|
2021-07-16 18:19:11 +00:00
|
|
|
#include "settings.hpp"
|
2021-07-14 18:57:52 +00:00
|
|
|
#include "heightfieldshape.hpp"
|
|
|
|
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct AddHeightfield
|
|
|
|
{
|
|
|
|
const DetourNavigator::Cell& mCell;
|
|
|
|
DetourNavigator::RecastMeshBuilder& mBuilder;
|
|
|
|
|
|
|
|
void operator()(const DetourNavigator::HeightfieldSurface& v)
|
|
|
|
{
|
|
|
|
mBuilder.addHeightfield(mCell.mSize, mCell.mShift, v.mHeights, v.mSize, v.mMinHeight, v.mMaxHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()(DetourNavigator::HeightfieldPlane v)
|
|
|
|
{
|
|
|
|
mBuilder.addHeightfield(mCell.mSize, mCell.mShift, v.mHeight);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
namespace DetourNavigator
|
|
|
|
{
|
2021-11-05 19:47:11 +00:00
|
|
|
RecastMeshManager::RecastMeshManager(const TileBounds& bounds, std::size_t generation)
|
|
|
|
: mGeneration(generation)
|
2021-05-26 23:59:07 +00:00
|
|
|
, mTileBounds(bounds)
|
2018-04-15 19:54:45 +00:00
|
|
|
{
|
|
|
|
}
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2021-08-01 00:13:55 +00:00
|
|
|
bool RecastMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
2018-07-18 19:09:50 +00:00
|
|
|
const AreaType areaType)
|
2018-03-13 22:49:08 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-05-27 14:38:04 +00:00
|
|
|
const auto object = mObjects.lower_bound(id);
|
|
|
|
if (object != mObjects.end() && object->first == id)
|
|
|
|
return false;
|
2021-07-11 19:43:19 +00:00
|
|
|
mObjects.emplace_hint(object, id,
|
2021-04-18 14:51:52 +00:00
|
|
|
OscillatingRecastMeshObject(RecastMeshObject(shape, transform, areaType), mRevision + 1));
|
2019-11-27 22:45:01 +00:00
|
|
|
++mRevision;
|
|
|
|
return true;
|
2018-03-13 22:49:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-22 15:36:57 +00:00
|
|
|
bool RecastMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType)
|
2018-05-26 14:44:25 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2018-05-26 14:44:25 +00:00
|
|
|
const auto object = mObjects.find(id);
|
|
|
|
if (object == mObjects.end())
|
|
|
|
return false;
|
2021-04-18 14:51:52 +00:00
|
|
|
const std::size_t lastChangeRevision = mLastNavMeshReportedChange.has_value()
|
|
|
|
? mLastNavMeshReportedChange->mRevision : mRevision;
|
2021-07-11 19:43:19 +00:00
|
|
|
if (!object->second.update(transform, areaType, lastChangeRevision, mTileBounds))
|
2018-05-26 14:44:25 +00:00
|
|
|
return false;
|
2019-11-27 22:45:01 +00:00
|
|
|
++mRevision;
|
|
|
|
return true;
|
2018-05-26 14:44:25 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 22:33:41 +00:00
|
|
|
std::optional<RemovedRecastMeshObject> RecastMeshManager::removeObject(const ObjectId id)
|
2018-03-13 22:49:08 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2018-04-01 00:44:16 +00:00
|
|
|
const auto object = mObjects.find(id);
|
|
|
|
if (object == mObjects.end())
|
2020-10-24 22:33:41 +00:00
|
|
|
return std::nullopt;
|
2021-07-11 19:43:19 +00:00
|
|
|
const RemovedRecastMeshObject result {object->second.getImpl().getShape(), object->second.getImpl().getTransform()};
|
2018-04-01 00:44:16 +00:00
|
|
|
mObjects.erase(object);
|
2019-11-27 22:45:01 +00:00
|
|
|
++mRevision;
|
2018-04-01 00:44:16 +00:00
|
|
|
return result;
|
2018-03-13 22:49:08 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 19:54:41 +00:00
|
|
|
bool RecastMeshManager::addWater(const osg::Vec2i& cellPosition, const int cellSize, const osg::Vec3f& shift)
|
2018-07-20 19:11:34 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-07-14 20:00:16 +00:00
|
|
|
if (!mWater.emplace(cellPosition, Cell {cellSize, shift}).second)
|
2018-07-20 19:11:34 +00:00
|
|
|
return false;
|
2019-11-27 22:45:01 +00:00
|
|
|
++mRevision;
|
2018-07-20 19:11:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-07-14 20:00:16 +00:00
|
|
|
std::optional<Cell> RecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
|
2018-07-20 19:11:34 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2018-07-20 19:11:34 +00:00
|
|
|
const auto water = mWater.find(cellPosition);
|
|
|
|
if (water == mWater.end())
|
2020-10-24 22:33:41 +00:00
|
|
|
return std::nullopt;
|
2019-11-27 22:45:01 +00:00
|
|
|
++mRevision;
|
2021-07-14 20:00:16 +00:00
|
|
|
const Cell result = water->second;
|
2018-07-20 19:11:34 +00:00
|
|
|
mWater.erase(water);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-07-14 18:57:52 +00:00
|
|
|
bool RecastMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const osg::Vec3f& shift,
|
|
|
|
const HeightfieldShape& shape)
|
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-07-14 18:57:52 +00:00
|
|
|
if (!mHeightfields.emplace(cellPosition, Heightfield {Cell {cellSize, shift}, shape}).second)
|
|
|
|
return false;
|
|
|
|
++mRevision;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<Cell> RecastMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
|
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-07-14 18:57:52 +00:00
|
|
|
const auto it = mHeightfields.find(cellPosition);
|
|
|
|
if (it == mHeightfields.end())
|
|
|
|
return std::nullopt;
|
|
|
|
++mRevision;
|
|
|
|
const auto result = std::make_optional(it->second.mCell);
|
|
|
|
mHeightfields.erase(it);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-08-08 14:58:47 +00:00
|
|
|
std::shared_ptr<RecastMesh> RecastMeshManager::getMesh() const
|
2018-03-13 22:49:08 +00:00
|
|
|
{
|
2021-11-05 19:47:11 +00:00
|
|
|
RecastMeshBuilder builder(mTileBounds);
|
2021-08-04 16:35:25 +00:00
|
|
|
using Object = std::tuple<
|
|
|
|
osg::ref_ptr<const osg::Referenced>,
|
|
|
|
std::reference_wrapper<const btCollisionShape>,
|
|
|
|
btTransform,
|
|
|
|
AreaType
|
|
|
|
>;
|
|
|
|
std::vector<Object> objects;
|
2021-08-01 00:43:36 +00:00
|
|
|
std::size_t revision;
|
2021-07-03 00:59:07 +00:00
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
|
|
|
for (const auto& [k, v] : mWater)
|
|
|
|
builder.addWater(v.mSize, v.mShift);
|
|
|
|
for (const auto& [cellPosition, v] : mHeightfields)
|
|
|
|
std::visit(AddHeightfield {v.mCell, builder}, v.mShape);
|
|
|
|
objects.reserve(mObjects.size());
|
|
|
|
for (const auto& [k, object] : mObjects)
|
2021-08-04 16:35:25 +00:00
|
|
|
{
|
|
|
|
const RecastMeshObject& impl = object.getImpl();
|
|
|
|
objects.emplace_back(impl.getHolder(), impl.getShape(), impl.getTransform(), impl.getAreaType());
|
|
|
|
}
|
2021-08-01 00:43:36 +00:00
|
|
|
revision = mRevision;
|
2021-07-03 00:59:07 +00:00
|
|
|
}
|
2021-08-04 16:35:25 +00:00
|
|
|
for (const auto& [holder, shape, transform, areaType] : objects)
|
|
|
|
builder.addObject(shape, transform, areaType);
|
2021-08-01 00:43:36 +00:00
|
|
|
return std::move(builder).create(mGeneration, revision);
|
2018-03-13 22:49:08 +00:00
|
|
|
}
|
|
|
|
|
2018-04-15 22:07:18 +00:00
|
|
|
bool RecastMeshManager::isEmpty() const
|
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-07-14 18:57:52 +00:00
|
|
|
return mObjects.empty() && mWater.empty() && mHeightfields.empty();
|
2018-04-15 22:07:18 +00:00
|
|
|
}
|
|
|
|
|
2021-06-25 19:52:02 +00:00
|
|
|
void RecastMeshManager::reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion)
|
2021-04-18 14:51:52 +00:00
|
|
|
{
|
|
|
|
if (recastMeshVersion.mGeneration != mGeneration)
|
|
|
|
return;
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-04-18 14:51:52 +00:00
|
|
|
if (mLastNavMeshReport.has_value() && navMeshVersion < mLastNavMeshReport->mNavMeshVersion)
|
|
|
|
return;
|
|
|
|
mLastNavMeshReport = {recastMeshVersion.mRevision, navMeshVersion};
|
|
|
|
if (!mLastNavMeshReportedChange.has_value()
|
|
|
|
|| mLastNavMeshReportedChange->mNavMeshVersion < mLastNavMeshReport->mNavMeshVersion)
|
|
|
|
mLastNavMeshReportedChange = mLastNavMeshReport;
|
|
|
|
}
|
|
|
|
|
2021-05-26 23:09:58 +00:00
|
|
|
Version RecastMeshManager::getVersion() const
|
|
|
|
{
|
2021-08-01 00:43:36 +00:00
|
|
|
const std::lock_guard lock(mMutex);
|
2021-05-26 23:09:58 +00:00
|
|
|
return Version {mGeneration, mRevision};
|
|
|
|
}
|
2018-03-13 22:49:08 +00:00
|
|
|
}
|