#include "serialization.hpp" #include "dbrefgeometryobject.hpp" #include "preparednavmeshdata.hpp" #include "recast.hpp" #include "recastmesh.hpp" #include "settings.hpp" #include #include #include #include #include #include #include #include namespace DetourNavigator { namespace { template struct Format : Serialization::Format> { using Serialization::Format>::operator(); template void operator()(Visitor&& visitor, const osg::Vec2i& value) const { visitor(*this, value.ptr(), 2); } template void operator()(Visitor&& visitor, const osg::Vec2f& value) const { visitor(*this, value.ptr(), 2); } template void operator()(Visitor&& visitor, const osg::Vec3f& value) const { visitor(*this, value.ptr(), 3); } template void operator()(Visitor&& visitor, const Water& value) const { visitor(*this, value.mCellSize); visitor(*this, value.mLevel); } template void operator()(Visitor&& visitor, const CellWater& value) const { visitor(*this, value.mCellPosition); visitor(*this, value.mWater); } template 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 void operator()(Visitor&& visitor, const TileBounds& value) const { visitor(*this, value.mMin); visitor(*this, value.mMax); } template 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 void operator()(Visitor&& visitor, const FlatHeightfield& value) const { visitor(*this, value.mCellPosition); visitor(*this, value.mCellSize); visitor(*this, value.mHeight); } template void operator()(Visitor&& visitor, const RecastMesh& value) const { visitor(*this, value.getWater()); visitor(*this, value.getHeightfields()); visitor(*this, value.getFlatHeightfields()); } template void operator()(Visitor&& visitor, const ESM::Position& value) const { visitor(*this, value.pos); visitor(*this, value.rot); } template void operator()(Visitor&& visitor, const ObjectTransform& value) const { visitor(*this, value.mPosition); visitor(*this, value.mScale); } template void operator()(Visitor&& visitor, const DbRefGeometryObject& value) const { visitor(*this, value.mShapeId); visitor(*this, value.mObjectTransform); } template void operator()(Visitor&& visitor, const RecastSettings& settings, const RecastMesh& recastMesh, const std::vector& dbRefGeometryObjects) const { visitor(*this, DetourNavigator::recastMeshMagic); visitor(*this, DetourNavigator::recastMeshVersion); visitor(*this, settings); visitor(*this, recastMesh); visitor(*this, dbRefGeometryObjects); } template auto operator()(Visitor&& visitor, T& value) const -> std::enable_if_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 auto operator()(Visitor&& visitor, T& value) const -> std::enable_if_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 auto operator()(Visitor&& visitor, T& value) const -> std::enable_if_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); } }; } } // namespace DetourNavigator namespace DetourNavigator { std::vector serialize(const RecastSettings& settings, const RecastMesh& recastMesh, const std::vector& dbRefGeometryObjects) { constexpr Format format; Serialization::SizeAccumulator sizeAccumulator; format(sizeAccumulator, settings, recastMesh, dbRefGeometryObjects); std::vector result(sizeAccumulator.value()); format(Serialization::BinaryWriter(result.data(), result.data() + result.size()), settings, recastMesh, dbRefGeometryObjects); return result; } std::vector serialize(const PreparedNavMeshData& value) { constexpr Format format; Serialization::SizeAccumulator sizeAccumulator; format(sizeAccumulator, value); std::vector result(sizeAccumulator.value()); format(Serialization::BinaryWriter(result.data(), result.data() + result.size()), value); return result; } bool deserialize(const std::vector& data, PreparedNavMeshData& value) { try { constexpr Format format; format(Serialization::BinaryReader(data.data(), data.data() + data.size()), value); return true; } catch (const std::exception&) { return false; } } }