#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESH_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESH_H #include "areatype.hpp" #include "bounds.hpp" #include "tilebounds.hpp" #include #include #include #include #include #include #include namespace DetourNavigator { class Mesh { public: Mesh(std::vector&& indices, std::vector&& vertices, std::vector&& areaTypes); const std::vector& getIndices() const noexcept { return mIndices; } const std::vector& getVertices() const noexcept { return mVertices; } const std::vector& getAreaTypes() const noexcept { return mAreaTypes; } std::size_t getVerticesCount() const noexcept { return mVertices.size() / 3; } std::size_t getTrianglesCount() const noexcept { return mAreaTypes.size(); } private: std::vector mIndices; std::vector mVertices; std::vector mAreaTypes; friend inline bool operator<(const Mesh& lhs, const Mesh& rhs) noexcept { return std::tie(lhs.mIndices, lhs.mVertices, lhs.mAreaTypes) < std::tie(rhs.mIndices, rhs.mVertices, rhs.mAreaTypes); } friend inline std::size_t getSize(const Mesh& value) noexcept { return value.mIndices.size() * sizeof(int) + value.mVertices.size() * sizeof(float) + value.mAreaTypes.size() * sizeof(AreaType); } }; struct Cell { int mSize; osg::Vec3f mShift; }; struct Heightfield { TileBounds mBounds; std::uint8_t mLength; float mMinHeight; float mMaxHeight; osg::Vec3f mShift; float mScale; std::vector mHeights; }; inline auto makeTuple(const Heightfield& v) noexcept { return std::tie(v.mBounds, v.mLength, v.mMinHeight, v.mMaxHeight, v.mShift, v.mScale, v.mHeights); } inline bool operator<(const Heightfield& lhs, const Heightfield& rhs) noexcept { return makeTuple(lhs) < makeTuple(rhs); } struct FlatHeightfield { TileBounds mBounds; float mHeight; }; inline bool operator<(const FlatHeightfield& lhs, const FlatHeightfield& rhs) noexcept { return std::tie(lhs.mBounds, lhs.mHeight) < std::tie(rhs.mBounds, rhs.mHeight); } class RecastMesh { public: RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector water, std::vector heightfields, std::vector flatHeightfields); std::size_t getGeneration() const { return mGeneration; } std::size_t getRevision() const { return mRevision; } const Mesh& getMesh() const noexcept { return mMesh; } const std::vector& getWater() const { return mWater; } const std::vector& getHeightfields() const noexcept { return mHeightfields; } const std::vector& getFlatHeightfields() const noexcept { return mFlatHeightfields; } const Bounds& getBounds() const { return mBounds; } private: std::size_t mGeneration; std::size_t mRevision; Mesh mMesh; std::vector mWater; std::vector mHeightfields; std::vector mFlatHeightfields; Bounds mBounds; friend inline bool operator <(const RecastMesh& lhs, const RecastMesh& rhs) noexcept { return std::tie(lhs.mMesh, lhs.mWater) < std::tie(rhs.mMesh, rhs.mWater); } friend inline std::size_t getSize(const RecastMesh& value) noexcept { return getSize(value.mMesh) + value.mWater.size() * sizeof(Cell) + value.mHeightfields.size() * sizeof(Heightfield) + std::accumulate(value.mHeightfields.begin(), value.mHeightfields.end(), std::size_t {0}, [] (std::size_t r, const Heightfield& v) { return r + v.mHeights.size() * sizeof(float); }) + value.mFlatHeightfields.size() * sizeof(FlatHeightfield); } }; inline bool operator<(const Cell& lhs, const Cell& rhs) noexcept { return std::tie(lhs.mSize, lhs.mShift) < std::tie(rhs.mSize, rhs.mShift); } } #endif