mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 22:26:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			282 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "serialization.hpp"
 | |
| 
 | |
| #include "agentbounds.hpp"
 | |
| #include "dbrefgeometryobject.hpp"
 | |
| #include "preparednavmeshdata.hpp"
 | |
| #include "recast.hpp"
 | |
| #include "recastmesh.hpp"
 | |
| #include "settings.hpp"
 | |
| #include "tilebounds.hpp"
 | |
| 
 | |
| #include <components/serialization/binaryreader.hpp>
 | |
| #include <components/serialization/binarywriter.hpp>
 | |
| #include <components/serialization/format.hpp>
 | |
| #include <components/serialization/sizeaccumulator.hpp>
 | |
| 
 | |
| #include <cstddef>
 | |
| #include <cstring>
 | |
| #include <type_traits>
 | |
| #include <vector>
 | |
| 
 | |
| namespace DetourNavigator
 | |
| {
 | |
|     namespace
 | |
|     {
 | |
|         template <Serialization::Mode mode>
 | |
|         struct Format : Serialization::Format<mode, Format<mode>>
 | |
|         {
 | |
|             using Serialization::Format<mode, Format<mode>>::operator();
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const osg::Vec2i& value) const
 | |
|             {
 | |
|                 visitor(*this, value.ptr(), 2);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const osg::Vec2f& value) const
 | |
|             {
 | |
|                 visitor(*this, value.ptr(), 2);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const osg::Vec3f& value) const
 | |
|             {
 | |
|                 visitor(*this, value.ptr(), 3);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const Water& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mCellSize);
 | |
|                 visitor(*this, value.mLevel);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const CellWater& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mCellPosition);
 | |
|                 visitor(*this, value.mWater);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const RecastSettings& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mCellHeight);
 | |
|                 visitor(*this, value.mCellSize);
 | |
|                 visitor(*this, value.mDetailSampleDist);
 | |
|                 visitor(*this, value.mDetailSampleMaxError);
 | |
|                 visitor(*this, value.mMaxClimb);
 | |
|                 visitor(*this, value.mMaxSimplificationError);
 | |
|                 visitor(*this, value.mMaxSlope);
 | |
|                 visitor(*this, value.mRecastScaleFactor);
 | |
|                 visitor(*this, value.mSwimHeightScale);
 | |
|                 visitor(*this, value.mBorderSize);
 | |
|                 visitor(*this, value.mMaxEdgeLen);
 | |
|                 visitor(*this, value.mMaxVertsPerPoly);
 | |
|                 visitor(*this, value.mRegionMergeArea);
 | |
|                 visitor(*this, value.mRegionMinArea);
 | |
|                 visitor(*this, value.mTileSize);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const TileBounds& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mMin);
 | |
|                 visitor(*this, value.mMax);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const Heightfield& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mCellPosition);
 | |
|                 visitor(*this, value.mCellSize);
 | |
|                 visitor(*this, value.mLength);
 | |
|                 visitor(*this, value.mMinHeight);
 | |
|                 visitor(*this, value.mMaxHeight);
 | |
|                 visitor(*this, value.mHeights);
 | |
|                 visitor(*this, value.mOriginalSize);
 | |
|                 visitor(*this, value.mMinX);
 | |
|                 visitor(*this, value.mMinY);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const FlatHeightfield& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mCellPosition);
 | |
|                 visitor(*this, value.mCellSize);
 | |
|                 visitor(*this, value.mHeight);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const RecastMesh& value) const
 | |
|             {
 | |
|                 visitor(*this, value.getWater());
 | |
|                 visitor(*this, value.getHeightfields());
 | |
|                 visitor(*this, value.getFlatHeightfields());
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const ESM::Position& value) const
 | |
|             {
 | |
|                 visitor(*this, value.pos);
 | |
|                 visitor(*this, value.rot);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const ObjectTransform& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mPosition);
 | |
|                 visitor(*this, value.mScale);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const DbRefGeometryObject& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mShapeId);
 | |
|                 visitor(*this, value.mObjectTransform);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const RecastSettings& settings, const AgentBounds& agentBounds,
 | |
|                 const RecastMesh& recastMesh, const std::vector<DbRefGeometryObject>& dbRefGeometryObjects) const
 | |
