mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
#include "generatenavmeshtile.hpp"
|
|
|
|
#include "dbrefgeometryobject.hpp"
|
|
#include "makenavmesh.hpp"
|
|
#include "preparednavmeshdata.hpp"
|
|
#include "serialization.hpp"
|
|
#include "settings.hpp"
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
#include <osg/io_utils>
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
|
|
namespace DetourNavigator
|
|
{
|
|
namespace
|
|
{
|
|
struct Ignore
|
|
{
|
|
ESM::RefId mWorldspace;
|
|
const TilePosition& mTilePosition;
|
|
std::shared_ptr<NavMeshTileConsumer> mConsumer;
|
|
|
|
~Ignore() noexcept
|
|
{
|
|
if (mConsumer != nullptr)
|
|
mConsumer->ignore(mWorldspace, mTilePosition);
|
|
}
|
|
};
|
|
}
|
|
|
|
GenerateNavMeshTile::GenerateNavMeshTile(ESM::RefId worldspace, const TilePosition& tilePosition,
|
|
RecastMeshProvider recastMeshProvider, const AgentBounds& agentBounds,
|
|
const DetourNavigator::Settings& settings, std::weak_ptr<NavMeshTileConsumer> consumer)
|
|
: mWorldspace(worldspace)
|
|
, mTilePosition(tilePosition)
|
|
, mRecastMeshProvider(recastMeshProvider)
|
|
, mAgentBounds(agentBounds)
|
|
, mSettings(settings)
|
|
, mConsumer(std::move(consumer))
|
|
{
|
|
}
|
|
|
|
void GenerateNavMeshTile::doWork()
|
|
{
|
|
impl();
|
|
}
|
|
|
|
void GenerateNavMeshTile::impl() noexcept
|
|
{
|
|
const auto consumer = mConsumer.lock();
|
|
|
|
if (consumer == nullptr)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Ignore ignore{ mWorldspace, mTilePosition, consumer };
|
|
|
|
const std::shared_ptr<RecastMesh> recastMesh = mRecastMeshProvider.getMesh(mWorldspace, mTilePosition);
|
|
|
|
if (recastMesh == nullptr || isEmpty(*recastMesh))
|
|
return;
|
|
|
|
const std::vector<DbRefGeometryObject> objects = makeDbRefGeometryObjects(
|
|
recastMesh->getMeshSources(), [&](const MeshSource& v) { return consumer->resolveMeshSource(v); });
|
|
std::vector<std::byte> input = serialize(mSettings.mRecast, mAgentBounds, *recastMesh, objects);
|
|
const std::optional<NavMeshTileInfo> info = consumer->find(mWorldspace, mTilePosition, input);
|
|
|
|
if (info.has_value() && info->mVersion == navMeshFormatVersion)
|
|
{
|
|
consumer->identity(mWorldspace, mTilePosition, info->mTileId);
|
|
ignore.mConsumer = nullptr;
|
|
return;
|
|
}
|
|
|
|
const auto data
|
|
= prepareNavMeshTileData(*recastMesh, mWorldspace, mTilePosition, mAgentBounds, mSettings.mRecast);
|
|
|
|
if (data == nullptr)
|
|
return;
|
|
|
|
if (info.has_value())
|
|
consumer->update(mWorldspace, mTilePosition, info->mTileId, navMeshFormatVersion, *data);
|
|
else
|
|
consumer->insert(mWorldspace, mTilePosition, navMeshFormatVersion, input, *data);
|
|
|
|
ignore.mConsumer = nullptr;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
Log(Debug::Warning) << "Failed to generate navmesh for worldspace \"" << mWorldspace << "\" tile "
|
|
<< mTilePosition << ": " << e.what();
|
|
consumer->cancel(e.what());
|
|
}
|
|
}
|
|
}
|