1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-21 01:23:53 +00:00
openmw/components/detournavigator/recastmeshmanager.cpp

178 lines
6.3 KiB
C++
Raw Normal View History

2018-03-13 22:49:08 +00:00
#include "recastmeshmanager.hpp"
#include "recastmeshbuilder.hpp"
#include "settings.hpp"
#include "heightfieldshape.hpp"
#include <components/debug/debuglog.hpp>
2021-11-04 02:19:41 +00:00
#include <components/misc/convert.hpp>
#include <utility>
namespace
{
struct AddHeightfield
{
2021-11-04 02:19:41 +00:00
osg::Vec2i mCellPosition;
int mCellSize;
DetourNavigator::RecastMeshBuilder& mBuilder;
void operator()(const DetourNavigator::HeightfieldSurface& v)
{
2021-11-04 02:19:41 +00:00
mBuilder.addHeightfield(mCellPosition, mCellSize, v.mHeights, v.mSize, v.mMinHeight, v.mMaxHeight);
}
void operator()(DetourNavigator::HeightfieldPlane v)
{
2021-11-04 02:19:41 +00:00
mBuilder.addHeightfield(mCellPosition, mCellSize, v.mHeight);
}
};
}
2018-03-13 22:49:08 +00:00
namespace DetourNavigator
{
RecastMeshManager::RecastMeshManager(const TileBounds& bounds, std::size_t generation)
: mGeneration(generation)
, mTileBounds(bounds)
{
}
2018-03-13 22:49:08 +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
{
const std::lock_guard lock(mMutex);
const auto object = mObjects.lower_bound(id);
if (object != mObjects.end() && object->first == id)
return false;
mObjects.emplace_hint(object, id,
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
{
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;
const std::size_t lastChangeRevision = mLastNavMeshReportedChange.has_value()
? mLastNavMeshReportedChange->mRevision : mRevision;
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
}
std::optional<RemovedRecastMeshObject> RecastMeshManager::removeObject(const ObjectId id)
2018-03-13 22:49:08 +00:00
{
const std::lock_guard lock(mMutex);
const auto object = mObjects.find(id);
if (object == mObjects.end())
return std::nullopt;
const RemovedRecastMeshObject result {object->second.getImpl().getShape(), object->second.getImpl().getTransform()};
mObjects.erase(object);
2019-11-27 22:45:01 +00:00
++mRevision;
return result;
2018-03-13 22:49:08 +00:00
}
2021-11-04 01:48:32 +00:00
bool RecastMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level)
2018-07-20 19:11:34 +00:00
{
const std::lock_guard lock(mMutex);
2021-11-04 01:48:32 +00:00
if (!mWater.emplace(cellPosition, Water {cellSize, level}).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-11-04 01:48:32 +00:00
std::optional<Water> RecastMeshManager::removeWater(const osg::Vec2i& cellPosition)
2018-07-20 19:11:34 +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())
return std::nullopt;
2019-11-27 22:45:01 +00:00
++mRevision;
2021-11-04 01:48:32 +00:00
Water result = water->second;
2018-07-20 19:11:34 +00:00
mWater.erase(water);
return result;
}
2021-11-04 02:19:41 +00:00
bool RecastMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize,
const HeightfieldShape& shape)
{
const std::lock_guard lock(mMutex);
2021-11-04 02:19:41 +00:00
if (!mHeightfields.emplace(cellPosition, SizedHeightfieldShape {cellSize, shape}).second)
return false;
++mRevision;
return true;
}
2021-11-04 02:19:41 +00:00
std::optional<SizedHeightfieldShape> RecastMeshManager::removeHeightfield(const osg::Vec2i& cellPosition)
{
const std::lock_guard lock(mMutex);
const auto it = mHeightfields.find(cellPosition);
if (it == mHeightfields.end())
return std::nullopt;
++mRevision;
2021-11-04 02:19:41 +00:00
auto result = std::make_optional(it->second);
mHeightfields.erase(it);
return result;
}
std::shared_ptr<RecastMesh> RecastMeshManager::getMesh() const
2018-03-13 22:49:08 +00:00
{
RecastMeshBuilder builder(mTileBounds);
using Object = std::tuple<
2021-11-04 00:57:27 +00:00
osg::ref_ptr<const Resource::BulletShapeInstance>,
ObjectTransform,
std::reference_wrapper<const btCollisionShape>,
btTransform,
AreaType
>;
std::vector<Object> objects;
std::size_t revision;
{
const std::lock_guard lock(mMutex);
for (const auto& [k, v] : mWater)
2021-11-04 01:48:32 +00:00
builder.addWater(k, v);
for (const auto& [cellPosition, v] : mHeightfields)
2021-11-04 02:19:41 +00:00
std::visit(AddHeightfield {cellPosition, v.mCellSize, builder}, v.mShape);
objects.reserve(mObjects.size());
for (const auto& [k, object] : mObjects)
{
const RecastMeshObject& impl = object.getImpl();
2021-11-04 00:57:27 +00:00
objects.emplace_back(impl.getInstance(), impl.getObjectTransform(), impl.getShape(),
impl.getTransform(), impl.getAreaType());
}
revision = mRevision;
}
2021-11-04 00:57:27 +00:00
for (const auto& [instance, objectTransform, shape, transform, areaType] : objects)
builder.addObject(shape, transform, areaType, instance->getSource(), objectTransform);
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
{
const std::lock_guard lock(mMutex);
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)
{
if (recastMeshVersion.mGeneration != mGeneration)
return;
const std::lock_guard lock(mMutex);
if (mLastNavMeshReport.has_value() && navMeshVersion < mLastNavMeshReport->mNavMeshVersion)
return;
mLastNavMeshReport = {recastMeshVersion.mRevision, navMeshVersion};
if (!mLastNavMeshReportedChange.has_value()
|| mLastNavMeshReportedChange->mNavMeshVersion < mLastNavMeshReport->mNavMeshVersion)
mLastNavMeshReportedChange = mLastNavMeshReport;
}
Version RecastMeshManager::getVersion() const
{
const std::lock_guard lock(mMutex);
return Version {mGeneration, mRevision};
}
2018-03-13 22:49:08 +00:00
}