|             {
 | |
|                 visitor(*this, DetourNavigator::recastMeshMagic);
 | |
|                 visitor(*this, DetourNavigator::recastMeshVersion);
 | |
|                 visitor(*this, settings);
 | |
|                 visitor(*this, agentBounds);
 | |
|                 visitor(*this, recastMesh);
 | |
|                 visitor(*this, dbRefGeometryObjects);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor, class T>
 | |
|             auto operator()(Visitor&& visitor, T& value) const
 | |
|                 -> std::enable_if_t<std::is_same_v<std::decay_t<T>, rcPolyMesh>>
 | |
|             {
 | |
|                 visitor(*this, value.nverts);
 | |
|                 visitor(*this, value.npolys);
 | |
|                 visitor(*this, value.maxpolys);
 | |
|                 visitor(*this, value.nvp);
 | |
|                 visitor(*this, value.bmin);
 | |
|                 visitor(*this, value.bmax);
 | |
|                 visitor(*this, value.cs);
 | |
|                 visitor(*this, value.ch);
 | |
|                 visitor(*this, value.borderSize);
 | |
|                 visitor(*this, value.maxEdgeError);
 | |
|                 if constexpr (mode == Serialization::Mode::Read)
 | |
|                 {
 | |
|                     if (value.verts == nullptr)
 | |
|                         permRecastAlloc(value.verts, getVertsLength(value));
 | |
|                     if (value.polys == nullptr)
 | |
|                         permRecastAlloc(value.polys, getPolysLength(value));
 | |
|                     if (value.regs == nullptr)
 | |
|                         permRecastAlloc(value.regs, getRegsLength(value));
 | |
|                     if (value.flags == nullptr)
 | |
|                         permRecastAlloc(value.flags, getFlagsLength(value));
 | |
|                     if (value.areas == nullptr)
 | |
|                         permRecastAlloc(value.areas, getAreasLength(value));
 | |
|                 }
 | |
|                 visitor(*this, value.verts, getVertsLength(value));
 | |
|                 visitor(*this, value.polys, getPolysLength(value));
 | |
|                 visitor(*this, value.regs, getRegsLength(value));
 | |
|                 visitor(*this, value.flags, getFlagsLength(value));
 | |
|                 visitor(*this, value.areas, getAreasLength(value));
 | |
|             }
 | |
| 
 | |
|             template <class Visitor, class T>
 | |
|             auto operator()(Visitor&& visitor, T& value) const
 | |
|                 -> std::enable_if_t<std::is_same_v<std::decay_t<T>, rcPolyMeshDetail>>
 | |
|             {
 | |
|                 visitor(*this, value.nmeshes);
 | |
|                 if constexpr (mode == Serialization::Mode::Read)
 | |
|                     if (value.meshes == nullptr)
 | |
|                         permRecastAlloc(value.meshes, getMeshesLength(value));
 | |
|                 visitor(*this, value.meshes, getMeshesLength(value));
 | |
|                 visitor(*this, value.nverts);
 | |
|                 if constexpr (mode == Serialization::Mode::Read)
 | |
|                     if (value.verts == nullptr)
 | |
|                         permRecastAlloc(value.verts, getVertsLength(value));
 | |
|                 visitor(*this, value.verts, getVertsLength(value));
 | |
|                 visitor(*this, value.ntris);
 | |
|                 if constexpr (mode == Serialization::Mode::Read)
 | |
|                     if (value.tris == nullptr)
 | |
|                         permRecastAlloc(value.tris, getTrisLength(value));
 | |
|                 visitor(*this, value.tris, getTrisLength(value));
 | |
|             }
 | |
| 
 | |
|             template <class Visitor, class T>
 | |
|             auto operator()(Visitor&& visitor, T& value) const
 | |
|                 -> std::enable_if_t<std::is_same_v<std::decay_t<T>, PreparedNavMeshData>>
 | |
|             {
 | |
|                 if constexpr (mode == Serialization::Mode::Write)
 | |
|                 {
 | |
|                     visitor(*this, DetourNavigator::preparedNavMeshDataMagic);
 | |
|                     visitor(*this, DetourNavigator::preparedNavMeshDataVersion);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     static_assert(mode == Serialization::Mode::Read);
 | |
|                     char magic[std::size(DetourNavigator::preparedNavMeshDataMagic)];
 | |
|                     visitor(*this, magic);
 | |
|                     if (std::memcmp(magic, DetourNavigator::preparedNavMeshDataMagic, sizeof(magic)) != 0)
 | |
|                         throw std::runtime_error("Bad PreparedNavMeshData magic");
 | |
|                     std::uint32_t version = 0;
 | |
|                     visitor(*this, version);
 | |
|                     if (version != DetourNavigator::preparedNavMeshDataVersion)
 | |
|                         throw std::runtime_error("Bad PreparedNavMeshData version");
 | |
|                 }
 | |
|                 visitor(*this, value.mUserId);
 | |
|                 visitor(*this, value.mCellSize);
 | |
|                 visitor(*this, value.mCellHeight);
 | |
|                 visitor(*this, value.mPolyMesh);
 | |
|                 visitor(*this, value.mPolyMeshDetail);
 | |
|             }
 | |
| 
 | |
|             template <class Visitor>
 | |
|             void operator()(Visitor&& visitor, const AgentBounds& value) const
 | |
|             {
 | |
|                 visitor(*this, value.mShapeType);
 | |
|                 visitor(*this, value.mHalfExtents);
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| } // namespace DetourNavigator
 | |
| 
 | |
| namespace DetourNavigator
 | |
| {
 | |
|     std::vector<std::byte> serialize(const RecastSettings& settings, const AgentBounds& agentBounds,
 | |
|         const RecastMesh& recastMesh, const std::vector<DbRefGeometryObject>& dbRefGeometryObjects)
 | |
|     {
 | |
|         constexpr Format<Serialization::Mode::Write> format;
 | |
|         Serialization::SizeAccumulator sizeAccumulator;
 | |
|         format(sizeAccumulator, settings, agentBounds, recastMesh, dbRefGeometryObjects);
 | |
|         std::vector<std::byte> result(sizeAccumulator.value());
 | |
|         format(Serialization::BinaryWriter(result.data(), result.data() + result.size()), settings, agentBounds,
 | |
|             recastMesh, dbRefGeometryObjects);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     std::vector<std::byte> serialize(const PreparedNavMeshData& value)
 | |
|     {
 | |
|         constexpr Format<Serialization::Mode::Write> format;
 | |
|         Serialization::SizeAccumulator sizeAccumulator;
 | |
|         format(sizeAccumulator, value);
 | |
|         std::vector<std::byte> result(sizeAccumulator.value());
 | |
|         format(Serialization::BinaryWriter(result.data(), result.data() + result.size()), value);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     bool deserialize(const std::vector<std::byte>& data, PreparedNavMeshData& value)
 | |
|     {
 | |
|         try
 | |
|         {
 | |
|             constexpr Format<Serialization::Mode::Read> format;
 | |
|             format(Serialization::BinaryReader(data.data(), data.data() + data.size()), value);
 | |
|             return true;
 | |
|         }
 | |
|         catch (const std::exception&)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| }
 |