// nav_shim.cpp - ludic.nav's door into Recast & Detour (phase 17). The shim rules of // packages/README.md: int, float and opaque handles cross; no struct by value, no callback into // Ludic; what a query finds is written into a buffer the package owns; errors are return codes. #include #include #include #include #include #include #include #include #include #include #include #include #if defined(_WIN32) #define NAV_SHIM extern "C" __declspec(dllexport) #else #define NAV_SHIM extern "C" __attribute__((visibility("default"))) #endif #include "nav_alloc.inl" #ifdef _WIN32 extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(long long *); extern "C" __declspec(dllimport) int __stdcall QueryPerformanceFrequency(long long *); #else #include #endif namespace { // a monotonic clock in nanoseconds, from the OS alone (KERNEL32 on Windows: no C++ runtime to ship) long long nav_now_ns() { #ifdef _WIN32 long long c = 0, f = 1; QueryPerformanceCounter(&c); QueryPerformanceFrequency(&f); return (long long)((double)c * 1e9 / (double)f); #else struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); return (long long)t.tv_sec * 1000000000LL + t.tv_nsec; #endif } const int NAV_MAX_POLYS = 512; // polygons a path may cross; a longer one is cut there const int NAV_MAX_NODES = 4096; // the search's open list const int NAV_FILTERS = 8; // costs per kind of ground: one set per kind of walker's taste // one tile of a file-backed mesh (nav_resident.inl): its cell, where its bytes are, whether it is in struct NavTileRec { int x = 0, y = 0, size = 0; long long offset = 0; unsigned long long ref = 0; bool in = false; }; // a navmesh and the one query that walks it, with the scratch a path needs struct Nav { dtNavMesh *mesh = nullptr; dtNavMeshQuery *query = nullptr; dtQueryFilter filters[NAV_FILTERS]; float ext[3] = {2.0f, 4.0f, 2.0f}; // how far to look for the mesh around a point dtPolyRef polys[NAV_MAX_POLYS]; int partial = 0; // the last path stopped short of its end long long ns = 0; // time spent finding paths, for the measure (17.10) std::vector tiles; // a file-backed mesh's index; empty for a built or loaded one }; // a navmesh with its query, from params (a set of tiles) or from one tile's data Nav *nav_open(dtNavMesh *mesh) { Nav *n = new Nav(); n->mesh = mesh; n->query = dtAllocNavMeshQuery(); if (!n->query || dtStatusFailed(n->query->init(n->mesh, NAV_MAX_NODES))) { dtFreeNavMeshQuery(n->query); dtFreeNavMesh(n->mesh); delete n; return nullptr; } for (int f = 0; f < NAV_FILTERS; ++f) { n->filters[f].setIncludeFlags(0xffff); n->filters[f].setExcludeFlags(0); } return n; } Nav *nav_from(unsigned char *data, int size) { dtNavMesh *mesh = dtAllocNavMesh(); if (!mesh || dtStatusFailed(mesh->init(data, size, DT_TILE_FREE_DATA))) { dtFree(data); dtFreeNavMesh(mesh); return nullptr; } return nav_open(mesh); } // filter f, the first when f is out of range const dtQueryFilter *nav_filter(Nav *n, int f) { return &n->filters[f >= 0 && f < NAV_FILTERS ? f : 0]; } } // namespace #include "nav_build.inl" #include "nav_tiles.inl" #include "nav_query.inl" #include "nav_crowd.inl" #include "nav_resident.inl"