mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 13:26:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			102 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			102 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());
 | |
|         }
 | |
|     }
 | |
| }
 |