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.
127 lines
5.3 KiB
C++
127 lines
5.3 KiB
C++
#include "navmeshtileview.hpp"
|
|
#include "ref.hpp"
|
|
|
|
#include <DetourCommon.h>
|
|
#include <DetourNavMesh.h>
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <stdexcept>
|
|
#include <tuple>
|
|
|
|
inline bool operator==(const dtMeshHeader& lhs, const dtMeshHeader& rhs) noexcept
|
|
{
|
|
const auto makeTuple = [](const dtMeshHeader& v) {
|
|
using DetourNavigator::ArrayRef;
|
|
return std::tuple(v.x, v.y, v.layer, v.userId, v.polyCount, v.vertCount, v.maxLinkCount, v.detailMeshCount,
|
|
v.detailVertCount, v.detailTriCount, v.bvNodeCount, v.offMeshConCount, v.offMeshBase, v.walkableHeight,
|
|
v.walkableRadius, v.walkableClimb, v.detailVertCount, ArrayRef(v.bmin), ArrayRef(v.bmax), v.bvQuantFactor);
|
|
};
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
|
|
inline bool operator==(const dtPoly& lhs, const dtPoly& rhs) noexcept
|
|
{
|
|
const auto makeTuple = [](const dtPoly& v) {
|
|
using DetourNavigator::ArrayRef;
|
|
return std::tuple(ArrayRef(v.verts), ArrayRef(v.neis), v.flags, v.vertCount, v.areaAndtype);
|
|
};
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
|
|
inline bool operator==(const dtPolyDetail& lhs, const dtPolyDetail& rhs) noexcept
|
|
{
|
|
const auto makeTuple
|
|
= [](const dtPolyDetail& v) { return std::tuple(v.vertBase, v.triBase, v.vertCount, v.triCount); };
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
|
|
inline bool operator==(const dtBVNode& lhs, const dtBVNode& rhs) noexcept
|
|
{
|
|
const auto makeTuple = [](const dtBVNode& v) {
|
|
using DetourNavigator::ArrayRef;
|
|
return std::tuple(ArrayRef(v.bmin), ArrayRef(v.bmax), v.i);
|
|
};
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
|
|
inline bool operator==(const dtOffMeshConnection& lhs, const dtOffMeshConnection& rhs) noexcept
|
|
{
|
|
const auto makeTuple = [](const dtOffMeshConnection& v) {
|
|
using DetourNavigator::ArrayRef;
|
|
return std::tuple(ArrayRef(v.pos), v.rad, v.poly, v.flags, v.side, v.userId);
|
|
};
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
|
|
namespace DetourNavigator
|
|
{
|
|
NavMeshTileConstView asNavMeshTileConstView(const unsigned char* data)
|
|
{
|
|
const dtMeshHeader* header = reinterpret_cast<const dtMeshHeader*>(data);
|
|
|
|
if (header->magic != DT_NAVMESH_MAGIC)
|
|
throw std::logic_error("Invalid navmesh magic");
|
|
|
|
if (header->version != DT_NAVMESH_VERSION)
|
|
throw std::logic_error("Invalid navmesh version");
|
|
|
|
// Similar code to
|
|
// https://github.com/recastnavigation/recastnavigation/blob/c5cbd53024c8a9d8d097a4371215e3342d2fdc87/Detour/Source/DetourNavMesh.cpp#L978-L996
|
|
const int headerSize = dtAlign4(sizeof(dtMeshHeader));
|
|
const int vertsSize = dtAlign4(sizeof(float) * 3 * header->vertCount);
|
|
const int polysSize = dtAlign4(sizeof(dtPoly) * header->polyCount);
|
|
const int linksSize = dtAlign4(sizeof(dtLink) * (header->maxLinkCount));
|
|
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail) * header->detailMeshCount);
|
|
const int detailVertsSize = dtAlign4(sizeof(float) * 3 * header->detailVertCount);
|
|
const int detailTrisSize = dtAlign4(sizeof(unsigned char) * 4 * header->detailTriCount);
|
|
const int bvtreeSize = dtAlign4(sizeof(dtBVNode) * header->bvNodeCount);
|
|
const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection) * header->offMeshConCount);
|
|
|
|
const unsigned char* ptr = data + headerSize;
|
|
|
|
NavMeshTileConstView view;
|
|
|
|
view.mHeader = header;
|
|
view.mVerts = dtGetThenAdvanceBufferPointer<const float>(ptr, vertsSize);
|
|
view.mPolys = dtGetThenAdvanceBufferPointer<const dtPoly>(ptr, polysSize);
|
|
ptr += linksSize;
|
|
view.mDetailMeshes = dtGetThenAdvanceBufferPointer<const dtPolyDetail>(ptr, detailMeshesSize);
|
|
view.mDetailVerts = dtGetThenAdvanceBufferPointer<const float>(ptr, detailVertsSize);
|
|
view.mDetailTris = dtGetThenAdvanceBufferPointer<const unsigned char>(ptr, detailTrisSize);
|
|
view.mBvTree = dtGetThenAdvanceBufferPointer<const dtBVNode>(ptr, bvtreeSize);
|
|
view.mOffMeshCons = dtGetThenAdvanceBufferPointer<const dtOffMeshConnection>(ptr, offMeshLinksSize);
|
|
|
|
return view;
|
|
}
|
|
|
|
NavMeshTileConstView asNavMeshTileConstView(const dtMeshTile& tile)
|
|
{
|
|
NavMeshTileConstView view;
|
|
|
|
view.mHeader = tile.header;
|
|
view.mPolys = tile.polys;
|
|
view.mVerts = tile.verts;
|
|
view.mDetailMeshes = tile.detailMeshes;
|
|
view.mDetailVerts = tile.detailVerts;
|
|
view.mDetailTris = tile.detailTris;
|
|
view.mBvTree = tile.bvTree;
|
|
view.mOffMeshCons = tile.offMeshCons;
|
|
|
|
return view;
|
|
}
|
|
|
|
bool operator==(const NavMeshTileConstView& lhs, const NavMeshTileConstView& rhs) noexcept
|
|
{
|
|
using DetourNavigator::Ref;
|
|
using DetourNavigator::Span;
|
|
const auto makeTuple = [](const DetourNavigator::NavMeshTileConstView& v) {
|
|
return std::tuple(Ref(*v.mHeader), Span(v.mPolys, v.mHeader->polyCount),
|
|
Span(v.mVerts, v.mHeader->vertCount), Span(v.mDetailMeshes, v.mHeader->detailMeshCount),
|
|
Span(v.mDetailVerts, v.mHeader->detailVertCount), Span(v.mDetailTris, v.mHeader->detailTriCount),
|
|
Span(v.mBvTree, v.mHeader->bvNodeCount), Span(v.mOffMeshCons, v.mHeader->offMeshConCount));
|
|
};
|
|
return makeTuple(lhs) == makeTuple(rhs);
|
|
}
|
|
}
|